quinta-feira, 29 de abril de 2010

Java - Pegar uma conexão Oracle (OracleConnection) real do Tomcat

Geralmente, precisamos pegar a Connection do banco de dados em que estamos trabalhando para uma porção de coisas: para pegar alguma informação do banco de dados, para chamar alguma stored procedure, para executar algum código específico do banco de dados, etc.

Em alguns casos, quando se está trabalhando com Java e Oracle, se formos utilizar alguns recursos avançados exclusivos do Oracle, veremos que algumas bibliotecas exigem que seja utilizado uma instância de OracleConnection (que seria o resultado normal quando você pega uma conexão com o Oracle via java).

No entanto, quando estamos utilizando o Tomcat e pegamos uma conexão do Oracle, percebemos que não pegamos uma instância de OracleConnection, mas sim uma instância de org.apache.tomcat.dbcp.dbcp.PoolableConnection.

Para conseguirmos pegar o OracleConnection a partir deste org.apache.tomcat.dbcp.dbcp.PoolableConnection retornado, devemos fazer dois passos:

1º) Primeiro devemos alterar o arquivo XML de conexão com o banco de dados do Tomcat. Este arquivo pode ser o context.xml ou o server.xml (ou ainda alguma outra configuração), depende de como você usa o Tomcat para se conectar ao banco de dados.

Este é um exemplo de arquivo de conexão ao banco de dados do Tomcat:


<Context docBase="c:\workspace\MinhaApp\WebContent" path="/minhaapp" reloadable="true">
   <Resource auth="Container"
      driverClassName="oracle.jdbc.driver.OracleDriver"
      maxActive="-1" maxIdle="30" maxWait="10000"
      name="jdbc/minhaapp" type="javax.sql.DataSource"
      username="minhaapp" password="minhaapp"
      url="jdbc:oracle:thin:@localhost:1521:xe"
   />
</Context>


Neste caso, estou usando o Tomcat para me conectar a um banco de dados Oracle XE.

O que devemos fazer aqui é - na tag Resource - que devemos adicionar o atributo "accessToUnderlyingConnectionAllowed" como true.

Dessa forma, o arquivo ficaria assim:

<Context docBase="c:\workspace\MinhaApp\WebContent" path="/minhaapp" reloadable="true">
   <Resource auth="Container"
      driverClassName="oracle.jdbc.driver.OracleDriver"
      maxActive="-1" maxIdle="30" maxWait="10000"
      name="jdbc/minhaapp" type="javax.sql.DataSource"
      username="minhaapp" password="minhaapp"
      url="jdbc:oracle:thin:@localhost:1521:xe"
      accessToUnderlyingConnectionAllowed="true"
   />
</Context>


Pronto, esta é a primeira parte da alteração que precisamos fazer.



2º) A segunda parte da alteração é no próprio código que pega a conexão com o banco de dados.

Digamos que este é o código que você usa para pegar uma conexão com o banco de dados:

InitialContext ic = new InitialContext();
DataSource dataSource = (DataSource) ic.lookup("java:comp/env/XXX");
Connection con = dataSource.getConnection();

Pronto, pegamos a conexão com o banco de dados. Só que, na verdade, pegamos uma instância de org.apache.tomcat.dbcp.dbcp.PoolableConnection.

Para pegar o OracleConnection, devemos utilizar o método "getInnermostDelegate()" da conexão recebida.

Desta forma, o nosso código completo para pegar o OracleConnection seria este:

InitialContext ic = new InitialContext();
DataSource dataSource = (DataSource) ic.lookup("java:comp/env/XXX");
Connection con = dataSource.getConnection();

OracleConnection oracleConnection;
if (connection instanceof org.apache.tomcat.dbcp.dbcp.DelegatingConnection) {
   oracleConnection = (OracleConnection) ((org.apache.tomcat.dbcp.dbcp.DelegatingConnection) connection).getInnermostDelegate();
} else {
   oracleConnection = (OracleConnection)connection;
}


Pronto, desta forma conseguimos pegar o OracleConnection a partir do PoolableConnection.


Atenção: a classe DelegatingConnection é de um .jar do Tomcat. Esta classe está no .jar chamado "naming-factory-dbcp.jar".

Como este .jar está dentro do Tomcat, você não precisa colocar ela dentro do .war do seu projeto. Mas você precisa colocar ela no classpath do seu projeto (build path do projeto no Eclipse, classpath da aplicação, etc.) senão você não irá conseguir compilar este código, ok?


Bem, é isso. Até mais, pessoal.

Nenhum comentário: