Excepciones pertenecientes al acceso a datos

Todos los beans CMP (persistencia gestionada por contenedor) de enterprise bean en la especificación EJB (Enterprise JavaBeans) 2.x reciben una excepción EJB estándar cuando falla alguna operación. Las aplicaciones JDBC (Java™ Database Connectivity) reciben una excepción SQL estándar si falla alguna operación JDBC. El producto proporciona excepciones especiales para el adaptador de recursos relacional (RRA), para indicar que la conexión que se está manteniendo actualmente ya no es válida.

Nota: La propiedad personalizada userDefinedErrorMap sobrescribe las entradas existentes en la correlación de errores iniciando el método DataStoreHelper.setUserDefinedMap. Puede utilizar la propiedad personalizada para añadir, cambiar o eliminar entradas de la correlación de errores.
  • Las entradas están delimitadas por un ; (punto y coma).
  • Cada entrada consta de una clave y un valor, donde la clave es un código de error (valor numérico) o SQLState, que es texto entrecomillado.
  • Las claves y los valores están separados por = (signo igual).
Por ejemplo, para eliminar la correlación de SQLState S1000, añadir una correlación del código de error 1062 para duplicar la clave y añadir una correlación de SQLState 08004 para la conexión obsoleta, puede especificar el siguiente valor para userDefinedErrorMap:
"S1000"=;1062=com.ibm.websphere.ce.cm.DuplicateKeyException;"08004"=
com.ibm.websphere.ce.cm.StaleConnectionException
userDefinedErrorMap se puede encontrar en la consola de administración seleccionando el origen de datos y configurando las propiedades personalizadas.

Conexiones caducadas

El producto proporciona una subclase especial de la clase java.sql.SQLException para utilizar la agrupación de conexiones para acceder a una base de datos relacional. Esta subclase com.ibm.websphere.ce.cm.StaleConnectionException existe en el origen de datos de WebSphere 4.0 y en la versión más reciente del origen de datos que utiliza el adaptador de recursos relacional. Esta clase se utiliza para indicar que la conexión que se mantiene actualmente ya no es válida.

Esta situación puede ocurrir por varias razones, incluidas las siguientes:
  • La aplicación intenta obtener una conexión y no lo consigue, del mismo modo que cuando la base de datos no está iniciada.
  • Una conexión ya no se puede utilizar más debido a una anomalía de la base de datos. Cuando una aplicación intenta utilizar una conexión obtenida anteriormente, la conexión ya no es válida. En este caso, es posible que todas las conexiones que la aplicación utiliza actualmente obtengan esta excepción.
  • La conexión se ha quedado huérfana (porque la aplicación no la ha utilizado como máximo durante un período de tiempo que duplica el intervalo de tiempo de espera de conexión no utilizada) y la aplicación intenta utilizar la conexión huérfana. Este caso sólo se aplica a los orígenes de datos de la versión 4.0.
  • La aplicación intenta utilizar un recurso JDBC, como una sentencia, que ha obtenido de una conexión en punto muerto.
  • La característica de limpieza automática de conexiones del origen de datos de la versión 4.0 ha cerrado la conexión y ya no se puede utilizar. La limpieza automática de conexiones es la modalidad estándar en la que funciona la gestión de conexiones. Esta modalidad indica que cuando finaliza la transacción, el gestor de transacciones cierra todas las conexiones incluidas en dicha transacción. Esto permite al gestor de transacciones asegurarse de que las conexiones no se retienen durante períodos excesivos de tiempo y que la agrupación no alcanza el número máximo de conexiones antes de tiempo.

    No obstante, aparece una ramificación negativa cuando el gestor de transacciones cierra las conexiones y devuelve la conexión a la agrupación libre una vez finalizada la transacción. Una aplicación no puede obtener una conexión en una transacción e intentar utilizarla en otra transacción. Si la aplicación lo intenta, se produce una ObjectClosedException, que a su vez es una StaleConnectionException, porque la conexión ya está cerrada.

Las configuraciones o los valores siguientes pueden ayudar a evitar encontrarse con StaleConnectionExceptions:
  • Si se establece el tamaño mínimo de agrupación de conexiones en 0, la agrupación de conexiones se mantiene vacía cuando el servidor de aplicaciones está inactivo durante periodos prolongados. Esto ayuda a evitar que las conexiones queden obsoletas debido a la actividad de mantenimiento en el lado de la base de datos.
  • Establezca la agrupación de conexiones Tiempo de espera no utilizado en un valor menor que el valor configurado para el tiempo de espera de cortafuegos. Esto asegura que la conexión no quede obsoleta hasta el Tiempo de espera no utilizado y permite que la conexión permanezca en la agrupación libre para volver a utilizarse.
  • Establezca la agrupación de conexiones Tiempo de recopilación en un valor menor que el tiempo de espera no utilizado. Cuanto menor es el valor, mayor es la frecuencia de la comprobación de hebra de mantenimiento de la agrupación y más preciso es el temporizador no utilizado. Sin embargo, las ejecuciones frecuentes de hebra de mantenimiento de la agrupación pueden degradar el rendimiento.

Si intenta utilizar una conexión huérfana o una conexión que no está disponible debido a la limpieza automática de conexiones, la excepción de conexión caducada indica que la aplicación ha intentado utilizar una conexión que ya se había devuelto a la agrupación de conexiones. Esto no significa que exista ningún problema con la conexión. No obstante, los otros casos de la excepción de conexión inactiva indican que la conexión con la base de datos ha fallado, o que está inactiva. Cuando la conexión está inactiva, no se puede recuperar, y se debe cerrar totalmente, en lugar de devolverse a la agrupación.

Detección de conexiones en punto muerto

Cuando una conexión con la base de datos pasa a estar inactiva, las operaciones en esa conexión generan una excepción SQL del controlador JDBC. Como una excepción SQL es una excepción bastante genérica, contiene valores de código de error y de estado que se pueden utilizar para determinar su significado. No obstante, el significado de estos estados y códigos de error varían según el proveedor de la base de datos. El tiempo de ejecución de la agrupación de conexiones mantiene una correlación de qué estado SQL y qué código de error indica una excepción de conexión inactiva para cada proveedor de base de datos soportado. Cuando el tiempo de ejecución de la agrupación de conexiones detecta una excepción SQL, comprueba si esta excepción SQL se considera una excepción de conexión inactiva para el servidor de la base de datos que se está utilizando.

Recuperación de conexiones en punto muerto
Una aplicación puede capturar una excepción de conexión caducada, en función del tipo de modelo de detección de anomalías que se configure en el origen de datos:
  • Cuando el modelo de detección de anomalías se configura para la correlación de excepciones, el servidor de aplicaciones sustituye la excepción emitida por el controlador HDBC por StaleConnectionException. En este caso, es posible que la aplicación atrape una excepción de conexión inactiva.
  • Cuando el modelo de detección de anomalías se configura para la comprobación de excepciones, el servidor de aplicaciones seguirá consultando la correlación de errores para gestionar la agrupación de conexiones, pero no sustituye la excepción. En este caso, la aplicación no debería atrapar una excepción de conexión inactiva.

Debido a las diferencias entre los modelos de detección de anomalías, el servidor de aplicaciones proporciona una API que las aplicaciones pueden utilizar con cualquiera de los casos para identificar conexiones inactivas. La API es com.ibm.websphere.rsadapter.WSCallHelper.getDataStoreHelper(datasource).isConnectionError(sqlexception).

No es necesario que las aplicaciones identifiquen explícitamente una excepción de conexión inactiva. Las aplicaciones ya deben capturar la excepción java.sql.SQLException, y la excepción de conexión inactiva o la excepción que emite el controlador JDBC siempre hereda datos de java.sql.SQLException. La excepción de conexión inactiva, que puede derivarse de cualquier método que se declare para emitir la excepción SQLException, se obtiene automáticamente en el bloque de obtención general. No obstante, la identificación explícita de una excepción de conexión inactiva hace posible que una aplicación pueda recuperarse de conexiones incorrectas. Cuando el código de la aplicación identifica una excepción de conexión inactiva, debería realizar pasos explícitos para la recuperación, como volver a intentar la operación bajo una transacción y conexión nuevas.

Ejemplo: manejo de la excepción de acceso a datos: conexión inactiva

Estos códigos de ejemplo muestran cómo se manejan de forma programada las excepciones relacionadas con las conexiones inactivas para los diferentes tipos de clientes de acceso a datos en los diferentes escenarios de transacciones.

Cuando una aplicación recibe una excepción de conexión inactiva en una operación de base de datos, significa que la conexión que se está manteniendo actualmente ya no es válida. Aunque es posible obtener una excepción para una conexión inactiva en cualquier operación de base de datos, el momento más típico para ver una excepción de conexión inactiva emitida es justo después de haberla recuperado. Puesto que las conexiones están agrupadas, no se detectan anomalías en la base de datos hasta la operación inmediatamente posterior a su recuperación de la agrupación, que es la primera vez que se intenta la comunicación con la base de datos. Sólo cuando se detecta una anomalía se indica que la conexión está en punto muerto. La excepción de conexión en punto muerto se da con menos frecuencia si cada método que accede a la base de datos obtiene una nueva conexión desde la agrupación.

Muchas excepciones de conexión inactiva vienen provocadas por problemas intermitentes con la red del servidor de la base de datos. Si se obtiene una nueva conexión y se reintenta la operación puede tener como resultado una finalización satisfactoria sin excepciones. En algunos casos, se recomienda añadir un pequeño tiempo de espera entre los reintentos, para darle al servidor de la base de datos más tiempo para recuperarse. No obstante, las aplicaciones no deben reintentar las operaciones indefinidamente, en el caso de que la base de datos esté desactivada un período prolongado de tiempo.
Avoid trouble Avoid trouble: Si está desarrollando aplicaciones para WebSphere Application Server con un entorno de desarrollo integrado (IDE) como Eclipse, es posible que tenga que importar el archivo raíz_serv_aplic/plugins/com.ibm.ws.runtime.jar en el entorno de desarrollo para utilizar el código proporcionado.gotcha

Antes de que la aplicación pueda obtener una nueva conexión para reintentar la operación, retrotraiga la transacción en la que estaba implicada la conexión original y empiece una nueva transacción. Puede desglosar los detalles de esta acción en las dos categorías siguientes:

Los objetos que operan en un contexto de transacción global gestionada por beans que empezó en el mismo método que el acceso a la base de datos.
Un servlet o un bean de sesión con BMT (transacciones gestionadas por beans) puede iniciar una transacción global de forma explícita llamando a begin() en un objeto javax.transaction.UserTransaction, que se puede recuperar a partir del nombre o a partir del objeto EJBContext del bean. Para comprometer una transacción gestionada por bean, la aplicación llama a commit() en el objeto UserTransaction. Para retrotraer la transacción, la aplicación llama a rollback(). Los beans de entidad y los beans de sesión que no son de BMT no pueden iniciar de forma explícita transacciones globales.

Si un objeto que inició de forma explícita una transacción gestionada por bean recibe una excepción de conexión en punto muerto en una operación de la base de datos, cierre conexión y retrotraiga la transacción. En este punto, el desarrollador de aplicaciones puede decidir empezar una nueva transacción, obtener una nueva conexión y reintentar la operación.

El siguiente fragmento de código muestra un ejemplo de cómo manejar las excepciones de conexión inactiva en este caso:
//get a userTransaction
javax.transaction.UserTransaction tran = getSessionContext().getUserTransaction();
//retry indica si se ha de reintentar o no
//numOfRetries indica el número de reintentos
// realizados
boolean retry = false;
int numOfRetries = 0;
java.sql.Connection conn = null;
java.sql.Statement stmt = null;
do {
  try {                                                               
    //iniciar una transacción
    tran.begin();
    //Presupone que ya se ha obtenido un origen de datos
    //desde JNDI
    conn = ds.getConnection();
    conn.setAutoCommit(false);
    stmt = conn.createStatement();
    stmt.execute("INSERT INTO EMPLOYEES VALUES
              (0101, 'Bill', 'R', 'Smith')");
    tran.commit();
    retry = false;
  } catch(java.sql.SQLException sqlX)
  {
    // Si el error indica que la conexión está inactiva,
    // restituir y reintentar la acción
    if (com.ibm.websphere.rsadapter.WSCallHelper
        .getDataStoreHelper(ds)
        .isConnectionError(sqlX))
    {
      try {                                                               
        tran.rollback();
      } catch (java.lang.Exception e) {
        //manejar la excepción
        //generalmente, se puede ignorar
      }
      if (numOfRetries < 2) {
        retry = true;
        numOfRetries++;
               } else {
        retry = false;
      }
    }
    else
    {
      //manejar con otra excepción de base de datos
      retry = false
    }
  } finally {
    //borrar siempre los recursos JDBC
    try {                                                               
      if (stmt != null) stmt.close();
    } catch (java.sql.SQLException sqle) {
      //generalmente se puede ignorar
    }
    try {                                                               
      if (conn != null) conn.close();
    } catch (java.sql.SQLException sqle) {
      //generalmente se puede ignorar
    }
  }
} while (retry) ;
Los objetos que operan en un contexto de transacción global que no empezó en el mismo método que el acceso a la base de datos.
Cuando el objeto que recibe la excepción de conexión en punto muerto no tiene control directo sobre la transacción, como en el caso de una transacción gestionada por contenedor, el objeto debe marcar la transacción para retrotraerla, e indicar al llamante que vuelva a intentar la transacción. En la mayoría de los casos, esto se puede hacer generando una excepción de aplicación para indicar que se vuelva a intentar la operación. Sin embargo, esta acción no siempre está permitida y a menudo se define un método para que genere solamente una excepción determinada. Este es el caso con los métodos ejbLoad() y ejbStore() en un enterprise bean. Los dos ejemplos siguientes describen cada uno de estos casos.
Ejemplo 1: El método de acceso a la base de datos crea una excepción de aplicación.
Cuando el método que accede a la base de datos puede generar libremente la excepción que necesita, el método recomendado es captar la excepción de conexión en punto muerto y volver a generar alguna excepción de la aplicación que se puede interpretar para reintentar el método. El ejemplo siguiente muestra un cliente EJB llamando a un método de un bean de entidad con una demarcación de transacción TX_REQUIRED, lo que significa que el contenedor inicia una transacción global cuando se llama a insertValue():
public class MyEJBClient
{
  //... aquí otros métodos ...

  public void myEJBClientMethod()
  {
    MyEJB myEJB = myEJBHome.findByPrimaryKey("myEJB");
    boolean retry = false;
    do
    {
      try
      {
        retry = false;
        myEJB.insertValue();
      }
      catch(RetryableConnectionException retryable)
      {
        retry = true;
      }
      catch(Exception e) { /* handle some other problem */ }
    }
    while (retry);
  }  
}  //finalizar MyEJBClient

public class MyEJB implements javax.ejb.EntityBean
{
  //... aquí otros métodos ...
  public void insertValue() throws RetryableConnectionException,
         java.rmi.EJBException
  {
    try
    {
      conn = ds.getConnection();
      stmt = conn.createStatement();
      stmt.execute("INSERT INTO my_table VALUES (1)");
    }
    catch(java.sql.SQLException sqlX)
    {
      // Determinar si el error indica que la conexión está inactiva
      if (com.ibm.websphere.rsadapter.WSCallHelper
          .getDataStoreHelper(ds)
          .isConnectionError(sqlX))
      {
        getSessionContext().setRollbackOnly();
        throw new RetryableConnectionException();
      }
      else
      {
        //manejar otros problemas de base de datos
      }
    }
    finally
    {
      //borrar siempre los recursos JDBC
      try
      {
        if (stmt != null) stmt.close();
      }
      catch (java.sql.SQLException sqle)
      {
        //generalmente se puede ignorar
      }
      try
      {
        if (conn != null) conn.close();
      }
      catch (java.sql.SQLException sqle)
      {
        //generalmente se puede ignorar
      }
    }
  }
}  //finalizar MyEJB

En primer lugar, MyEJBClient obtiene un bean MyEJB de la interfaz de factoría, que se presupone que se ha recuperado previamente desde JNDI (Java Naming and Directory Interface). A continuación, llama a insertValue() en el bean. En el bean, el método obtiene una conexión e intenta insertar un valor en una tabla. Si uno de los métodos no se ejecuta correctamente con una excepción de conexión en punto muerto, marca la transacción para rollbackOnly (lo que obliga al llamante a restituir esta transacción) y genera una excepción de conexión reintentable nueva, lo que borra los recursos antes de que se genere la excepción. La conexión reintentable es simplemente una excepción definida por la aplicación que indica al llamante que vuelva a intentar el método. El llamante supervisa la excepción de conexión reintentable y, si se capta, reintenta el método. En este ejemplo, dado que el contenedor inicia y finaliza la transacción; no es necesaria ninguna gestión de transacciones en el cliente ni en el servidor. Por supuesto, el cliente podría iniciar una transacción gestionada por beans y el comportamiento seguiría siendo el mismo, siempre que el cliente haya comprometido o restituido también la transacción.

Ejemplo 2: El método de acceso a la base de datos crea una excepción de sólo remota o una excepción de EJB.
No todos los métodos pueden generar excepciones definidas por la aplicación. Si utiliza BMP (persistencia generada por beans), utilice los métodos ejbLoad() y ejbStore() para almacenar el estado del bean. Las únicas excepciones emitidas a partir de estos métodos son java.rmi.Remote o javax.ejb.EJB, por lo que no puede utilizar nada que se parezca al ejemplo anterior.
Si utiliza CMP (persistencia gestionada por contenedor), el contenedor maneja el bean de persistencia y es el contenedor el que ve la excepción de conexión inactiva. Si se detecta una conexión inactiva cuando se devuelve la excepción al cliente, simplemente se trata de una excepción remota, por lo tanto, un simple bloque de obtención no será suficiente. Hay un modo de determinar si la causa raíz de una excepción remota es una excepción de conexión inactiva. Cuando se genera una excepción remota para envolver otra excepción, normalmente se retiene la excepción original. Todas las instancias de excepción remota tienen una propiedad detallada cuyo tipo es java.lang.Throwable. Con este detalle, se puede localizar la excepción original y, si se trata de una excepción de conexión inactiva, se puede volver a intentar la transacción. En realidad, cuando una de estas excepciones remotas fluye de una API de Máquina virtual Java a la siguiente se pierden los detalles, por lo tanto, es mejor iniciar la transacción en el mismo servidor en que se produce el acceso a los datos. Por este motivo, el ejemplo siguiente muestra un bean de entidad al que accede un bean de sesión con una demarcación de transacción gestionada por bean.
public class MySessionBean extends javax.ejb.SessionBean
{
  ... aquí otros métodos ...
  public void mySessionBMTMethod() throws
    java.rmi.EJBException
  {
    javax.transaction.UserTransaction tran =
    getSessionContext().getUserTransaction();
    boolean retry = false;
    do
    {
      try
      {
        retry = false;
        tran.begin();
        // hace que se invoque ejbLoad()
        myBMPBean.myMethod();
        // hace que se invoque ejbStore()
        tran.commit();
      }
      catch(java.rmi.EJBException re)
      {
        try
        {
          tran.rollback();
        }
        catch (Exception e)
        {
          //can ignore
        }
        if (causedByStaleConnection(re))
          retry = true;
        else
          throw re;
      }
      catch (Exception e)
      {
        // manejar otro problema
      }
      finally
      {
        //borrar siempre los recursos JDBC
        try
        {
          if (stmt != null) stmt.close();
        }
        catch (java.sql.SQLException sqle)
        {
          //generalmente se puede ignorar
        }
        try
        {
          if (conn != null) conn.close();
        }
        catch (java.sql.SQLException sqle)
        {
          //generalmente se puede ignorar
        }
      }
    }
    while (retry);
  }

  public boolean causedByStaleConnection(java.rmi.EJBException re)
  {
    // Buscar errores en cadena de excepciones
    // que indiquen una conexión inactiva
    for (Throwable t = re; t != null; t = t.getCause())
      if (t instanceof RetryableConnectionException)
        return true;

    // No se ha determinado como inactiva
    return false;
  }
}

public class MyEntityBean extends javax.ejb.EntityBean
{
  ... aquí otros métodos ...
  public void ejbStore() throws java.rmi.EJBException
  {
    try
    {
      conn = ds.getConnection();
      stmt = conn.createStatement();
      stmt.execute("UPDATE my_table SET value=1 WHERE
      primaryKey=" + myPrimaryKey);
    }
    catch(java.sql.SQLException sqlX)
    {
      // Determinar si el error indica que la conexión está inactiva
      if (com.ibm.websphere.rsadapter.WSCallHelper
          .getDataStoreHelper(ds)
          .isConnectionError(sqlX))
      {
        // restituir la transacción cuando regrese el método
        getEntityContext().setRollbackOnly();
        throw new java.rmi.EJBException(
          "Exception occurred in ejbStore",
          new RetryableConnectionException(sqlX));
      }
      else
      {
        // manejar otro problema
      }
    }
    finally
    {
      //borrar siempre los recursos JDBC
      try
      {
        if (stmt != null) stmt.close();
      }
      catch (java.sql.SQLException sqle)
      {
        //generalmente se puede ignorar
      }
      try
      {
        if (conn != null) conn.close();
      }
      catch (java.sql.SQLException sqle)
      {
        //generalmente se puede ignorar
      }
    }
  }
}
En mySessionBMTMethod() del ejemplo anterior:
  • El bean de sesión recupera en primera lugar un objeto UserTransaction del contexto de sesión y luego inicia una transacción global.
  • A continuación, llama a un método en el bean de entidad, el cual llama al método ejbLoad(). Si ejbLoad() se ejecuta correctamente, el cliente compromete la transacción, lo que hace que se llame al método ejbStore().
  • En ejbStore(), el bean de entidad obtiene una conexión y graba su estado en la base de datos; si la conexión recuperada está caducada, se marca como rollbackOnly y se genera una EJBException nueva que envuelve la RetryableConnectionException. A continuación, el cliente capta esta excepción, borra los recursos JDBC, restituye la transacción y llama a causedByStaleConnection(), que determina si en algún lugar de la excepción se encuentra la excepción de conexión en punto muerto.
  • Si el método devuelve el valor true, se establece el distintivo retry y se reintenta la transacción. De lo contrario, se vuelve a emitir la excepción para el llamante.
  • El método causedByStaleConnection() busca por la cadena de atributos detallados para buscar la excepción original. En el momento en que la excepción se devuelve finalmente al cliente, es posible que contenga varias excepciones envueltas, por lo tanto, el método continúa buscando hasta que encuentra una excepción de conexión inactiva y se devuelve true; de lo contrario, no habrá ninguna excepción de conexión inactiva en la lista y se devolverá false.
  • Si habla con un bean CMP en lugar de un bean BMP, el bean de sesión es el mismo. El método ejbStore() del bean CMP estará muy probablemente vacío y después de llamar al contenedor éste permanecerá en el bean con el código generado.
  • Si durante la persistencia se produce una excepción de conexión en punto muerto, se envolverá con una excepción remota y se devolverá al llamante. Una vez más, el método causedByStaleConnection() buscará en la cadena de excepciones hasta encontrar la excepción raíz que será de conexión en punto muerto.
Los objetos que operan en un contexto de transacción local
Cuando se ejecuta una operación de base de datos fuera del contexto de transacción global, el contenedor empieza implícitamente una transacción local. Esto incluye servlets o JSP que no empiezan transacciones con la interfaz UserTransaction, así como enterprise beans que se ejecutan en contextos de transacción sin especificar. Al igual que con las transacciones globales, debe retrotraer la transacción local antes de volver a intentar la operación. En estos casos, el contenedor de transacción local finaliza normalmente cuando finaliza el método de empresa. La única excepción es si está utilizando sesiones de actividad. En este caso, la sesión de actividad deberá finalizar antes de intentar obtener una nueva conexión.

Cuando la transacción local se produce en un enterprise bean que se ejecuta en un contexto de transacción sin especificar, el objeto de cliente de enterprise bean, fuera del contenedor de transacción local, podría utilizar el método descrito en el párrafo anterior para volver a intentar la transacción. Sin embargo, cuando el contenedor de transacción local forma parte de un servlet o un archivo JSP, no hay ningún objeto de cliente disponible para volver a intentar la operación. Debido a esta razón, se recomienda evitar las operaciones de bases de datos en servlets y archivos JSP, a menos que formen parte de una transacción de usuario.

Conexión en punto muerto en sistemas Linux

Es posible que tenga que establecer un bucle de retorno para acceder a bases de datos DB2 desde el servidor de aplicaciones en una plataforma Linux.

Un semáforo Linux puede interferir con el acceso JDBC a la base de datos DB2 en cualquiera de estas configuraciones:
  • Utilización del controlador JDBC de DB2 Universal Tipo 2 para la conexión con una base de datos DB2 local
  • Utilización del controlador JDBC de DB2 Universal de tipo 2 para acceder a DB2 para z/OS mediante una instalación de DB2 Connect en la misma máquina que el servidor de aplicaciones. El problema se produce sólo si DB2 Connect impide que los clientes locales se ejecuten desde un agente. Esto es, si el valor de DB2_IN_APP_PROCESS no es el valor por omisión o si el valor es Yes. Establezca el valor en No solucionar el problema y evite realizar el procedimiento siguiente.
El problema suele hacer que los registros de la JVM muestren la excepción de conexiones en punto muerto de DB2 SQL1224. Dado que el código de excepción SQL puede variar debe comprobar, no obstante, el registro de DB2 cuando encuentre una conexión caducada. Si observa el siguiente dato de error, el problema es debido al comportamiento del semáforo de Linux:
'71' -SQLCC_ERR_CONN_CLOSED_BY_PARTNER y SQLCODE -XXXX
Para solucionar el problema, establezca el bucle de retorno de la base de datos. Por ejemplo, si el nombre de la base de datos es WAS, el nombre del host ess LHOST y el número de puerto del servicio de base de datos es 50000, emita los siguientes mandatos en la ventana de la línea de mandatos de DB2:
db2 catalog TCPIP node RHOST remote LHOST server 50000
db2 uncatalog db WAS
db2 catalog db WAS as WASAlias at node loop authentication server
//Si se conecta a WASAlias, es una conexión mediante bucle de retorno;
//Si se conecta a WAS, es una conexión "normal". 
db2 catalog db WASAlias as WAS at node RHOST

Ejemplo: manejo de las excepciones de conexiones JDBC del servlet

En el siguiente código de ejemplo se muestra cómo se establecen las propiedades de gestión de transacciones y de gestión de conexiones como, por ejemplo, los reintentos de operaciones, para tratar las excepciones de conexiones inactivas dentro de una transacción JDBC del servlet.

Este código de ejemplo realiza las acciones siguientes:
  • inicializa un servlet
  • busca un origen de datos
  • especifica los mensajes de error, los reintentos de conexiones y los requisitos de retrotracción de transacciones
//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*; 
// Importar paquetes JDBC y paquetes de servicio de denominación.
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import javax.transaction.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;

public class EmployeeListTran extends HttpServlet {
    private static DataSource ds   = null;   
    private UserTransaction ut = null;
    private static String title    = "Employee List";    

// ****************************************************************
// * Inicializar el servlet al cargarlo por primera vez.                  *
// * Obtener información del archivo de propiedades y buscar el   *
// * objeto DataSource de JNDI para mejorar el rendimiento de los *
// * métodos de servicio del servlet.                               *
// ****************************************************************
    public void init(ServletConfig config)
    throws ServletException
    {
        super.init(config);
        getDS();
    }

// ****************************************************************
// * Realizar la búsqueda JNDI del objeto DataSource.             *
// * Objetos de transacciones de usuario.                                    *
// * Este método se invoca desde init() y desde el método de      *
// * de DataSource resulta nulo.                                  *
// ****************************************************************
    private void getDS() {
        try {                                                               
            Hashtable parms = new Hashtable();
            parms.put(Context.INITIAL_CONTEXT_FACTORY, 
 com.ibm.websphere.naming.WsnInitialContextFactory);
            InitialContext ctx = new InitialContext(parms);
            // Realizar búsqueda de servicio de denominación para obtener objeto DataSource.
            ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
            ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
        } catch (Exception e) {
            System.out.println("Naming service exception: " + e.getMessage());
            e.printStackTrace();                                            
        }
    }

// ****************************************************************
// * Responder a solicitudes GET de usuario                        *
// ****************************************************************
    public void doGet(HttpServletRequest req, HttpServletResponse res) throws        ServletException, IOException
    {
        Connection conn  = null;
        Statement stmt = null;
        ResultSet rs = null;
        Vector employeeList = new Vector();
        // Establecer retryCount en el número de reintentos que desea después de
        // stale connection exception
        int retryCount = 5;      
        // Si el código de base de datos se procesa bien, se establecerá error = false
        boolean error = true;
        do
        {
            try
            {          
                //Iniciar una transacción nueva
                ut.begin();
                // Obtener un objeto de conexión conn mediante la fábrica DataSource.
                conn = ds.getConnection();
                // Ejecutar consulta DB mediante codificación JDBC estándar.
                stmt = conn.createStatement();
                String query   = "Select FirstNme, MidInit, LastName " + 
                                     "from Employee ORDER BY LastName";
                rs   = stmt.executeQuery(query);
                while (rs.next())
                {
                    employeeList.addElement(rs.getString(3) + ", "+ rs.getString(1)" +     " + rs.getString(2));
                }                           
                //Definir error = false para indicar que la base de datos ha finalizado bien su trabajo
                error=false;                    
            }
            catch (SQLException sqlX)
            {
              // Determinar si se ha excedido el tiempo de espera de la solicitud de conexión.
              // Este código funciona independientemente del modelo de detección de errores
              // que se utilice. Si se habilita la correlación de excepciones,
              // tendrá que buscar ConnectionWaitTimeoutException.
              // Si se ha habilitado la comprobación de excepciones, busque
              // SQLTransientConnectionException con una
              // ConnectionWaitTimeoutException encadenada.

              if ( sqlX instanceof ConnectionWaitTimeoutException
                || sqlX instanceof SQLTransientConnectionException
                   && sqlX.getCause() instanceof ConnectionWaitTimeoutException)
              {
                // Esta excepción se genera si no se puede obtener una conexión de la
                // agrupación en un período de tiempo configurable.  Si aparece mucho
                // esta excepción la agrupación de conexiones se ha ajustado mal

                System.out.println("Connection Wait Timeout Exception during get connection or 
process SQL: " + c.getMessage());  
     
                //En general, no se desean reintentos después de esta excepción, así que establezca el número de reintentos en 0
                //y restituya la transacción
                try
                {
                    ut.setRollbackOnly();
                } 
                catch (SecurityException se)
                {
                    //Se genera para indicar que la hebra no puede restituir la transacción.
                    System.out.println("Security Exception setting rollback only!" + se.getMessage());
                } 
                catch (IllegalStateException ise)
                {
                    //Se genera si la hebra actual no está asociada a una transacción.
                    System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
                } 
                catch (SystemException sye)
                {
                    //Se genera si el gestor de transacciones encuentra una condición de error imprevista
                    System.out.println("System Exception setting rollback only!" + sye.getMessage());
                }
                retryCount=0;   
              }
              else if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
              {
                // Esta excepción indica que la conexión con la base de datos ya no es válida.
                //Restituya la transacción, reintente varias veces obtener una conexión válida  
                //, visualice un mensaje de error si la conexión sigue sin obtenerse.

                System.out.println("Connection is stale: " + sc.getMessage());
                
                try
                {
                    ut.setRollbackOnly();
                } 
                catch (SecurityException se)
                {
                    //Se genera para indicar que la hebra no puede restituir la transacción.
                    System.out.println("Security Exception setting rollback only!" + se.getMessage());
                } 
                catch (IllegalStateException ise)
                {
                    //Se genera si la hebra actual no está asociada a una transacción.
                    System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
                } 
                catch (SystemException sye)
                {
                    //Se genera si el gestor de transacciones encuentra una condición de error imprevista
                    System.out.println("System Exception setting rollback only!" + sye.getMessage());
                }
                if (--retryCount == 0)
                {
                    System.out.println("Five stale connection exceptions, displaying error page.");
                }
              } 
              else
              {
                System.out.println("SQL Exception during get connection or process SQL: "                                  + sq.getMessage());

                //En general, no se desean reintentos después de esta excepción, así que establezca el número de reintentos en 0
                //y restituya la transacción
                try
                {
                    ut.setRollbackOnly();
                } 
                catch (SecurityException se)
                {
                    //Se genera para indicar que la hebra no puede restituir la transacción.
                    System.out.println("Security Exception setting rollback only!" + se.getMessage());
                } 
                catch (IllegalStateException ise)
                {
                    //Se genera si la hebra actual no está asociada a una transacción.
                    System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
                } 
                catch (SystemException sye)
                {
                    //Se genera si el gestor de transacciones encuentra una condición de error imprevista
                    System.out.println("System Exception setting rollback only!" + sye.getMessage());
                }
                retryCount=0;
              } 
            }
            catch (NotSupportedException nse)
            {
                //La genera el método UerTransaction begin si la hebra ya está asociada con una
                //transacción y la implementación del gestor de transacciones no soporta transacciones  
                //anidadas.
                System.out.println("NotSupportedException on User Transaction begin: "                                     + nse.getMessage());
            } 
            catch (SystemException se)
            {
                //Se genera si el gestor de transacciones encuentra una condición de error imprevista
                System.out.println("SystemException in User Transaction: " +se.getMessage());
            } 
            catch (Exception e)
            {
                System.out.println("Exception in get connection or process SQL: " + e.getMessage());
                //En general, no se desean reintentos después de esta excepción, así que establezca el número de reintentos en 5
                //y restituya la transacción
                try
                {
                    ut.setRollbackOnly();
                } 
                catch (SecurityException se)
                {
                    //Se genera para indicar que la hebra no puede restituir la transacción.
                    System.out.println("Security Exception setting rollback only!" + se.getMessage());
                } 
                catch (IllegalStateException ise)
                {
                    //Se genera si la hebra actual no está asociada a una transacción.
                    System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
                } 
                catch (SystemException sye)
                {
                    //Se genera si el gestor de transacciones encuentra una condición de error imprevista
                    System.out.println("System Exception setting rollback only!" + sye.getMessage());
                }
                retryCount=0;
            } 
            finally
            {
                // Cerrar siempre la conexión en una sentencia final para que en todos los
                // casos el cierre sea correcto. Al cerrar la conexión no se cierra la conexión 
                // real, sino que se libera para que pueda reutilizarse en la agrupación.

                if (rs != null)
                {
                   try
                   {
                      rs.close();
                   } 
                   catch (Exception e)
                   {
                      System.out.println("Close Resultset Exception: " + e.getMessage());
                   }
                }
                if (stmt != null)
                {
                   try
                   {
                      stmt.close();
                   } 
                   catch (Exception e)
                   {
                      System.out.println("Close Statement Exception: " + e.getMessage());
                   }
                }
                if (conn != null)
                {
                   try
                   {
                      conn.close();
                   } 
                   catch (Exception e)
                   {
                      System.out.println("Close connection exception: " + e.getMessage());
                   }
                }
                try
                {
                    ut.commit();
                } 
                catch (RollbackException re)
                {
                    //Se genera para indicar que la transacción se ha restituido en lugar de comprometerse.
                    System.out.println("User Transaction Rolled back!" + re.getMessage());
                } 
                catch (SecurityException se)
                {
                    //Se genera para indicar que la hebra no puede comprometer la transacción.
                    System.out.println("Security Exception thrown on transaction commit: "                                     + se.getMessage());
                } 
                catch (IllegalStateException ise)
                {
                    //Se genera si la hebra actual no está asociada a una transacción.
                    System.out.println("Illegal State Exception thrown on transaction commit: " + ise.getMessage());
                } 
                catch (SystemException sye)
                {
                    //Se genera si el gestor de transacciones encuentra una condición de error imprevista
                    System.out.println("System Exception thrown on transaction commit: "                                       + sye.getMessage());
                } 
                catch (Exception e)
                {
                    System.out.println("Exception thrown on transaction commit: " +                                            e.getMessage());
                }
            }
        }
        while ( error==true && retryCount > 0 );

        // Preparar y devolver respuesta HTML, impedir el almacenamiento del contenido
        // dinámico en la memoria caché de los navegadores.
        res.setContentType("text/html");
        res.setHeader("Pragma", "no-cache");
        res.setHeader("Cache-Control", "no-cache");
        res.setDateHeader("Expires", 0);
        try
        {
            ServletOutputStream out = res.getOutputStream();
            out.println("<HTML>");
            out.println("<HEAD><TITLE>" + title + "</TITLE></HEAD>");
            out.println("<BODY>");                  
            if (error==true)
            {
                out.println("<H1>Se ha producido un error al procesar esta petición.</H1>" +
                  "Vuelva a intentar la solicitud o póngase en contacto con " +
                   " el administrador del sistema <a href='mailto:sysadmin@my.com'></a>");
            } 
            else if (employeeList.isEmpty())
            {
               out.println("<H1>Employee List is Empty</H1>");
            } 
            else
            {
               out.println("<H1>Employee List </H1>");
               for (int i = 0; i < employeeList.size(); i++)
               {
                  out.println(employeeList.elementAt(i) + "<BR>"); 
               }
            }
            out.println("</BODY></HTML>");
            out.close();
        } 
        catch (IOException e)
        {
           System.out.println("HTML response exception: " + e.getMessage());
        }
    }
}

Ejemplo: manejo de excepciones de conexión para beans de sesión en transacciones de base de datos gestionadas por contenedor

El siguiente código de ejemplo muestra cómo se restituyen las transacciones y se emiten excepciones al cliente de bean en casos de excepciones de conexiones inactivas.

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

import java.util.*; 
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;

/*************************************************************************************
* Este bean se ha diseñado para mostrar las conexiones de base de datos                *                      
* de un bean de sesión de transacciones gestionadas por contenedor.  Su atributo        *
* de transacción debe establecerse en TX_REQUIRED o TX_REQUIRES_NEW.                                     *
**************************************************************************************
*/
public class ShowEmployeesCMTBean implements SessionBean {
		 private javax.ejb.SessionContext mySessionCtx = null;
		 final static long serialVersionUID = 3206093459760846163L;
		 
		 private javax.sql.DataSource ds;

//************************************************************************************
//* ejbActivate llama al método getDS que ejecuta la búsqueda JNDI de DataSource.
//* Dado que la búsqueda de DataSource se ejecuta en un método distinto, se puede 
//* invocar desde getEmployees cuando el campo DataSource sea nulo.		 		 
//************************************************************************************
public void ejbActivate() throws java.rmi.EJBException {
		 getDS();
}
/**
 * ejbCreate method
 * @exception javax.ejb.CreateException
 * @exception java.rmi.EJBException
 */
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.EJBException {}
/**
 * ejbPassivate method 
 * @exception java.rmi.EJBException
 */
public void ejbPassivate() throws java.rmi.EJBException {}
/**
 * ejbRemove method 
 * @exception java.rmi.EJBException 
 */
public void ejbRemove() throws java.rmi.EJBException {}

//************************************************************************************
//* getEmployees devuelve la consulta de base de datos para recuperar empleados
//* solo se llama a getDS si la variable DataSource es nula.	
//* Como este bean de sesión utiliza transacciones gestionadas por contenedor, no puede
//* reintentar la transacción en una StaleConnectionException.  Pero sí puede generar
//* una excepción a su cliente indicando que se puede reintentar la operación.
//************************************************************************************

public Vector getEmployees() throws ConnectionWaitTimeoutException, SQLException,
       RetryableConnectionException
{
   Connection conn  = null;
   Statement stmt = null;
   ResultSet rs = null;
   Vector employeeList = new Vector();

   if (ds == null) getDS();
   		 
   try
   {
      // Obtener un objeto de conexión conn mediante la fábrica DataSource.
      conn = ds.getConnection();
      // Ejecutar consulta DB mediante codificación JDBC estándar.
      stmt = conn.createStatement();
      String query   = "Select FirstNme, MidInit, LastName " + 
                       "from Employee ORDER BY LastName;"
      rs   = stmt.executeQuery(query);
      while (rs.next())
      {
         employeeList.addElement(rs.getString(3) + ", "+ rs.getString(1)" + " + rs.getString(2));
      }                           
   } 
   catch (SQLException sqlX)
   {
     // Determinar si la conexión está inactiva
     if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
     {
       // Esta excepción indica que la conexión con la base de datos ya no es válida.
       // Restituya la transacción y genere una excepción para el cliente indicando que
       // puede volver a intentar la transacción si lo desea.

       System.out.println("Connection is stale: " + sqlX.getMessage());
       System.out.println("Rolling back transaction and throwing  RetryableConnectionException");

       mySessionCtx.setRollbackOnly();
       throw new RetryableConnectionException(sqlX.toString());
     }
     // Determinar si se ha excedido el tiempo de espera de la solicitud de conexión.
     else if ( sqlX instanceof ConnectionWaitTimeoutException
            || sqlX instanceof SQLTransientConnectionException
               && sqlX.getCause() instanceof ConnectionWaitTimeoutException)
     {
       // Esta excepción se genera si no se puede obtener una conexión de la
       // agrupación en un período de tiempo configurable.  Si aparece mucho
       // esta excepción la agrupación de conexiones se ha ajustado mal

       System.out.println("Connection Wait Timeout Exception during get connection or process SQL: " +
       sqlX.getMessage());
       throw sqlX instanceof ConnectionWaitTimeoutException ?
             sqlX :
             (ConnectionWaitTimeoutException) sqlX.getCause();
     } 
     else
     {
       //Generar una excepción remota restituirá automáticamente la transacción 
       //gestionada por contenedor

       System.out.println("SQL Exception during get connection or process SQL: " +
		 		 		 		 sqlX.getMessage());
       throw sqlX;
     } 
   }
   finally
   {
     // Cerrar siempre la conexión en una sentencia final para que en todos los 
     // casos el cierre sea correcto. Al cerrar la conexión no se cierra la conexión 
     // real, sino que se libera para que pueda reutilizarse en la agrupación.

     if (rs != null)
     {
       try
       {
         rs.close();
       } 
       catch (Exception e)
       {
         System.out.println("Close Resultset Exception: " + 
                       e.getMessage());
       }
     }
     if (stmt != null)
     {
       try
       {
         stmt.close();
       } 
       catch (Exception e)
       {
         System.out.println("Close Statement Exception: " + 
                       e.getMessage());
       }
     }
     if (conn != null)
     {
       try
       {
         conn.close();
       } 
       catch (Exception e)
       {
         System.out.println("Close connection exception: " + e.getMessage());
       }
     }
   }
   return employeeList;
}

/**
 * getSessionContext method
 * @return javax.ejb.SessionContext
 */
public javax.ejb.SessionContext getSessionContext() {
		 return mySessionCtx;
}
//************************************************************************************
//* El método getDS realiza la búsqueda JNDI de origen de datos.	
//* Este método se llama desde ejbActivate y desde getEmployees si el origen de datos	  
//* es nulo.	
//************************************************************************************

private void getDS() {
		 try {                                                               
		 		 Hashtable parms = new Hashtable();
		 		 parms.put(Context.INITIAL_CONTEXT_FACTORY, 
		 		 		 		 com.ibm.websphere.naming.WsnInitialContextFactory);
		 		 InitialContext ctx = new InitialContext(parms);
		 		 // Realizar búsqueda de servicio de denominación para obtener objeto DataSource.
		 		 ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
		 } 
       catch(Exception e){
		 		 System.out.println("Naming service exception: " + e.getMessage());
		 		 e.printStackTrace();                                            
		 }
}
/**
 * setSessionContext method 
 * @param ctx javax.ejb.SessionContext
 * @exception java.rmi.EJBException
 */
public void setSessionContext(javax.ejb.SessionContext ctx) throws java.rmi.EJBException {
		 mySessionCtx = ctx;
}
}

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * Esta es una interfaz de factoría para el bean de sesión
 */
public interface ShowEmployeesCMTHome extends javax.ejb.EJBHome {

/**
 * método create para un bean de sesión
* @return WebSphereSamples.ConnPool.ShowEmployeesCMT
 * @exception javax.ejb.CreateException
 * @exception java.rmi.RemoteException
 */
WebSphereSamples.ConnPool.ShowEmployeesCMT create() throws javax.ejb.CreateException,
   java.rmi.RemoteException;
}

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * Esta es una interfaz remota de Enterprise Java Bean
 */
public interface ShowEmployeesCMT extends javax.ejb.EJBObject {

/**
 * 
 * @return java.util.Vector
 */
java.util.Vector getEmployees() throws java.sql.SQLException, java.rmi.RemoteException,
 ConnectionWaitTimeoutException, WebSphereSamples.ConnPool.RetryableConnectionException;
}
//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * Excepción que indica que puede reintentarse la operación
 * Fecha de creación: (4/2/2001 10:48:08 AM)
 * @author: Administrador
 */
public class RetryableConnectionException extends Exception {
/**
 * RetryableConnectionException constructor.
 */
public RetryableConnectionException() {
		 		super();
}
/**
 * RetryableConnectionException constructor.
 * @param s java.lang.String
 */
public RetryableConnectionException(String s) {
		 super(s);
}
}

Ejemplo: manejo de excepciones de conexión para beans de sesión en transacciones de base de datos gestionadas por beans

El siguiente código de ejemplo muestra las opciones para tratar las excepciones de conexiones inactivas. Puede establecer diferentes parámetros de gestión de transacciones y de gestión de conexiones como, por ejemplo, el número de reintentos de operaciones y el intervalo de tiempo de espera de conexión.

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

import java.util.*; 
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import javax.transaction.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;

/**********************************************************************************
* Este bean se ha diseñado para mostrar las conexiones de base de datos en un          *
* bean de sesión de transacciones gestionadas por contenedor.  Su atributo        *
* debe establecerse en TX_BEANMANAGED.                                                 
**********************************************************************************/
public class ShowEmployeesBMTBean implements SessionBean {
		 private javax.ejb.SessionContext mySessionCtx = null;
		 final static long serialVersionUID = 3206093459760846163L;

		 private javax.sql.DataSource ds;

		 private javax.transaction.UserTransaction userTran;

//************************************************************************************
//* ejbActivate llama a getDS que efectúa la búsqueda JNDI de DataSource
//* Dado que la búsqueda de DataSource se ejecuta en un método distinto, se puede  
//* invocar desde getEmployees cuando el campo DataSource sea nulo.		 		 
//************************************************************************************
public void ejbActivate() throws java.rmi.EJBException {
		 getDS();
}
/**
 * ejbCreate method 
 * @exception javax.ejb.CreateException
 * @exception java.rmi.EJBException
 */
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.EJBException {}
/**
 * ejbPassivate method 
 * @exception java.rmi.EJBException
 */
public void ejbPassivate() throws java.rmi.EJBException {}
/**
 * ejbRemove method 
 * @exception java.rmi.EJBException
 */
public void ejbRemove() throws java.rmi.EJBException {}

//************************************************************************************
//* getEmployees devuelve la consulta de base de datos para recuperar empleados	    
//* solo se llama a getDS si la variable DataSource o userTran es nula.
//* Si se produce una conexión inactiva, el bean reintenta la transacción 5 veces,		 
//* luego genera una EJBException.
//************************************************************************************

public Vector getEmployees() throws EJBException {
   Connection conn  = null;
   Statement stmt = null;
   ResultSet rs = null;
   Vector employeeList = new Vector();

   // Establecer retryCount en el número de reintentos que desea después de
   // conexión inactiva
   int retryCount = 5;  
    
   // Si el código de base de datos se procesa bien, se establecerá error = false
   boolean error = true;
   
   if (ds == null || userTran == null) getDS();
   do
   {		 		 
         try
         { 
            //try/catch block for UserTransaction work
            //Begin the transaction
            userTran.begin();
            try
            { 
               //try/catch block for database work
               // Obtener un objeto de conexión conn mediante la fábrica DataSource.
               conn = ds.getConnection();
               // Ejecutar consulta DB mediante codificación JDBC estándar.
               stmt = conn.createStatement();
               String query   = "Select FirstNme, MidInit, LastName " + 
		 		 		     "from Employee ORDER BY LastName";
               rs   = stmt.executeQuery(query);
               while (rs.next())
               {
                  employeeList.addElement(rs.getString(3) + ", " +                                                               rs.getString(1) + " " + rs.getString(2));
               }
               //Definir error = false, porque todas las operaciones de base de datos finalizan bien
               error = false;
            } 
            catch (SQLException sqlX)
            {
              if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
              {
                // Esta excepción indica que la conexión con la base de datos ya no es válida.
                // Restituya la transacción y genere una excepción para el cliente indicando que
                // puede volver a intentar la transacción si lo desea.

                System.out.println("Stale connection: " +
                se.getMessage());
                userTran.rollback();
                if (--retryCount == 0)
                {
                  //Si ya ha realizado el número de reintentos solicitado, generar una EJBException.
                  throw new EJBException("Transaction Failure: " + sqlX.toString());
                } 
                else
                {
                  System.out.println("Retrying transaction, retryCount = " +          
                         retryCount);
                }
              } 
              else if (sqlX instanceof ConnectionWaitTimeoutException
                    || sqlX instanceof SQLTransientConnectionException
                       && sqlX.getCause() instanceof ConnectionWaitTimeoutException)
              {
                // Esta excepción se genera si no se puede obtener una conexión de la
                // agrupación en un período de tiempo configurable.  Si aparece mucho
                // esta excepción la agrupación de conexiones se ha ajustado mal

                System.out.println("Connection request timed out: " + 
                sqlX.getMessage());
                userTran.rollback();
                throw new EJBException("Transaction failure: " + sqlX.getMessage());
              } 
              else
              {                   
		  	  // Este catch maneja todas las demás excepciones SQL
                System.out.println("SQL Exception during get connection or process SQL: " +
		 		 		 		 sqlX.getMessage());
                userTran.rollback();
                throw new EJBException("Transaction failure: " + sqlX.getMessage());
              } 
            finally
            {
              // Cerrar siempre la conexión en una sentencia final para que en todos los 
              // casos el cierre sea correcto. Al cerrar la conexión no se cierra la conexión 
              // real, sino que se libera para que pueda reutilizarse en la agrupación.

              if (rs != null) {
               try {                                                               
                  rs.close();
               } 
               catch(Exception e){
                  System.out.println("Close Resultset Exception: " + e.getMessage());
               }
            }
            if (stmt != null) {
               try {                                                               
                  stmt.close();
 } 
            catch(Exception e){
               System.out.println("Close Statement Exception: " + e.getMessage());
            }
         }         
         if (conn != null) {
            try {                                                               
               conn.close();
            } 
            catch(Exception e){
               System.out.println("Close connection exception: " + e.getMessage());
            }
         }
      }		   		 
      if (!error) {
         //La tarea de base de datos se ha realizado correctamente, comprometer la transacción
         userTran.commit();
      }
      //Capturar excepciones UserTransaction
      } 
      catch (NotSupportedException nse) {

//La genera el método UerTransaction begin si la hebra ya está asociada con una 
//transacción y la implementación del gestor de transacciones no soporta transacciones anidadas.
 System.out.println("NotSupportedException on User Transaction begin: " +
                                 nse.getMessage());
         throw new EJBException("Transaction failure: " + nse.getMessage());
      } 
      catch (RollbackException re) {
//Se genera para indicar que la transacción se ha restituido en lugar de comprometerse.
         System.out.println("User Transaction Rolled back!" + re.getMessage());
         throw new EJBException("Transaction failure: " + re.getMessage());
      } 
      catch (SystemException se) {
		   //Se genera si el gestor de transacciones encuentra una condición de error imprevista
         System.out.println("SystemException in User Transaction: "+ se.getMessage());
         throw new EJBException("Transaction failure: " + se.getMessage());
      } 
      catch(Exception e){
         //Manejar excepciones genéricas o imprevistas
         System.out.println("Exception in User Transaction: " + e.getMessage());
         throw new EJBException("Transaction failure: " + e.getMessage());		 		 
      }
   } 
   while (error);
   return employeeList;
}
/**
 * getSessionContext method comment
 * @return javax.ejb.SessionContext
 */
public javax.ejb.SessionContext getSessionContext() {
		 return mySessionCtx;
}

//************************************************************************************
//* getDS efectúa la búsqueda JNDI de DataSource.		 		 		 
//* Este método se llama desde ejbActivate y desde getEmployees si el objeto DataSource		 
//* es nulo.		 		 		 		 		 		 		 		 		 
//************************************************************************************
private void getDS() {
   try {                                                               
      Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY, 
         com.ibm.websphere.naming.WsnInitialContextFactory);
      InitialContext ctx = new InitialContext(parms);

      // Realizar búsqueda de servicio de denominación para obtener objeto DataSource.
      ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
      //Crear el objeto UserTransaction
      userTran = mySessionCtx.getUserTransaction();
   } 
   catch(Exception e){
      System.out.println("Naming service exception: " + e.getMessage());
      e.printStackTrace();                                            
}
}
/**
 * setSessionContext method
 * @param ctx javax.ejb.SessionContext
 * @exception java.rmi.EJBException
 */
public void setSessionContext(javax.ejb.SessionContext ctx) throws java.rmi.EJBException {
		 mySessionCtx = ctx;
}
}
//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * Esta es una interfaz de factoría para el bean de sesión
 */
public interface ShowEmployeesBMTHome extends javax.ejb.EJBHome {

/**
 * método create para un bean de sesión
 * @return WebSphereSamples.ConnPool.ShowEmployeesBMT
 * @exception javax.ejb.CreateException
 * @exception java.rmi.RemoteException
 */
WebSphereSamples.ConnPool.ShowEmployeesBMT create() throws javax.ejb.CreateException,
    java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * Esta es una interfaz remota de Enterprise Java Bean
 */
public interface ShowEmployeesBMT extends javax.ejb.EJBObject {

/**
 * 
 * @return java.util.Vector
 */
java.util.Vector getEmployees() throws java.rmi.RemoteException, javax.ejb.EJBException;
}

Ejemplo: manejo de excepciones de conexión para beans BMP en transacciones de base de datos gestionadas por contenedor

El siguiente código de ejemplo muestra cómo se restituyen las transacciones y se emiten excepciones al cliente de bean en casos de excepciones de conexiones inactivas.

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2005,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

import java.util.*; 
import javax.ejb.*;
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import com.ibm.websphere.rsadapter.WSCallHelper;

/**
 * Esta es una clase de bean de entidad con cinco campos BMP
 * String firstName, String lastName, String middleInit
 * String empNo, int edLevel
 */
public class EmployeeBMPBean implements EntityBean {
       private javax.ejb.EntityContext entityContext = null;
       final static long serialVersionUID = 3206093459760846163L;

       private java.lang.String firstName;
       private java.lang.String lastName;
       private String middleInit;
       private javax.sql.DataSource ds;
       private java.lang.String empNo;
       private int edLevel;
/**
 * ejbActivate method 
 * ejbActivate calls getDS(), which performs the 
 * JNDI lookup for the datasource.
 */
public void ejbActivate() {
       getDS();
}
/**
 * ejbCreate method for a BMP entity bean
 * @return WebSphereSamples.ConnPool.EmployeeBMPKey
 * @param key WebSphereSamples.ConnPool.EmployeeBMPKey
 * @exception javax.ejb.CreateException 
 */
public WebSphereSamples.ConnPool.EmployeeBMPKey ejbCreate(String empNo, 
String firstName, String lastName, String middleInit, int edLevel) throws 
javax.ejb.CreateException {

   Connection conn = null;
   PreparedStatement ps = null;
       
   if (ds == null) getDS();
              
   this.empNo = empNo;
   this.firstName = firstName;
   this.lastName = lastName;
   this.middleInit = middleInit;
   this.edLevel = edLevel;

   String sql = "insert into Employee (empNo, firstnme, midinit, lastname,
        edlevel) values (?,?,?,?,?)";
              
   try {                                                               
      conn = ds.getConnection();
      ps = conn.prepareStatement(sql);                     
      ps.setString(1, empNo);
      ps.setString(2, firstName);
      ps.setString(3, middleInit);
      ps.setString(4, lastName);
      ps.setInt(5, edLevel);
              
 if (ps.executeUpdate() != 1){
         System.out.println("ejbCreate Failed to add user.");
         throw new CreateException("Failed to add user.");
      }
   } 
   catch (SQLException se)
   {
      if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
      {
         // Esta excepción indica que la conexión con la base de datos ya no es válida.
         // Restituya la transacción y genere una excepción para el cliente indicando que
         // puede volver a intentar la transacción si lo desea.

         System.out.println("Connection is stale: " +  se.getMessage());
         throw new CreateException(se.getMessage());
      } 
      else
      {
         System.out.println("SQL Exception during get connection or process SQL: " +
                          se.getMessage());
         throw new CreateException(se.getMessage());
      } 
   }
   finally
   {
      // Cerrar siempre la conexión en una sentencia final para que en todos los 
      // casos el cierre sea correcto. Al cerrar la conexión no se cierra la conexión
      // real, sino que se libera para que pueda reutilizarse en la agrupación.
      if (ps != null)
      {
         try
         {
            ps.close();
         } 
         catch (Exception e)
         {
            System.out.println("Close Statement Exception: " + e.getMessage());
         }
      }
      if (conn != null)
      {
         try
         {
            conn.close();
         } 
         catch (Exception e)
         {
            System.out.println("Close connection exception: " + e.getMessage());
         }
      }
   }
   return new EmployeeBMPKey(this.empNo);
}
/**
 * ejbFindByPrimaryKey method
 * @return WebSphereSamples.ConnPool.EmployeeBMPKey
 * @param primaryKey WebSphereSamples.ConnPool.EmployeeBMPKey
 * @exception javax.ejb.FinderException
 */
public WebSphereSamples.ConnPool.EmployeeBMPKey
     ejbFindByPrimaryKey(WebSphereSamples.ConnPool.EmployeeBMPKey primaryKey)
                 javax.ejb.FinderException {
       loadByEmpNo(primaryKey.empNo);
       return primaryKey;
}
/**
 * ejbLoad method
 */
public void ejbLoad() {
       try {                                                               
              EmployeeBMPKey pk = (EmployeeBMPKey) entityContext.getPrimaryKey();
              loadByEmpNo(pk.empNo);
       } catch (FinderException fe) {
              throw new EJBException("Cannot load Employee state from database.");
       }       
}
/**
 * ejbPassivate method
 */
public void ejbPassivate() {}
/**
 * método ejbPostCreate para un bean de entidad BMP
 * @param key WebSphereSamples.ConnPool.EmployeeBMPKey
 */
public void ejbPostCreate(String empNo, String firstName, String lastName, String middleInit,
    int edLevel) {}
/**
 * ejbRemove method
 * @exception javax.ejb.RemoveException
 */
public void ejbRemove() throws javax.ejb.RemoveException
{
       
   if (ds == null) 
      GetDS();

   String sql = "delete from Employee where empNo=?";
   Connection con = null;
   PreparedStatement ps = null;
   try
   {                     
      con = ds.getConnection();   
      ps = con.prepareStatement(sql);   
      ps.setString(1, empNo);
      if (ps.executeUpdate() != 1)
      {
         throw new EJBException("Cannot remove employee: " + empNo);
      }
   } 
   catch (SQLException se)
   {
      if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
      {
         // Esta excepción indica que la conexión con la base de datos ya no es válida.
         // Restituya la transacción y genere una excepción para el cliente indicando que
         // puede volver a intentar la transacción si lo desea.

         System.out.println("Connection is stale: " +  se.getMessage());
         throw new EJBException(se.getMessage());   
      } 
      else
      {
         System.out.println("SQL Exception during get connection or process SQL: " +
                          se.getMessage());
         throw new EJBException(se.getMessage());   
      } 
   }
   finally
   {
      // Cerrar siempre la conexión en una sentencia final para que en todos los 
      // casos el cierre sea correcto. Al cerrar la conexión no se cierra la conexión
      // real, sino que se libera para que pueda reutilizarse en la agrupación.
      if (ps != null)
      {
         try
         {
            ps.close();
         } 
         catch (Exception e)
         {
            System.out.println("Close Statement Exception: " + e.getMessage());
         }
      }
      if (con != null)
      {
         try
         {
            con.close();
         } 
         catch (Exception e)
         {
            System.out.println("Close connection exception: " + e.getMessage());
         }
      }
   }
}
/**
 * Obtener edLevel de empleado
 * Fecha de creación: (4/20/2001 3:46:22 PM)
 * @return int
 */
public int getEdLevel() {
       return edLevel;
}
/**
 * getEntityContext method
 * @return javax.ejb.EntityContext
 */
public javax.ejb.EntityContext getEntityContext() {
       return entityContext;
}
/**
 * Obtener el nombre del empleado
 * Fecha de creación: (4/19/2001 1:34:47 PM)
 * @return java.lang.String
 */
public java.lang.String getFirstName() {
       return firstName;
}
/**
 * Obtener el apellido del empleado
 * Fecha de creación: (4/19/2001 1:35:41 PM)
 * @return java.lang.String
 */
public java.lang.String getLastName() {
       return lastName;
}
/**
* obtener la inicial del segundo apellido del empleado
 * Fecha de creación: (4/19/2001 1:36:15 PM)
 * @return char
 */
public String getMiddleInit() {
       return middleInit;
}
/**
 * Buscar DataSource desde JNDI
 * Fecha de creación: (4/19/2001 3:28:15 PM)
 */
private void getDS() {
       try {                                                               
              Hashtable parms = new Hashtable();
              parms.put(Context.INITIAL_CONTEXT_FACTORY, 
                            com.ibm.websphere.naming.WsnInitialContextFactory);
              InitialContext ctx = new InitialContext(parms);
              // Realizar búsqueda de servicio de denominación para obtener objeto DataSource.
              ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
       } 
       catch(Exception e){
              System.out.println("Naming service exception: " + e.getMessage());
              e.printStackTrace();                                            
       }
}
/**
 * Cargar el empleado desde la base de datos
 * Fecha de creación: (4/19/2001 3:44:07 PM)
 * @param empNo java.lang.String
 */
private void loadByEmpNo(String empNoKey) throws javax.ejb.FinderException
{
       String sql = "select empno, firstnme, midinit, lastname, edLevel from employee where empno = ?";
       Connection conn = null;
       PreparedStatement ps = null;
       ResultSet rs = null;

       if (ds == null) getDS();
       
       try
       {
              // Obtener un objeto de conexión conn mediante la fábrica DataSource.
              conn = ds.getConnection();
              // Ejecutar consulta DB mediante codificación JDBC estándar.
              ps = conn.prepareStatement(sql);                     
              ps.setString(1, empNoKey);
              rs = ps.executeQuery();
              if (rs.next())
              {
                     empNo= rs.getString(1);
                     firstName=rs.getString(2);
                     middleInit=rs.getString(3);
                     lastName=rs.getString(4); 
                     edLevel=rs.getInt(5);
              } 
              else
              {
                throw new ObjectNotFoundException("Cannot find employee number " +
                                                   empNoKey);
              }
       } 
       catch (SQLException se)
       {
         if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
         {
           // Esta excepción indica que la conexión con la base de datos ya no es válida.
           // Restituya la transacción y genere una excepción para el cliente indicando que
           // puede volver a intentar la transacción si lo desea.

           System.out.println("Connection is stale: " +  se.getMessage());
           throw new FinderException(se.getMessage());
         } 
         else
         {
           System.out.println("SQL Exception during get connection or process SQL: " +
                               se.getMessage());
           throw new FinderException(se.getMessage());
         } 
       }
       finally
       {
         // Cerrar siempre la conexión en una sentencia final para que en todos los 
         // casos el cierre sea correcto. Al cerrar la conexión no 
         // se cierra la conexión real, si no que se libera de nuevo a la agrupación 
         // para que pueda reutilizarse.
         if (rs != null)
         {
            try
            {
               rs.close();
            } 
            catch (Exception e)
            {
               System.out.println("Close Resultset Exception: " + e.getMessage());
            }
         }
         if (ps != null)
         {
            try
            {
               ps.close();
            } 
            catch (Exception e)
            {
               System.out.println("Close Statement Exception: " + e.getMessage());
            }
         }
         if (conn != null)
         {
            try
            {
               conn.close();
            } 
            catch (Exception e) 
            {
               System.out.println("Close connection exception: " + e.getMessage());
            }
         }
       }      
}
/**
 * establecer el nivel de formación del empleado
 * Fecha de creación: (4/20/2001 3:46:22 PM)
 * @param newEdLevel int
 */
public void setEdLevel(int newEdLevel) {
       edLevel = newEdLevel;
}
/**
 * setEntityContext method
 * @param ctx javax.ejb.EntityContext
 */
public void setEntityContext(javax.ejb.EntityContext ctx) {
       entityContext = ctx;
}
/**
 * establecer el nombre del empleado
 * Fecha de creación: (4/19/2001 1:34:47 PM)
 * @param newFirstName java.lang.String
 */
public void setFirstName(java.lang.String newFirstName) {
       firstName = newFirstName;
}
/**
 * establecer el apellido del empleado
 * Fecha de creación: (4/19/2001 1:35:41 PM)
 * @param newLastName java.lang.String
 */
public void setLastName(java.lang.String newLastName) {
       lastName = newLastName;
}
/**
 * establecer la inicial del segundo apellido del empleado
 * Fecha de creación: (4/19/2001 1:36:15 PM)
 * @param newMiddleInit char
 */
public void setMiddleInit(String newMiddleInit) {
       middleInit = newMiddleInit;
}
/**
 * unsetEntityContext method
 */
public void unsetEntityContext() {
       entityContext = null;
}
}

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * Esta es una interfaz remota de Enterprise Java Bean
 */
public interface EmployeeBMP extends javax.ejb.EJBObject {

/**
 * 
 * @return int
  */
int getEdLevel() throws java.rmi.RemoteException;
/**
 * 
 * @return java.lang.String
 */
java.lang.String getFirstName() throws java.rmi.RemoteException;
/**
 * 
 * @return java.lang.String
 */
java.lang.String getLastName() throws java.rmi.RemoteException;
/**
 * 
 * @return java.lang.String
 */
java.lang.String getMiddleInit() throws java.rmi.RemoteException;
/**
 * 
 * @return void
 * @param newEdLevel int
 */
void setEdLevel(int newEdLevel) throws java.rmi.RemoteException;
/**
 * 
 * @return void
 * @param newFirstName java.lang.String
 */
void setFirstName(java.lang.String newFirstName) throws java.rmi.RemoteException;
/**
 * 
 * @return void
 * @param newLastName java.lang.String
 */
void setLastName(java.lang.String newLastName) throws java.rmi.RemoteException;
/**
 * 
 * @return void
 * @param newMiddleInit java.lang.String
 */
void setMiddleInit(java.lang.String newMiddleInit) throws java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * Esta es una interfaz remota de Enterprise Java Bean
 */
public interface EmployeeBMP extends javax.ejb.EJBObject {

/**
 * 
 * @return int
  */
int getEdLevel() throws java.rmi.RemoteException;
/**
 * 
 * @return java.lang.String
 */
java.lang.String getFirstName() throws java.rmi.RemoteException;
/**
 * 
 * @return java.lang.String
 */
java.lang.String getLastName() throws java.rmi.RemoteException;
/**
 * 
 * @return java.lang.String
 */
java.lang.String getMiddleInit() throws java.rmi.RemoteException;
/**
 * 
 * @return void
 * @param newEdLevel int
 */
void setEdLevel(int newEdLevel) throws java.rmi.RemoteException;
/**
 * 
 * @return void
 * @param newFirstName java.lang.String
 */
void setFirstName(java.lang.String newFirstName) throws java.rmi.RemoteException;
/**
 * 
 * @return void
 * @param newLastName java.lang.String
 */
void setLastName(java.lang.String newLastName) throws java.rmi.RemoteException;
/**
 * 
 * @return void
 * @param newMiddleInit java.lang.String
 */
void setMiddleInit(java.lang.String newMiddleInit) throws java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002,2008
//   Todos los derechos reservados
//   Material bajo licencia, propiedad de IBM
//   Derechos limitados de los usuarios del gobierno de EE.UU.: el uso, la
//   duplicación o revelación queda limitada por el contrato GSA ADP Schedule con IBM Corp.
//
//   IBM RENUNCIA A TODAS LAS GARANTÍAS RELACIONADAS CON ESTE SOFTWARE, INCLUIDAS
//   LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD E IDONEIDAD PARA UNA FINALIDAD
//   DETERMINADA. EN NINGÚN CASO IBM SE HACE RESPONSABLE DE DAÑOS ESPECIALES, INDIRECTOS
//   O COMO CONSECUENCIA RESULTANTES DE LA PÉRDIDA DE USO, DE DATOS O
//   BENEFICIOS, YA SEA DEBIDO CONTRATO, NEGLIGENCIA O CUALQUIER OTRA
//   ACCIÓN RELACIONADA O ASOCIADA CON EL USO O CON EL RENDIMIENTO DE ESTE
//   SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
* Esta es una clase de clave primaria para el bean de entidad
**/
public class EmployeeBMPKey implements java.io.Serializable { 
		 public String empNo;
		 final static long serialVersionUID = 3206093459760846163L;

/**
* EmployeeBMPKey() constructor 
*/
public EmployeeBMPKey()  {
}
/**
* EmployeeBMPKey(String key) constructor 
*/
public EmployeeBMPKey(String key)  {
		 empNo = key;
}
/**
* método equals
* - el usuario debe proporcionar una implementación correcta del método equal. El método 
*   generado presupone que la clave es un objeto String.
*/
public boolean equals (Object o)  {
		 if (o instanceof EmployeeBMPKey) 
		 		 return empNo.equals(((EmployeeBMPKey)o).empNo);
		 else
		 		 return false;
}
/**
* método hashCode
* - el usuario debe proporcionar una implementación correcta del método hashCode. El método
*   generado presupone que la clave es un objeto String.
*/
public int hashCode ()  {
		 return empNo.hashCode();

Ejemplo: manejo de la excepción de acceso a datos: ConnectionWaitTimeoutException (para la API JDBC)

Este ejemplo de código muestra cómo se especifican las condiciones bajo las cuales el servidor de aplicaciones emite la excepción ConnectionWaitTimeoutException para una aplicación JDBC.

No se puede hacer gran cosa para intentar la recuperación, si la excepción que se obtiene es ConnectionWaitTimeoutException.

public void test1() {
		 		 java.sql.Connection conn = null;
		 		 java.sql.Statement stmt = null;
		 		 java.sql.ResultSet rs = null;

		 		 try {                                                               
		 		 		 // Buscar el origen de datos
		 		 		 java.util.Properties props = new java.util.Properties();
		 		 		 props.put(
		 		 		 		 javax.naming.Context.INITIAL_CONTEXT_FACTORY,
		 		 		 		 com.ibm.websphere.naming.WsnInitialContextFactory);
		 		 		 ic = new javax.naming.InitialContext(props);
		 		 		 javax.sql.DataSource ds1 = (javax.sql.DataSource) ic.lookup(jndiString);

		 		 		 // Obtener la conexión.
		 		 		 conn = ds1.getConnection();
		 		 		 stmt = conn.createStatement();
		 		 		 rs = stmt.executeQuery("select * from mytable where this = 54");
		 		 }
		 		 catch (java.sql.SQLException sqlX) {
					if (sqlX instanceof com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException
					 || sqlX instanceof java.sql.SQLTransientConnectionException
					    && sqlX.getCause() instanceof com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException)
					{
		 		 		 //notificar al usuario que el sistema no ha podido proporcionar una 
		 		 		 //conexión a la base de datos.  Esto ocurre normalmente cuando la 
		 		 		 //agrupación de conexiones está llena y no hay ninguna conexión 
		 		 		 //disponible para compartir.
		 			}
					else
					{
		 		 		 // manejar otros problemas de base de datos.
					}
		 		 }
		 		 finally {
		 		 		 if (rs != null)
		 		 		 		 try {                                                               
		 		 		 		 		 rs.close();
		 		 		 		 }
		 		 		 		 catch (java.sql.SQLException sqle1) {
		 		 		 		 }
		 		 		 if (stmt != null)
		 		 		 		 try {                                                               
		 		 		 		 		 stmt.close();
		 		 		 		 }
		 		 		 		 catch (java.sql.SQLException sqle1) {
		 		 		 		 }
		 		 		 if (conn != null)
		 		 		 		 try {                                                               
		 		 		 		 		 conn.close();
		 		 		 		 }
		 		 		 		 catch (java.sql.SQLException sqle1) {
		 		 		 		 }
		 		 }
		 }

Ejemplo: manejo de la excepción de acceso a datos - ConnectionWaitTimeoutException para la arquitectura de conector de Java EE (Java EE Connector Architecture)

Este ejemplo de código muestra cómo se especifican las condiciones bajo las cuales WebSphere Application Server emite la excepción ConnectionWaitTimeout para una aplicación JDBC.

En todos los casos en que se obtenga la excepción ConnectionWaitTimeout, se puede hacer muy poco por la recuperación.

El siguiente fragmento de código muestra cómo se utiliza esta excepción en JCA (Java Platform, Enterprise Edition (Java EE) Connector Architecture):

/**
 * Este método realiza una sencilla comprobación de la conexión. 
 */
public void testConnection()
   throws javax.naming.NamingException, javax.resource.ResourceException, 
       com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException {
   javax.resource.cci.ConnectionFactory factory = null;
   javax.resource.cci.Connection conn = null;
   javax.resource.cci.ConnectionMetaData metaData = null;
   try {                                                               
      // buscar la fábrica de conexiones
      if (verbose) System.out.println("Look up the connection factory...");
try {                                                               
factory = 
	 (javax.resource.cci.ConnectionFactory) (new InitialContext()).lookup("java:comp/env/eis/Sample");
  }
   catch (javax.naming.NamingException ne) {
      // No se puede buscar la fábrica de conexiones.
      throw ne;
   }
    // Obtener la conexión
      if (verbose) System.out.println("Get the connection...");
      conn = factory.getConnection();
      // Obtener ConnectionMetaData
      metaData = conn.getMetaData();
      // Imprimir la información de los metadatos.
      System.out.println("EISProductName" is + metaData.getEISProductName());
   }
   catch (com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException cwtoe) {
      // Tiempo de espera de la conexión
      throw cwtoe;
   }
   catch (javax.resource.ResourceException re) {
      // Existe un error en las conexiones.
      throw re;
   }
   finally {
      if (conn != null) {
         try {                                                               
            conn.close();
         }
         catch (javax.resource.ResourceException re) {
         }
      }
   }
}

Manejo de la excepción de acceso a datos: Error de correlación en DataStoreHelper

El servidor de aplicaciones proporciona una interfaz DataStoreHelper para correlacionar diferentes códigos de error SQL de base de datos con las excepciones adecuadas del servidor de aplicaciones.

La correlación de errores es necesaria porque varios proveedores de bases de datos pueden proporcionar distintos códigos y errores SQL que signifiquen lo mismo. Por ejemplo, la excepción de conexión inactiva tiene códigos diferentes en distintas bases de datos. Los SQLCODE de DB2 de 1015, 1034, 1036 indican que la conexión ya no está disponible debido a un problema en la base de datos temporal. Los SQLCODE de Oracle de 28, 3113, 3114, etc. indican la misma situación.

Si se correlacionan estos códigos de error con las excepciones estándar se mantiene la coherencia que permite que las aplicaciones se puedan portar entre las diferentes instalaciones del servidor de aplicaciones. El segmento de código siguiente ilustra la forma de añadir dos códigos de error en la correlación de errores:
public class NewDSHelper extends GenericDataStoreHelper
{
  public NewDSHelper(java.util.Properties dataStoreHelperProperties)  
  {
    super(dataStoreHelperProperties);
    java.util.Hashtable myErrorMap = null;
    myErrorMap = new java.util.Hashtable();
    myErrorMap.put(new Integer(-803), myDuplicateKeyException.class);
    myErrorMap.put(new Integer(-1015), myStaleConnectionException.class);
    myErrorMap.put("S1000", MyTableNotFoundException.class);
    setUserDefinedMap(myErrorMap);
    ...
  }
}

Una opción de configuración conocida como Modelo de detección de errores controla el modo en que se utiliza la correlación de errores. En la versión 6 y anteriores, la correlación de excepciones era la única opción disponible para el modelo de detección de errores. En la versión 7 y posteriores, también se encuentra disponible otra opción llamada Comprobación de excepciones. En el modelo de la correlación de excepciones, el servidor de aplicaciones consulta la correlación de errores y sustituye las excepciones por el tipo de excepción correspondiente listada en la correlación de errores. En el modelo de comprobación de excepciones, el servidor de aplicaciones sigue consultando la correlación de errores con fines propios pero no sustituye excepciones. Si desea continuar utilizando la correlación de excepciones, no es necesario que cambie nada. La correlación de excepciones es el modelo de detección de errores predeterminado. Si desea utilizar el modelo de comprobación de excepciones, consulte el tema "Modificación del modelo de detección de errores para utilizar el modelo de comprobación de excepciones" en los enlaces relacionados.

Conflictos entre claves foráneas y bloqueos de base de datos

Si se repiten determinados mensajes de error SQL significa que existen problemas como, por ejemplo, violaciones de la integridad referencial de la base de datos, que puede evitar utilizando la característica de agrupación de secuencias CMP (Container Managed Persistence).

Excepciones resultantes de conflictos de claves foráneas, debidos a la violación de la integridad referencial de base de datos

Una política de integridad referencial (RI) de base de datos dicta las normas sobre cómo se escriben los datos en las tablas de base de datos y cómo se eliminan de éstas para mantener la coherencia relacional. Los requisitos del tiempo de ejecución para la gestión de la persistencia de los beans puede hacer que una aplicación EJB (Enterprise JavaBeans) viole las reglas RI, que pueden provocar excepciones de base de datos.

La aplicación EJB viola la RI de base de datos si aparece un mensaje de excepción en el archivo de anotaciones cronológicas o de rastreo de WebSphere Application Server que sea parecido a uno de los siguientes mensajes (producidos en un entorno que ejecute DB2):
El valor de inserción o actualización de
FOREIGN KEY tabla1.nombre_de_restricción_de_claves_foráneas
no es igual a ningún valor de la clave padre de la tabla padre.
o
Una
fila padre no se puede eliminar porque la relación
tabla1.nombre_de_restricción_de_claves_foráneas
no es igual a ningún valor de la clave padre de la tabla padre.

Para evitar estas excepciones, debe designar el orden en el que los beans de entidad actualicen las tablas de bases de datos relacionales mediante la definición de grupos de secuencia para los beans.

Excepciones que resultan de los puntos muertos provocados por esquemas de control de simultaneidad optimista

Adicionalmente, la agrupación de secuencias puede minimizar las excepciones de retrotracción de transacciones de los beans de entidad que se configuran para el control de simultaneidad optimista. El control de simultaneidad optimista determina que los bloqueos de base de datos se mantengan por un periodo mínimo de tiempo de modo que un número máximo de transacciones tenga acceso a los datos de modo coherente. En esta base de datos de alta disponibilidad, las transacciones simultáneas pueden intentar bloquear la misma fila de tabla y crear un punto muerto. Las excepciones resultantes pueden generar mensajes similares al que aparece a continuación (que se ha producido en un entorno que ejecute DB2):

Ejecución incorrecta
producida por un punto muerto o tiempo de espera excedido.

Utilice la característica de agrupación de secuencias para ordenar la persistencia de beans de forma que disminuya la probabilidad de la aparición de puntos muertos de base de datos.


Icon that indicates the type of topic Concept topic



Timestamp icon Last updated: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=cdat_daexcp
File name: cdat_daexcp.html