Category Archives: séries

Série EJB 3.0: Interceptors

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/