Foros del Web » Programación para mayores de 30 ;) » Java »

Ayuda Urgente!!! PoolDeConexiones en SERVLETS

Estas en el tema de Ayuda Urgente!!! PoolDeConexiones en SERVLETS en el foro de Java en Foros del Web. Hola a todos!! Tengo un tema por ally de "potencia de mis java servlets" en el que se armaron unas buenas cuestiones. Lo cierto del ...
  #1 (permalink)  
Antiguo 10/11/2003, 13:44
Avatar de alexbariv  
Fecha de Ingreso: septiembre-2003
Ubicación: Mérida, Venezuela
Mensajes: 766
Antigüedad: 21 años, 3 meses
Puntos: 0
Ayuda Urgente!!! PoolDeConexiones en SERVLETS

Hola a todos!!

Tengo un tema por ally de "potencia de mis java servlets" en el que se armaron unas buenas cuestiones.

Lo cierto del caso es que apartir de ese tema fue que decidi hacer este para ver quien me ayuda;

Necesito crear un Servlet maestro que ADMINISTRE las conexiones a la BD.

Tengo un sistema de casi 200 servlets, y cada uno realiza una conexion unica, y necesito que en vez de que ellos hagan la conexion le preguten al pool, este les de la conexion y luego el servlet la devuelva al pool para que este la cierre.

Espero haberme explicado bien.

El metodo por el cual hago mi conexion a la bd es:

"ATENCION, DICE PHP, ES PORQUE ESTOY USANDO LA ETIQUETA DE PHP PARA QUE LE SALGAN LOS COLORES, PERO ESTO ES JAVA SERVLETS!!!"

Código PHP:
public  void init (ServletConfig configthrows ServletException {

    
super.init(config);
    try {
       Class.
forName("sun.jdbc.odbc.JdbcOdbcDriver");
                  
conn=DriverManager.getConnection("jdbc:odbc:BASEDATOS","USER","PASS");

    }catch (
ClassNotFoundException e) {
      throw new 
UnavailableException (this"Couldnt find class "+e.getMessage());
    }catch (
SQLException se) {
      
System.out.println("!!!SQL Exception caught: " se);
        }

    } 
Cada servlet tiene este sistema de conexion, que quiero ahora que lo contenga uno solo para que las administre.

Si no entienden bien la cuestion dense una vuelta por este mensj http://www.forosdelweb.com/showthrea...0&pagenumber=1

Me vendria bien algo de codigo, GRACIAS!!!!!
__________________
"Piensa como una persona de acción y actúa como una persona que piensa."
  #2 (permalink)  
Antiguo 10/11/2003, 16:45
Avatar de susaniux  
Fecha de Ingreso: diciembre-2002
Mensajes: 21
Antigüedad: 22 años, 1 mes
Puntos: 0
Yo tenia entendido que quien implementa el pool de conexiones ya es en si el "driver" , quien al fin de cuentas es el que debe de administrar los objetos de conexion.

?
__________________
:-P*****;-)
  #3 (permalink)  
Antiguo 10/11/2003, 17:59
Avatar de alexbariv  
Fecha de Ingreso: septiembre-2003
Ubicación: Mérida, Venezuela
Mensajes: 766
Antigüedad: 21 años, 3 meses
Puntos: 0
No entendi eso....

Dame un ejemplo de codigo o algo...

Explicate mejor

Gracias!!!
__________________
"Piensa como una persona de acción y actúa como una persona que piensa."
  #4 (permalink)  
Antiguo 10/11/2003, 21:31
 
Fecha de Ingreso: enero-2003
Mensajes: 52
Antigüedad: 22 años
Puntos: 0
Hola

Sobre Connection Pooling, generalmente esto lo tienes que implementar por tu propia cuenta. Aunque algunos app servers ya lo traen, en la mayoria de los sistemas se usa uno desarrollado in-house.


El connection pooling consiste en evitar abrir las conexiones directamente y en lugar de ello, utilizar un Layer donde tengas un componente que administre las utilizacion de las conexiones.

Esto puede ser implementado en una clase donde a traves de un metodo sincronizado, se pida una conexion, entonces el connection pool, revisa entre su vector de conexiones, alguna que no este en uso, entonces, la devuelve. Al terminar de usarla desde tu clase donde tengas la logica de acceso a datos, puedes invocar algun metodo release, que le indique al pool que esa ya no la vas a usar.


En fin, esta interesante, buscate algo del topico "Connection Pooling" veras que te salen muchas paginas con mas detalles.



Saludos!!
  #5 (permalink)  
Antiguo 11/11/2003, 11:55
 
Fecha de Ingreso: octubre-2003
Mensajes: 3.578
Antigüedad: 21 años, 2 meses
Puntos: 51
Hola,
Normalmente los contenedores de servlets ya suelen implementar este tipo de pools, asi que mirate la documentacion del que utilices a ver que te dice. Por ejemplo, si usas Tomcat 5 (es un suponer), la página a mirar es esta:
http://jakarta.apache.org/tomcat/tom...les-howto.html
Sobre todo la parte de ejemplos. Nosotros usamos el Resin y tiene algo parecido, etc...
PD: Repito lo de "cuidado con el ODBC-JDBC bridge" ;).
Saludos
__________________
Para obtener respuestas, pregunta de forma inteligente o si no, pregunta lo que quieras que yo contestaré lo que me dé la gana.
  #6 (permalink)  
Antiguo 12/11/2003, 08:45
Avatar de bakanzipp  
Fecha de Ingreso: noviembre-2001
Ubicación: santiago de shilli
Mensajes: 2.554
Antigüedad: 23 años, 1 mes
Puntos: 0
para manejar un pool de conexion yo trabajo de la siguiente manera (a ver si te sirve, en mi caso me conecto con sql server 7.0 y con tomcat)..

1ro
declaro en el turbineResource.properties el string de conexion

Código PHP:
## Database SQL Server
database.conector.driver=com.inet.tds.TdsDriver
database
.conector.url=jdbc:servidor:1433?database=mi_base
database
.conector.username=sa
database
.conector.password
2do
cree una clase que maneja el pool

Código PHP:

import org
.apache.turbine.services.resources.TurbineResources;
import org.apache.turbine.util.Log;

import java.sql.*;
import java.util.Vector;

public class 
SQLServerJDBC
{
    
String driver "";
    
String url "";
    
String login "";
    
String password "";
    
int codError 0;
    
String mensajeError "";

    
Connection connection null;

    public 
SQLServerJDBC()
    {
        try
        {
            
driver TurbineResources.getString("database.conector.driver""");
            
url TurbineResources.getString("database.conector.url""");
            
login TurbineResources.getString("database.conector.username""");
            
password TurbineResources.getString("database.conector.password""");

            Class.
forName(driver);

            
DriverManager.setLoginTimeout(30);
            
connection DriverManager.getConnection(urlloginpassword);
            
connection.setAutoCommit(false);
        }
        catch(
Exception e)
        {
            
Log.error(e);
            
codError 1;
            
mensajeError e.toString();
        }
    }

    public 
boolean doCommit()
    {
        
clearError();
        try
        {
            
connection.commit();
        }
        catch(
Exception e)
        {
            
Log.error(e);
            
codError 1;
            
mensajeError e.toString();
            return 
false;
        }
        return 
true;
    }

    public 
boolean doRollback()
    {
        
clearError();
        try
        {
            
connection.rollback();
        }
        catch(
Exception e)
        {
            
Log.error(e);
            
codError 1;
            
mensajeError e.toString();
            return 
false;
        }
        return 
true;
    }

    public 
Vector doSelect(String sql)
    {
        
Vector data = new Vector();
        
clearError();
        try
        {
            
Statement st connection.createStatement();
            
ResultSet rs st.executeQuery(sql);

            while (
rs.next())
            {
                
Vector rec = new Vector();
                for (
int i 1<= rs.getMetaData().getColumnCount(); i++)
                {
                    
rec.addElement(rs.getObject(i));
                }
                
data.addElement(rec);
            }
            
st.close();
        }
        catch(
Exception e)
        {
            
Log.error(e);
            
codError 1;
            
mensajeError e.toString();
            return new 
Vector();
        }
        return 
data;
    }

3ro instancio la conexion desde mis servlets

Código PHP:
import org.apache.velocity.context.Context;
import org.apache.turbine.util.Log;

import java.lang.Integer;
import java.lang.String;
import java.util.Date;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.text.SimpleDateFormat;
import com.package.modulo.util.SQLServerJDBC;


public class 
mi_clase
{
    
SQLServerJDBC jdbc null;


     public 
Vector Operacion(Hashtable tablaVector detalle)
    {
      try
      {
            
jdbc = new SQLServerJDBC();
            
String sql "";
            
Vector data_ null;

            
sql "select * from tabla";

            
sql "select * from tabla";
            
data_ jdbc.doSelect(sql);

            if (
data_ == null || data_.size() < 1)
            {
                
jdbc.doRollback();
                
jdbc.doClose();
                return 
false;
            }    }
      catch(
Exception e)
      {
            
Log.error(e);
      }
        return 
data_;
    }


saludos
  #7 (permalink)  
Antiguo 12/11/2003, 08:52
Avatar de alexbariv  
Fecha de Ingreso: septiembre-2003
Ubicación: Mérida, Venezuela
Mensajes: 766
Antigüedad: 21 años, 3 meses
Puntos: 0
MUCHISIMAS GRACIAS POR ESE CODIGO!! AHORA TENGO MAS POR DONDE GUIARME.

SOLO 2 PREGUNTICAS:

Podrias explicarme el funcionamiento de esta linea?

import org.apache.turbine.services.resources.TurbineResou rces;
import org.apache.turbine.util.Log;




DriverManager.setLoginTimeout(30);




import com.package.modulo.util.SQLServerJDBC




public boolean doCommit()
{
clearError();
try
{
connection.commit();
}
catch(Exception e)
{
Log.error(e);
codError = 1;
mensajeError = e.toString();
return false;
}
return true;
}







Vector rec = new Vector();
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++)
{
rec.addElement(rs.getObject(i));
}
data.addElement(rec);





Y, donde va el servlet controlador? en la misma carpeta de las aplicaciones???


DENUEVO, MUCHISIMAS GRACIAS!!!!!
__________________
"Piensa como una persona de acción y actúa como una persona que piensa."
  #8 (permalink)  
Antiguo 12/11/2003, 12:31
Avatar de bakanzipp  
Fecha de Ingreso: noviembre-2001
Ubicación: santiago de shilli
Mensajes: 2.554
Antigüedad: 23 años, 1 mes
Puntos: 0
Código PHP:
import org.apache.turbine.services.resources.TurbineResources;
import org.apache.turbine.util.Log

estas dos lineas la uso para poder usar los metodos instanciados en estas clases que me sirven para leer lo que hay dentro de mi archivo turbineResource.properties que en este caso es el string de conexion configurado en este archivo, el log lo utilizo para generar un archivo Turbine.log pero en este caso le quite el comentario de mis logs.

Código PHP:
DriverManager.setLoginTimeout(30); 
espera conectarse a la base de datos por 30 segundos, si no lo hace arrojara el correspondiente mensaje de error

Código PHP:
public boolean doCommit() 
despues de hacer cualquier trx con la base de datos (gralmente delete,insert,update) realizo un commit; para que el cambio se refleje en la base de datos.

Código PHP:
for (int i 1<= rs.getMetaData().getColumnCount(); i++)
{
rec.addElement(rs.getObject(i));

los datos que te devuelve la consulta son almacenados en un resultset, este lo recorro y se lo agrego a un vector.

saludos
  #9 (permalink)  
Antiguo 12/11/2003, 14:09
Avatar de alexbariv  
Fecha de Ingreso: septiembre-2003
Ubicación: Mérida, Venezuela
Mensajes: 766
Antigüedad: 21 años, 3 meses
Puntos: 0
Hola, gracias de nuevo.

Una ultima cosilla:

import org.apache.turbine.services.resources.TurbineResou rces;
import org.apache.turbine.util.Log;


Estas lineas me dan error.

Me faltara alguna cosa? tengo el jsdk 1.4.2, y lo trabajo con netBeans 3.5.1 y tomcat 5.0


Gracias!!!
__________________
"Piensa como una persona de acción y actúa como una persona que piensa."
  #10 (permalink)  
Antiguo 13/11/2003, 07:07
Avatar de bakanzipp  
Fecha de Ingreso: noviembre-2001
Ubicación: santiago de shilli
Mensajes: 2.554
Antigüedad: 23 años, 1 mes
Puntos: 0
eso es lo de menos, si no tienes el turbineResources puedes guardar el string de conexion en el web xml o en algun archivo de texto y leerlos desde tus servlets.

saludos
  #11 (permalink)  
Antiguo 13/11/2003, 07:30
Avatar de alexbariv  
Fecha de Ingreso: septiembre-2003
Ubicación: Mérida, Venezuela
Mensajes: 766
Antigüedad: 21 años, 3 meses
Puntos: 0
bakanzipp de verdad gracias!, agarre tu codigo y le hice algunas modificaciones y logre conectar a la base de datos pero tengo un ultimo problema (aparentemente)...

En esta linea logro la conexion sin problemas

jdbc = new SQLServerJDBC();
String sql = "";
Vector data_ = null;

sql = "select * from tabla";

sql = "select * from tabla";
data_ = jdbc.doSelect(sql);


Pero como hago para lograr el efecto que tenia antes???

Porque no se como hacer para usar los datos que regresa....

Antes tenia el resultSet en el mismo servlet, y de ally llenaba tablas, datos y varias cosas....

De esta manera :

Código PHP:
                                        stmt conn.createStatement();
                                        
String SQL "SELECT ";
                                        
SQL+=column1;
                                        
SQL+=",";
                                        
SQL+=column2;
                                        
SQL+=" FROM ";
                                        
SQL+=table;
                                        
SQL+=" WHERE CodX='";
                                        
SQL+=codpades;
                                        
SQL+="'";
                                        
SQL+=" ORDER By ";
                                        
SQL+=column2;
                                        
ResultSet rs stmt.executeQuery(SQL);

                                        if (
rs.next()){
                                                        
combo "";
                                                        do{
                                                                
codigo = (rs.getInt(column1));
                                                                
valor = (rs.getString(column2));

                                                                
combo += "<option> ";
                                                                
combo += valor;
                                                                
combo += "</option>\n";
                                                        }while(
rs.next());
                                            }
´ 

Ves que con el rs. me muevo por la tabla y demas.

Como implemento esto para conseguir esos datos??????
__________________
"Piensa como una persona de acción y actúa como una persona que piensa."
  #12 (permalink)  
Antiguo 13/11/2003, 08:04
Avatar de bakanzipp  
Fecha de Ingreso: noviembre-2001
Ubicación: santiago de shilli
Mensajes: 2.554
Antigüedad: 23 años, 1 mes
Puntos: 0
a verr...

primero que todo tendrias que cambiar la salida al metodo doSelect para que en vez de retornar un vector retorne un resulset

public Resultset doSelect(Hashtable tabla, Vector detalle)...esto nunca lo he hecho, retornar un resultset pero me imagino que se podra..o no?..jjejejej

Código PHP:
public ResultSet doSelect(String sql)

    {

        
clearError();

        try

        {

            
Statement st connection.createStatement();



            
ResultSet rs st.executeQuery(sql);

            
st.close();

        }

        catch(
Exception e)

        {

            
Log.error(e);

            
codError 1;

            
mensajeError e.toString();

            return new 
Vector();

        }

        return 
data;

    } 
y cuando llames al doSelect tendras el resultset y ahi podras manejarlo..

rs = jdbc.doSelect(sql);

donde rs es un resultset...si te das cuenta el metodo public Vector Operacion(Hashtable tabla, Vector detalle) igual devuelve un vector...ese tambien tendrias que modificarlo...o desde ese mismo metodo recorrer el resultset y enviar los datos hacia afuera....saludos.
  #13 (permalink)  
Antiguo 13/11/2003, 08:48
Avatar de alexbariv  
Fecha de Ingreso: septiembre-2003
Ubicación: Mérida, Venezuela
Mensajes: 766
Antigüedad: 21 años, 3 meses
Puntos: 0
Ok amigo bakan...

Este es el codigo de mi pool de conexiones, corrigeme si me equivoco, ya logre todo, pero quiero saber si de verdad esto abre y cierra la conexion a la bd para adiminstrarlas....

Código PHP:
package XAlX;


import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import java.util.Vector;

public final class 
poolBaseDatos
{

    
String driver "";
    
String url "";
    
String login "";
    
String password "";
    
int codError 0;
    
String mensajeError "";
    
Statement st=null;
    
    
Connection connection null;

    public 
poolBaseDatos() 
    {
        try
        {
            
            
driver = ("sun.jdbc.odbc.JdbcOdbcDriver"); 
            
url = ("jdbc:odbc:XDB"); 
            
login = ("xa"); 
            
password = ("skl");

            Class.
forName(driver);

            
DriverManager.setLoginTimeout(30);
            
connection DriverManager.getConnection(urlloginpassword);
            
connection.setAutoCommit(false);
            
System.out.println("Conectandose a la bd");
        }

        catch(
Exception e)

        {
      
//      Log.error(e);
            
System.out.println("Catch del conector a la bd");
            
mensajeError e.toString();
            
            
codError 1;

        }
    }

    public 
boolean doCommit()
    {
//        clearError();
        
try
        {
            
connection.commit();
            
st.close();
            
System.out.println("connection commit");
        }

        catch(
Exception e)
        {
  
//          Log.error(e);
            
System.out.println("Catch del docommit");
            
mensajeError e.toString();
            
            
codError 1;
            
            return 
false;
            
        }
        return 
true;
    }

    public 
boolean doRollback()
    {
    
//    clearError();
        
try
        {
            
st.close();
            
connection.rollback();
            
System.out.println("conecction roll back");
        }
        catch(
Exception e)
        {
   
//         Log.error(e);
            
System.out.println("Catch del dorollback");
            
System.out.println(e.getMessage());
            
codError 1;

            return 
false;
            
        }
        return 
true;
    }

    public 
ResultSet doSelect(String sql)
    {
        
ResultSet rs=null;
  
//      clearError();
        
try
        {
            
            
st connection.createStatement();
            
            
rs st.executeQuery(sql);
            
            
System.out.println("Creando la conexion");
            
        }
        catch(
Exception e)
        {
            
            
System.out.println("Catch del doselect en el pool...");
            
System.out.println(e.getMessage());
            
            
codError 1;
            
        }
         return 
rs;
    }


En el servlet utilizo esto para conseguir los datos


Código PHP:
conn = new poolBaseDatos();
                
        try{
                        
String SQL "SELECT ";
                        
SQL+=column
                        
SQL+=" FROM ";
                        
SQL+=table;
                        
SQL+=" ORDER By ";
                        
SQL+=column;
                        
                        
ResultSet rs;
                        
                
rs conn.doSelect(SQL);
                        
            if (
rs.next()){
                    
combo "";
                     do{
                                                
combo += "<option>";
                        
combo += (rs.getString(column));
                        
combo += "</option>";
                    }while(
rs.next());
            }else 
               return -
1;
                        
                        
                        
conn.doCommit();
            
conn.doRollback();
        
        }catch (
Exception e){
            
System.out.println("Se produjo un error creando la sentencia SQL");
                        
System.out.println(e.getMessage());
            return -
2;    
        }

            return 
0;    
        } 

TODO FUNCIONA, PERO QUIERO SABER SI ESTA CORRECTO!!

BYE!!!
__________________
"Piensa como una persona de acción y actúa como una persona que piensa."
  #14 (permalink)  
Antiguo 13/11/2003, 08:54
Avatar de bakanzipp  
Fecha de Ingreso: noviembre-2001
Ubicación: santiago de shilli
Mensajes: 2.554
Antigüedad: 23 años, 1 mes
Puntos: 0
compadre en el doSelect te falta cerrar la conexion despues que rescatas el resultset

........
st = connection.createStatement();
rs = st.executeQuery(sql);
System.out.println("Creando la conexion");
st.close();
.............

Saludos
  #15 (permalink)  
Antiguo 13/11/2003, 08:56
Avatar de alexbariv  
Fecha de Ingreso: septiembre-2003
Ubicación: Mérida, Venezuela
Mensajes: 766
Antigüedad: 21 años, 3 meses
Puntos: 0
Pero si le pongo el st.close()

como pongo el return rs?

me tira un error de que el rs esta cerrado
__________________
"Piensa como una persona de acción y actúa como una persona que piensa."
  #16 (permalink)  
Antiguo 13/11/2003, 09:24
Avatar de bakanzipp  
Fecha de Ingreso: noviembre-2001
Ubicación: santiago de shilli
Mensajes: 2.554
Antigüedad: 23 años, 1 mes
Puntos: 0
hhhmmm...tamaño problema, por eso trabajo con vectore asi me puedo cerrar la conexion sin problemas....

dos posibilidades

1. devuelve un vector y podras cerrar la conexion
2. trabajar el resultset en el metodo doSelect...pero eso implica trabajar con una capa menos y no es conveniente

si quieres trabajar con vectores no es nada del otro mundo.

sorry no se si alguien mas tendra otro aporte o solucion para este caso
  #17 (permalink)  
Antiguo 13/11/2003, 14:47
Avatar de alexbariv  
Fecha de Ingreso: septiembre-2003
Ubicación: Mérida, Venezuela
Mensajes: 766
Antigüedad: 21 años, 3 meses
Puntos: 0
Cheka esto, es lo ultimo que pienso hacerle al pool, ya que funciona perfectamente.

Antes con mi viejo sistema de conexiones luego de abrir 10 servlets tiraba un error de limite de conexiones excedido, ahora me meto en 15 y no dice nada...

Pero hay una ultima cosa que quiero clarificar:

Lo del resultset lo solucione de la manera que te mostre hace rato, y lo de cerrar la conexion, como te daras cuenta la variable st para el statment es global, y la puedo cerrar en cualquiera de los metodos, asi que la cerre en el docomit, y tambien lap use en el rollback para probar...

Todo funciona perfectamente hasta ahorita, pero el connection.close() es el que me tiene pensando

Puse en el rollback despues de hacer el st.close() un connection.close(), esto cerraria la conexion. Que dices esta de mas o de menos?, o esto me traera problemas a la larga, porque el rollo es que este sistema esta diseñado para que se conecten muchas personas al mismo tiempo.

GRACIAS!!!
__________________
"Piensa como una persona de acción y actúa como una persona que piensa."
  #18 (permalink)  
Antiguo 13/11/2003, 15:25
Avatar de bakanzipp  
Fecha de Ingreso: noviembre-2001
Ubicación: santiago de shilli
Mensajes: 2.554
Antigüedad: 23 años, 1 mes
Puntos: 0
a ver,

el proceso rollback se ejecuta ante cualquier salto por error, no cada vez que ejecutas un trx hacia la b de datos

el proceso commit deberia realizarse cada vez que cambian los registros de la b de datos o su estructura (update, insert, delete, drop, alter, etc)... para un select normal no es necesario hacer un commit; aunque si lo hiciera no te arrojara ningun error asi que igual te cerrara la conexion.

espero que te haya servido, yo gralmente trabajo con j2ee (EJB) + websphere el cual maneja el pool via JNDI ,asi que ahorro un poco el tema de las conexion por un lado.

Como te dijo un forista por ahi trata de conseguirte el webstress para forzar al maximo tus servlets y ver que tal el rendimiento de las conexiones de la b de datos.

suerte alex
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 02:42.