martes, noviembre 06, 2007

Api de Pesistencia de Java (JPA) y Netbeans

Cuando intentaba probar el Api de Pesistencia de Java (JPA) desde la última versión de Netbeans (NB 6 Beta 2.0) me he encontrado con algunos problemas, que tras un par de días he conseguido resolver.
Tras crear la conexión a la base de datos y la unidad de persistencia, las clases de persistencia que se incluyen por defecto en NB, TopLink (Oracle), no conseguían acceder al datasource de Tomcat.
El problema es que el datasource sí que estaba presente, ya que usando el método descrito en un post anterior en este mismo blog, sí que se recuperaba una conexión. El mensaje obtenido era el siguiente:

oracle.toplink.essentials.exceptions.ValidationExceptionException Description: Cannot acquire data source [jdbc/TestDS].
Después de mucho indagar, el problema es que es necesario modificar la forma en que TopLink recupera el datasource de Tomcat. Primero es preciso crear una clase que implemente oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer:

package test;
import oracle.toplink.essentials.jndi.JNDIConnector;
import oracle.toplink.essentials.sessions.Session;
import oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer;


public class TopLinkSessionCustomizer implements SessionCustomizer {
    public void customize(Session session) throws Exception {
        JNDIConnector connector = (JNDIConnector) session.getLogin().getConnector();
        connector.setLookupType(JNDIConnector.STRING_LOOKUP);
    }
}
Después es necesario modificar la unidad de persistencia (persistence.xml), para indicarle que debe usar esta clase y para modificar el nombre con el que se debe recuperar el datasource. En nuestro caso, el datasource se creaba con el nombre "jdbc/TestDS" y este es el nombre con el que se referencia en los archivos "context.xml", "web.xml" y "persistence.xml".
Pero en "persistence.xml" esto no es válido (al menos cuando se configura para un Tomcat). En este archivo debemos referenciar el nombre del datasource como "java:comp/env/jdbc/TestDS", de lo contrario, las clases de TopLink no encontrarán la referencia al datasource. En definitiva el archivo "persistence.xml" original pintaba así:

oracle.toplink.essentials.PersistenceProvider
jdbc/TestDS
test.entities.Test
Y el archivo modificado cambia el nombre del datasource y referencia a la clase SessionCustomizer que hemos creado:

oracle.toplink.essentials.PersistenceProvider
java:comp/env/jdbc/TestDS
test.entities.Test
Ahora ya somos capaces de acceder al datasource de Tomcat usando la el api JPA.
Una cosa más: la solución la encontré aquí.
Saludos

domingo, septiembre 09, 2007

Configurar el pool de datos de Tomcat

En varias ocasiones he tenido problemas a la hora de configurar una aplicación para que utilizase el pool de conexiones de un servidor de aplicaciones (normalmente Tomcat). Por ello, voy a exponer los pasos que se deben dar para poder usar esta característica.

El primer paso es configurar adecuadamente el contexto. El contexto (siempre hablando de Tomcat) se puede configurar de varios modos. El primero (nada aconsejable) es editar el fichero sever.xml e insertar el elemento <context></context> dentro de <host>. No es el mejor método, ya que no siempre vamos a tener acceso a ese fichero... además de la necesidad de parar el servidor para que los cambios surtan efecto.

Yo uso otro método. Antes de crear el fichero war con la aplicación, creo un fichero llamado context.xml dentro de una carpeta META-INF. En este fichero pongo lo siguiente:

<context path="/nombreAplicacion">
<resource auth="Container"
driverclassname="com.mysql.jdbc.Driver"
maxactive="100"
maxidle="30"
maxwait="10000"
name="jdbc/NombreAplicacionDS"
password="password"
type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/aplicacionBBDD?autoReconnect=true"
username="user">
</resource>
</context>

Como puedes ver, declaro un nuevo recurso para la aplicación llamado "jdbc/NombreAplicacionDS". Este nombre es muy importante, ya que ahora lo usaré como referencia web.xml. Ahora en el fichero web.xml, añado un elemento nuevo (asegurate de cumplir con el orden dentro de los elementos) dentro del elemento web-app:

<resource-ref>
<res-ref-name>jdbc/NombreAplicacionDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

Una vez incluido este elemento, ya sólo queda usarlo desde el código:

Context contexto = new InitialContext();
DataSource ds = (DataSource)ctx.lookup(
"java:comp/env/jdbc/NombreAplicacionDS");
if (ds != null) {
Connection conexion = ds.getConnection();
}

Cuidado al crear la cadena para el lookup, si lo haces mediante variables (recomendable), la cadena debería ser "java:comp/env/" para que el ejemplo funcione.

Si ahora despliegas el war en un Tomcat (Ver. 5.5), verás como bajo la carpeta $HOME_TOMCAT$/conf/Catalina/localhost se habrá creado un fichero con extensión .xml y con el mismo nombre que nuestra aplicación. Si lo abres, verás el mismo contenido que introducimos en el fichero context.xml

Espero que os aproveche.

P.D.
Aseguraros que los drivers de la bb.dd. estén sólo en un único sitio. Este debe ser %TOMCAT_HOME%/common/lib. Si los tenéis en el lib del proyecto y en el lib del Tomcat (o cualquier otro sitio), fallará.