Extensões para APIs de Acesso a Dados

Se uma única API de acesso a dados não fornecer uma solução completa para seus aplicativos, utilize as extensões do WebSphere Application Server para obter interoperabilidade entre as APIs JCA e JDBC.

Aplicativos extraídos de configurações de gerenciamento de recursos distintas e complexas podem exigir o uso das APIs Java™ Platform, Enterprise Edition (Java EE) Connector Architecture (JCA) e Java Database Connectivity (JDBC). No entanto, em alguns casos, o modelo de programação JDBC não se integra completamente ao JCA (mesmo se a integração total for uma fundação da especificação JCA). Estas inconsistências podem limitar as opções de acesso a dados para um aplicativo que utiliza ambas as APIs. O WebSphere Application Server fornece extensões de API para resolver os problemas de compatibilidade.

Exemplo:

Sem o benefício de uma extensão, os aplicativos que utilizam as APIs não podem modificar as propriedades de uma conexão que pode ser compartilhada após fazer o pedido de conexão, se existirem outros manuseios para esta conexão. (Se nenhum outro manuseio estiver associado à conexão, as propriedades de conexão poderão ser alteradas.) Esta limitação é derivada de uma incompatibilidade entre as políticas de configuração de conexão das APIs:

A especificação de Arquitetura de Conector (JCA) suporta retransmissão para o adaptador de recursos das configurações de propriedades específicas no momento em que você solicita a conexão, utilizando o método getConnection(), transmitindo um objeto ConnectionSpec. O objeto ConnectionSpec contém as propriedades de conexão necessárias utilizadas para obter uma conexão. Depois de obter uma conexão desse ambiente, o aplicativo não necessita alterar as propriedades. O modelo de programação JDBC, no entanto, não possui a mesma interface para especificar as propriedades de conexão. Em vez disso, ele primeiro obtém a conexão e, em seguida, define as propriedades na conexão.

O WebSphere Application Server fornece as seguintes extensões para preencher estas lacunas entre as especificações JDBC e JCA:

Exemplo: Usando APIs estendidas da IBM para conexões com o banco de dados.

Usando a API estendida WSDataSource, é possível codificar seu aplicativo JDBC para definir as propriedades da conexão por meio de um objeto antes de obter uma conexão. Esse comportamento aumenta as oportunidades de compartilhamento do aplicativo de uma conexão com outro componente, como por exemplo um CMP.

Se o seu aplicativo for executado com uma conexão compartilhável que possa ser compartilhada com outros beans de persistência gerenciada por contêiner (CMP) em uma transação, é recomendável utilizar as APIs estendidas do WebSphere Application Server para obter a conexão. Quando estas APIs são utilizadas, não é possível portar o aplicativo para outros servidores de aplicativos.

É possível codificar com a API estendida diretamente em seu aplicativo JDBC; em vez de utilizar a interface DataSource para obter uma conexão, utilize a interface WSDataSource. O segmento de código a seguir ilustra a interface WSDataSource:

import com.ibm.websphere.rsadapter.*;
... 
// Crie uma JDBCConnectionSpec e defina as propriedades da conexão. Se essa conexão
// for compartilhado com o bean CMP, certifique-se de que o nível de isolamento é o mesmo que o
// nível de isolamento mapeado pela Intenção de acesso no bean CMP. 

JDBCConnectionSpec connSpec = WSRRAFactory.createJDBCConnectionSpec(); 
connSpec.setTransactionIsolation(CONNECTION.TRANSACTION_REPEATABLE_READ); 
connSpec.setCatalog("DEPT407");

// Usar o WSDataSource para obter a conexão 
Connection conn = ((WSDataSource)datasource).getConnection(connSpec);

Exemplo: Usando as APIs Estendidas IBM para Compartilhar Conexões entre Beans CMP e Beans BMP.

Em um componente de aplicativo que acessa dados por meio de objetos JDBC, como um bean de persistência gerenciada por bean (BMP), é possível usar uma API estendida do WebSphere para definir propriedades de conexão através de um objeto antes de obter uma conexão. Esse comportamento aumenta as oportunidades de compartilhamento do bean BMP de uma conexão com um bean CMP (Container-Managed Persistence).

Se o seu bean BMP for executado com uma conexão compartilhável que possa ser compartilhada com outros beans de persistência gerenciada por contêiner (CMP) em uma transação, é recomendável utilizar as APIs estendidas do WebSphere Application Server para obter a conexão. Quando essas APIs são utilizadas, não é possível portar o aplicativo para outros servidores de aplicativos.

Nesse caso, utilize a interface WSDataSource da API estendida, em vez da interface DataSource. Para assegurar que os beans CMP e BMP (Bean-managed Persistence) estejam compartilhando a mesma conexão física, defina o mesmo perfil de intenção de acesso nos beans CMP e BMP. Dentro do método de BMP, é possível obter o nível de isolamento correto a partir da classe auxiliar do adaptador de recursos relacional.

package fvt.example;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.ejb.CreateException;
import javax.ejb.DuplicateKeyException;
import javax.ejb.EJBException;
import javax.ejb.ObjectNotFoundException;
import javax.sql.DataSource;

// as importações a seguir são usadas pela API estendida IBM
import com.ibm.websphere.appprofile.accessintent.AccessIntent;
import com.ibm.websphere.appprofile.accessintent.AccessIntentService;
import com.ibm.websphere.rsadapter.JDBCConnectionSpec;
import com.ibm.websphere.rsadapter.WSCallHelper;
import com.ibm.websphere.rsadapter.WSDataSource;
import com.ibm.websphere.rsadapter.WSRRAFactory;

/**
 * Classe de implementação do bean para Enterprise Bean: Simple
 */

public class SimpleBean implements javax.ejb.EntityBean {
 private javax.ejb.EntityContext myEntityCtx;

 // Contexto inicial utilizado para pesquisa.

 private javax.naming.InitialContext ic = null;

 // defina uma JDBCConnectionSpec como variável da instância

 private JDBCConnectionSpec connSpec;

 // defina uma AccessIntentService que é utilizada para obter 
 // um objeto AccessIntent.

 private AccessIntentService aiService;

 // objeto AccessIntent utilizado para obter o nível de isolamento

 private AccessIntent intent = null;
 
 // Nome da tabela de persistência

 private String tableName = "cmtest";

 // Nome JNDI do DataSource

 private String dsName = "java:comp/env/jdbc/SimpleDS";

 // DataSource

 private DataSource ds = null;

 // variáveis da instância do bean.

 private int id;
 private String name;

 /**
  * No método setEntityContext, é necessário obter o objeto AccessIntentService 
  * para que os métodos subseqüentes obtenham o objeto AccessIntent.
  *  um objeto String. 
  * Outros métodos de ejb chamarão o getConnection() privado para obter a
  * conexão que tem todas as propriedades de conexão específicas
  */

 public void setEntityContext(javax.ejb.EntityContext ctx) {
  myEntityCtx = ctx;

  try {
   aiService =
    (AccessIntentService) getInitialContext().lookup(
     "java:comp/websphere/AppProfile/AccessIntentService");
   ds = (DataSource) getInitialContext().lookup(dsName);
  }
  catch (javax.naming.NamingException ne) {
   throw new javax.ejb.EJBException(
    "Naming exception: " + ne.getMessage());
  }
 }

  /**
  * ejbCreate
  */

 public fvt.example.SimpleKey ejbCreate(int newID)
  throws javax.ejb.CreateException, javax.ejb.EJBException {
  Connection conn = null;
  PreparedStatement ps = null;

  // Insira Cadeia SQL

  String sql = "INSERT INTO"  + tableName +  "(id, name) VALUES (?, ?)";

  id = newID;
  name = "";

  try {
                    // chame o método comum para obter a conexão específica

   conn = getConnection();
  }
  catch (java.sql.SQLException sqle) {
   throw new EJBException("SQLException caught: " + sqle.getMessage());
  }
  catch (javax.resource.ResourceException re) {
   throw new EJBException(
    "ResourceException caught: " + re.getMessage());
  }

  try {
   ps = conn.prepareStatement(sql);
   ps.setInt(1, id);
   ps.setString(2, name);

   if (ps.executeUpdate() != 1) {
    throw new CreateException("Failed to add a row to the DB");
   }
  }
  catch (DuplicateKeyException dke) {
   throw new javax.ejb.DuplicateKeyException(
    id + "has already existed");
  }
  catch (SQLException sqle) {
   throw new javax.ejb.CreateException(sqle.getMessage());
  }
  catch (CreateException ce) {
   throw ce;
  }
  finally {
   if (ps != null) {
    try {
     ps.close();
    }
    catch(Exception e){
    }
   }
  }
  return new SimpleKey(id);
 }

  /**
  * ejbLoad
  */

 public void ejbLoad() throws javax.ejb.EJBException {

  Connection conn = null;
  PreparedStatement ps = null;
  ResultSet rs = null;

  String loadSQL = null;

  try {
                    // chame o método comum para obter a conexão específica

   conn = getConnection();
  }
  catch (java.sql.SQLException sqle) {
   throw new EJBException("SQLException caught: " + sqle.getMessage());
  }
  catch (javax.resource.ResourceException re) {
   throw new EJBException(
    "ResourceException caught: " + re.getMessage());
  }

  // É preciso determinar qual instrução select será utilizada com base no
  // tipo de AccessIntent:
  // Se for READ, utiliza uma instrução SELECT normal. Caso contrário, utiliza 
  // a instrução SELECT...FORUPDATE
  // Se o backend for SQLServer, é possível utilizar sintaxe diferente para
  // a cláusula FOR UPDATE.

  if (intent.getAccessType() == AccessIntent.ACCESS_TYPE_READ) {
   loadSQL = "SELECT * FROM"  + tableName +  "WHERE id = ?";
  }
  else {
   loadSQL = "SELECT * FROM"  + tableName +  "WHERE id = ? FOR UPDATE";
  }

  SimpleKey key = (SimpleKey) getEntityContext().getPrimaryKey();

  try {
   ps = conn.prepareStatement(loadSQL);
   ps.setInt(1, key.id);
   rs = ps.executeQuery();
   if (rs.next()) {
    id = rs.getInt(1);
    name = rs.getString(2);
   }
   else {
    throw new EJBException("Cannot load id = " + key.id);
   }
  }
  catch (SQLException sqle) {
   throw new EJBException(sqle.getMessage());
  }
  finally {
   try {
    if (rs != null)
     rs.close();
   }
   catch(Exception e){
   }
   try {
    if (ps != null)
     ps.close();
   }
   catch(Exception e){
   }
   try {
    if (conn != null)
     conn.close();
   }
   catch(Exception e){
   }
  }
 }

        /**
         * Este método utilizará o AccessIntentService para obter a intenção de acesso;
         * em seguida, obtém o nível de isolamento do DataStoreHelper 
         * e o define na especicação da conexão; depois utiliza essa especificação da conexão 
         * para obter uma conexão que tenha as propriedades de conexão 
         * customizadas.
         **/

 private Connection getConnection()
  throws java.sql.SQLException, javax.resource.ResourceException, EJBException {

  // obtenha o objeto de intenção de acesso atual utilizando o contexto de EJB
  intent = aiService.getAccessIntent(myEntityCtx);
  
  // Suponha que este bean suporta somente a simultaneidade pessimista
  if (intent.getConcurrencyControl()
   != AccessIntent.CONCURRENCY_CONTROL_PESSIMISTIC) {
   throw new EJBException("Bean supports only pessimistic concurrency");
  }

  // determinar o nível de isolamento correto para o banco de dados configurado atualmente 
  // utilizando DataStoreHelper
  int isoLevel =
   WSCallHelper.getDataStoreHelper(ds).getIsolationLevel(intent);
   connSpec = WSRRAFactory.createJDBCConnectionSpec();
  connSpec.setTransactionIsolation(isoLevel);

  // Obtenha a conexão utilizando a especificação da conexão
  Connection conn = ((WSDataSource) ds).getConnection(connSpec);
  return conn;
 }

Ícone que indica o tipo de tópico Tópico de Referência



Ícone de registro de data e hora Última atualização: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=rdat_cextiapi
Nome do arquivo: rdat_cextiapi.html