11 octubre, 2007

Connection Pooling

.
Las especificaciones de J2ee definen que los servers compatibles deben proveer una implementacion de DataSource (o "Pool de Conexiones") para que los programadores lo puedan utilizar dentro de sus aplicaciones.

En este capítulo explicaremos los motivos por los cuales es necesario utilizar un DataSource y como configurarlo en Tomcat y JBoss.


El Pool de Conexiones

Un Pool de Conexiones (jdbc) es un conjunto de conexiones pre-instanciadas que serán "prestadas" a los threads a medida que estos lo requieran para que la usen y luego la devuelvan al pool.

Es como si se tratase de videos en un videoclub. El videoclub puede tener 500 socios, pero no por eso tiene que tener disponibles 500 copias de cada película. Sería muy costoso y ridículo ya que es muy improbable que los 500 socios requieran las misma película en el mismo momento. Por lo tanto (quizá) con 5 o 6 copias de la película pueda alcanzar para satisfacer la demanda.

En el caso de las aplicaciones abiertas en Internet o con gran cantidad de usuarios potenciales el análisis es el mismo. Nuestro recurso es la conexión a la base de datos. Tendremos un conjunto de n conexiones para asignarlas (o prestarlas) a los hilos que lo requieran.

Los ejemplos que veremos son para conectarnos con HSQL pero aplican (cambiando el driver y el url) a cualquier base de datos.


Como Configurar un DataSource en Tomcat 5

1 - Copiar el driver jdbc (hsqldb.jar) en el directorio %CATALINA_HOME%\common\lib.

2 - Tenemos que declarar el recurso que vamos a requerir en la aplicacion web. Para esto debemos agregar las siguientes líneas en el archivo web.xml, justo antes del cierre del tag </web-app>.

web.xml (agregar estas líneas)
   1:
2: <resource-ref>
3: <res-ref-name>jdbc/HSqlDS</res-ref-name>
4: <res-type>javax.sql.DataSource</res-type>
5: <res-auth>Container</res-auth>
6: </resource-ref>
7:

3 - Crear el siguiente archivo entro del directorio /META-INF de la aplicación web.

context.xml
   1:
2:<Context>
3: <Resource name="jdbc/HSqlDS"
4: auth="Container"
5: type="javax.sql.DataSource"
6: username="sa"
7: password=""
8: url="jdbc:hsqldb:hsql://localhost/xdb"
9: driverClassName="org.hsqldb.jdbcDriver"
10: maxActive="8"
11: maxIdle="4" />
12:</Context>
13:

4 - Para acceder al pool de conexiones (DataSource) para pedirle una conexión debemos utilizar algunas líneas de código de la API JNDI.

En este ejemplo lo hacemos a través de una página JSP:

testDS.jsp
   1:
2:<%@ page import="java.sql.Connection" %>
3:<%@ page import="javax.naming.Context" %>
4:<%@ page import="javax.naming.InitialContext" %>
5:<%@ page import="javax.sql.DataSource" %>
6:
7:<%
8: // obtengo el contexto inicial
9: Context ctx=new InitialContext();
10:
11: // lookapeo el DataSource
12: DataSource ds=(DataSource)
13: ctx.lookup("java:comp/env/jdbc/HSqlDS");
14:
15: // Tengo el DataSource, le pido una conexion
16: Connection con=ds.getConnection();
17:
18: // la uso...
19: // en este caso muestro el toString() para ver si
20: // esta instanciada o si es null
21: out.println(con);
22:
23: // al cerrar la conexion en realidad la estoy
24: // devolviendo al pool
25: con.close();
26:%>
27:

Si estuviéramos trabajando con Struts, dentro de un Action, la conexión la tenemos que devolver en un finally para asegurarnos de que, pase lo que pase, la devolvemos.

TestDSAction.java
   1:
2:package test.action;
3:
4:import java.sql.Connection;
5:
6:import javax.naming.*;
7:import javax.servlet.http.*;
8:import javax.sql.DataSource;
9:import org.apache.struts.action.*;
10:
11:public class TestDSAction extends Action
12:{
13: public ActionForward execute(
14: ActionMapping mapping
15: , ActionForm form
16: , HttpServletRequest request
17: , HttpServletResponse response)
18: {
19: Connection con=null;
20: try
21: {
22: // hago el lookup del pool de conexiones
23: Context ctx=new InitialContext();
24: DataSource ds=(DataSource)ctx.lookup(
25: "java:comp/env/jdbc/HSqlDS");
26:
27: // pido una conexion
28: con=ds.getConnection();
29:
30: // la uso
31: System.out.println(con);
32:
33: // la devuelvo en el finally (OJO!)
34: return mapping.findForward("ok");
35: }
36: catch(Exception ex)
37: {
38: ex.printStackTrace();
39: throw new RuntimeException(ex);
40: }
41: finally
42: {
43: try
44: {
45: if( con!=null )
46: {
47: // devuelvo la conexion al pool
48: con.close();
49: }
50: }
51: catch(Exception ex)
52: {
53: ex.printStackTrace();
54: throw new RuntimeException(ex);
55: }
56: }
57: }
58:}
59:


Como Configurar un DataSource en JBoss 3

En JBoss el tema es mucho más simple.

1 - Creamos el siguiente archivo en el directorio %JBOSS_HOME%/server/default/deploy

test-ds.xml
   1:<?xml version="1.0" encoding="UTF-8"?>
2:
3:<datasources>
4: <local-tx-datasource>
5: <jndi-name>HSqlDS</jndi-name>
6: <connection-url>
7: jdbc:hsqldb:hsql://localhost/xdb
8: </connection-url>
9: <driver-class>
10: org.hsqldb.jdbcDriver
11: </driver-class>
12: <user-name>sa</user-name>
13: <password></password>
14: <min-pool-size>5</min-pool-size>
15: <max-pool-size>20</max-pool-size>
16: <idle-timeout-minutes>5</idle-timeout-minutes>
17: </local-tx-datasource>
18:</datasources>
19:

2 - Luego, en nuestro código el lookup de la conexión lo hacemos de la siguiente manera:
   1:
2:DataSource ds=(DataSource)
3: ctx.lookup("java:/HSqlDS");
4:











.

1 comentario:

Anónimo dijo...

cabe aclarar que el nombre del archivo xml para jboss debe terminar en "-ds" sino no lo tiene en cuenta ;)