2010-04-25 7 views
6

Esto es un problema.JDBC/OSGi y cómo cargar de forma dinámica los controladores sin indicar explícitamente las dependencias en el paquete?

Tengo una base de código bien estructurada pero monolítica que tiene una arquitectura modular primitiva (todos los módulos implementan interfaces pero comparten la misma ruta de clase). Me doy cuenta de la locura de este enfoque y los problemas que representa cuando voy a implementar en los servidores de aplicaciones que pueden tener diferentes versiones en conflicto de mi biblioteca.

Depende de alrededor de 30 jarras en este momento y estoy a mitad de camino, sin embargo. Ahora, algunos de mis módulos son fáciles de declarar como dependencias versionadas, como mis componentes de red. Ellos referencian estáticamente las clases dentro del JRE y otras bibliotecas BNDded, pero mis componentes relacionados con JDBC instancian a través de Class.forName (...) y pueden usar uno de varios controladores.

Estoy dividiendo todo en paquetes OSGi por área de servicio.

  • Mi core classes/interfaces.
  • Informar de componentes relacionados.
  • Componentes relacionados con el acceso a la base de datos (a través de JDBC).
  • etc ....

que deseo para mi código para poder seguir utilizándose sin OSGi través archivo JAR individual con todos mis dependencias y sin OSGi en absoluto (a través de jarjar) y también para ser modular a través de los metadatos OSGi y paquetes granulares con información de dependencia.

  • ¿Cómo puedo configurar mi paquete y mi código para que se pueda utilizar de forma dinámica cualquier conductor en la ruta de clase y/o dentro del entorno contenedor OSGi (Felix/Equinox/etc.)?

  • ¿Hay un método en tiempo de ejecución para detectar si estoy ejecutando en un contenedor OSGi que es compatible con contenedores (Felix/Equinox/etc.)?

  • ¿Debo usar un mecanismo de carga de clase diferente si estoy en un contenedor OSGi?

  • ¿Tengo que importar clases OSGi en mi proyecto para poder cargar un controlador JDBC en tiempo de paquete desconocido a través de mi módulo de base de datos?

  • También tengo un segundo método para obtener un controlador (a través de JNDI, que solo es realmente aplicable cuando se ejecuta en un servidor de aplicaciones). ¿Necesito cambiar mi código de acceso JNDI para servidores de aplicaciones OSGi-aware?

Respuesta

7
  • Utilizando cualquier conductor dentro del entorno OSGi requiere que el uso de un DynamicImport-paquete: * comunicado para que su paquete puede resolver estos paquetes cuando se carga un conductor con Class.forName (..).
  • Probablemente la forma más fácil es intentar acceder a una clase que está en el paquete org.osgi.framework. Esos deberían al menos estar siempre presentes en un entorno OSGi (ver fragmento a continuación). Existen mecanismos más sofisticados, así que avíseme si necesita algo más avanzado. Además, eche un vistazo a la especificación central OSGi R4.2, párrafo 3.8.9 que muestra algunos métodos para encontrar el Bundle y el BundleContext de una clase y, por lo tanto, ayuda indirectamente a determinar si está en un marco o no.
  • Eso depende de lo que esté haciendo, no hay respuestas genéricas de "sí" o "no" aquí. OSGi usa cargadores de clases y lo hace de una manera que no es "típica" para una aplicación Java estándar, pero dependiendo de lo que esté haciendo, puede que no lo note.
  • No.
  • Eche un vistazo a las especificaciones empresariales OSGi recientemente lanzadas. Tienen un capítulo sobre integración JNDI en OSGi que probablemente le permite dejar su código (en gran parte) sin modificaciones.

Un ejemplo sencillo fragmento:

public static boolean inOSGi() { 
    try { 
    Class.forName("org.osgi.framework.FrameworkUtil"); 
    return true; 
    } 
    catch (ClassNotFoundException e) { 
    return false; 
    } 
} 

Sólo asegúrese de que si se pone este código en un paquete, el paquete debe importar org.osgi.framework (de lo contrario, nunca se dará cuenta de que la clase) .

+0

Gracias por la información, especialmente la DynamicImport-paquete: * punta que, sorprendentemente, no pude encontrar a través de búsqueda en Internet. Con respecto a la segunda respuesta, un fragmento podría ser bueno si tiene tiempo. Sin embargo, marcaré esto como la respuesta aprobada de todos modos, ya que usted respondió mis preguntas principales. Gracias. – Chris

0

Hice un administrador de controladores JDBC para OSGI en un Eclipse RCP y le mostraré cómo jugar bien con OSGI. Primero, olvídese de DynamicImport-Package, la única buena manera de usar OSGI es instalar/iniciar/detener paquetes y usar el mecanismo OSGI de la manera en que fue diseñado.

  1. usted tiene su paquete JDBC, y crear otro "paquete de controladores" que tiene la inicialización de la DriverClass, la lógica de conexión y añadir los campos comunes tales como bibliotecas necesarias dbcp2 y pool2.

  2. Exporte el paquete de controladores como un JAR/ZIP e inclúyalo en su paquete JDBC como recurso.

  3. Deje que su paquete JDBC descomprima el paquete de controladores en su área de trabajo.

    String workdir= Platform.getStateLocation(jdbc_bundle).toPortableString(); 
    
  4. agregar mediante programación frascos conductor y modificar el archivo MANIFEST.MF del paquete de controlador en consecuencia.

  5. Cargar el paquete de programación del controlador del área de trabajo

    getBundleContext().installBundle("file:/"+workdir); 
    
  6. Uso bundle.start(), stop(), desinstalación() si es necesario cuando se modifica mediante programación la lista de controladores.

0

El Pax-JDBC se puede utilizar para delegar dataSources vía manera declarativa, significa que puede crear una entrada de configuración en el servicio ConfigAdmin, y la fuente de datos se puede acceder a través de JNDI. El controlador JDBC se implementa como paquete. (La mayoría de ellos tienen versión OSGi)

Por ejemplo:

La entrada config PID es org.ops4j.datasource-test

Propiedades:

osgi.jdbc.driver.name=H2 
databaseName=test 
user=sa 
password= 
dataSourceName=testds-h2 

El servicio es identificado por la dado dataSourceName. De modo que puede filtrarlo con (& (objectClass = javax.sql.DataSource) (dataSourceName = test2)).

Y se puede acceder a través de la fuente de datos JNDI:

osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=test2) 
Cuestiones relacionadas