java spring osgi modularization

java - ¿Cómo modularizar una aplicación JSF/Facelets/Spring con OSGi?



modularization (5)

Estoy trabajando con aplicaciones JSF / Facelets muy grandes que utilizan Spring para la administración de DI / bean. Mis aplicaciones tienen una estructura modular y actualmente estoy buscando enfoques para estandarizar la modularización.

Mi objetivo es componer una aplicación web a partir de una serie de módulos (posiblemente dependiendo uno del otro). Cada módulo puede contener lo siguiente:

  • Clases
  • Recursos estáticos (imágenes, CSS, scripts);
  • Plantillas facelet;
  • Beans gestionados: contextos de aplicación de Spring, con beans de solicitud, de sesión y de ámbito de aplicación (la alternativa es beans gestionados de JSF)
  • Servlet API stuff: servlets, filtros, escuchas (esto es opcional).

Lo que me gustaría evitar (casi a toda costa) es la necesidad de copiar o extraer recursos del módulo (como las plantillas de Facelets) al WAR o extender el web.xml para los servlets, filtros, etc. del módulo. Debe ser suficiente para agregue el módulo (JAR, paquete, artefacto, ...) a la aplicación web ( WEB-INF/lib , bundles , plugins , ...) para extender la aplicación web con este módulo.

Actualmente resuelvo esta tarea con una solución de modularización personalizada que se basa en gran medida en el uso de recursos de classpath:

  • El servlet de recursos especiales sirve recursos estáticos de recursos classpath (JAR).
  • El sistema especial de resolución de recursos de Facelets permite cargar plantillas de Facelet desde recursos de classpath.
  • Spring carga los contextos de la aplicación a través del patrón classpath*:com/acme/foo/module/applicationContext.xml : esto carga los contextos de la aplicación definidos en los módulos JAR.
  • Finalmente, un par de servlets y filtros delegados delegan el procesamiento de solicitudes a los servlets y filtros configurados en contextos de aplicaciones Spring desde módulos.

Los últimos días leí mucho sobre OSGi y estaba considerando cómo (y si) podría usar OSGi como un enfoque de modularización estandarizado. Estaba pensando en cómo se podrían resolver las tareas individuales con OSGi:

  • Recursos estáticos: los paquetes OSGi que desean exportar recursos estáticos registran las instancias de ResourceLoader con el contexto del paquete. Un ResourceServlet central utiliza estos cargadores de recursos para cargar recursos de paquetes.
  • Plantillas facelet: similares a las anteriores, un ResourceResolver central utiliza servicios registrados por paquetes.
  • #{myBean.property} administrados: no tengo idea de cómo usar una expresión como #{myBean.property} si myBean está definido en uno de los paquetes.
  • Servlet API stuff: use algo como WebExtender / Pax Web para registrar servlets, filtros, etc.

Mis preguntas son:

  • ¿Estoy inventando una bicicleta aquí? ¿Hay soluciones estándar para eso? He encontrado una mención de Spring Slices pero no pude encontrar mucha documentación al respecto.
  • ¿Crees que OSGi es la tecnología adecuada para la tarea descrita?
  • ¿Mi bosquejo de aplicación OSGI es más o menos correcto?
  • ¿Cómo deben manejarse los beans gestionados (especialmente el alcance de la solicitud / sesión)?

Estaré generalmente agradecido por sus comentarios.


Debería buscar en Spring DM Server (se está realizando la transición a Eclipse Virgo, pero aún no se ha publicado). Hay muchas cosas buenas en la reciente especificación de OSGi para empresas que también se acaba de publicar.

Algunos de los tutoriales de Spring DM ayudarán, me imagino. Pero sí, es posible tener recursos y clases cargados desde fuera del paquete web utilizando modularidad estándar. En eso, es un buen ajuste.

En cuanto al contexto de la sesión, se maneja como cabría esperar en una sesión. Sin embargo, es posible que tenga problemas para compartir esa sesión entre paquetes web en la medida en que no esté seguro de si es posible.

También puede buscar tener un solo paquete web y luego usar, por ejemplo, el registro de extensión Eclipse para ampliar las capacidades de su aplicación web.


El "fragmento del descriptor de implementación del módulo web" (también conocido como web-fragment.xml) introducido por la especificación Servlet 3.0 sería bueno aquí. La especificación lo define como:

Un fragmento web es una partición lógica de la aplicación web de tal manera que los marcos que se utilizan dentro de la aplicación web pueden definir todos los artefactos sin pedir a los desarrolladores que editen o agreguen información en web.xml.

Sin embargo, Java EE 6 quizás no sea una opción para ti en este momento. Aún así, sería la solución estandarizada.


Enterprise OSGi es un dominio bastante nuevo, así que no piense que obtendrá una solución que satisfaga directamente su necesidad. Dicho esto, una de las cosas que encontré que faltan en Equinox (¡el motor osgi detrás de eclipse y por lo tanto uno con la base de usuarios más grande!) Es un servicio de configuración / DI consistente. Recientemente, en mi proyecto tuvimos algunas necesidades similares y terminamos de construir un servicio de configuración simple de osgi.

Uno de los problemas que serán inherentes a las aplicaciones modulares sería alrededor de DI, ya que la visibilidad del módulo podría impedir el acceso de clase en algunos casos. Hemos superado esto utilizando una política de amigos registrados, que no es demasiado ideal pero funciona.

Aparte de la configuración, puede echar un vistazo al libro Equinox recientemente publicado para obtener orientación sobre el uso de OSGi como base para crear aplicaciones modulares. Los ejemplos pueden ser específicos de Equinox, pero los principios funcionarían con cualquier marco OSGi. Enlace - http://equinoxosgi.org/


Estoy enfrentando los mismos problemas en mi proyecto actual. En mi opinión, OSGi es la mejor y más limpia solución en términos de estándares y compatibilidad futura, pero actualmente puede encontrar algunos problemas si intenta usarla en una aplicación web:

  1. todavía no existe una solución bien integrada entre un contenedor web y la plataforma OSGi.
  2. OSGi puede ser demasiado para una aplicación web de compilación personalizada que solo está buscando una arquitectura modular simple. Consideraría OSGi si mi proyecto necesita admitir extensiones de terceros que no están 100% bajo nuestro control, si el proyecto necesita redistribuciones en caliente, reglas de acceso estrictas entre complementos, etc.

Una solución personalizada basada en cargadores de clases y filtros de recursos me parece muy apropiada. Como ejemplo, puede estudiar el código fuente de Hudson o el Proyecto de Java Plug-in Framework (JPF) (http://jpf.sourceforge.net/).

Con respecto a la extensión del web.xml, podemos tener suerte con la especificación Servlet 3.0 (http://today.java.net/pub/a/today/2008/10/14/introduction-to-servlet-3.html# conectabilidad y extensibilidad).


Lo que pretendes hacer sonidos se puede hacer, con algunas advertencias:

La capa de vista: Primero, su capa de vista suena un poco saturada. Existen otras formas de modularizar los componentes JSF utilizando componentes personalizados que evitarán los dolores de cabeza que implica tratar de crear algo tan dramático como los beans administrados que se unen en el tiempo.

Los módulos en sí mismos: en segundo lugar, sus módulos no parecen particularmente modulares. Su primera lista de viñetas hace que parezca que está intentando crear aplicaciones web interoperables, en lugar de módulos per se. Mi idea de un módulo es que cada componente tiene un propósito bien definido y más o menos discreto. Me gusta como ex subyace vi . Si va por la ruta OSGi, entonces deberíamos definir modular de esta manera: modular, por el bien de esta discusión, significa que los componentes son intercambiables en caliente, es decir, se pueden agregar y eliminar sin romper la aplicación.

Dependencias: Estoy un poco preocupado por su descripción de los módulos como "posiblemente dependiendo uno del otro". Probablemente (espero) ya lo sepas, pero tus dependencias deberían formar un gráfico acíclico dirigido. Una vez que introduce una dependencia circular, está pidiendo un mundo de daño en términos de la capacidad de mantenimiento final de la aplicación. Una de las mayores debilidades de OSGi es que no evita las dependencias circulares, por lo que depende de usted hacer cumplir esto. De lo contrario, sus dependencias crecerán como kudzu y ahogarán gradualmente el resto del ecosistema de su sistema.

Servlets: Fuhgeddaboudit. No se pueden vincular los servlets a una aplicación web, no hasta que la especificación Servlet 3.0 esté en producción (como señaló Pascal). Para iniciar un servlet de utilidades por separado, deberá colocarlo en su propia aplicación.

OK, tanto para las advertencias. Pensemos en cómo podría funcionar esto:

Has definido tu propio módulo JSF para hacer ... ¿qué, exactamente? Vamos a darle un propósito definido, bastante trivial: una pantalla de inicio de sesión. Así que creas tu pantalla de inicio de sesión, la vinculas tarde usando OSGi en tu aplicación y ... ¿entonces qué? ¿Cómo sabe la aplicación que existe la funcionalidad de inicio de sesión, si no la ha definido en su página .jspx? ¿Cómo sabe la aplicación para navegar a algo que no puede saber está ahí?

Hay formas de evitar este uso de <c:if #{loginBean.notEmpty}> condicional y similares (p. Ej., <c:if #{loginBean.notEmpty}> ), pero, como usted dijo, las cosas se ponen un poco complicadas cuando su loginBean administrado existe en otro módulo que puede Aún no se han introducido a la aplicación todavía. De hecho, obtendrá una excepción de servlet a menos que exista loginBean. Entonces, ¿Qué haces?

Usted define una API en uno de sus módulos. Todos los beans gestionados que pretende compartir entre módulos deben especificarse como interfaces en esta capa API. Y todos sus módulos deben tener implementaciones predeterminadas de cualquiera de estas interfaces que pretenden usar. Y esta API debe ser compartida entre todos los módulos interoperables. Luego puede usar OSGi y Spring para conectar los beans especificados con su implementación.

Necesito tomarme un momento para señalar que no es así como abordaría este problema. De ningún modo. Dado algo tan simple como una página de inicio de sesión, o incluso tan complicado como un gráfico de cotizaciones, personalmente prefiero crear un componente JSF personalizado. Pero si el requisito es "Quiero que mis beans administrados sean modulares (es decir, intercambiables en caliente, etc.)", esta es la única manera que conozco para hacer que funcione. Y ni siquiera estoy completamente seguro de que funcionará. Este intercambio de correo electrónico sugiere que es un problema en el que los desarrolladores de JSF acaban de empezar a trabajar.

Normalmente considero que los beans administrados forman parte de la capa de vista, y como tal los uso solo para la lógica de vista y delego todo lo demás en la capa de servicio. En mi opinión, hacer que los beans administrados se vinculen más tarde es promoverlos fuera de la capa de vista y en la lógica empresarial. Hay una razón por la que todos esos tutoriales están tan centrados en los servicios: porque la mayoría del tiempo desea considerar qué tomaría para que su aplicación se ejecute "sin cabeza", y lo fácil que sería "ajustar" su vista si, para Por ejemplo, desea que se ejecute, con todas sus funciones, en un teléfono Android.

Pero parece que gran parte de lo que está trabajando es la lógica de la vista, por ejemplo, la necesidad de intercambiar una plantilla de vista diferente. OSGi / Spring debería poder ayudarlo, pero necesitará algo en su aplicación para elegir entre las implementaciones disponibles: prácticamente para lo que fue creado el Registro de servicios de OSGi.

Eso deja recursos estáticos. Puede modularizarlos, pero recuerde que deberá definir una interfaz para recuperar estos recursos y deberá proporcionar una implementación predeterminada para que su aplicación no se ahogue si están ausentes. Si i18n es una consideración, esta podría ser una buena forma de proceder. Si desea ser realmente aventurero, puede insertar sus recursos estáticos en JNDI. Eso los haría completamente intercambiables en caliente, y le ahorraría el dolor de tratar de resolver qué implementación usar mediante programación, pero hay algunas desventajas: cualquier búsqueda fallida hará que su aplicación lance una NamingException. Y es una exageración. JNDI se usa normalmente en aplicaciones web para la configuración de aplicaciones.

En cuanto a tus preguntas restantes:

¿Estoy inventando una bicicleta aquí? ¿Hay soluciones estándar para eso?

Tú eres, un poco. He visto aplicaciones que hacen este tipo de cosas, pero parece que te has topado con un conjunto de requisitos bastante único.

¿Crees que OSGi es la tecnología adecuada para la tarea descrita?

Si necesita que los módulos sean intercambiables en caliente, sus opciones son OSGi y la interfaz de ServiceLocator más liviana.

¿Mi bosquejo de aplicación OSGI es más o menos correcto?

Realmente no puedo decir sin saber más acerca de dónde están los límites de sus componentes. En este momento, suena como si estuvieras presionando a OSGi para que haga más de lo que es capaz de hacer.

Pero no tome mi palabra para ello. blog.springsource.com/2008/04/29/web-applications-and-osgi other material de lectura en estos lugares.

Y ya que pregunta por Spring Slices, esto debería ser suficiente para comenzar . Necesitará un cliente Git, y parece que se entrenará usted mismo en la aplicación mirando el código fuente. Y es el código del prototipo muy temprano.