See:
http://www.mkyong.com/java/jaxb-hello-world-example/
viernes, 30 de mayo de 2014
lunes, 19 de mayo de 2014
Web Service + REST + JAX-RS
En WebServices existen dos modalidades: SOAP y REST
JAX WS es la implementación estándar de web services SOAP en Java. Viene desde la versión de JDK 6.
Link muy util:
Algunas implementaciones REST:
Ejemplo usando RESTeasy:
http://howtodoinjava.com/2013/05/09/resteasy-tomcat-hello-world-application/
Ejemplo usando CXF con Spring:
http://dhruba.name/2008/12/08/rest-service-example-using-cxf-22-jax-rs-10-jaxb-and-spring/
http://www.luckyryan.com/2013/06/15/apache-cxf-with-spring-integration/
Luego para acceder a la URL, vamos a:
http://localhost:8081/WSRestWithSpringProject/services
Y haciendo clic en la URL, vemos lo siguiente:
Para acceder a alguno de los dos servicios expuestos hacemos:
Si queremos acceder a un método pasando por parámetro un valor:
El método es del estilo:
@GET
@Path("/users")
@Produces("application/xml") //The @Produces annotation is used to
specify the format of the response. W
@Override
public Response getUsers(@QueryParam("id")String id) {
UserCollection usersList = new UserCollection(users.values());
if (StringUtils.hasText(id)){
Integer idAsInt = Integer.valueOf(id);
User user = users.get(idAsInt);
System.out.println("user: " + user);
return Response.status(200).entity(user).build();
}
return Response.status(200).entity(usersList).build();
}
Leer:
http://stackoverflow.com/questions/11552248/when-to-use-queryparam-vs-pathparam
Otro Ejemplo usando CXF con Spring + JSON:
This is a simple link to demostrate how to create a simple JAX-RS Web Service in Java using Spring and Apache CXF. This service will be follow the request/response pattern, it will using HTTP POSTs which are formatted JSON requests and it will produce JSON responses:
- JAX-WS represents SOAP
- JAX-RS represents REST
JAX WS es la implementación estándar de web services SOAP en Java. Viene desde la versión de JDK 6.
REST es una implementación posterior. Más rica, no sólo utiliza un tipo de mensaje HTTP para el intercambio de mensajes, si no que permite más mensajes. Esto es, con Rest puedes tener un cliente que envíe mensajes HTTP de tipo GET, PUT, POST y DELETE. Cada mensaje enviará los datos correspondientes asociados hacia el servidor, que, recibirá la petición, la entenderá, y delegará en el método correspondiente. GET sirve para recuperar un dato desde el cliente al servidor, PUT para insertar un dato, POST para enviar información para modificar y DELETE para eliminar información del servidor.
The important thing to know about the request body is that it is unique to each service. The service designer must define the format of the request body and convey that to service consumers. Information in the request body is typically encoded in XML or JSON format. Here is a typical HTTP request that contains XML information within the body:
The important thing to know about the request body is that it is unique to each service. The service designer must define the format of the request body and convey that to service consumers. Information in the request body is typically encoded in XML or JSON format. Here is a typical HTTP request that contains XML information within the body:
Service Call | Description |
---|---|
GET http://{server}/MyRestService/library/books | Get a list of books |
PUT http://{server}/MyRestService/library/books/12345 | Create a new book with ISBN 12345 |
GET http://{server}/MyRestService/library/books/12345 | Get a single book with ISBN 12345 |
DELETE http://{server}/MyRestService/library/books/12345 | Delete a single book with ISBN 12345 |
Link muy util:
Algunas implementaciones REST:
- Apache CXF
- Jersey
- RESTeasy (is JBOSS provided implementation of JAX-RS specification for building RESTful Web Services and RESTful Java applications. Though this is not limited to be used in JBOSS only, and you can use with other servers also. In this post, I am building such a hello world application in tomcat server)
- Restlet
- Apache Wink
Ejemplo usando RESTeasy:
http://howtodoinjava.com/2013/05/09/resteasy-tomcat-hello-world-application/
Ejemplo usando CXF con Spring:
http://dhruba.name/2008/12/08/rest-service-example-using-cxf-22-jax-rs-10-jaxb-and-spring/
http://www.luckyryan.com/2013/06/15/apache-cxf-with-spring-integration/
Luego para acceder a la URL, vamos a:
http://localhost:8081/WSRestWithSpringProject/services
Y haciendo clic en la URL, vemos lo siguiente:
Para acceder a alguno de los dos servicios expuestos hacemos:
- http://localhost:8081/WSRestWithSpringProject/myservice/users
- http://localhost:8081/WSRestWithSpringProject/myservice/customers
Si queremos acceder a un método pasando por parámetro un valor:
El método es del estilo:
@GET
@Path("/users")
@Produces("application/xml") //The @Produces annotation is used to
specify the format of the response. W
@Override
public Response getUsers(@QueryParam("id")String id) {
UserCollection usersList = new UserCollection(users.values());
if (StringUtils.hasText(id)){
Integer idAsInt = Integer.valueOf(id);
User user = users.get(idAsInt);
System.out.println("user: " + user);
return Response.status(200).entity(user).build();
}
return Response.status(200).entity(usersList).build();
}
http://stackoverflow.com/questions/11552248/when-to-use-queryparam-vs-pathparam
Otro Ejemplo usando CXF con Spring + JSON:
This is a simple link to demostrate how to create a simple JAX-RS Web Service in Java using Spring and Apache CXF. This service will be follow the request/response pattern, it will using HTTP POSTs which are formatted JSON requests and it will produce JSON responses:
http://www.dreamsyssoft.com/blog/blog.php?/archives/7-Simple-JAX-RS-Web-Service-in-Java-with-Spring-and-CXF.html
@Path("/myservice")
@Consumes("application/json")
@Produces("application/json")
public interface UserManagerJson {
@GET
@Path("/fetchUserById")
public UserResponseJson fetchUserById(@QueryParam("id")String request);
..
}
public class UserManagerimplJson implements UserManagerJson {
@Override
public UserResponseJson fetchUserById(String request) {
UserResponseJson userResponseJson = new UserResponseJson();
userResponseJson.setSuccess(true);
userResponseJson.setErrorMessage("OK");
userResponseJson.setUsers(new ArrayList<String>());
return userResponseJson;
}
.....
.....
POM.XML
....
....
<!-- Provider para jax-rs para devolver una respuesta en formato json -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.1.1</version>
</dependency>
....
....
@Path("/myservice")
@Consumes("application/json")
@Produces("application/json")
public interface UserManagerJson {
@GET
@Path("/fetchUserById")
public UserResponseJson fetchUserById(@QueryParam("id")String request);
..
}
public class UserManagerimplJson implements UserManagerJson {
@Override
public UserResponseJson fetchUserById(String request) {
UserResponseJson userResponseJson = new UserResponseJson();
userResponseJson.setSuccess(true);
userResponseJson.setErrorMessage("OK");
userResponseJson.setUsers(new ArrayList<String>());
return userResponseJson;
}
..
}
ApplicationContext.xml
.....
.....
<!-- 2. CON JSON RESPONSE -->
<jaxrs:server id="userManagerWithJson" address="/dos">
<jaxrs:serviceBeans>
<ref bean="userManagerService"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean='jsonProvider' />
</jaxrs:providers>
</jaxrs:server>
<bean id="jsonProvider"
class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
<bean id="userManagerService" class="service.json.UserManagerimplJson"/>
.....
.....
POM.XML
....
....
<!-- Provider para jax-rs para devolver una respuesta en formato json -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.1.1</version>
</dependency>
....
....
jueves, 15 de mayo de 2014
Implementing an EJB as Web Service using jax-ws
Creando un EJB como un Web Service utilizando JAX-WS
Vamos a copiar las siguientes librerias desde c:\server\jboss-5.0.0.GA\client\ y a c:\server\jboss-5.0.0.GA\lib\endorsed\
Luego, creamos el EJB y le agregamos la anotación @WebService
POM.XML
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.mockejb</groupId>
<artifactId>mockejb</artifactId>
<version>0.6-beta2</version>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-ejb-api</artifactId>
<version>4.2.0.GA</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-client</artifactId>
<version>4.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- slf4j dependencies for Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- logback dependencies -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
Note: Existen dependencias de este POM que no son necesarias.
Para acceder al WSDL, vamos a:
Creando un POJO como un Web Service utilizando JAX-WS
Deploying your ejb as webservice is not your only option: you can deploy a POJO as web service as well. In this case you just need to tag@WebService in a plain java class.
When you choose EJB over a POJO for a web service?
JAX-WS 2.0 allows both regular Java classes and stateless EJBs to be exposed as web services. If you
were using J2EE 1.4, you’re probably wondering why you’d use a stateless EJB as a web service. A
look at the code for a POJO and for EJB 3 web services reveals that there are hardly any differences,
with the exception that the EJB 3 web service will have a few extra annotations. A Java class web
service is packaged in a web module whereas an EJB web service is packaged in an EJB-JAR.
Both a Java web service and an EJB web service support dependency injection and lifecycle
methods such as @PostConstruct and @PreDestroy, but you get a few extra benefits from
using EJB 3 web services.
Leer: http://www.mastertheboss.com/jboss-web-services/jboss-web-services-part-1
Requerimientos:
- JBoss 5.0.0.GA
- librerias JBoss WS native.
Vamos a copiar las siguientes librerias desde c:\server\jboss-5.0.0.GA\client\ y a c:\server\jboss-5.0.0.GA\lib\endorsed\
- jbossws-native-jaxrpc.jar
- jbossws-native-jaxws-ext.jar
- jbossws-native-saaj.jar
- jbossws-native-jaxws.jar
Luego, creamos el EJB y le agregamos la anotación @WebService
@WebService
@Stateless
public class BancoServiceImpl implements BancoService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final long SALDO_ESTATICO=1000000;
/* (non-Javadoc)
* @see com.gemalto.inlakech.spring.ejb.template.example.BancoService#consultarSaldo(java.lang.String)
*/
@Override
public long consultarSaldo(String cuenta){
logger.info("Entering to method with paraemeters[cuenta:"+cuenta+"]");
//TODO here business logic to get REAL balance
logger.info("The current balance for cuenta["+cuenta+"] is ["+SALDO_ESTATICO+"]");
return SALDO_ESTATICO;
}
}
@Remote
public interface BancoService {
public long consultarSaldo(String cuenta);
}
POM.XML
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.mockejb</groupId>
<artifactId>mockejb</artifactId>
<version>0.6-beta2</version>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-ejb-api</artifactId>
<version>4.2.0.GA</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-client</artifactId>
<version>4.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- slf4j dependencies for Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- logback dependencies -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
Note: Existen dependencias de este POM que no son necesarias.
Y por ultimo, creamos un JAR utilizando mvn clean package y lo copiamos en c:\server\jboss-5.0.0.GA\server\default\deploy\
Para ver que el WS esta deployado correctamente, vamos a:
http://localhost:8099/jbossws/services
Para acceder al WSDL, vamos a:
Deploying your ejb as webservice is not your only option: you can deploy a POJO as web service as well. In this case you just need to tag@WebService in a plain java class.
Pero para esto, vamos a necesitar armar un WAR y decir que el POJO sera un servlet
When you choose EJB over a POJO for a web service?
JAX-WS 2.0 allows both regular Java classes and stateless EJBs to be exposed as web services. If you
were using J2EE 1.4, you’re probably wondering why you’d use a stateless EJB as a web service. A
look at the code for a POJO and for EJB 3 web services reveals that there are hardly any differences,
with the exception that the EJB 3 web service will have a few extra annotations. A Java class web
service is packaged in a web module whereas an EJB web service is packaged in an EJB-JAR.
Both a Java web service and an EJB web service support dependency injection and lifecycle
methods such as @PostConstruct and @PreDestroy, but you get a few extra benefits from
using EJB 3 web services.
Leer: http://www.mastertheboss.com/jboss-web-services/jboss-web-services-part-1
Connecting to EJB using lookup + JBoss 5
Creamos un EJB
@Remote//Anotamos la interface como remote para poder ser accedida desde JNDI
public interface BancoService {
public long consultarSaldo(String cuenta);
}
@Stateless
public class BancoServiceImpl implements BancoService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final long SALDO_ESTATICO=1000000;
/* (non-Javadoc)
* @see com.gemalto.inlakech.spring.ejb.template.example.BancoService#consultarSaldo(java.lang.String)
*/
@Override
public long consultarSaldo(String cuenta){
logger.info("Entering to method with paraemeters[cuenta:"+cuenta+"]");
//TODO here business logic to get REAL balance
logger.info("The current balance for cuenta["+cuenta+"] is ["+SALDO_ESTATICO+"]");
return SALDO_ESTATICO;
}
}
Deployamos el EJB en JBoss (version 5.0.0.GA)
Creamos un JAR con las dos clases y la deployamos en la carpeta apps:
Ex:
c:\server\jboss-5.0.0.GA\server\default\deploy\ejb-banco-service.jar
Levantamos el JBoss
c:\server\jboss-5.0.0.GA\bin\run.bat
Aqui vemos como el EJB se deployó correctamente bajo el jndi name:
BancoServiceImpl/remote-com.gemalto.inlakech.spring.ejb.template.example.BancoService
óBancoServiceImpl/remote
Cremos un test de integracion
@BeforeClass
public static void setUp() throws NamingException {
Properties props = new Properties();
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
ctx = new InitialContext(props);
}
@AfterClass
public static void tearDown() throws NamingException {
ctx.close();
}
@Test//Consultar SALDO desde API de EE
public void conlsutarSaldoRemoteEJBTest() throws NamingException {
BancoService service = (BancoService) ctx.lookup("BancoServiceImpl/remote-com.gemalto.inlakech.spring.ejb.template.example.BancoService");
long result = service.consultarSaldo("666");
Assert.assertEquals(SALDO_ESPERADO, result);
BancoService service2 = (BancoService) ctx.lookup("BancoServiceImpl/remote");
long result2 = service2.consultarSaldo("666");
Assert.assertEquals(SALDO_ESPERADO, result2);
}
POM.XML (tanto para crear el jar con el EJB como para crear el test de integracion)
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-ejb-api</artifactId>
<version>4.2.0.GA</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- slf4j dependencies for Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- logback dependencies -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
Nota: Existen dependencias en este POM que a los fines de esta prueba pueden no ser necesarias
Importante: la dependencia "jbossall-client" NO ESTA EN EL POM ya que tuve problemas para bajar dicha dependencia... PERO USE LA QUE TRAE EL JBOSS y la agregue al classpath, pero hay que tener en cuenta que este JAR esta vacio, solo tiene referencias a los JARs que se necesitan:
c:\server\jboss-5.0.0.GA\client\jbossall-client.jar
Esta dependencia es vital para acceder remotamente al EJB deployado en el JBOSS.
This jar file contains a classpath reference to various client jar files used by jboss client applications.
Each of the jar files in the following list must available in the same directory as the jbossall-client.jar, Otherwise they will not be found by the classloader.
The classpath includes the following files:
http://www.javahelp.info/2010/01/27/get-the-right-dependencies-for-jboss-5-client-and-maven/
Segunda alternativa
Otra alternativa de configuracion y consumo de EJB gracias al aporte de Carlos Weckesser
- La configuración de nuestro pom es la siguiente:
<properties>
...
<jboss-as-client-version>5.1.0.GA</jboss-as-client-version>
...
</properties>
<dependencies>
...
<dependency>
<groupId>org.jboss.jbossas</groupId>
<artifactId>jboss-as-client</artifactId>
<version>${jboss-as-client-version}</version>
<type>pom</type>
<scope>test</scope>
</dependency>
...
</dependencies>
- Luego definimos una interfaz comun con los metodos necesarios:
package com.myCompany.myProject.interfaces;
public interface MyPrettyInterfaceCommon {
/** Mapped name for this EJB custom */
public static final String MAPPED_NAME = "MyPrettyImplementationConnector";
public void performPrettyAction1();
public void performPrettyAction2();
}
- Posteriormente, creamos nuestra interfaz local, extendiendo la misma de la interfaz comun y utilizando las anotaciones correspondientes a un componente "local":
package com.myCompany.myProject.interfaces;
@Local(MyPrettyInterfaceLocal.class)
@LocalBinding(jndiBinding = MyPrettyInterfaceLocal.MAPPED_NAME + "/local")
public interface MyPrettyInterfaceLocal extends MyPrettyInterfaceCommon {
}
- A continuación, creamos nuestra interfaz remota, extendiendo la misma de la interfaz comun y utilizando las anotaciones correspondientes a un componente "remoto":
package com.myCompany.myProject.interfaces;
@Remote(MyPrettyInterfaceRemote.class)
@RemoteBinding(jndiBinding = MyPrettyInterfaceRemote.MAPPED_NAME + "/remote")
public interface MyPrettyInterfaceRemote extends MyPrettyInterfaceCommon {
}
- Después, definimos una implementación para las interfaces local y remota de la siguiente manera:
package com.myCompany.myProject.implementations;
@Stateless(mappedName = MyPrettyImplementationConnector.MAPPED_NAME)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class MyPrettyImplementationConnector implements MyPrettyInterfaceLocal,
MyPrettyInterfaceRemote {
...
}
- Por último, vemos un ejemplo de como podemos utilizar inyección de dependencias y resolución de componentes por JNDI para obtener instancias de nuestros componentes:
package com.myCompany.myProject.implementations;
public class AnotherClass {
// Inyeccion de dependencia de interfaz local
@EJB
protected MyPrettyInterfaceLocal myPrettyConnectorLocal;
// Inyeccion de dependencia de interfaz remota
@EJB
protected MyPrettyInterfaceRemote myPrettyConnectorRemote;
// Lookup via JNDI de interfaz local
public void useLocalInterface() {
MyPrettyInterfaceLocal connector = (MyPrettyInterfaceLocal) ctx
.lookup("MyPrettyImplementationConnector/local-com" +
".myCompany.myProject.interfaces.MyPrettyInterfaceLocal");
connector.performPrettyAction1();
}
// Lookup via JNDI de interfaz remota
public void useRemoteInterface() {
MyPrettyInterfaceRemote connector = (MyPrettyInterfaceRemote) ctx
.lookup("MyPrettyImplementationConnector/remote-com" +
".myCompany.myProject.interfaces.MyPrettyInterfaceRemote");
connector.performPrettyAction1();
}
}
@Remote//Anotamos la interface como remote para poder ser accedida desde JNDI
public interface BancoService {
public long consultarSaldo(String cuenta);
}
@Stateless
public class BancoServiceImpl implements BancoService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final long SALDO_ESTATICO=1000000;
/* (non-Javadoc)
* @see com.gemalto.inlakech.spring.ejb.template.example.BancoService#consultarSaldo(java.lang.String)
*/
@Override
public long consultarSaldo(String cuenta){
logger.info("Entering to method with paraemeters[cuenta:"+cuenta+"]");
//TODO here business logic to get REAL balance
logger.info("The current balance for cuenta["+cuenta+"] is ["+SALDO_ESTATICO+"]");
return SALDO_ESTATICO;
}
}
Deployamos el EJB en JBoss (version 5.0.0.GA)
Creamos un JAR con las dos clases y la deployamos en la carpeta apps:
Ex:
c:\server\jboss-5.0.0.GA\server\default\deploy\ejb-banco-service.jar
Levantamos el JBoss
c:\server\jboss-5.0.0.GA\bin\run.bat
Aqui vemos como el EJB se deployó correctamente bajo el jndi name:
BancoServiceImpl/remote-com.gemalto.inlakech.spring.ejb.template.example.BancoService
óBancoServiceImpl/remote
Cremos un test de integracion
@BeforeClass
public static void setUp() throws NamingException {
Properties props = new Properties();
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
ctx = new InitialContext(props);
}
@AfterClass
public static void tearDown() throws NamingException {
ctx.close();
}
@Test//Consultar SALDO desde API de EE
public void conlsutarSaldoRemoteEJBTest() throws NamingException {
BancoService service = (BancoService) ctx.lookup("BancoServiceImpl/remote-com.gemalto.inlakech.spring.ejb.template.example.BancoService");
long result = service.consultarSaldo("666");
Assert.assertEquals(SALDO_ESPERADO, result);
BancoService service2 = (BancoService) ctx.lookup("BancoServiceImpl/remote");
long result2 = service2.consultarSaldo("666");
Assert.assertEquals(SALDO_ESPERADO, result2);
}
POM.XML (tanto para crear el jar con el EJB como para crear el test de integracion)
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-ejb-api</artifactId>
<version>4.2.0.GA</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- slf4j dependencies for Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- logback dependencies -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
Nota: Existen dependencias en este POM que a los fines de esta prueba pueden no ser necesarias
c:\server\jboss-5.0.0.GA\client\jbossall-client.jar
Esta dependencia es vital para acceder remotamente al EJB deployado en el JBOSS.
This jar file contains a classpath reference to various client jar files used by jboss client applications.
Each of the jar files in the following list must available in the same directory as the jbossall-client.jar, Otherwise they will not be found by the classloader.
The classpath includes the following files:
- commons-logging.jar
- concurrent.jar
- ejb3-persistence.jar
- hibernate-annotations.jar
- jboss-aop-client.jar
- jboss-appclient.jar
- jboss-aspect-jdk50-client.jar
- jboss-client.jar
- jboss-common-core.jar
- jboss-deployers-client-spi.jar
- jboss-deployers-client.jar
- jboss-deployers-core-spi.jar
- jboss-deployers-core.jar
- jboss-deployment.jar
- jboss-ejb3-common-client.jar
- jboss-ejb3-core-client.jar
- jboss-ejb3-ext-api.jar
- jboss-ejb3-proxy-client.jar
- jboss-ejb3-proxy-clustered-client.jar
- jboss-ejb3-security-client.jar
- jboss-ha-client.jar
- jboss-ha-legacy-client.jar
- jboss-iiop-client.jar
- jboss-integration.jar
- jboss-j2se.jar
- jboss-javaee.jar
- jboss-jsr77-client.jar
- jboss-logging-jdk.jar
- jboss-logging-log4j.jar
- jboss-logging-spi.jar
- jboss-main-client.jar
- jboss-mdr.jar
- jboss-messaging-client.jar
- jboss-remoting.jar
- jboss-security-spi.jar
- jboss-serialization.jar
- jboss-srp-client.jar
- jboss-system-client.jar
- jboss-system-jmx-client.jar
- jbosscx-client.jar
- jbosssx-as-client.jar
- jbosssx-client.jar
- jmx-client.jar
- jmx-invoker-adaptor-client.jar
- jnp-client.jar
- slf4j-api.jar
- slf4j-jboss-logging.jar
- xmlsec.jar
http://www.javahelp.info/2010/01/27/get-the-right-dependencies-for-jboss-5-client-and-maven/
Segunda alternativa
Otra alternativa de configuracion y consumo de EJB gracias al aporte de Carlos Weckesser
- La configuración de nuestro pom es la siguiente:
<properties>
...
<jboss-as-client-version>5.1.0.GA</jboss-as-client-version>
...
</properties>
<dependencies>
...
<dependency>
<groupId>org.jboss.jbossas</groupId>
<artifactId>jboss-as-client</artifactId>
<version>${jboss-as-client-version}</version>
<type>pom</type>
<scope>test</scope>
</dependency>
...
</dependencies>
- Luego definimos una interfaz comun con los metodos necesarios:
package com.myCompany.myProject.interfaces;
public interface MyPrettyInterfaceCommon {
/** Mapped name for this EJB custom */
public static final String MAPPED_NAME = "MyPrettyImplementationConnector";
public void performPrettyAction1();
public void performPrettyAction2();
}
- Posteriormente, creamos nuestra interfaz local, extendiendo la misma de la interfaz comun y utilizando las anotaciones correspondientes a un componente "local":
package com.myCompany.myProject.interfaces;
@Local(MyPrettyInterfaceLocal.class)
@LocalBinding(jndiBinding = MyPrettyInterfaceLocal.MAPPED_NAME + "/local")
public interface MyPrettyInterfaceLocal extends MyPrettyInterfaceCommon {
}
- A continuación, creamos nuestra interfaz remota, extendiendo la misma de la interfaz comun y utilizando las anotaciones correspondientes a un componente "remoto":
package com.myCompany.myProject.interfaces;
@Remote(MyPrettyInterfaceRemote.class)
@RemoteBinding(jndiBinding = MyPrettyInterfaceRemote.MAPPED_NAME + "/remote")
public interface MyPrettyInterfaceRemote extends MyPrettyInterfaceCommon {
}
- Después, definimos una implementación para las interfaces local y remota de la siguiente manera:
package com.myCompany.myProject.implementations;
@Stateless(mappedName = MyPrettyImplementationConnector.MAPPED_NAME)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class MyPrettyImplementationConnector implements MyPrettyInterfaceLocal,
MyPrettyInterfaceRemote {
...
}
- Por último, vemos un ejemplo de como podemos utilizar inyección de dependencias y resolución de componentes por JNDI para obtener instancias de nuestros componentes:
package com.myCompany.myProject.implementations;
public class AnotherClass {
// Inyeccion de dependencia de interfaz local
@EJB
protected MyPrettyInterfaceLocal myPrettyConnectorLocal;
// Inyeccion de dependencia de interfaz remota
@EJB
protected MyPrettyInterfaceRemote myPrettyConnectorRemote;
// Lookup via JNDI de interfaz local
public void useLocalInterface() {
MyPrettyInterfaceLocal connector = (MyPrettyInterfaceLocal) ctx
.lookup("MyPrettyImplementationConnector/local-com" +
".myCompany.myProject.interfaces.MyPrettyInterfaceLocal");
connector.performPrettyAction1();
}
// Lookup via JNDI de interfaz remota
public void useRemoteInterface() {
MyPrettyInterfaceRemote connector = (MyPrettyInterfaceRemote) ctx
.lookup("MyPrettyImplementationConnector/remote-com" +
".myCompany.myProject.interfaces.MyPrettyInterfaceRemote");
connector.performPrettyAction1();
}
}
Connecting to EJB using lookup + OpenEJB
Creamos un EJB
@Remote//Anotamos la interface como remote para poder ser accedida desde JNDI
public interface BancoService {
public long consultarSaldo(String cuenta);
}
@Stateless
public class BancoServiceImpl implements BancoService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final long SALDO_ESTATICO=1000000;
/* (non-Javadoc)
* @see com.gemalto.inlakech.spring.ejb.template.example.BancoService#consultarSaldo(java.lang.String)
*/
@Override
public long consultarSaldo(String cuenta){
logger.info("Entering to method with paraemeters[cuenta:"+cuenta+"]");
//TODO here business logic to get REAL balance
logger.info("The current balance for cuenta["+cuenta+"] is ["+SALDO_ESTATICO+"]");
return SALDO_ESTATICO;
}
}
Deployamos el EJB en OpenEJB (version 4.6.0.2)
Creamos un JAR con las dos clases y la deployamos en la carpeta apps:
Ex:
c:\server\apache-openejb-4.6.0.2\apps\ejb-banco-service.jar
Levantamos el OpenEJB
c:\server\apache-openejb-4.6.0.2\bin\Start.bat
Cremos un test de integracion
@BeforeClass
public static void setUp() throws NamingException {
/**
* Inicializando contexto de JEE
*/
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory");
env.put(Context.PROVIDER_URL, "ejbd://localhost:4201");
ctx = new InitialContext(env);
}
@AfterClass
public static void tearDown() throws NamingException {
ctx.close();
}
@Test//Consultar SALDO desde API de EE
public void conlsutarSaldoRemoteEJBTest() throws NamingException {
BancoService service = (BancoService) ctx.lookup("BancoServiceImplRemote");
long result = service.consultarSaldo("666");
Assert.assertEquals(SALDO_ESPERADO, result);
}
POM.XML (tanto para crear el jar con el EJB como para crear el test de integracion)
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ejb_3.0_spec</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.mockejb</groupId>
<artifactId>mockejb</artifactId>
<version>0.6-beta2</version>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-ejb-api</artifactId>
<version>4.2.0.GA</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-client</artifactId>
<version>4.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- slf4j dependencies for Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- logback dependencies -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
Importante: la dependencia "openejb-client" tiene que ser la version 4.0 o superior
Nota: Existen dependencies en este POM que a los fines de esta prueba pueden no ser necesarias
@Remote//Anotamos la interface como remote para poder ser accedida desde JNDI
public interface BancoService {
public long consultarSaldo(String cuenta);
}
@Stateless
public class BancoServiceImpl implements BancoService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final long SALDO_ESTATICO=1000000;
/* (non-Javadoc)
* @see com.gemalto.inlakech.spring.ejb.template.example.BancoService#consultarSaldo(java.lang.String)
*/
@Override
public long consultarSaldo(String cuenta){
logger.info("Entering to method with paraemeters[cuenta:"+cuenta+"]");
//TODO here business logic to get REAL balance
logger.info("The current balance for cuenta["+cuenta+"] is ["+SALDO_ESTATICO+"]");
return SALDO_ESTATICO;
}
}
Deployamos el EJB en OpenEJB (version 4.6.0.2)
Creamos un JAR con las dos clases y la deployamos en la carpeta apps:
Ex:
c:\server\apache-openejb-4.6.0.2\apps\ejb-banco-service.jar
Levantamos el OpenEJB
c:\server\apache-openejb-4.6.0.2\bin\Start.bat
Cremos un test de integracion
@BeforeClass
public static void setUp() throws NamingException {
/**
* Inicializando contexto de JEE
*/
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory");
env.put(Context.PROVIDER_URL, "ejbd://localhost:4201");
ctx = new InitialContext(env);
}
@AfterClass
public static void tearDown() throws NamingException {
ctx.close();
}
@Test//Consultar SALDO desde API de EE
public void conlsutarSaldoRemoteEJBTest() throws NamingException {
BancoService service = (BancoService) ctx.lookup("BancoServiceImplRemote");
long result = service.consultarSaldo("666");
Assert.assertEquals(SALDO_ESPERADO, result);
}
POM.XML (tanto para crear el jar con el EJB como para crear el test de integracion)
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ejb_3.0_spec</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.mockejb</groupId>
<artifactId>mockejb</artifactId>
<version>0.6-beta2</version>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-ejb-api</artifactId>
<version>4.2.0.GA</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-client</artifactId>
<version>4.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- slf4j dependencies for Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- logback dependencies -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
Importante: la dependencia "openejb-client" tiene que ser la version 4.0 o superior
Nota: Existen dependencies en este POM que a los fines de esta prueba pueden no ser necesarias
Suscribirse a:
Entradas (Atom)