🎮 Services (Controllers)
Acesso Antecipado (Beta)Esta documentação refere-se a uma versão em acesso antecipado do SDK Sankhya. As funcionalidades e APIs estão sujeitas a modificações. Para obter acesso, envie um e-mail para [email protected] informando a
appkeydo seu projeto.
🎮 Camada de Serviço (@Service)
@Service)No SDK Sankhya, a anotação @Service transforma uma classe Java em um endpoint para requisições externas, funcionando como um Controller no padrão MVC. Ela orquestra a interação entre o mundo exterior e a lógica de negócio da aplicação.
Por que usar @Service?
@Service?- Clareza Arquitetural: Separa a camada de apresentação da lógica de negócio.
- Padrão de Mercado: Alinhado com frameworks como Spring.
- Integração Total: Suporte a injeção de dependências, validação e controle transacional.
- Separação de Responsabilidades: O serviço recebe, valida e delega requisições, sem executar regras de negócio complexas.
Abordagem Antiga vs. Nova
A abordagem antiga exigia a manipulação manual de ServiceContext, resultando em um código verboso, acoplado e difícil de testar.
❌ Abordagem Tradicional (ServiceBean)
ServiceBean)// Código legado: verboso, acoplado e difícil de testar
/**
* @ejb.bean name="PedidoServiceSP"
* jndi-name="mge/placemm/ejb/session/PedidoServiceSP"
* type="Stateless" transaction-type="Container" view-type="remote"
* @ejb.transaction type="Supports"
* @ejb.util generate="false"
*/
public class PedidoServiceSPBean extends ServiceBean {
public void criarPedido(ServiceContext sctx) throws Exception {
JapeSession.SessionHandle hnd = null;
try {
hnd = JapeSession.open();
// Lógica manual de transação, parsing de JSON, etc.
JsonObject json = (JsonObject) sctx.getJsonRequestBody();
// ... muito código boilerplate ...
} finally {
JapeSession.close(hnd);
}
}
}✅ Nova Abordagem com @Service
@ServiceA nova abordagem é declarativa, limpa e integrada com os demais pilares do SDK.
@Service(serviceName = "PedidoServiceSP")
public class PedidoService {
private final PedidoBusinessService businessService;
@Inject
public PedidoService(PedidoBusinessService businessService) {
this.businessService = businessService;
}
@Transactional // O SDK gerencia a transação
public void criarPedido(@Valid PedidoDTO pedido) {
// 1. @Valid: Validação automática do DTO
// 2. Delegação para a camada de negócio
businessService.criar(pedido);
}
}Como funciona o @Service
@Service- Atributo obrigatório
serviceName: Define o nome do serviço registrado na plataforma (por convenção, termina comSP). - Métodos públicos: Tornam-se "ações" do serviço, acessíveis externamente.
- Injeção de dependências: Via construtor.
URL de acesso:
.../service.sbr?serviceName=<nomeDoServico>.<nomeDoMetodo>
Exemplo:
.../mge/service.sbr?serviceName=PedidoServiceSP.criarPedido
Controle Transacional (transactionType)
transactionType)A anotação @Service permite configurar o comportamento transacional padrão para todos os métodos da classe através do atributo transactionType:
@Service(
serviceName = "RelatorioServiceSP",
transactionType = TransactionType.NotSupported
)
public class RelatorioService {
// ...
}TransactionType | Descrição | Quando Usar |
|---|---|---|
Required | Garante que o método sempre execute dentro de uma transação. Se já existir, utiliza-a; senão, cria uma nova. | Ideal para operações de escrita (CRUD). |
NotSupported | Executa fora de qualquer transação. Se houver uma ativa, ela é suspensa. | Operações de leitura que não precisam de consistência transacional. |
Supported | Executa dentro de uma transação se já houver uma ativa; caso contrário, executa sem transação. | Operações de leitura que podem ou não fazer parte de uma transação maior. (Padrão) |
Nota: A anotação
@Transactionalem um método sempre tem precedência sobre otransactionTypedefinido na classe, permitindo controle granular.
Sobrepondo o padrão com @Transactional
@Transactional@Service(serviceName = "ConsultaServiceSP", transactionType = TransactionType.NotSupported)
public class ConsultaService {
// Este método usa o padrão da classe (NotSupported)
public List<ProdutoDTO> listarProdutos() {
// ... lógica de consulta ...
}
@Transactional(type = TransactionType.RequiresNew) // Sobrepõe o padrão
public void registrarLogDeConsulta() {
// Executa em sua própria transação
}
}Boas Práticas
-
Mantenha Controllers "Magros": O
@Servicedeve apenas receber a requisição, validar (@Valid) e delegar para um componente de negócio. Não coloque regras de negócio complexas no Controller.@Service(serviceName = "UsuarioServiceSP") public class UsuarioController { private final UsuarioService usuarioService; @Inject public UsuarioController(UsuarioService usuarioService) { this.usuarioService = usuarioService; } @Transactional public void ativarUsuario(Long usuarioId) { usuarioService.ativar(usuarioId); } } -
Use DTOs: Sempre utilize Data Transfer Objects para entrada e saída, desacoplando a camada de serviço da persistência e evitando exposição de dados sensíveis.
-
Injeção via construtor: Prefira sempre a injeção de dependências via construtor para facilitar testes e explicitar dependências.
-
Serviços de leitura: Para serviços apenas de consulta, use
transactionType = TransactionType.NotSupportedpara otimizar desempenho. -
Valide entradas: Use
@Validnos DTOs para garantir dados corretos antes do processamento.
A anotação @Service é a peça central que conecta seu Add-on ao ecossistema Sankhya, permitindo a criação de serviços robustos, testáveis e alinhados com as melhores práticas do mercado.
Updated 11 days ago
