Install
$ agentstack add skill-snk-devcenter-addon-studio-action-button ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Botao de Acao (@ActionButton) — Addon Studio 2.0
@ActionButton associa uma classe Java ao menu "Acoes" de telas nativas do Sankhya Om. Disponivel a partir do Addon Studio 2.0.
> Referencias complementares: > - addon-studio — Stack + restricoes Java 8 > - dependency-injection — Injecao de dependencia (Guice)
1. Quando usar
Use @ActionButton quando o usuario precisar disparar manualmente uma rotina de back-end a partir de registros de uma tela nativa.
Casos de uso:
| Caso | Exemplo | |:-----|:--------| | Integracao manual | "Enviar para E-commerce" | | Geracao de arquivo/relatorio | "Exportar para Excel", "Gerar PDF" | | Acao em massa | "Aprovar Lotes Selecionados" | | Coleta de dados adicionais | Formulario antes de executar logica |
> Nao use para logica que dispara automaticamente ao salvar/excluir/modificar registros — use @BusinessRule ou Listener.
2. Anatomia de um @ActionButton
import br.com.sankhya.extensions.actionbutton.AcaoRotinaJava;
import br.com.sankhya.extensions.actionbutton.ContextoAcao;
import br.com.sankhya.studio.annotations.hooks.ActionButton;
import br.com.sankhya.studio.annotations.hooks.TransactionType;
import com.google.inject.Inject;
@ActionButton(
description = "Enviar para E-commerce", // Obrigatorio: texto no menu
instanceName = "CabecalhoNota", // Obrigatorio: nome da entidade
transactionType = TransactionType.AUTOMATIC, // Obrigatorio: AUTOMATIC ou MANUAL
resourceId = "br.com.sankhya.core.mov.central" // Recomendado: restringir a tela
)
public class EnviarEcommerceAction implements AcaoRotinaJava {
private final EcommerceService ecommerceService;
@Inject
public EnviarEcommerceAction(EcommerceService ecommerceService) {
this.ecommerceService = ecommerceService;
}
@Override
public void doAction(ContextoAcao contexto) throws Exception {
// Logica orquestrada — negocio fica no Service
ecommerceService.enviar(contexto.getLinhas());
contexto.setMensagemRetorno("Registros enviados com sucesso.");
}
}
3. Atributos da anotacao @ActionButton
| Atributo | Obrigatorio | Padrao | Descricao | |:-------------------|:------------|:------------------|:--------------------------------------------------------------------------------------------| | description | Sim | — | Texto exibido no menu "Acoes" para o usuario. | | instanceName | Sim | — | Nome da entidade (instancia) associada ao botao (ex.: "CabecalhoNota"). | | transactionType | Sim | — (sem default) | TransactionType.AUTOMATIC (framework gerencia a tx) ou TransactionType.MANUAL (controle manual). | | form | Nao | sem form | Formulario exibido antes de executar a acao. Ver secao 4. | | accessControlled | Nao | false | true = visibilidade respeita as permissoes de acesso do usuario a tela. Default false. | | resourceId | Nao | "" (todas telas)| Restringe o botao a uma tela especifica pelo seu ID de recurso. | | refreshType | Nao | NONE_ITEM | O que atualizar apos execucao. Valores: NONE_ITEM, SELECTED_ITEMS, PARENT_ITEM, MASTER_ITEM, ALL_ITEMS. |
> transactionType nao tem default — e obrigatorio. Valores validos: apenas TransactionType.AUTOMATIC e TransactionType.MANUAL. Nao existe REQUIRES_NEW (esse pertence ao EJBTransactionType de @Controller/@Job, nao ao hook do botao).
// Exemplo com todos os atributos
@ActionButton(
description = "Aprovar Nota",
instanceName = "CabecalhoNota",
resourceId = "br.com.sankhya.core.mov.centraldenotas",
transactionType = TransactionType.AUTOMATIC,
accessControlled = true,
refreshType = RefreshTypeEnum.ALL_ITEMS
)
4. Formulario (@Form)
Exibido ao usuario antes de doAction() ser chamado. Framework coleta os dados e os disponibiliza via contexto.getParam().
Tipos de campo (FieldType)
| FieldType | Tipo retorno em getParam() | Uso tipico | |:-------------|:-----------------------------|:----------------------------| | LIST | String (value da @Option)| Selecao de opcoes fixas | | DATE | java.sql.Timestamp | Data/hora | | BOOLEAN | "S" ou "N" como String | Flag booleano |
> Valores de FieldType: TEXT, INTEGER, SEARCH, DECIMAL, DATE, DATE_TIME, BOOLEAN, LIST. Nao existe CHECKBOX — use BOOLEAN. Campo SEARCH exige instance; campo LIST exige options.
Anatomia do @Form
form = @Form(
fields = {
@Field(
name = "NOME_PARAM", // Chave usada em contexto.getParam("NOME_PARAM")
label = "Rotulo ao usuario",
type = FieldType.LIST,
required = true, // Opcional, padrao false
options = { // Somente para FieldType.LIST
@Option(value = "A", label = "Opcao A"),
@Option(value = "B", label = "Opcao B")
}
),
@Field(
name = "DATA_REF",
label = "Data de Referencia",
type = FieldType.DATE,
required = true
),
@Field(
name = "FLAG",
label = "Incluir detalhes?",
type = FieldType.BOOLEAN
)
}
)
Leitura dos parametros em doAction()
// LIST -> String
String formato = (String) contexto.getParam("FORMATO");
// DATE -> java.sql.Timestamp
java.sql.Timestamp dataRef = (java.sql.Timestamp) contexto.getParam("DATA_REF");
// BOOLEAN -> "S" ou "N"
boolean incluir = "S".equals(contexto.getParam("FLAG"));
5. ContextoAcao — API completa
| Metodo | Descricao | |:------------------------------------|:-----------------------------------------------------------------------| | contexto.getLinhas() | Registros selecionados na tela. Iterar para operacoes em massa. | | contexto.getParam("NOME") | Parametro preenchido no formulario. Cast necessario conforme tipo. | | contexto.setMensagemRetorno("msg")| Mensagem de sucesso ou erro exibida ao usuario apos execucao. |
6. Exemplo completo com formulario
import br.com.sankhya.extensions.actionbutton.AcaoRotinaJava;
import br.com.sankhya.extensions.actionbutton.ContextoAcao;
import br.com.sankhya.studio.annotations.hooks.*;
import com.google.inject.Inject;
@ActionButton(
description = "Exportar Dados para Planilha",
instanceName = "CabecalhoNota",
transactionType = TransactionType.AUTOMATIC,
resourceId = "br.com.sankhya.core.mov.centraldenotas",
form = @Form(
fields = {
@Field(
name = "TIPO_ARQUIVO",
label = "Formato",
type = FieldType.LIST,
required = true,
options = {
@Option(value = "XLSX", label = "Excel (XLSX)"),
@Option(value = "CSV", label = "CSV")
}
),
@Field(
name = "DATA_INICIAL",
label = "Data Inicial",
type = FieldType.DATE,
required = true
),
@Field(
name = "INCLUIR_ITENS",
label = "Incluir Itens da Nota?",
type = FieldType.BOOLEAN
)
}
)
)
public class ExportarDadosAction implements AcaoRotinaJava {
private final ExportacaoService exportacaoService;
@Inject
public ExportarDadosAction(ExportacaoService exportacaoService) {
this.exportacaoService = exportacaoService;
}
@Override
public void doAction(ContextoAcao contexto) throws Exception {
String tipoArquivo = (String) contexto.getParam("TIPO_ARQUIVO");
java.sql.Timestamp dataInicial = (java.sql.Timestamp) contexto.getParam("DATA_INICIAL");
boolean incluirItens = "S".equals(contexto.getParam("INCLUIR_ITENS"));
exportacaoService.exportar(tipoArquivo, dataInicial, incluirItens, contexto.getLinhas());
contexto.setMensagemRetorno("Exportacao iniciada para o formato: " + tipoArquivo);
}
}
7. Boas Praticas
- Logica em Services:
doAction()orquestra — nao implementa regra de negocio. Delegue para@Component. resourceIdsempre que possivel: Evita poluir menu "Acoes" de outras telas que usam a mesma entidade.- Feedback obrigatorio: Sempre chame
contexto.setMensagemRetorno(). Usuario sem retorno pensa que nada ocorreu. accessControlled: Default efalse. Definatruequando a visibilidade do botao deve respeitar as permissoes de acesso do usuario a tela.- Descricoes objetivas: "Enviar para E-commerce" e correto. "Processar" ou "Executar" sao ambiguos.
8. Anti-Patterns (PROIBIDO)
| Anti-Pattern | Correcao | |:-------------|:---------| | Omitir transactionType (e obrigatorio) | Sempre definir TransactionType.AUTOMATIC ou MANUAL | | transactionType = TransactionType.REQUIRES_NEW | Nao existe — usar AUTOMATIC ou MANUAL | | type = FieldType.CHECKBOX | Nao existe — usar FieldType.BOOLEAN | | refreshType = RefreshTypeEnum.ALL / ITEM | Usar ALL_ITEMS / NONE_ITEM (valores reais) | | Logica de negocio no doAction() | Mover para Service (@Component) | | Nao chamar setMensagemRetorno() | Sempre fornecer feedback ao usuario | | Usar para logica automatica (salvar/excluir) | Usar @BusinessRule ou Listener | | description generica ("Processar", "Executar") | Descricao clara e contextualizada | | new em dependencias gerenciadas | Injetar via construtor com @Inject | | Usar para telas customizadas | Em telas customizadas, crie botoes proprios na UI |
9. Checklist: Novo @ActionButton
- [ ] Criar classe implementando
AcaoRotinaJava(nomearAction). - [ ] Anotar com
@ActionButton(description = "...", instanceName = "...", transactionType = TransactionType.AUTOMATIC). - [ ] Definir
resourceIdpara restringir a tela especifica. - [ ] Se precisar de dados do usuario: definir
@Formcom@Fields adequados (FieldTypevalido). - [ ] Injetar dependencias via construtor com
@Inject(Guice). - [ ] Implementar
doAction()delegando logica para Service. - [ ] Chamar
contexto.setMensagemRetorno()em todos os caminhos (sucesso e erro). - [ ] Confirmar
transactionType(obrigatorio):AUTOMATIC(framework gerencia) ouMANUAL(controle manual). - [ ] Definir
refreshTypese precisar atualizar mais que o registro atual (ALL_ITEMS,SELECTED_ITEMS, etc.). - [ ] Registrar no modulo Guice os services/dependencias injetados na classe — a action em si nao precisa de binding (o SDK a descobre pela anotacao
@ActionButton). Verdependency-injection.
Skills relacionadas
entity— modelo de dados que o botão lê/escrevecontroller— alternativa REST quando ação não é botão de tela mas endpoint HTTPbusiness-rule— regra de negócio dispara via barramento — alternativa a botão para validaçõesdependency-injection— wiring Guice dos services injetados na actiontest— JUnit 5 + Mockito daAcaoRotinaJava
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: snk-devcenter
- Source: snk-devcenter/addon-studio
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.