JBoss 5.0.1.GA, EJB3, Maven2 e Cargo Juntos e na Prática

Neste post vou mostrar como criar um projeto EJB 3 bem simples usando Maven 2. Vamos fazer o deploy no JBoss 5.o.1.GA através do plugin do maven do cargo. Além disso vamos criar um projeto cliente que acessa o EJB criado através de JNDI.

Meu objetivo é mostrar de uma maneira simples e que funciona :) como usar maven 2 com projetos ejb3, de barbada vamos fazer o deploy no JBoss 5.0.1.GA, no fim do post você irá encontrar os códigos fontes e bem como as dependências(jars) da aplicação cliente.

Criar uma aplicação Java com Maven é realmente muito fácil mais quando falamos de fazer um deploy no servidor com o cargo usando o plugin do maven as coisas não são tão simples, por que a documentação do Cargo não é 100% intuitiva e faltam exemplos práticos de como usar as configurações. Além disso o JBoss 5 ainda não está 100% com o maven 2, mais para frente do post vocês irão entender o por que disso.

Cuidado com o JDK

Recomendo que você use um JDK acima do JDKu10, eu estou usando no momento o JDKu13. Caso você use um inferior ao JDKu10 você terá sérios problemas para subir o comtainer do JBoss 5. Existem diversos posts em blogs e tutoriais na web que recomendam você colocar os jars do jaxb e jaxws no diretório endorsed da jvm, para mim isso não funcionou. A melhor saída é usar um JDK mais novo.

Nota: Até por que o JDK tem uma performance melhor do que as dos anteriores e recursos bem interessantes em termos de ferramentas.



O Projeto EJB 3

Nesse projeto vamos criar uma interface de negocio chamada de DateService. Essa interface é simples seu objetivo e representar o contrato de um serviço de datas, que informa através de uma String a data atual do container. Vamos ao código da interface:


package com.blogspot.diegopacheco.services;

/**
* Interface de Servico de Data
*
* @author Diego Pacheco
* @version 1.0
* @since 03/05/2009
*
*/
public interface DateService {
public String getDateTime();
}

Agora vamos a implementação do EJB 3. Vou usar os novos recursos do EJB 3 em termos de anotações. Vamos ver o código então:


package com.blogspot.diegopacheco.services;

import java.util.Date;

import javax.ejb.Remote;
import javax.ejb.Stateless;

/**
* Stateless Session Bean que eh uma implementacao do Servico de Data
*
* @author Diego Pacheco
* @version 1.0
* @since 03/05/2009
*
*/
@Stateless
@Remote(DateService.class)
public class DateServiceBean implements DateService{
public String getDateTime() {
return new Date().toString();
}   
}

Como podem ver a implementação é simples, por que o meu objetivo no post é mostrar como integrar e usar essas tecnologias. Muito bem agora vamos ao pom do maven desse projeto:


4.0.0
com.blogspot.diegopacheco
mvn2-jboss5-ejb3
1.0-SNAPSHOT
ejb
Maven 2 + EJB 3.0 + Jboss 5




org.apache.maven.plugins
maven-compiler-plugin

1.6
1.6
UTF-8



true
org.apache.maven.plugins
maven-source-plugin


attach-sources

jar





org.apache.maven.plugins
maven-ejb-plugin

3.0



org.codehaus.cargo
cargo-maven2-plugin
0.3-SNAPSHOT

false

jboss4x
remote

runtime
D:/Diego/Java/bin/jboss-5.0.1.GA/server/default







javax.ejb
ejb-api
3.0
   




Vocês podem ver que estou usando o plugin de ejb do maven e bem como o plugin do cargo. Não repare ao onde diz 'jboss4x' pois isso funciona no JBoss 5. Na propriedade 'home' você tem que apontar para a sua intalação do JBoss 5.

Agora suba o JBoss 5.0 pelo console e após o JBoss ter subido execute os seguintes goals do maven:

mvn clean install cargo:deploy

Com o 'cargo:deploy' você irá fazer o deploy do seu ejb no JBoss 5 através do plugin do cargo do maven. Agora verifique no console do JBoss5, ele deve ter mostrado algo parecido com isso:
20:26:11,545 INFO  [MainDeployer] deploy, url=file:/D:/Diego/workspace-gps/mvn2-jboss5-ejb3/target/mvn2-jboss5-ejb3-1.0-SNAPSHOT.jar
20:26:11,717 INFO  [Ejb3DependenciesDeployer] Encountered deployment AbstractVFSDeploymentContext@19623251{vfszip:/D:/Diego/workspace-gps/mvn2-jboss5-ejb3/target/mvn2-jboss5-ejb3-1.0-SNAPSHOT.jar/}
20:26:11,718 INFO  [Ejb3DependenciesDeployer] Encountered deployment AbstractVFSDeploymentContext@19623251{vfszip:/D:/Diego/workspace-gps/mvn2-jboss5-ejb3/target/mvn2-jboss5-ejb3-1.0-SNAPSHOT.jar/}
20:26:14,862 INFO  [JBossASKernel] Created KernelDeployment for: mvn2-jboss5-ejb3-1.0-SNAPSHOT.jar
20:26:14,871 INFO  [JBossASKernel] installing bean: jboss.j2ee:jar=mvn2-jboss5-ejb3-1.0-SNAPSHOT.jar,name=DateServiceBean,service=EJB3
20:26:14,871 INFO  [JBossASKernel]   with dependencies:
20:26:14,871 INFO  [JBossASKernel]   and demands:
20:26:14,872 INFO  [JBossASKernel]     jboss.ejb:service=EJBTimerService
20:26:14,872 INFO  [JBossASKernel]   and supplies:
20:26:14,872 INFO  [JBossASKernel]     jndi:DateServiceBean/remote-com.blogspot.diegopacheco.services.DateService
20:26:14,872 INFO  [JBossASKernel]     jndi:DateServiceBean/remote
20:26:14,872 INFO  [JBossASKernel]     Class:com.blogspot.diegopacheco.services.DateService
20:26:14,872 INFO  [JBossASKernel] Added bean(jboss.j2ee:jar=mvn2-jboss5-ejb3-1.0-SNAPSHOT.jar,name=DateServiceBean,service=EJB3) to KernelDeployment of: mvn2-jboss5-ejb3-1.0-SNAPSHOT.jar
20:26:15,068 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=mvn2-jboss5-ejb3-1.0-SNAPSHOT.jar,name=DateServiceBean,service=EJB3
20:26:15,086 INFO  [EJBContainer] STARTED EJB: com.blogspot.diegopacheco.services.DateServiceBean ejbName: DateServiceBean
20:26:15,169 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

DateServiceBean/remote - EJB3.x Default Remote Business Interface
DateServiceBean/remote-com.blogspot.diegopacheco.services.DateService - EJB3.x Remote Business Interface

Agora podemos ir para o projeto ejb-client. Nesse projeto vamos usar maven, mas será necessário o uso de bibliotecas fora as do maven.

Por que não usar Maven no Ejb3-Client?

Por que ao utilizar os repositórios do maven do JBoss que são:
  • http://repository.jboss.org/maven2/
  • http://repository.jboss.com/maven2/
Até existem os jars necessários para o uso da aplicação de ejb cliente com JBoss 5.0.1.GA, porem os jars estão em versões mais antigas do que as bibliotecas que existem no JBoss 5.0.1.GA, você pode conferir isso, vá nesses diretórios:
  • $JBOSS_HOME/lib
  • $JBOSS_HOME/common/lib
Hoje(03/05/2009) as dependências dos repositórios do jboss acima não são compatíveis, são de versões mais antigas, mas não são todas as bibliotecas são algumas, para não ficar com o projeto capenga resolvi usar essas dependências da maneira tradicional criando uma pasta lib e a adicionando ao classpath no eclipse.

A Classe de testes do projeto cliente, ela chama o ejb através e um lookup JNDI feito por uma classe helper chamada de ServiceLocator que por sinal é um padrão de design da sun.

package com.blogspot.diegopacheco.services;

import org.junit.Test;
import com.blogspot.diegopacheco.services.DateService;

/**
* Classe de testes unitarios que usa o ejb 3.
*
* @author Diego Pacheco
* @version 1.0
* @since 03/05/2009
*
*/
public class ClientEjb3Test {

@Test
public void testDateServiceAsGetDate(){

try{
System.out.println("Inicio dos testes.");
DateService ds = ServiceLocator.getServiceRemote(DateService.class);
System.out.println("A Data retornada do EJB eh:" + ds.getDateTime());
System.out.println("Fim dos testes.");
}catch(Throwable t){
t.printStackTrace();
}

}

}

Vamos a classe de ServiceLocator. Essa classe é genérica, e melhora a qualidade do código mas para isso você deve criar as suas implementação de ejb com o sufixo Bean.

package com.blogspot.diegopacheco.services;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
* Classe utitilária para recuperação de EJBs.
*
* @author Diego Pacheco
* @version 1.0
* @since 03/05/2009
*
*/
public class ServiceLocator {

public static final String RemoteJNDIName = "Bean/remote";

private static String BASE;   
private static FileInputStream PATH_SIMPLE;   
private static String BASE_PATH;

private static Context context;

static{
try {
BASE = new File(".").getCanonicalPath();
BASE_PATH = BASE + "/src/main/resources/jndi.properties";
PATH_SIMPLE = new FileInputStream(new File(BASE_PATH));
} catch (Throwable t) {       
throw new RuntimeException(t);           
}       
}

static{   
try
{
Properties properties = new Properties();
try {
properties.load(PATH_SIMPLE);               
properties.list(System.out);               
} catch (FileNotFoundException e) {           
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

context = new InitialContext(properties);

} catch (NamingException e){
e.printStackTrace();       
}
}


@SuppressWarnings("unchecked")
public static  T getServiceRemote(Class clazz) throws NamingException{
T temp  = (T)context.lookup( clazz.getSimpleName() + RemoteJNDIName );
return temp;
}

}

As configurações de JNDI estão em um arquivo properties. São as configurações default para o JBoss.

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099

E por fim vamos ver o pom desse projeto. Perceba que as dependências não estão aqui:


4.0.0
com.blogspot.diegopacheco
mvn2-jboss5-ejb3-client
jar
1.0-SNAPSHOT
Maven 3 + EJB3 + Jboss 5 Client




org.apache.maven.plugins
maven-compiler-plugin

1.6
1.6
UTF-8



true
org.apache.maven.plugins
maven-source-plugin


attach-sources

jar









junit
junit
4.3




com.blogspot.diegopacheco
mvn2-jboss5-ejb3
1.0-SNAPSHOT






Os Jars necessários ao projeto cliente são:
  • concurrent.jar
  • jboss-aop.jar
  • jboss-common-core.jar
  • jboss-ejb3-common.jar
  • jboss-ejb3-core.jar
  • jboss-ejb3-proxy.jar
  • jboss-ejb3-security.jar
  • jboss-integration.jar
  • jboss-javaee.jar
  • jboss-logging-spi.jar
  • jboss-remoting.jar
  • jboss-remoting-aspects.jar
  • jboss-security-spi.jar
  • jbosssx.jar
  • jboss-transaction-aspects.jar
  • jnpserver.jar

Como eu já disse antes você acha esses jars aqui: $JBOSS_HOME/lib e e $JBOSS_HOME/common/lib.

Ok, podemos rodar a classe client, perceba que ela é uma classe de testes do Junit. Vamos rodar o teste, o resultado deve ser algo como esse:

Inicio dos testes.
-- listing properties --
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
A Data retornada do EJB eh:Sun May 03 20:50:37 BRT 2009
Fim dos testes.

Você pode pegar os fontes completos no meu repositório do Subersion. São esses urls:
Espero que tenham gostado, a idéia é que na sequencia foi adaptar esse projeto para funcionar no Websphere e no ORACLE weblogic.

Abraços e até a próxima.

Popular posts from this blog

Kafka Streams with Java 15

Rust and Java Interoperability

HMAC in Java