EJB

Testando JavaEE 6 com Glassfish e Eclipse

Neste post, vou mostrar algumas novidades do Java EE 6.
Eu vou usar os seguintes softwares:

Glassfish v3
Eclipse Galileo JEE Edition

Depois de instalá-los, vou criar um Dynamic Web Project no Eclipse chamado de FirstProjectJEE6:

Agora vou substituir o conteúdo do arquivo web.xml por este abaixo:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

Para compilar nosso projeto, precisamos adicionar um jar externo chamado javaee.jar ao projeto (Build Path), o arquivo jar pode ser encontrado em [glassfish_directory]/glassfish/lib/javaee.jar

Criei também um script ant para fazer o deploy da nossa aplicação diretamente no glassfish. Este script deve ser salvo na raiz do projeto, salvei ele com o nome de build.xml. A seguir segue seu conteúdo:

<?xml version="1.0" encoding="UTF-8"?>
<project name="FirstProject JavaEE 6" basedir="." default="deploy">
	<property name="warfile" value="FirstProject" />
	<target name="create">
		<war destfile="${warfile}.war" webxml="WebContent/WEB-INF/web.xml" update="true">
			<classes dir="build/classes" />
			<fileset dir="WebContent">
				<exclude name="WEB-INF/web.xml" />
			</fileset>
		</war>
	</target>
	<target name="copy">
		<copy todir="/Users/rodrigolazoti/Programs/glassfishv3/glassfish/domains/domain1/autodeploy" overwrite="true">
			<fileset dir=".">
				<include name="*.war" />
			</fileset>
		</copy>
	</target>
	<target name="deploy">
		<antcall target="create" />
		<antcall target="copy" />
	</target>
</project>

Note que esse local:
/Users/rodrigolazoti/Programs/glassfishv3/glassfish/domains/domain1/autodeploy
Deve ser substituído por:
[your glassfish]/glassfish/domains/domain1/autodeploy

Agora, vamos codificar um pouco, primeiro vamos criar dois EJB’s usando um pouco da nova especificação.
Vou criar um EJB Stateless e um EJB Staleful, o stateful servirá apenas para representar o número de requisições feitas e o stateless servirá para retornar alguma mensagem para o usuário.

Esse é o código do EJB Stateless:

package br.com.rodrigolazoti.firstproject.service;

import javax.ejb.Stateless;

@Stateless
public class MyStatelessSessionBean {

	public String createMessage( String username ) {
		String message = "Hello World, ";

		if ( username != null && !"".equals( username.trim() ) ) {
			message += username + "!";
		}
		else {
			message += "stranger!";
		}

		return message;
	}

}

E este é o código do EJB Stateful:

package br.com.rodrigolazoti.firstproject.service;

import javax.ejb.Stateful;

@Stateful
public class MyStatefulSessionBean {

	private int amountOfrequests = 0;

	public int getAmountOfrequests() {
		return ++amountOfrequests;
	}

}

Note que em ambos EJB’s, não foi necessário criar interfaces locais ou remotas. :)

Com nossos EJB’s prontos, vamos criar um servlet para responder ao seguintes métodos http GET e POST.

package br.com.rodrigolazoti.firstproject.controller;

import java.io.IOException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import br.com.rodrigolazoti.firstproject.service.MyStatefulSessionBean;
import br.com.rodrigolazoti.firstproject.service.MyStatelessSessionBean;

@WebServlet( name = "MyServlet", urlPatterns = { "/hello" } )
public class MyServlet extends HttpServlet {

	private static final long serialVersionUID = -2206981309178199835L;

	@EJB
	private MyStatefulSessionBean myStatefulSessionBean;

	@EJB
	private MyStatelessSessionBean myStatelessSessionBean;

	@Override
	protected void doGet( HttpServletRequest request, HttpServletResponse response )
			throws ServletException, IOException {
		String message = myStatelessSessionBean.createMessage( null );
		request.setAttribute( "message", message );

		int amountOfRequests = myStatefulSessionBean.getAmountOfrequests();
		request.setAttribute( "amountOfRequests", amountOfRequests );

		request.getRequestDispatcher( "/hello.jsp" ).forward( request, response );
	}

	@Override
	protected void doPost( HttpServletRequest request, HttpServletResponse response )
			throws ServletException, IOException {
		String username = request.getParameter( "username" );
		String message = myStatelessSessionBean.createMessage( username );
		request.setAttribute( "message", message );

		int amountOfRequests = myStatefulSessionBean.getAmountOfrequests();
		request.setAttribute( "amountOfRequests", amountOfRequests );

		request.getRequestDispatcher( "/hello.jsp" ).forward( request, response );
	}

}

E finalmente, vamos criar os arquivos jsp. O arquivo index.jsp servirá pra fazer as chamados ao servlet e o arquivo hello.jsp irá mostrar o resultado do servlet.

Conteúdo do arquivo index.jsp:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
  <meta name="author" content="Rodrigo Lazoti"/>
  <title>First Java EE 6 Example</title>
</head>
<body>
  <p><a href="hello">Execute Servlet (GET)</a></p>

  <hr width="100%" noshade="noshade"/>

  <form action="hello" method="post">
    <p>Name:<input type="text" name="username"/></p>
    <p><button type="submit">Execute Servlet (POST)</button></p>
  </form>
</body>
</html>

E o conteúdo do arquivo hello.jsp:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
  <meta name="author" content="Rodrigo Lazoti"/>
  <title>First Java EE 6 Example</title>
</head>
<body>
  <h2>Result: ${requestScope.message}</h2><br/>
  <h3>This servlet was executed ${requestScope.amountOfRequests} time(s).</h3><br/>
  <hr width="100%" noshade="noshade"/>
  <h4><a href="index.jsp">Back to main page</a></h4>
</body>
</html>

Pronto, nosso exemplo já esta pronto e pode ser testado. Com vimos algumas novidades como:

  • Interface local e remota são opcionais no EJB 3.1.
  • No EJB 3.1, vôce pode empacotar seus EJB’s em arquivos WAR junto com componentes da camada web. Você não precisa ter sua classes EJB definidas em um arquivo ejb-jar.
  • Agora as annotations podem ser usadas em mais tipos de componentes Java EE e o conjunto de anotações usados para injeção de dependência foi padronizada.
  • Ao invés de criar deployment descriptors, você pode anotar as classes para especificar que ela é um servlet.

Este exemplo criado está disponível no github: http://github.com/rlazoti/tutorial-javaee6-first-project

SCBCD 5 – Test Status: Pass

Como tinha um voucher vencendo decidi fazer a prova agora no começo de abril, depois de duas semanas me dedicando ao estudo do conteúdo cobrado pela certificação SCBCD 5 – Sun Certified Business Component Developer Java EE Platform 5 e retorno agora de um centro Prometric feliz da vida por ter passado na certificação.

Não tive muito tempo pra me dedicar e estudar tudo sobre a prova, por isso estudei basicamente o conteudo do livro Enterprise Javabeans 3 de Bill Burke & Richard Monson-Haefel. O livro em si tem um bom conteudo, mas nao abrange completamente a prova. Prova disso foi que desconhecia algumas questoes mais teoricas e outras acabei aprendendo no simulado.

O que utilizei para estudar:

  • Livro – Enterprise Javabeans 3.
  • Simulado – EJBPlus 5

Sobre o livro:

Como disse anteriormente, embora o livro seja bom ele não abrenge todo o conteudo cobrado no exame, pois se você pretende se preparar totalmente para a prova recomendo a leitura da especificao EJB3.

Sobre o simulado:

Realmente este simulado é muito bom, valeu a pena os $29,00 gastos nele e embora eu não consegui utiliza-lo muito, pois realizei apenas 4 testes (iniciei com o score de 54% e no ultimo fiquei com 75%), mas mesmo assim recomendo.

Sobre a prova:

Cairam muitas questoes de transactions, exceptions, session beans (SFSB, SLSB e MDB) e JPA. Interceptors e timers foram muito poucas. Cairam algumas que cobravam um pequeno conhecinhento de tags XML. Security foi bem tranquilo tambem. Uma ultima dica é que treine bastante seu ingles, pois diferente das outras provas que fiz, esta tem questoes com enunciados maiores e uma palavra entendida de forma errada pode fazer voce marcar uma alternativa incorreta.

 

Agora é descançar um pouco e comemorar a nova conquista! :D

Gerando Log de EJB com Interceptor e Log4J

Uma forma simples de gerar log de uma aplicação é utilizando bibliotecas como Log4J ou Commons Logging, mas ficar incluindo em todas as classes necessárias, chamadas a métodos para gerar log pode ser uma tarefa muito repetitiva.

O Spring framework resolve esse problema utilizando AOP (programação orientada a aspectos), onde podemos criar uma classe que inspeciona e gera os logs de chamadas a métodos de outras classes, assim economizamos tempo e poupa-se código também.

Utilizando a espeficicação EJB 3.0 podemos também nos beneficiar de um recurso parecido com o utilizando pelo Spring na qual chama-se Interceptors, com ele podemos interceptar chamadas aos métodos de negócio dos nossos Sessions Beans e Message Driven Beans.

Para demonstrar seu funcionamento, Vou criar um pequeno exemplo utilizando um Stateless Session Bean e um Interceptor utilizando Log4J, porém este post não visa explicar como configurar um projeto EJB e a ferramente Log4J, mas simplesmente demonstrar como utilizar Interceptors em uma simples aplicação que utiliza EJB.

Primeiro vou criar o Interceptor, o método intercept tem a finalidade de gerar o log de todas as classes que ele interceptar, o método é definico com a anotação @AroundInvoke, este método pode se encontrar em uma classe separada (como no exemplo a seguir) ou no próprio session bean, lembrando apenas que só pode ter um único método anotado por classe, mas nada impede de termos várias classes de interceptors.

package br.com.rodrigolazoti;

import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

import org.apache.log4j.Logger;

public class LoggerInterceptor {

@AroundInvoke
public Object intercept( InvocationContext invocationContext ) throws Exception {
Logger log = Logger.getLogger( "myProject" );
String methodName = invocationContext.getMethod().getName();
String className = invocationContext.getTarget().getClass().getName();

log.debug( "Calling Method: " + className + "." + methodName );
long timeBefore = System.currentTimeMillis();

try {
return invocationContext.proceed();
}
catch ( Exception e ) {
log.error( "Error on calling method " + className + "." + methodName );
log.error( "Root cause: ", e );
throw e;
}
finally {
long timeAfter = System.currentTimeMillis();
log.info( "Method " + className + "." + methodName + " called in " +
( timeAfter - timeBefore ) + "ms" );
}
}
}

Agora vou criar o interface remota do meu session bean:

package br.com.rodrigolazoti;

import javax.ejb.Remote;

@Remote
public interface MyServiceBean {
Integer sum( Integer[] values );

String createWelcomeMessage( String name );
}

Finalmente a implementação do session bean, repare que utilizo a anotação @Interceptors, onde posso definir um ou mais interceptors para esta classe, podemos também definir um interceptor para um método ou até mesmo excluir um interceptor de um método ou classe utilizando a anotação @ExcludeClassInterceptors. Utilizando a configuração via XML podemos definir um interceptor para um grupo de ejb’s por exemplo.

Mais >