bases de datosAntes de Java EE 6, podíamos crear objetos DataSource usando mecanismos propietarios de cada proveedor (como comandos), y así usábamos el DataSource en la aplicación. Sin embargo, Java EE 6 hace que la definición de DataSource sea más flexible. Java EE 6 presenta un nuevo mecanismo para definir objetos DataSource, que podemos declarar de forma portable en cualquier servidor de aplicaciones compatible con Java EE 6. Ahora podemos declarar las definiciones de los DataSource usando anotaciones o en los descriptores de despliegue.

Las aplicaciones Java EE usan objetos DataSource cuando acceden a bases de datos relacionales usando el API JDBC. Un DataSource tiene un conjunto de propieades que identifica y describe el origen de datos que representa. Estas propiedades incluyen información como la ubicación del servidor de la base de datos, el nombre de la base, y el protocolo de red para comunicarse. Además, los objetos DataSource trabajan con el servicio de nombres JNDI (Java Naming and Directory Interface). Una vez que un objeto DataSource está registrado en el servicio JNDI, las aplicaciones puedan usar el API JNDI para acceder al objeto DataSource, el cual se usa para conectarse a la base de datos que representa.

Crear DataSource usando anotaciones

Java EE 6 brinda dos nuevas anotaciones para crear definiciones de DataSource: @DataSourceDefinition y @DataSourceDefinitions. Ambas anotaciones están en el paquete javax.annotation.sql. Usamos la anotación @DataSourceDefinition para crear una única definición de DataSource. usamos la anotación @DataSourceDefinitions para crear múltiples definiciones de DataSource.

La anotación @DataSourceDefinition

Usamos la anotación @DataSourceDefinition para crear una definición de DataSource. Podemos usar esta anotación en una clase de componente de aplicación, como un cliente de aplicación, servlet o EJB (Enterprise Java Bean). Esta anotación define un objeto DataSource y lo registra con JNDI. Configuramos al DataSource con las propiedades de la anotación. También podemos agregar propiedades específicas para cada proveedor con el elemento properties de la anotación.

Por ejemplo, la siguiente anotación crea una definición de DataSource para una base de datos Derby: 

 
   @DataSourceDefinition(name = "java:app/env/Servlet_DataSource",
      minPoolSize = 0,
      initialPoolSize = 0,
      className = "org.apache.derby.jdbc.ClientXADataSource",
      user = "APP",
      password = "APP",
      databaseName = "testdb",
      properties = {"connectionAttributes=;create=true"}
   )

La definición del DataSource se identifica de forma unívoca con el elemento name. Este es el nombre JNDI con el cual se registrará el DataSource. Noten que el nombre de este elemento comienza con un namespace de alcance, en este caso java:app. Java EE 6 introduce namespaces de entorno para componentes de aplicaciones, que incluye los siguientes alcances: 

  • java:comp. Los nombres en este namespace tienen visibilidad para el componente.
  • java:module. Los nombres en este namespace son compartidos por todos los componentes de un módulo. Por ejemplo, los componentes EJB definidios en el archivo ejb-jar.xml
  • java:app. Los nombres en este namespace son compartidos por todos los componentes y módulos de una aplicación. Por ejemplo, los componentes de application-client, web y EJB en un archivo .ear
  • java:global. Los nombres en este namespace son compartidos por todas las aplicaciones en el servidor.

Dependiendo del namespace de alcance que indiquemos en el elemento name, podremos hacer que el DataSource esté disponible en un todo módulo, una aplicación, o globalmente en todo el servidor. Entonces, si usamos los siguientes prefijos en el atributo name

  • java:comp/env/, el datasource estará disponible en todos los componentes en donde fue definido, como un servlet o EJB.
  • java:module/env/, el datasource estará disponible para todos los componentes EJB definidos en el archivo ejb-jar.xml
  • java:app/env/, el datasource estará disponible para todos los componentes y módulos de la aplicación, como componentes EJB, servlet y clientes de aplicación.

La anotación @DataSourceDefinitions

Podemos usar la anotación @DataSourceDefinitions para crear múltiples definiciones de DataSource en una clase de componente. Indicamos cada definición de DataSource en el elemento value de la anotación. Veamos un ejemplo para crear mútiples definiciones para Derby en un EJB:

 
   @DataSourceDefinitions(
      value = {
 
        @DataSourceDefinition(name = "java:app/env/HelloStatefulEJB_DataSource",
           minPoolSize = 0,
           initialPoolSize = 0,
           className = "org.apache.derby.jdbc.ClientXADataSource",
           portNumber = 1527,
           serverName = "localhost",
           user = "APP",
           password = "APP",
           databaseName = "testdb",
           properties = {"connectionAttributes=;create=true"}
                   ),
 
        @DataSourceDefinition(name = "java:comp/env/HelloStatefulEJB_DataSource",
           minPoolSize = 0,
           initialPoolSize = 0,
           className = "org.apache.derby.jdbc.ClientXADataSource",
           portNumber = 1527,
           serverName = "localhost",
           user = "APP",
           password = "APP",
           databaseName = "testdb",
           properties = {"connectionAttributes=;create=true"}
        )
      }
   )
   @Stateful
   public class HelloStatefulEJB implements HelloStateful {
   ...
   ...
   }
 

Crear DataSource usando descriptores de despliegue

Podemos crear definiciones de DataSource usando un descriptor de despliegue, como application.xml, application-client.xml, web.xml, ejb-jar.xml. Por ejemplo, el siguiente descriptor crea las mismas definiciones de DataSource que usamos en el ejemplo anterior: 

 
   <data-source>
     <name>java:app/env/Application_Level_DataSource</name>
     <class-name>org.apache.derby.jdbc.ClientXADataSource</class-name>
     <server-name>localhost</server-name>
     <port-number>1527</port-number>
     <database-name>testdb</database-name>
     <user>APP</user>
     <password>APP</password>
     <property>
       <name>connectionAttributes</name>
       <value>;create=true</value>
     </property>
   </data-source>
 

Vimos dos ejemplos para crear la misma definición de DataSource, usando anotaciones y usando el descriptor de despliegue. De hecho, de esta manera es posible crear dos definiciones de DataSource con el mismo nombre. En este caso, los valores especificados en el descriptor de despliegue tienen precedencia por sobre las anotaciones. Por ejemplo, si creamos dos definiciones de DataSource con el mismo nombre, una usando anotaciones y la otra con el descriptor de despliegue, e indicamos un nombre de base de datos en cada lugar, se usará el nombre de base de datos configurado en el descritpor. Sin embargo, y indicamos un valor en la anotación y no lo especificamos en el descriptor, se usará el valor de la anotación en conjunto con la información del descriptor.

Traducido de DataSource resource definition in Java EE 6, por Jagadish Ramu.

Inspiración.

"Si tú tienes una manzana y yo tengo una manzana e intercambiamos las manzanas, entonces tanto tú como yo seguiremos teniendo una manzana cada uno. Pero si tú tienes una idea y yo tengo una idea, e intercambiamos las ideas, entonces ambos tendremos dos ideas"

Bernard Shaw