OSGI es una de esas cosas de las que quería enterarme de qué iba y aprovechando el manual de OSGi de Roberto Montero publicado en javahispano, me he puesto a ello.
El manual, para alguien como yo que tiene ciertos conocimientos de java y no le suenan a chino cosas como fichero de manifiesto, classloader o maven, pero que no tiene ni puñetera idea de qué es OSGi, está muy bien. Da una explicación desde el principio y mostrando un ejemplo "Hola Mundo" en diversas plataformas y con distintas herramientas (Equinox, Apache Félix, Eclipse, Pax Constructor, etc). Al final me queda más o menos claro qué es OSGi y sólo queda hacerme mis propios ejemplos y pruebas.
La idea básica de OSGi es que es una forma de desarrollar aplicaciones java a base de hacer módulos más o menos independientes, pero que pueden colaborar entre ellos. Estos módulos (llamados bundles) no son más que jars con algunas clases especiales propias de OSGi y un fichero de manifiesto con campos especiales, que entiende OSGi. Los bundles pueden colaborar entre ellos, indicando qué paquetes java exportan a otros módulos y qué paquetes java de otros módulos necesitan. Una plataforma que implemente OSGi (Equinox o Apache Félix entre otras) es capaz de cargar, arrancar o parar estos módulos en tiempo de ejecución, sin necesidad de tirar la aplicación y volver a arrancarla. También es capaz de saber qué módulos dependen de cuales para pararlos si les faltan dependencias o arrancarlos sólo cuando todas sus dependencias están cargadas.
Sin embargo hay un problema que tengo de hace mucho y que veo que OSGi no me va a solucionar. Cuando hay dos módulos (jars) que se quiere que colaboren, al final no queda más remedio que uno de ellos vea (necesite) al otro para compilar, ya que si un módulo usa otro, debe ver al menos alguna interface o tipo de dato. Esto hace que los módulos no sean realmente independientes y no puedas aprovechar un módulo para otro proyecto. Si en otro proyecto quiero llevarme el móudlo A y este tira de una interface de B, pues me tengo que llevar B también y éste, desgraciadamente, en una de sus clases que no necesito para nada, tira de una interface del módulo C y así sucesivamente. Para proyectos grandes con muchos programadores (expertos y novatos), lo normal es que todos los módulos acaben dependiendo de todos e incluso empiece a haber dependencias cruzadas. Sí, ya sé que "sólo" es cuestión de pensar antes que módulos debe haber, cómo dependen unos de otros y "sólo" hay que conseguir que todos los programadores respeten esa arquitectura.
Una posible solución, que había descartado, para este problema es que cada módulo fuera en realidad dos módulos. Uno pequeño, con sólo las interfaces y clase de datos (beans) que es lo que dependerían los demás módulos. Y otro módulo más grande con todo el resto del código. Lo descarté porque en un proyecto grande con 30 o 40 módulos, se nos duplica el número de módulos y de jars.
Sin embargo, en los ejemplos OSGi que he visto, parece que hace eso mismo. Si crea un módulo que es un servicio que van a ver otros módulos, crea dos módulos: uno con la interface del servicio y los bean de datos, el otro con la implementación. Los módulos que usen servicios de éste, sólo dependen del módulo pequeño con la interface.
En fin, a jugar un poco con OGSi y a repensar esto de partir los módulos en dos submódulos: lo visible al exterior y la implementación concreta.