Master J2EE de Oracle: Paso 6 de 12: Masterizar Java en el Lado del Servidor

Puede encontrar la versión original de este artículo en Inglés en:

http://www.oracle.com/technology/pub/articles/masterj2ee/index.html

Dejar que el Caché de Objetos basado en JMS Haga el Trabajo duro

Aprenda cómo sincronizar los cachés en-memoria entre servidores en un cluster J2EE para mejorar el rendimieno y la escalibidad de aplicaciones Java del lado del servidor.

Descargas necesarias para este artículo

J2EE ha emergido como la plataforma estándar para desarrollar aplicaciones Java del lado del servidor, y aunque ofrece muchos beneficios a los desarrolladores Java (portabilidad, escalabilidad y capacidades de integración, por ejemplo) también ofrece un gran número de retos, entre los que se encuentra verse atrapado por alguna de la enorme cantidad de poderosas tecnologías o decidir cuál de ellas utilizar para un proyecto dado.

Por ejemplo, además de soportar Enterprise JavaBeans, Servlets y componentes JavaServer Pages, y unos APIs de servicios Web, la especificación de la plataforma J2EE define varios servicios para usarlos con componentes J2EE, incluyendo:

  • Java Naming and Directory Service (JNDI)
  • JDBC
  • Java Management Extension (JMX)
  • JavaMail
  • CORBA Compliance (JavaIDL)
  • Java Transaction API (JTA)
  • Java Transaction Service (JTS)
  • JAAS (Security)
  • Java Connector Architecture (JCA)
  • Java Message Service (JMS)
  • XML

Como puede ver es fácil perderse entre ese montón de tecnologías, y no es extraño que los desarrolladores que se inician en el desarrollo de aplicaciones J2EE del lado del servidor se hagan algunas preguntas:

  • ¿Qué servidores de aplicaciones J2EE debería utilizar? ¿Cuáles son lo criterios para elegir un servidor de aplicaciones J2EE?
    Elegir el servidor de aplicaciones para su aplicación del lado del servidor no es algo sencillo. Lo más importante a la hora de desarrollar su aplicación es centrarse en la especificación, y no en la implementación particular de un vendedor. Esta es la mejor forma de mantener la independencia del servidor de aplicaciones, no sólo cuando haga la primera elección, sino también cuando su aplicación madure. El servidor de aplicaciones "correcto" depende en su mayor parte de los requerimientos de su aplicación, pero entre las consideraciones más importantes se incluyen:
    • Cumplimiento de los Estándares
    • Coste
    • Escalabilidad y rendimiento
    • Productividad del desarrollador
    • Soporte
  • ¿Debería utilizar EJB para la capa intermedia?
    Esta es una decisión importante, y que normalmente se pospone durante la fase de diseño. Una mala decisión puede lastrar el proyecto y también puede tener implicación en los costes. Si su diseño no requiere EJB, un contendor de código abierto, como Apache Tomcat puede hacer el trabajo. Generalmente los EJB se pensaron para ser transacionales y para acceder a la lógica de negocio que reside en el servidor, pero podrían no adecuarse a todos los diseños. Por ejemplo, si está diseñando un servidor de ficheros, el protocolo RMI/IIOP utilizado por EJB podría ser excesivo por la enorme transferencia de datos. Los protocolos de transporte de datos, como HTTP y FTP son mejores elecciones para este trabajo. Una implementación de servidor que soporte sólo el contenedor web sería suficiente en este caso.
  • ¿Cuándo debería utilizar Beans de Sesión sin Estado en vez de Beans de Sesión con Estado?
    Los beans de sesión con o sin estado son prácticamente iguales excepto porque los que tienen estado manejan el estado conversacional entre las llamadas a métodos. Tenga en mente que los beans de sesión con estado no son tan escalables como los beans de sesión sin estado. Los beans de sesión con estado están sujetos a un nodo específico de un cluster por lo tanto no tienen balance de carga. Además, no se requiere que los beans de sesión con estado sobrevivan a una caida del servidor. Una regla del pulgar indica que debe evitar los beans de sesión con estado siempre que sea posible. Considere utilizar HttpSession en lugar de mantener el estado en aplicaciones basadas en web.
  • ¿Cómo debería ser la interacción entre el UI y la lógica de negocio?
    Separar claramente la presentación de la lógica de negocio indudablemente es uno de los aspectos más importantes de desarrollo del lado del servidor. Con la facilidad de uso de Servlets y JSP es tentador mezclar código HTML y lógica de negocio en un JSP. Pero su aplicación se volverá inmanejable rápidamente. Afortunadamente, tiene a su disposición excelentes patrones de diseño como el de Modelo-Vista-Controlador (MVC) que le ayudarán a organizar mejor su código. El marco de trabajo de código abierto Struts soporta el patrón MVC
  • ¿Cómo puedeo asegurar mi aplicación?
    La seguridad es una parte muy importante pero frecuentemente olvidada del desarrollo del lado del servidor. La mayoría de los desarrolladores están tentados de utilizar sus propios mecanismos de seguridad, lo que sólo les traerá problemas en el futuro, cuando cambien los requerimientos de seguridad de la aplicación. Su mejor apuesta es dirigirse a la arquitectura de seguridad estándar de J2EE, que también facilita la integración con proveedores de seguridad de terceras partes, como SiteMinder para un simple log-on. La seguridad J2EE comprende la autentificación y la autorización. En algunos casos, la seguridad basada en roles de J2EE podría no ser adecuada para algunas necesidades de seguridad complejas, pero puede aproximarse cuanto sea posible al sistema de seguridad J2EE y construir los requerimientos de seguridad más complejos sobre el estándar J2EE.
  • ¿¿Qué tecnologías J2EE debería utilizar?
    No hay una respuesta fácil para esta pregunta; depende de los requerimientos de su aplicación, incluyendo EJB, Servlets, JSP. La elección de tecnologías auxiliares J2EE depende de su aplicación, pero algunas decisiones son óbvias. Por ejemplo, si su aplicación usa una base de datos para el respaldo, debería utilizar JDBC. Cuando use EJB, inheremente debería utilizar otras tecnologías como JNDI, JTA y XML por ejemplo. Debería evaluar cuidadosamente las tecnologías J2EE disponibles y elegir la que mejor se adpate a sus requerimientos.
  • ¿Cómo manejo las transaciones?
    Si ha pensado en usar EJB en su aplicación, la respuesta es sencilla: Utilice las transaciones manejadas por el contenedor tanto como pueda. Las transaciones EJB están demarcadas por los límites de método, y se especifican declarativamente en los descriptores de despliegue, por eso el contenedor maneja automáticamente las transaciones. Sin embargo, hay casos, como transaciones que tardan mucho tiempo, en las que debería tomar el control. Puede utilizar las transaciones manejadas por el usuario para dividir este tipo de transaciones en unidades más pequeñas.
  • ¿Cómo persisto mis objetos en el servidor?
    Es una buena práctica utilizar beans de entidad CMP para persistir sus objetos del lado del servidor. Sin embargo, si el modelo de datos de sus beans es demasiado complejo para ser manejado por un bean de entidad CMP, o si quiere tener el control sobre la persistencia de su bean, debería considerar la utilización de beans de entidad BMP. Considere la utilización de un marco de trabajo de persistencia de objetos como TopLink o Hibernate, mejor que tener que codificar su própia lógica de persistencia.
  • ¿Cuáles son las mejores prácticas para desarrollar aplicaciones J2EE?
    La buena noticia es que los desarrolladores tienen una enorme cantidad de recursos entre los que elegir, incluyendo muchos patrones de diseño J2EE.
  • ¿Debería utilizar caché en mi aplicación? ¿Cuáles son los retos de utilizar el caché en un entorno distribuido?
    El caché puede mejorar drásticamente el rendimiento de su aplicación. La idea detrás de todo esto del caché es almacenar localmente cualquier dato que cambie de forma poco frecuente pero que no sería costoso de obtener desde la fuente de datos (como datos obtenidos desde una base de datos). Para aplicaciones independientes, se puede utilizar una simple tabla hash, pero para entornos distribuidos, esta aproximación no funcionará porque el caché debe estar sincronizado a través del cluster.

Aunque cubrir todos estos tópicos en detalle va más allá del ámbito del este artículo, nos centraremos en esté último, cuándo utilizar el caché y cómo. Tocaré la mayoría de los retos de la utilización de un caché distribuido y cómo solucionarlos, explorando los problemas en el contexto de de la aplicación de ejemplo incluida, una sencillo navegador de objetos basado en Web que le permite nevegar por los objetos almacenados en una base de datos. Esta aplicación de ejemplo es una aplicación J2EE totalmente funcional que utiliza un caché distribuido y muestra cómo sincronizar el caché en un cluster (usando JMS).

Además, la aplicación toca muchas de las importantes tecnologías Java del lado del servidor, incluyendo EJB, Servlets, JSP, Struts, JMS y Beans dirigidos por mensaje, por ejemplo. En la sección de recursos podrá encontrar enlaces a la aplicación de ejemplo e información de cómo configurar y ejecutar el ejemplo.

'Cachear' Objetos frecuentemente utilizados mejora el rendimiento del lado del servidor en J2EE

La plataforma J2EE proporciona una plataforma escalable para aplicaciones del lado del servidor. Cualquier gran aplicación J2EE contiene muchos objetos, y la mayoría de ellos se cargan desde una base de datos. Sin embargo, debido a la naturaleza compleja de la mayoría de las consultas, las operaciones de carga son bastante costosas, afectando al rendimiento de la aplicación y la escalabilidad general. La mejor forma de mejorar el rendimiento y la escalabilidad es hacer un caché con los objetos utilizados de forma frecuente.

Por ejemplo, la aplicación del navegador de objetos, permite a un usuario navegar por los objetos almacenados en la base de datos. La aplicación utiliza metadatos para describir los datos de los objetos, y carga y muestra los datos de cualquier objeto, sin importar su tipo. La ventaja de utilizar metadatos es que la aplicación puede construir consultas automáticamente para cargar los datos, y también puede construir el UI de forma automática basándose en los metadatos.

La aplicación está dirigida a repositorio, por eso debe chequear el repositoro en cada paso, porque la velocidad de los accesos a estos datos es importante para el rendimiento y la escalabilidad.

Es obvio que necesitamos cachear el repositorio, pero lo que podría no parecer tan obvio es cómo implementar este caché. Al principio, podríamos estar tentados de implementar el repositorio como un singleton: cargar el repositorio una sóla vez desde la base de datos, en la memoria de la JVM, devolver los datos desde la memoria en los siguientes accesos al repositorio como en este ejemplo:

Listado 1:

			
public class RepositoryCache {
    private static RepositoryCache instance = null;

    private List classes;

    public static RepositoryCache getInstance() {
        If (instance == null) {
            instance = new RepositoryCache();
        }
        return instance;
    }

    // Prevent instantiation
    private RepositoryCache() {
        classes = loadClassesFromDB();
    }

    public List getClasses() {
        return classes;
    }
...
}
			
		

Esta aproximación (un repositorio de objetos Singleton) funciona bien mientras su aplicación se ejecute dentro de una única JVM. Sin embargo, según crezca la demanda y se añadan más usuarios al sistema, deberá distribuir la carga entre varios servidores de aplicaciones, lo que presenta nuevos problemas.

Sincronizar Cachés en memoria

En un entorno de clusters cada servidor se ejecuta en su propia JVM, lo que plantea un problema interesante. ¿Qué sucede cuando se modifica el respositorio en uno de los nodos del cluster? El caché residente en los otros nodos servidores de aplicación se vuelve obsoleto, y los usuarios conectados a esos otros servidores obtendrán datos incorrectos.

Necesitamos un mecanismo para sincronizar los cachés en memoria entre todos los servidores del cluster, este es el tipo de tareas para Java Message Service (JMS) en aplicaciones J2EE del lado del servidor. JMS es una solución natural para este problema y tiene estas tres ventajas:

  • JMS proporciona un simple pero flexible API para mensajería
  • JMS es el estándar para cualquier servidor de aplicaciones compatible con J2EE
  • JMS está basado en Message Driven Beans (MDB) de EJB 2.0, lo que simplifica enormemente la escritura de aplicaciones J2EE asíncronas

En la aplicación de ejemplo utilizamos MDB. Para mantenerla simple, la aplicación cachea sólo los metadatos (no los datos normales), las técnicas que verá en este artículo se puede extender fácilmente para cachear también los datos.

Sobre la aplicación de ejemplo: Utilizar una arquitectura basada en JMS

La aplicación de ejemplo ("Simple Object Browser," como puede ver en la Figura 1) trata con un caché de objetos basado en JMS para cargar y mostrar clases definidas al vuelo. La aplicación tiene dos elementos clave:

  • El Repositorio. Utilizado para definir y acceder a los metadatos. Utilizando el API repository puede crear nuevas clases, añadir atributos a una clase y definir las propiedades de un atributo.
  • El Navegador de Datos. Utilizado para navegar y crear objetos basados en las clases definidas en el repositorio.

Como puede ver en las siguientes imágenes, la aplicación de ejemplo es una aplicación basada en Web. Utiliza el marco de trabajo Apache Struts para construir el interface de usuario:


Figura 1: Menú principal de la aplicación de ejemplo.


Figura 2: El manejador de classes le permite añadir nuevas definiciones de clases..


Figura 3: Añadir una clase address.


Figura 4: Añadir una nueva dirección.

La capa de negocio utiliza Enterprise Java Beans (EJB) desplegados y ejecutándose sobre Oracle Containers for J2EE (OC4J) (standalone); los EJBs trabajan en conjunción con una base de datos Oracle Database 10g.

He desarrollado la aplicación utilizando Oracle JDeveloper 10g, porque lo encontré más sencillo para ponerlo todo junto; desde el modelado de las entidades de la base de datos (vea la Figura 7), pasando por el modelado de las definiciones de clases Java (vea la Figura 9) y los EJBs (vea la Figura 8), hasta el diseño del flujo de páginas Struts de la aplicación (vea la Figura 5):


Figura 5: Diagrama del flujo de páginas Struts para la aplicación de ejemplo en Oracle JDeveloper 10g.

El diagrama de secuencia de la Figura 6 muestra cómo se mantienen sincronizados los repositorios en memoria de los diferentes servidores de aplicaciones. Aquí puede ver como funciona:

  • El cliente actualiza una clase del repositorio llamando a RepositorySessionBean
  • RepositorySessionBean actualiza la base de datos y envía un mensaje sobre un tópico JMS.
  • Cada servidor del cluster recibe este mensaje mediante RepositoryMDBean, el bean dirigido a mensaje (MDB), que actualiza el caché local en memoria.


Figura 6: Diagrama de Secuencia de la aplicación de ejemplo.

El repositorio es un árbol de clases que se almacena en la base de datos. La representación tiene que ser lo más flexible posible. Debido a la naturaleza flexible del esquema, puede ser muy costoso cargar todo el repositorio desde la base de datos, una de las principales razones para usar caché.


Figura 7: Diagrama de la Base de Datos de la aplicación de ejemplo.


Figura 8: Diagrama de EJBs de la aplicación de ejemplo.

Entre los componentes principales utilizados en el diseño se incluyen:

  • Bean de sesión sin estado del repositorio (RepositoryBean) contiene métodos para acceder y manipular el repositorio.
  • Bean dirigido a mensaje del repositorio (RepositoryMDBean) escucha los mensajes de sincronización e invalida las clases cacheadas correspondientes.
  • ObjectManagerSessionBean contiene métodos para devolver los datos como una colección de objetos de una clase dada, y contiene métodos para manipular objetos.

El valor del objeto ClassDescriptor describe una clase y AttributeDescriptor describe un atributo de una clase. Repository está hecho de clases. El valor de los objetos DataObject y Attribute describen un objeto de datos flexible y sus atributos.


Figura 9: Diagrama de clases Java de la aplicación de ejemplo.

Caché de lectura

En general, el caché funciona mejor cuando hay más lecturas que escrituras, como es el caso de la mayoría de las aplicaciones. Esto es perfecto para nuestro ejemplo de repositorio porque el repositorio cambia menos frecuentemente que los datos de la aplicación.

Dependiendo de la complejidad de los datos, la carga desde la base de datos puede ser bastante costosa, por eso es importante minimizar el número de conexiones a la base de datos consiguiendo así la máxima escalabilidad.

Como puede ver en la aplicación de ejemplo, el bean del repositorio simplemente devuelve los datos desde la memoria para todas las operaciones de lectura. Sólo toca la base de datos para las operaciones de actualización.

Guias para la Implementación del Caché de Datos

La aplicación de ejemplo almacena todo el repositorio en memoria. El repositorio carga todos los datos desde la base de datos en el primer acceso al repositorio y devuelve los datos desde la memoria en los siguientes accesos. Esto está bien porque los datos del repositorio suelen ser pequeños.

La aplicación de ejemplo sólo cachea los metadatos y no los propios datos. Sin embargo, usted puede ampliarla fácilmente para cachear los datos. El caché puede ayudar a acelerar los accesos a los datos. Las técnicas de caché para datos son algo diferentes. Los datos de la aplicación pueden ser enormes y no es práctico mantener todos los datos en memoria. Tenga los siguientes puntos en cuenta cuando implemente un caché de datos:

  • Limite el tamaño del caché. Considere la utilización de cachés LRU para limitar su tamaño.
  • Invalidación de Caché contra propagación de cambios. Algunas veces es mejor invalidar el caché que propagar los cambios. Use JMS para enviar una mensaje de invalidación de caché a los servidores del cluster. Es posible combinar ambas técnicas.

Asegurar la consistencia de los datos entre cachés sin que importen los fallos

Como los datos están replicados en los cachés de varios servidores, es importante mantener la consistencia entre ellos. Por ello, por ejemplo, cuando un usuario añada una nueva clase al repositorio, el método addClass() de RepositorySessionBean realiza dos operaciones distintas; actualiza la base de datos (dao.addClass(cd);), y luego publica un mensaje en un tópico JMS para sincronizar los otros cachés del cluter (Util.publishCacheEvent(new CacheEvent(CacheEvent.ADD_CLASS, cd)).


public void addClass(ClassDescriptor cd) throws RepositoryException {
    RepositoryCache cache = RepositoryCache.getInstance();
    RepositoryDAO dao = RepositoryDAO.getInstance();
    try {
        cd.setId(Util.getNextClassID());
        dao.addClass(cd);
        cache.addClass(cd);
        Util.publishCacheEvent(new CacheEvent(CacheEvent.ADD_CLASS, cd));
    } catch (Exception ex) {
        context.setRollbackOnly();
        throw new RepositoryException(ex.getMessage());
    }
}

			

Un fallo en alguna de estas operaciones puede resultar en datos inconsistentes entre los distintos cachés y la base de datos. Especificacmente, hay tres posibles escenarios de fallo:

  1. Fallo en la operación con la base de datos:
    Esto puede acabar en datos inconsistentes si vamos más allá y actualizamos al caché. Como se muestra en el listado anterior, si ocurre un error durante la actualización de la base de datos, no se publicará el mensaje de sincronización del caché.
  2. Fallo en la publicación del mensaje:
    La operación de la base de datos podría tener éxito pero puede haber un error al publicar el mensaje de sincronización del caché. Como se muestra en el código, se pueden capturar los errores JMS y deshacer la transación. La transación controlada por el contenedor iniciada automáticamente por el RepositorySessionBean asegura que esas operaciones son tratadas como una única unidad de trabajo (UOW).
  3. Fallo en el Proveedor de JMS:
    El RepositorySessionBean publica un mensaje sobre un tópico JMS para sincronizar los cachés. Según el contrato del emisor con el proveedor JMS, un mensaje se considera publicado con éxito si el proveedor reconoce la recepción del mensaje. Sin embargo, esto no garantiza la recepción del mensaje por parte de los clientes (MDB). Existe un espacio de tiempo entre que el proveedor JMS recibe el mensaje y el MDB tiene la oportunidad de procesarlo. ¿Qué sucede si el proveedor se cae en ese momento? El mensaje se perderá dejando datos inconsistentes.

    Afortunadamente JMS proporciona mecanismos para garantizar la entrega de los mensajes. JMS soporta persistencia de mensajes, subscritores durables, y reconocimiento de mensajes. Es responsabilidad del servidor almacenar los servidores de un subscriptor durable desconectado y entregarlos cuando el subscriptor vuelva a estar conectado.

    Si se marca un mensaje como persistente, el proveedor JMS graba el mensaje en un almacenamiento persistente, como un disco, tan pronto como lo recibe, y le envía una respuesta al emisor. Si el proveedor se cae recupera el mensaje del almacenamiento persistente y lo envía a los consumidores (MDB) para su procesamiento.

Para la sincronización del caché sólo necesitamos preocuparnos de los fallos del proveedor JMS. Todo ira vien si alguno de los otros nodos del cluster se caen porque recargaran automaticamente el repositorio desde la base de datos. Como la base de datos siempre mantiene la última información el caché debería estar actualizado. Por eso no son necesarios los suscriptores durables. Usamos mensajes persistentes para manejar los fallos del proveedor JMS:


public static void publishCacheEvent(CacheEvent event) 
    throws JMSException, NamingException {

    InitialContext ctx = new InitialContext();
    TopicConnectionFactory tcf = 
        (TopicConnectionFactory)ctx.lookup("jms/RepositoryTopicConnectionFactory");
    TopicConnection topicConnection = tcf.createTopicConnection();
    topicConnection.start();

    TopicSession session = 
        topicConnection.createTopicSession(false, ssion.AUTO_ACKNOWLEDGE);
    Topic newTopic = (Topic)ctx.lookup("jms/RepositoryTopic");

    TopicPublisher sender = session.createPublisher(newTopic);
    event.setSource(SERVER_ID);
    ObjectMessage om = session.createObjectMessage(event);
    sender.publish(om, DeliveryMode.PERSISTENT, Message.DEFAULT_PRIORITY, 3600000);
}

			

Observe la línea event.setSource(SERVER_ID);

Todos los nodos del cluster son productores y consumidores de mensajes de sincronización. Los mensajes de caché generalmente están dirigidos a otras JMV del cluster. Pero es posible que un productor reciba sus propios mensajes. El siguiente fragmento de código de la clase RepositoryMDBean.onMessage() se asegura que se salte la misma JVM:

    // Ignore this event if it was originated from the same VM
    if (Util.SERVER_ID.equals(event.getSource())) {
        return;
    }
			

Crear Clusters de JMS para evitar un sólo punto de fallo

Actualmente muchos servidores de aplicaciones no soportan clusters de JMS. En un cluster con varios nodos, sólo uno de los nodos ejecuta el proveedor JMS. ¿Qué pasa si se cae ese nodo? Todas las actualizaciones fallarán porque el bean no podrá publicar el mensaje de sincronziación del caché. En este caso debe reiniciar el proveedor JMS. (Observe que las futuras versiones de Oracle Application Server 10g soportaran clusters de JMS).

Sumario

Las aplicaciones dirigidas a metadatos se adaptan bien a los requerimientos cambiantes. Acceder a los metadatos debe ser tan rápido como sea posible. Esto hace de los metadatos el candidato ideal para el caché. El caché debe estar sincronizado en clusters. Como hemos visto en el ejemplo del repositorio JMS proporciona un mecanismo simple pero efectivo para la sincronización de cachés entre los nodos de un cluster.

Cómo Configurar y Ejecutar la aplicación de ejemplo

Descargue el fichero ZIP con todo el código fuente desde aquí, y descomprímala en un directorio temporal. Los siguientes pasos le guiarán a través del proceso de configuración del ejemplo de principio al fin, desde la configuración de JMS hasta la prueba de sincronización del caché.

Estas instrucciones asumen que tiene instalado Oracle JDeveloper 10g en su ordenador, así como Oracle Database 10g y Oracle Application Server10g

  • Configurar JMS:
    Añada esto al fichero jms.xml situado en JDEVELOPER_HOME/jdev/system9.0.5.2.1618/oc4j-config folder:
    <topic-connection-factory location="jms/RepositoryTopicConnectionFactory">
    </topic-connection-factory>
    
    <topic name="RepositoryMDB" location="jms/RepositoryTopic">
        <description>For synchronizing repository cache</description>
    </topic>
    						
  • Configurar la fuente de datos:
    1. Cargue el proyecto de la aplicación de ejemplo en JDeveloper (ObjBrowser.jws)
    2. En el menú Tools elija Embedded OC4J Server -> Preferences
    3. Expanda Data Sources y pulse sobre OracleDS
    4. En la pestaña Connection introduzca los detalles de su base de datos
  • Crear el esquema de base de datos:
    En Oracle database, ejecute el fichero objbrowser.sql utilizando sqlplus. Podrá encontrar el script objbrowser.sql en el proyecto de la aplicación de ejemplo.
  • Ejecutar la aplicación:
    1. En el panel Applications - Navigator de JDeveloper 10g, pulse el botón derecho y elija Rebuild desde el menú.
    2. Expanda ObjBrowser, pulse con el botón derecho sobre ViewController y elija Run en el menú.

La sincronización del caché de repositorio en acción:

Puede probar la sincronización del caché utilizando un cluster, o simplemente ejecutando la misma aplicación en dos servidores OC4J diferentes (el OC4J que está embebido en Oracle JDeveloper 10g) utilizando un único servidor JMS.

  • Paso 1: instale JDeveloper 10g en dos máquinas, por ejemplo Server1 y Server2
  • Paso 2; Configure JMS:
    Añada esto al fichero jms.xml situado en JDEVELOPER_HOME/jdev/system9.0.5.2.1618/oc4j-config en los dos servidores:
    <topic-connection-factory location="jms/RepositoryTopicConnectionFactory" host="Server1">
    </topic-connection-factory>
    
    <topic name="RepositoryMDB" location="jms/RepositoryTopic" host="Server1">
        <description>For synchronizing repository cache</description>
    </topic>
    						

    Observe la entrada host="Server1". Esto hace que los ejemplares de OC4J hablen con el mismo servidor JMS que se está ejecutando en Server1.
  • Paso 3: Prueba de la aplicación de ejemplo sin sincronización:
    Como demostración primero deshabilitaremos la sincronización del caché. Para hacerlo comente la llamada a Util.publishCacheEvent() en RepositorySessionBean.java. Reconstruya la aplicación en los dos servidores:
    1. Lance la aplicación de ejemplo en los dos servidores.
    2. En el Server1 haga click en Manage Classes.
    3. Pulse en el botón New para crear una nueva clase. Introduzca Employee para el nombre y la descripción de la clase.
    4. Observe que la clase Employee no existe en la aplicación que se ejecuta en Server2.
  • Paso 4: Prueba con sicronización de caché:
    Active la sincronización, quitando el comentario de la llamada a Util.publishCacheEvent() en RepositorySessionBean.java. Reconstruya la aplicación en los dos servidores:
    1. Vaya a la página principal del Server1 y pulse sobre Manage Classes
    2. Pulse sobre la clase Employee y añada un nuevo atributo llamado favoriteColor.
    3. Conecte ahora con el Server2, pulse sobre Manage Classes y luego pulse sobre la clase Employee.

    Ahora también podrá ver el atributo favoriteColor en el Server2.

Próximos pasos

  1. Lea los excelentes OC4J 10.1.3 How-tos
  2. Visite Using a JMS Provider with MDBs via the J2EE Connector Architecture.
    Donde podrá encontrar una breve introducción a MDB y JCA.
  3. Oracle Java Object Cache 10g.
    Un conjunto de clases Java diseñadas para menajear objetos Java dentro de un proceso, entre procesos o en disco local.
  4. Oracle Web Cache
    Aprenda más sobre el estado al caché y las tecnologías de compresión para optimizar el rendimiento de la aplicación.
  5. J2EE Blueprints

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP