Introdução
Uma das novidades da versão 3.0 do EJB são os Interceptors, uma maneira ainda rudimentar de utilizar AOP (Aspect Oriented Programming) em aplicações que utilizam EJB, o inverso do que ocorre com aplicações que utilizam o Spring (falarei sobre isso em outro post). AOP é um paradigma chamado de separation of concerns, que tem como característica quebrar o programa em diversas partes para interferir em seu processamento.
Segundo a especificação, um Interceptor é uma classe POJO (Plain Old Java Object) que não precisa ser anotada ou configurada como um session bean (utilizando as anotações @Stateless ou @Statefull). Ela deve conter um método método público anotado com @AroundInvoke, que retorna um Object, possuir o objeto InvocationContext como parâmetro e lançar a exceção Exception. Ela pode obter recursos do ENC (Enterprise Naming Context) JNDI, como injeção de dependências através da anotação @EJB, recursos através da anotação @Resource e o objeto EntityManager, através da anotação @PersistenceContext.
O objeto InvocationContext contém métodos que retornam a instância do objeto interceptado, bem como seus parâmetros e também um objeto Method que retorna o método que foi interceptado. A lógica de sua utilização gira em torno do método proceed desse objeto, pois quando ele é chamado o método interceptado será executado. Se no ciclo de processamento de um Interceptor um método tiver anotado com @AroundInvoke, o ciclo executará primeiro o Interceptor do método interceptado. Após isto o ciclo será executado normalmente.
Portanto, a lógica da utilização de Interceptors é gerar ou obter informações antes ou depois do método proceed ser chamado.
Para utilizar seus Interceptors em seus EJBs, basta utilizar a anotação @Interceptors(Class[] clazz). Essa anotação pode ser utilizada de duas formas: em métodos ou em classes. Se você utilizá-la em classes, todos os métodos dessa classe serão interceptados. Utilize a anotação @ExcludeClassInterceptors caso queira que seus métodos não sejam interceptados.
Caso não queira utilizar anotações, os Interceptors também podem ser configurados via arquivos XML. Registros (logs), segurança, auditoria e transações são exemplos mais comuns da utilização de Interceptors.
Criando a aplicação
Como IDE utilizei o Eclipse Europa (webtools) e o JBoss 4.2 como servidor de aplicação. No Eclipse, crie um projeto EJB Project (File – New – Project – EJB – EJB Project). Lembre-se de configurar o projeto com o JBoss 4.2, EJB 3.0 e Java 5.0 ou 6.0.
Para fazer o deploy do projeto basta clicar com o botão direito do mouse e escolha a opção Export – EJB JAR File. Feito isso, copie o arquivo gerado (.jar) e coloque na pasta ${CLASSPATH_DO_SEU_JBOSS}/server/default/deploy do seu JBoss. Inicialize o servidor pelo Eclipse (configure-o na opção Servers) ou pelo prompt de commando executando o comando ${CLASSPATH_DO_SEU_JBOSS}/bin/run.bat.
Códigos
AuditPersonInterceptor
public class AuditPersonInterceptor { /**
* This method contains the logic for intercepting the flow.
*
* @param invocationContext
* @return
* @throws Exception
*/
@AroundInvoke
public Object auditPerson(InvocationContext invocationContext)
throws Exception {
System.out.println("Before method execute...");
Object proceed = invocationContext.proceed();
System.out.println("After method execute...");
return proceed;
}
}
PersonService
@Remote
public interface PersonService { /**
* Insert an Person.
*/
public void insertPerson();
}
PersonServiceBean
@Stateless
public class PersonServiceBean implements PersonService { /*
* (non-Javadoc)
*
* @see org.rafaelcarneiro.service.PersonService#insertPerson()
*/
@Override
@Interceptors(AuditPersonInterceptor.class)
public void insertPerson() {
System.out.println("Inserting an Person...");
}
}
Client
public class Client { /**
* Method main that obtain the EJB from JNDI and insert an Person.
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Context context = new InitialContext();
PersonService personService = (PersonService) context
.lookup("PersonServiceBean/remote");
personService.insertPerson();
}
}
Comentários dos códigos
- AuditPersonInterceptor: representa o nosso Interceptor;
- PersonService: interface remota para o session bean;
- PersonServiceBean: session bean do tipo Stateless (sem estado) que implementa a interface remota PersonService e contém o método a ser interceptado;
- Client: classe que obtém e executa o session bean PersonServiceBean.
Executando
Ao executar a aplicação no JBoss, você verá as mensagens abaixo no console do JBoss:
INFO [STDOUT] Before method execute…
INFO [STDOUT] Inserting an Person…
INFO [STDOUT] After method execute…
Conclusão
EJB 3.0 veio para simplificar o desenvolvimento de softwares baseado em componentes, usando massivamente annotations e diminuindo a quantidade de arquivos e o trabalho com configurações. Interceptor é fácil de ser implementado, basta a utilização de algumas anotações. Como mencionei na introdução desse artigo, os Interceptors do EJB 3.0 ainda tem muito a desejar comparando com o uso de AOP com Spring. Mas quem sabe o JCP (Java Community Procces) e a Sun melhorem seus recursos.
No próximo artigo da Série EJB 3.0 iremos abordar os Web services.
Download do código fonte
Application LearningInterceptors
Referências
Wikipedia: http://en.wikipedia.org/
The Java Community Procces: http://jcp.org/Tweet





