jueves, 15 de mayo de 2014

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:
  • 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
Leer para entender que pasa con las dependencias del JBoss 5:
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();
                                }
                }



1 comentario:

  1. La segunda alternativa de configuracion y consumo de EJB es gracias al aporte de Carlos Weckesser

    ResponderEliminar