Interceptando un EJB en JBoss

0
19132

Interceptando un EJB en JBoss

Los
ejemplos de este tutorial están hechos con el siguiente
entorno de desarrollo:

  • Jboss Eclipse
    IDE.

  • JDK 1.5

  • JBoss
    4.0.5 GA

En
este
tutorial os vamos a enseñar (un poco) la arquitectura de EJBs en
JBoss y a como modificarla, insertando un interceptor propio dentro de
la cadena de interceptores del Proxy Cliente.

EJBs en JBoss

La arquitectura de EJBs
en JBoss está basada en la funcionalidad que provee la clase
Proxy del paquete java.lang.reflect (esta clase apareció en la
versión 1.3)

La clase Proxy es una clase especial que nos permite interceptar un conjunto de métodos definidos en un interfaz.

Para una breve explicación ver: http://www.javalobby.org/java/forums/t18631.html

Cuando nosotros en JBoss, hacemos un lookUp del Interfaz Home o del
Interfaz Remoto de un EJB, lo que obtenemos en realidad es una clase de
tipo Proxy que encapsula la funcionalidad de ambos interfaces. La
imágen que se muestra a continuación explica un poco toda
esta arquitectura (esta imágen está obtenida de la
documentación de JBoss)

arquitectura proxy cliente


Toda esta arquitectura nos ahorra el problema de tener que compilar los EJBs para crear los stubs y los skeletons.

Todas las invocaciones a los métodos de la clase Proxy son
delegadas sobre el ClientContainer, que está compuesto por una
cadena de Interceptores (clases que extienden la clase org.jboss.proxy.Interceptor
que serán los manejadores reales de la funcionalidad). Nosotros
podemos añadir o quitar funcionalidad modificando la cadena de
interceptores.

El único que no podemos eliminar es el último
interceptor, que será el que gestiones la comunicación
con el servidor. Este último interceptor podrá ser RMI,
RMI en cluster, HTTP, HTTP en cluster, CORBA etc… . En el lado
servidor, existirá un componente (detached invoker) que
hablará con el cliente (último invoker de la cadena) y
nos pondrá en contacto con el contenedor de EJBs a través
del servidor JMX de MBeans: (la imágen también
está obtenida de la documentación de JBoss)

Arquitectura EJbs lado servidor


Toda esta arquitectura de EJBs es modificable en el fichero de configuración:
<RUTA_JBOSS>\server\<TU_CONFIGURACION>\conf\standardjboss.xml

También podemos cambiar la configuración de esta arquitectura para un EJB usando su descriptor jboss.xml.

Un EJB que no trabaja en Domingo.

Para explicar un poco esto, vamos a generarnos un EJB de sesión
sin estado que sólo podrá ser invocado de lunes a
sábado, porque los domingos descansa. Para ello crearemos un
interceptor que colocaremos en la cadena de interceptores del
ClientContainer en primer lugar para evitar que sea invocado en domingo.

Primero nos crearemos el interceptor que denominaremos
SundayInterceptor y que extenderá org.jboss.proxy.Interceptor
(no olvidéis importar en el proyecto la librería <RUTA_JBOSS>\client\jbossall-client.jar)

package com.autentia.jboss.interceptor;

import java.util.Calendar;
import java.util.Date;
import org.jboss.invocation.Invocation;
import org.jboss.proxy.Interceptor;

public class SundayInterceptor extends Interceptor {
   
    public Object invoke(Invocation invocation) throws Throwable {
        System.out.println(«INVOCANDOME AL INTERCEPTOR:»
                +invocation.getMethod().getName());
       
        Date fechaActual = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(fechaActual);
        int dia = calendar.get(Calendar.DAY_OF_WEEK);       
       
        if(Calendar.SUNDAY == dia) {
            throw new SecurityException(«LO SIENTO, PERO ES DOMINGO » +
   
           
           
           
           
    «Y ESTOY DESCANSANDO.»);

        }       
        /* SI NO ES DOMINGO, LLAMO AL SIGUIENTE
        * INTERCEPTOR DE LA CADENA */       
        return getNext().invoke(invocation);               
    }
}

Ahora creamos el EJB. Primero el Bean:

package com.autentia.jboss.interceptor;

import java.rmi.RemoteException;

import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

import javax.ejb.CreateException;

public class InterceptedBean implements SessionBean {

    public InterceptedBean() {
        super();       
    }

    public void setSessionContext(SessionContext ctx)
        throws EJBException,
        RemoteException {
    }

    public void ejbRemove() throws EJBException, RemoteException {
    }

    public void ejbActivate() throws EJBException, RemoteException {       
    }

    public void ejbPassivate() throws EJBException, RemoteException {       
    }   
   
    public void ejbCreate() throws CreateException {       
    }

    public void unMetodo() throws java.rmi.RemoteException {
        System.out.println(«Invocando unMetodo()»);
    }
}

Luego el Interfaz Home:

package com.autentia.jboss.interceptor;

public interface InterceptedHome
   extends javax.ejb.EJBHome
{
  
   public Intercepted create()
      throws javax.ejb.CreateException,java.rmi.RemoteException;
}

Luego el Interfaz Remoto:

package com.autentia.jboss.interceptor;

public interface Intercepted
   extends javax.ejb.EJBObject
{
 
   public void unMetodo(  )
      throws java.rmi.RemoteException;
}

Ahora crearemos los descriptores:

El ejb-jar.xml

<?xml version=»1.0″ encoding=»UTF-8″?>
<!DOCTYPE ejb-jar PUBLIC
«-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN»
«http://java.sun.com/dtd/ejb-jar_2_0.dtd»>
<ejb-jar>
   <description>Interceptando</description>
   <display-name>Interceptando</display-name>
   <enterprise-beans>
      <session>
         <description>Intercepted Bean</description>
         <display-name>Intercepted Bean</display-name>
         <ejb-name>Intercepted</ejb-name>
         <home>com.autentia.jboss.interceptor.InterceptedHome</home>
         <remote>com.autentia.jboss.interceptor.Intercepted</remote>
        
<ejb-class>com.autentia.jboss.interceptor.InterceptedBean</ejb-class>

         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>
      </session>
   </enterprise-beans>
</ejb-jar>

El jboss.xml

<?xml version=»1.0″ encoding=»UTF-8″?>
<!DOCTYPE jboss PUBLIC «-//JBoss//DTD JBOSS 3.0//EN»
«http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd»>
<jboss>
   <enterprise-beans>    
      <session>
         <ejb-name>Intercepted</ejb-name>
         <jndi-name>ejb/Intercepted</jndi-name>
         <configuration-name>Standard Stateless SessionBean</configuration-name>
         <invoker-bindings>
         <invoker>         
            <invoker-proxy-binding-name>
                stateless-paco-invoker
            </invoker-proxy-binding-name>     
        </invoker>
        </invoker-bindings>
      </session>  
   </enterprise-beans>      
  <invoker-proxy-bindings>
    <invoker-proxy-binding>
      <name>stateless-paco-invoker</name>
      <invoker-mbean>jboss:service=invoker,type=jrmp</invoker-mbean>
      <proxy-factory>org.jboss.proxy.ejb.ProxyFactory</proxy-factory>
      <proxy-factory-config>
        <client-interceptors>
          <home>
              <interceptor>
            com.autentia.jboss.interceptor.SundayInterceptor
            </interceptor>       
           
<interceptor>org.jboss.proxy.ejb.HomeInterceptor</interceptor>

           
<interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>

           
<interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>

            <interceptor call-by-value=»false»>
                org.jboss.invocation.InvokerInterceptor
            </interceptor>
           <interceptor call-by-value=»true»>
                org.jboss.invocation.MarshallingInvokerInterceptor
            </interceptor>
          </home>
          <bean>
            <interceptor>
                com.autentia.jboss.interceptor.SundayInterceptor
             </interceptor>

           
<interceptor>org.jboss.proxy.ejb.StatelessSessionInterceptor</interceptor>

           
<interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>

           
<interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>

            <interceptor call-by-value=»false»>
                org.jboss.invocation.InvokerInterceptor
            </interceptor>
            <interceptor call-by-value=»true»>
                org.jboss.invocation.MarshallingInvokerInterceptor
            </interceptor>
          </bean>
        </client-interceptors>
      </proxy-factory-config>
    </invoker-proxy-binding>
    </invoker-proxy-bindings>
</jboss>

Empaquetamos el EJB y lo desplegamos en el servidor de aplicaciones.

Nos creamos una clase cliente para invocarlo:

package com.autentia.jboss.interceptor;

import java.rmi.RemoteException;
import java.util.Properties;

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

public class ClienteEJB {
   
    public static void main(String[] args) {
        Context ctx = null;
        Properties props = new Properties();
            props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
      
           
             
          »org.jnp.interfaces.NamingContextFactory»);

            props.setProperty(Context.PROVIDER_URL,»jnp://localhost:1099″);
            props.setProperty(Context.URL_PKG_PREFIXES,
   
           
           
           
   »org.jboss.naming:org.jnp.interfaces»);

       
        try {
            ctx = new InitialContext(props);
        } catch (NamingException e) {           
            e.printStackTrace();
        }       
       
        Intercepted remoto=null;
        try{
            Object obj=ctx.lookup(«ejb/Intercepted»);
            InterceptedHome home=
            (InterceptedHome)
                PortableRemoteObject.narrow(obj,InterceptedHome.class);
            remoto=(Intercepted)home.create();
        }catch (Exception e){
            System.out.println(«Excepcion invocando el EJB->»+e.toString());
        }       
        try {
            remoto.unMetodo();
        } catch (RemoteException e) {           
            e.printStackTrace();
        }
               
    }

}

Ejecutamos el cliente: (como hoy es
viernes, no debería haber ningún problema: ) Mostramos la
consola del lado cliente:

Consola cliente


Mostramos la consola del lado servidor:

Lado servidor

Vamos a modificar el interceptor para que no trabaje los viernes y volvemos a empaquetar y desplegar el ejb:
 ….
        if(Calendar.FRIDAY == dia) {
            throw new SecurityException(«LO SIENTO, PERO ES DOMINGO » +
   
           
           
           
           
    «Y ESTOY DESCANSANDO.»);

        }   
….

Ejecutamos el cliente:
Mostramos la consola del lado cliente:



El lado servidor no muestra nada porque la llamada ha sido interceptada.
Al colocar el interceptor tanto en home como en remoto, como el
método create() es parte del home, no se permite ni crear el
ejb. Vamos a modificar el jboss.xml eliminando el interceptor de la
cadena de interceptores de <home> y vamos a dejar sólo el
de <bean>, reempaquetamos,  redesplegamos y volvemos a
ejecutar el cliente a ver que pasa:

Lado cliente

Vemos que ahora, la interrupción se produce al invocar al método unMetodo() que pertenece al interfaz remoto.

Pues esto es todo, espero que os haya ayudado a entender un poco la arquitectura de EJBs en JBoss…

Si necesitáis ayuda: http://www.autentia.com



 

Dejar respuesta

Please enter your comment!
Please enter your name here