¿Cómo modularizar una Aplicación Empresarial con OSGi y EE6?
Frecuentes
Visto 1,184 equipos
6
Sé que ya hay algunas preguntas relacionadas con este tema, pero aún no pude encontrar una solución real.
Actualmente estoy desarrollando aplicaciones con EE6, usando JPA, CDI, JSF. Me gustaría adoptar un enfoque más modular que empaquetar todo en un WAR o EAR e implementar todo en un servidor de aplicaciones.
Estoy tratando de diseñar mis aplicaciones lo más modular posible separando un módulo en 3 proyectos maven:
- API: contiene las interfaces para servicios (sin estado)
- Modelo: contiene las entidades JPA para el módulo específico
- Impl: contiene la implementación de la API, principalmente beans CDI
La lógica de visualización de cada módulo se incluye actualmente en un gran proyecto web, lo cual es feo. Ya pensé en fragmentos web, pero si distribuyo mis clases de bean y archivos xhtml en archivos jar, tendría que implementar un gancho para que una aplicación web principal pueda buscar los recursos. Este tipo de solución al menos me permitiría tener un cuarto proyecto por módulo que contendría toda la lógica de vista relacionada con el módulo, lo cual es un buen comienzo.
Lo que quiero no es solo que pueda tener esos 4 tipos de proyectos, sino también que todos los proyectos sean intercambiables en caliente. Esto me llevó a OSGi, que al principio fue realmente genial hasta que me di cuenta de que las tecnologías EE6 no son muy compatibles con un contenedor OSGi.
JPA
Veamos primero JPA. Hay algunos tutoriales[1] que explican cómo hacer un paquete OSGi habilitado para JPA, pero ninguno de estos tutoriales muestra cómo distribuir entidades en diferentes paquetes (el proyecto modelo de un módulo). Me gustaría tener, por ejemplo, tres módulos diferentes
- Core
- Usuario
- Blog
El proyecto modelo del módulo de blog tiene una dependencia (en tiempo de compilación) del proyecto modelo del usuario. El proyecto modelo del módulo de usuario tiene una dependencia (en tiempo de compilación) del proyecto modelo del núcleo.
¿Cómo puedo hacer que JPA funcione en tal escenario sin tener que crear una Unidad de Persistencia para cada proyecto modelo de un módulo? Quiero una unidad de persistencia que conozca todas las entidades disponibles en tiempo de ejecución. Los proyectos modelo en los que se encuentran las entidades deben, por supuesto, ser intercambiables en caliente. Tal vez necesite crear un proyecto separado para cada cliente que importe todas las entidades necesarias de los proyectos y contenga un archivo persistence.xml que incluya todas las cosas de configuración necesarias. ¿Hay complementos maven disponibles para crear proyectos de este tipo o incluso otros enfoques para resolver ese problema?
CDI
CDI es muy agradable. ¡Me encanta y no me lo quiero perder más! ¡Utilizo extensiones CDI como MyFaces CODI y DeltaSpike que son increíbles! Inyecto mis servicios (sin estado) en otros servicios o en la capa de vista, lo cual es genial. Dado que mis servicios no tienen estado, no debería ser un problema usarlos como servicios OSGi, pero ¿qué pasa con la integración de CDI en OSGi? Encontré una extensión CDI glassfish [2] que inyectaría servicios OSGi en beans CDI, pero también quiero que los servicios OSGi sean beans CDI. No estoy totalmente seguro de cómo lograrlo, probablemente tendría que usar BeanManager para instanciar las implementaciones y luego registrar cada implementación para su interfaz en ServiceRegistry dentro de BundleActivator. ¿Hay alguna forma estándar de hacerlo? Me gustaría evitar cualquier dependencia (en tiempo de compilación) del marco OSGi.
También me gustaría usar mis servicios tal como los uso ahora, sin cambiar nada (implementaciones no anotadas y puntos de inyección no calificados). Hay una extensión/subproyecto de JBoss Weld[3] que parece abordar ese problema, pero parece estar inactivo, no puedo encontrar ninguna de las mejores prácticas o procedimientos. ¿Cómo puedo dejar mi implementación como está pero aún poder usar OSGi? Quiero decir que no sería un gran problema agregar una anotación a las implementaciones ya que cada implementación ya está anotada con una anotación de estereotipo, de todos modos me gustaría evitar eso.
JSF
Como se mencionó antes, me gustaría poder difundir mi módulo lógico de vista de manera inteligente. Hasta donde yo sé, esto no es realmente posible fuera de la caja. Pax Web[4] debería resolver eso de alguna manera, pero no estoy familiarizado con él.
Me gustaría tener un proyecto "CoreWeb" en el módulo "core" que contenga una plantilla de Facelet, llamémoslo "template.xhtml". Una página JSF en un proyecto llamado "BlogWeb" en el módulo "blog" debería poder hacer referencia a esa plantilla y aplicar una composición.
Para poder ampliar la vista, introduciría una "Extensión" de interfaz Java que puede implementarse mediante una clase específica de un módulo. Un controlador para una vista luego inyectaría todas las implementaciones de la extensión. Una extensión, por ejemplo, proporcionaría una lista de subvistas que se incluirán en una vista principal.
El mecanismo de extensión descrito se puede implementar fácilmente, pero se deben cumplir los siguientes requisitos:
- Al agregar nuevos paquetes OSGi al servidor de aplicaciones, el conjunto de extensiones disponibles puede cambiar, las extensiones deben estar disponibles para el controlador de la vista.
- Las subvistas (de un paquete separado) que deben incluirse en una vista principal deben ser accesibles.
El concepto de un solo host pero múltiples aplicaciones de corte de Spring Slices[5] es muy interesante, pero parece limitado a Spring DM Server y el proyecto también parece estar inactivo.
Resumen
Después de todos los ejemplos y comportamientos que describí, espero que sepas lo que me gustaría lograr. Es simplemente una aplicación EE6 que es muy dinámica y modularizada.
Lo que busco al final es al menos documentación sobre cómo hacer que todo funcione como lo esperaría o incluso mejor, ¡una solución que ya funcione!
[ 1 ] http://jaxenter.com/tutorial-using-jpa-in-an-osgi-environment-36661.html
[ 2 ] https://blogs.oracle.com/sivakumart/entry/typesafe_injection_of_dynamic_osgi
[ 3 ] http://www.slideshare.net/TrevorReznik/weldosgi-injecting-easiness-in-osgi
1 Respuestas
1
Para responder algunas de sus preguntas, use una sola unidad de persistencia pero distribuya sus entidades en múltiples paquetes no se recomienda, pero puede funcionar ocasionalmente. Sin embargo, si sus entidades están tan estrechamente relacionadas que necesitan compartir una unidad de persistencia, es posible que no tenga sentido dividirlas en módulos. Además, no olvide que puede manejar las dependencias en tiempo de compilación separando la implementación y la interfaz para cada entidad; la interfaz y la implementación no necesitan estar en el mismo paquete.
Para la inyección de dependencia, puede que le guste Blueprint. Hay varias implementaciones disponibles y la mayoría de los servidores de aplicaciones con soporte OSGi empresarial admiten Blueprint de fábrica. Utiliza XML para agregar metadatos, por lo que las clases en sí mismas no necesitarán ninguna modificación.
Respondido 03 Jul 12, 08:07
El módulo principal también contiene acceso genérico a las entidades disponibles, por lo que debo tener exactamente una PU, pero sería bueno si no tuviera que empaquetarlas en un archivo jar. Probablemente haya algunos complementos maven que harán el empaquetado, pero en mi opinión, de alguna manera no es muy parecido a OSGi. Ya analicé algunos ejemplos de Blueprint y no me gusta la seguridad de tipos de la configuración xml. Si no hay otra opción, entonces probablemente tendría que usar eso o implementar una solución CDI por mi cuenta. - Christian Beikov
Christian, ¿encontró alguna solución perfecta para su aplicación modular? puedes compartir conmigo . Estoy teniendo el mismo problema ? - Suraj
No pude encontrar ninguna solución directa a eso. Estoy esperando Java 9 (Jigsaw) y una versión EE que haga uso de los módulos. Solución actual para proyectos JPA: use un proyecto de persistencia que incluya los archivos orm.xml de los submódulos. Solución actual para proyectos CDI: Deje los proyectos separados como están y tenga cuidado al agregar dependencias. Solución actual para el proyecto web: separe las cosas, si es posible, en subproyectos y combine todo en la compilación. Vuelva a implementar si desea agregar nuevos módulos o poner todos los módulos en la aplicación pero solo mostrar subconjuntos. - Christian Beikov