2010-04-04 13 views
26

Estoy trabajando con aplicaciones JSF/Facelets muy grandes que usan Spring para la administración de DI/bean. Mis aplicaciones tienen una estructura modular y actualmente estoy buscando enfoques para estandarizar la modularización.¿Cómo modularizar una aplicación JSF/Facelets/Spring con OSGi?

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

  • Clases;
  • Recursos estáticos (imágenes, CSS, scripts);
  • Plantillas de facetas;
  • beans gestionados - Contextos de aplicaciones de primavera, con petición, sesión y beans con ámbito de aplicación (alternativa es beans gestionados por JSF);
  • Cosas de Servlet API: servlets, filters, listeners (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 plantillas de Facelets) para la guerra o para extender el web.xml para los servlets de módulo, filtros, etc. debe ser suficiente para agregar 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 me resuelve esta tarea con una solución personalizada modularización que se basa principalmente en el uso de los recursos de ruta de clases:

  • recursos especiales servlet sirve recursos estáticos a partir de recursos de ruta de clases (JAR).
  • El solucionador de recursos Special Facelets permite cargar plantillas de Facelet desde recursos de classpath.
  • El muelle carga contextos de aplicación a través del patrón classpath*:com/acme/foo/module/applicationContext.xml - esto carga contextos de aplicación definidos en módulos JAR.
  • Finalmente, un par de servlets y filtros de delegado delegan el procesamiento de solicitud a los servlets y filtros configurados en los contextos de aplicación Spring desde los módulos.

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

  • recursos estáticos - paquetes OSGi, que desean exportar recursos estáticos registrar un ResourceLoader casos con el contexto paquete. Un ResourceServlet central utiliza estos cargadores de recursos para cargar recursos de paquetes.
  • Plantillas de facetas: similar a la anterior, una central ResourceResolver utiliza servicios registrados por paquetes.
  • beans gestionados - No tengo idea cómo usar una expresión como #{myBean.property} si myBean se define en uno de los paquetes.
  • Cosas de Servlet API: utilice algo como WebExtender/Pax Web para registrar servlets, filtros, etc.

Mis preguntas son:

  • ¿Estoy inventando una bicicleta aquí? ¿Hay soluciones estándar para eso? Encontré 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 la aplicación OSGI es más o menos correcto?
  • ¿Cómo se deben manejar los beans administrados (especialmente el alcance de solicitud/sesión)?

Estaría generalmente agradecido por sus comentarios.

+0

http://blog.springsource.com/2008/04/29/web-applications-and-osgi/ – Bozho

+0

http://sites.google.com/site/springosgi/ – Bozho

Respuesta

13

Lo que la intención que tenga suena factible, con algunas salvedades:

La Vista: primer lugar, su capa de vista suena un poco mullido. Existen otras formas de modularizar los componentes JSF mediante el uso de componentes personalizados que evitarán los dolores de cabeza implicados al tratar de crear algo tan espectacular como los beans administrados de enlace tardío.

Los módulos en sí: En segundo lugar, sus módulos no parecen particularmente modulares. Su primera lista de viñetas lo hace parecer como si estuviera tratando de crear aplicaciones web interoperables, en lugar de módulos en sí. Mi idea de un módulo es que cada componente tenga un propósito bien definido y más o menos discreto. Al igual que ex es la base de vi. Si va por la ruta OSGi, entonces deberíamos definir modular como este: Modular, por el bien de esta discusión, significa que los componentes son intercambiables en caliente, es decir, pueden agregarse y eliminarse sin romperse la aplicación.

Dependencias: Me preocupa un poco su descripción de los módulos como "posiblemente dependiendo el uno del otro". Probablemente (espero) ya lo sepan, pero sus dependencias deben formar un gráfico acíclico dirigido. Una vez que introduce una dependencia circular, está pidiendo un mundo de dolor en términos de la posibilidad de mantenimiento de la aplicación. Una de las mayores debilidades de OSGi es que no impide 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 tarde los servlets en una aplicación web, no hasta que la especificación de Servlet 3.0 esté en producción (como señaló Pascal). Para iniciar un servlet de utilidad por separado, deberá colocarlo en su propia aplicación.


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

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. Entonces creas tu pantalla de inicio de sesión, únete a ella con OSGi en tu aplicación y ... ¿luego qué? ¿Cómo sabe la aplicación que la funcionalidad de inicio de sesión está allí, si no la ha definido en su página .jspx? ¿Cómo sabe la aplicación navegar a algo que no puede saber que hay allí?

Hay formas de evitar esto usando inclusiones condicionales y similares (por ejemplo, <c:if #{loginBean.notEmpty}>), pero, como dijiste, las cosas se ponen un poco feas cuando tu loginBean administrado existe en otro módulo que puede que ni siquiera se haya introducido en la aplicación todavía De hecho, obtendrá una excepción de servlet a menos que exista loginBean. Entonces, ¿Qué haces?

Define una API en uno de sus módulos. Todos los beans administrados 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 pretendan usar. Y esta API debe ser compartida entre todos los módulos interoperables. Luego puede usar OSGi y Spring para conectar juntos los beans especificados con su implementación.

Necesito tomar 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 inventario, personalmente preferiría crear un componente JSF personalizado. Pero si el requisito es "Quiero que mis beans administrados sean modulares (es decir, hot-swappable, etc.)", esta es la única forma que conozco para que funcione. Y ni siquiera estoy completamente seguro de que funcionará. This email exchange sugiere que es un problema que los desarrolladores de JSF acaban de comenzar a trabajar. habas

me consideraría normalmente logrado ser parte de la capa de vista, y como tal, los utilizo sólo para la vista lógica y delegar todo lo demás a la capa de servicio. En mi opinión, hacer que los beans administrados sean de enlace tardío los promueve fuera de la capa de vista y dentro de la lógica comercial. Hay una razón por la cual todos esos tutoriales están tan enfocados en los servicios: porque la mayoría de las veces quiere considerar lo que le tomaría a su aplicación funcionar "sin cabeza", y lo fácil que sería "desollar" su vista si, por Por ejemplo, quería que se ejecutara, con toda su funcionalidad, en un teléfono Android.

Pero parece que mucho de lo que está trabajando es la lógica de visualización, por ejemplo, la necesidad de cambiar una plantilla de vista diferente. OSGi/Spring debería ser capaz de ayudar, pero necesitará algo en su aplicación para elegir entre las implementaciones disponibles: más o menos para lo que fue creado el Registro de Servicios de OSGi.

Eso deja recursos estáticos. Puede modularizar estos, 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 faltan. Si i18n es una consideración, esta podría ser una buena manera de hacerlo. Si quisiera ser realmente intrépido, podría insertar sus recursos estáticos en JNDI. Eso los haría completamente intercambiables en caliente, y le ahorrará el esfuerzo de tratar de resolver qué implementación utilizar mediante programación, pero hay algunas desventajas: cualquier búsqueda fallida hará que su aplicación genere una NamingException. Y es excesivo. JNDI normalmente se usa en aplicaciones web para la configuración de la aplicación.

En cuanto a sus preguntas restantes:

Am I inventar una bicicleta aquí? ¿Hay soluciones estándar para eso?

Usted es, un poco. He visto aplicaciones que hacen esto tipo, pero pareces haber tropezado con un conjunto bastante único de requisitos.

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

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

¿Es mi bosquejo de la aplicación OSGI más o menos correcto?

Realmente no puedo decir sin saber más sobre dónde están los límites de tus componentes. Por el momento, parece que está presionando a OSGi para que haga más de lo que es capaz de hacer.

Pero no confíe en mi palabra. Ifoundother leyendo material en estos lugares.

Y como preguntas sobre Spring Slices, this should be enough to get you started.Necesitarás un cliente de Git, y parece que te entrenarás en la aplicación mirando el código fuente. Y es un código de prototipo muy temprano.

+1

Muchas gracias por la extensa respuesta. Poco a poco voy adquiriendo la visión de cómo se deben hacer las cosas en este caso. Tengo una respuesta de Costin Leau: http://forum.springsource.org/showthread.php?p=293995#post293995 También he encontrado el proyecto SevenHats que tenga intención de hacer lo que quiera: http://www.sevenhats.org/ – lexicore

+0

Un ejemplo de módulo es un módulo de "administración de usuarios". Contiene todos los servicios (usuario/rol DAO), plantillas de Facelets, imágenes/CSS, solicitud y beans de sesión necesarios para agregar la administración de usuarios a la aplicación. Dentro de la aplicación, el módulo simplemente agrega un elemento de menú al menú del administrador. – lexicore

+0

Con "posiblemente dependiendo de otro" quise decir A que depende de B, donde B también puede depender de otro módulo C. No me refiero a las dependencias circulares, las estamos evitando. – lexicore

0

Debería consultar el servidor de Spring DM (está en transición a Eclipse Virgo pero aún no se ha lanzado). Hay muchas cosas buenas en la reciente especificación empresarial de OSGi que también acaba de lanzarse.

Algunos de los tutoriales de Spring DM ayudarán, me imagino. Pero sí, es posible tener tanto recursos como clases cargados desde fuera del paquete web utilizando modularidad estándar. En eso, es una buena opción.

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

También podría intentar tener un solo paquete web y luego usar, por ejemplo, el registro de extensión Eclipse para extender las capacidades de su aplicación web.

+0

Gracias por sus respuestas. Desafortunadamente no pude encontrar las respuestas en los tutoriales. Todo está demasiado orientado al servicio. Me gusta, cómo exponer y consumir MyService a través de OSGi. ¿Y qué tal MyRequestBean y MySessionBean? Estoy realmente mirando a Spring DM, pero no podemos movernos al servidor de Spring DM. Nuestra aplicación web debe ejecutarse en contenedores de servlets "normales", como WAR simple, sin asumir un entorno OSGi. Por lo tanto, estoy mirando en la dirección del enfoque del "puente servlet". – lexicore

1

Enterprise OSGi es un dominio bastante nuevo, así que no piense que obtendrá una solución que satisfaga directamente sus necesidades. ¡Eso decía que una de las cosas que me faltaba en Equinox (el motor de osgi detrás del eclipse y, por lo tanto, uno con la base de usuarios más grande!) Es un servicio de configuración/DI consistente. En mi proyecto recientemente tuvimos algunas necesidades similares y terminé construyendo un servicio de configuración de osgi simple.

Uno de los problemas que será inherente a las aplicaciones modulares sería en torno a DI, ya que la visibilidad del módulo podría evitar el acceso de clase en algunos casos. Lo solucionamos usando una política de amigo registrado, que no es demasiado ideal, pero funciona.

Además de la configuración, puede consultar el 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/

2

El "fragmento de descriptor de despliegue de módulo web" (también conocido como web-fragment.xml) introducido por el Servlet 3.0 specification estaría bien aquí. La especificación define como:

Un fragmento de web es un lógico partición de la aplicación web de tal manera que los marcos se utilizan dentro de la aplicación web puede definir todos los artefactos sin pedir devlopers a edite o agregue información en el web.xml.

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

+0

Gracias, Pascal. Conozco Servlet 3.0, resuelve el problema de modularizar "cosas de servlet" - servlets, filtros, etc. Es solo una parte de lo que necesito. – lexicore

3

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 normas y apoyo en el futuro, pero en la actualidad se puede golpear algunos problemas si intenta utilizarlo en una aplicación web:

  1. existe ninguna solución bien integrada entre una Web Container y la plataforma OSGi todavía.
  2. OSGi puede ser demasiado para una aplicación web de compilación personalizada que solo está buscando una arquitectura modular simple. Yo consideraría OSGi si mi proyecto necesita para soportar extensiones de terceros que no son 100% bajo nuestro control, si el proyecto necesita redistribuciones calientes, las reglas estrictas de acceso entre los plugins, etc.

Una solución personalizada basada en los cargadores de clases y los filtros de recursos me parecen muy apropiados. Como ejemplo, puede estudiar el proyecto Hudson source code o Java Plug-in Framework (JPF) (http://jpf.sourceforge.net/).

En cuanto a extender el 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 # pluggability-y-extensibilidad).

+0

Al igual que con respecto a la entrega de recursos, eche un vistazo a jsf2.0. Puede ser una sorpresa para usted ver que han agregado soporte para tales cosas. Ver http://blogs.sun.com/rlubke/entry/jsf_2_0_new_feature5 –

Cuestiones relacionadas