23/3/2011

Configurar Spring para uso de Datasources JNDI en JBOSS 6.0.0

He comprobado que crear DataSource JNDI para su uso con JBoss en una aplicación basada en Spring tiene tela marinera, en concreto con Spring 3.0.3.RELEASE, si además añadimos un par de frameworks más...


Hoy me he encontrado con la problemática de configurar un DataSource, bueno realmente era alguno más, pero la solución se aplica a uno y luego todos a disfrutar del "Cut&Paste", despues de googlear y goolglear he visto que no hay ningún sitio en el cual te digan de forma clara como hacerlo, así que he decidido intentar ponerlo yo en unas pocas palabras, así que vamos a ello.


Lo primero que hay que hacer es crear un archivo XML en $JBOSS_HOME/server/default/deploy/ que siga la nomenclatura <nombre_datasource>-ds.xml el contenido del archivo debe ser como el siguiente (en esta configuración se ha definido un pool con un mínimo y máximo):


Contenido de MiDataSourceDS-ds.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<datasources>
    <local-tx-datasource>
        <jndi-name>MiDataSourceDS</jndi-name>
        <connection-definition>javax.sql.DataSource</connection-definition>
        <jmx-invoker-name>jboss:service=invoker,type=unified</jmx-invoker-name>
        <min-pool-size>10</min-pool-size>
        <max-pool-size>100</max-pool-size>
        <use-java-context>false</use-java-context>
        <user-name>username</user-name>
        <password>password</password>
        <blocking-timeout-millis>30000</blocking-timeout-millis>
        <idle-timeout-minutes>30</idle-timeout-minutes>
        <prefill>false</prefill>
        <background-validation>false</background-validation>
        <background-validation-millis>0</background-validation-millis>
        <validate-on-match>true</validate-on-match>
        <statistics-formatter>org.jboss.resource.statistic.pool.JBossDefaultSubPoolStatisticFormatter</statistics-formatter>
        <isSameRM-override-value>false</isSameRM-override-value>
        <allocation-retry>0</allocation-retry>
        <allocation-retry-wait-millis>5000</allocation-retry-wait-millis>
        <application-managed-security xsi:type="securityMetaData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
        <metadata>
           <type-mapping>Oracle9i</type-mapping>
        </metadata>
        <local-transaction/>
        <check-valid-connection-sql>SELECT 1 FROM DUAL</check-valid-connection-sql>
        <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
        <prepared-statement-cache-size>0</prepared-statement-cache-size>
        <share-prepared-statements>false</share-prepared-statements>
        <set-tx-query-timeout>false</set-tx-query-timeout>
        <query-timeout>0</query-timeout>
        <use-try-lock>60000</use-try-lock>
        <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
        <connection-url>jdbc:oracle:thin:@localhost:1521:XE</connection-url>
    </local-tx-datasource>
</datasources>


Una vez que tenemos esto en el directorio de JBoss, si arrancamos el servidor comprobaremos que tenemos el DataSource recién creado dado de alta y disponible.
Ahora nos toca ir a la configuración spring, para ello nos vamos a nuestro proyecto y editamos el archivo de configuración, en mi caso suelo llamarlo application-context.xml (no soy muy original poniendo nombres), en este archivo tenemos que añadir la configuración necesaria para el uso de JNDI, para ello se incluyen unas pocas líneas.
Contenido de application-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  <!--  Jboss jndi Template s -->
  <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
       <props>
         <prop key="java.naming.factory.initial">
            org.jnp.interfaces.NamingContextFactory
         </prop>
         <prop key="java.naming.factory.url.pkgs">
            org.jboss.naming:org.jnp.interfaces
         </prop>
         <prop key="java.naming.provider.url">
            jnp://127.0.0.1:1099
         </prop>
       </props>
     </property>
  </bean>
  <bean id="dataSource" 
        class="org.springframework.jndi.JndiObjectFactoryBean" 
        lazy-init="true">
    <property name="jndiTemplate" ref="jndiTemplate" />
    <property name="jndiName" value="MiDataSourceDS" />
  </bean>
  ...
</beans>

Despues de configurar esto tenemos que añadir unas líneas más a otro archivo XML, esta vez le toca a jboss-web.xml que es donde vamos a configurar la aplicación para que despliegue de forma correcta en JBoss, este documento debería estar en la carpeta <home_proyecto>/src/main/webapp/WEB-INF/.

Contenido de jboss-web.xml:
<jboss-web>
  <context-root>/jnditest</context-root>
  <class-loading>
    <loader-repository>
      jnditest:loader=jnditest.war
      <loader-repository-config>
        java2ParentDelegation=false
      </loader-repository-config>
    </loader-repository>
  </class-loading>
  <resource-ref>
    <description>Mi DataSource Connection</description>
    <res-ref-name>MiDataSourceDS</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <jndi-name>MiDataSourceDS</jndi-name>
    <res-auth>Container</res-auth>
  </resource-ref>
</jboss-web>


Y con esto ya tenemos configurado el datasource JNDI en JBoss y nuestra aplicación haciendo uso de este.


NOTA: Los drivers JDBC de Oracle se deben añadir en el directorio $JBOSS_HOME/common/lib/

Espero que os sirva de ayuda. A disfrutar!!!