Oracle native JDBC connection extractor
Par guillaume le jeudi 1 avril 2010, 20:00 - java / j2ee - Lien permanent
L'utilisation d'API Oracle Java, comme par exemple la SDO API (sdoapi.jar) ou Oracle Network Modeling (sdonm.jar) pour gérer les graphes, nécessite d'avoir une connexion native Oracle. Or les applications sont souvent configurées avec un pool de connexions gérées par le conteneur JEE. Ceci pose alors problème pour les opérations spécifiques qui nécessitent d'avoir une connexion de type oracle.jdbc.OracleConnection et non une connexion de type java.sql.Connection. Cette dernière ne pourra en effet pas être utilisée avec les méthodes des API Oracle en Java.
Il faut alors extraire la connexion native sous-jacente à la connexion du pool de connexions.
Extraction d'une connexion native JDBC
1) avec Spring
Ceux qui utilisent Spring connaissent probablement le package org.springframework.jdbc.support.nativejdbc qui contient des extracteurs de connexion.Voici par exemple comment récupérer une connexion native sous-jacente avec un extracteur Spring :
import javax.sql.DataSource;
import java.sql.Connection;
import org.springframework.jdbc.datasource.DataSourceUtils;
import
org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor;
DataSource dataSource = ... // récupération par JNDI par exemple et/ou injecté
par Spring
Connection conn = DataSourceUtils.getConnection(dataSource);
SimpleNativeJdbcExtractor extractor = new SimpleNativeJdbcExtractor();
OracleConnection oraConn = (OracleConnection)
extractor.getNativeConnection(conn);Généralement les applications conçues avec Spring gère généralement les ressources base de données à haut niveau (niveau DataSource). La classe utilitaire DataSourceUtils de Spring permet notamment de récupérer la connexion sous-jacente à la DataSource. Ensuite, le SimpleNativeJdbcExtractor permet d'extraire la connexion native en réalisant un
unwrapde la connexion du pool. D'autres extracteurs existent dans ce package utilitaire de Spring, mais malheureusement, cela ne fonctionne pas toujours.
2) sans Spring
En effet, si vous avez un pool de connexionfait maisonil sera alors beaucoup plus difficile d'utiliser les classes utilitaires Spring. Un autre cas de figure est lorsque l'application doit pouvoir être déployée sur différents conteneurs JEE, dont certains non identifiés par les outils Spring.
Dans certains cas, la méthode getMetadata() de l'objet Connection peut-être utilisé directement pour récupérer la connexions native. Dans d'autres cas, il faut utiliser la méthode getUnderlyingConnection() (pas toujours présente) pour récupérer la connexion native (comme c'est le cas pour le wrapper JBoss).
Voici la classe utilitaire permettant de récupérer une connexion native Oracle quelque soit le conteneur (pas testé partout) :
package com.openfarm.util;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import oracle.jdbc.OracleConnection;
import org.apache.log4j.Logger;
/**
* Classe statique réalisant quasiment la même chose que la classe spring
suivante
*
org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor
* c'est à dire extraire la connection native sous-jacente d'un pool de
connexion.
* La récupération à travers les metadata fonctionne avec la plupart des
pools de
* connexion (JBoss 3.x, DBCP 1.x, Resin, etc.)
* La récupération de la connexion native est parfois nécessaire notamment
pour
* l'utilisation de l'API Network Data Model d'Oracle.
*
* @author guillaume viel at openfarm dot fr
*
*/
public class OracleNativeJdbcExtractor {
private static final Logger logger =
Logger.getLogger(OracleNativeJdbcExtractor.class);
/**
* Retourne la connexion native sous-jacente au pool de
connexion
* @param poolConn La connexion du pool
* @return Connection La connexion native
* @throws SQLException
*/
public static Connection getNativeConnection(Connection
poolConn) throws SQLException {
Connection nativeConn = poolConn;
if(poolConn != null) {
nativeConn =
poolConn.getMetaData().getConnection();
logger.info(poolConn +
" encapsulates ["+nativeConn+"]");
}
return nativeConn;
}
/**
* Retourne la connexion native Oracle sous-jacente au
pool de connexion
* @param poolConn La connexion du pool
* @return OracleConnection La connexion Oracle
sous-jacente au pool
* @throws SQLException
*/
public static OracleConnection
getNativeOracleConnection(Connection poolConn) throws SQLException {
OracleConnection oraConn = null;
if(poolConn != null) {
logger.debug(
poolConn.getClass().getName() ); // permet d'identifier le nom du wrapper
try {
oraConn = (OracleConnection)poolConn.getMetaData().getConnection();
logger.info(poolConn + " wraps [" + oraConn + "]");
}
catch(ClassCastException e) {
//
fonctionne par exemple avec le wrapper JBoss qui supporte la methode
getUnderlyingConnection
try
{
Method method =
poolConn.getClass().getDeclaredMethod("getUnderlyingConnection",
(Class[])null);
if(method != null) {
oraConn =
(OracleConnection)method.invoke(poolConn, (Object[])null);
logger.info(poolConn + " encapsulates
["+oraConn+"]");
}
}
catch (Exception e1) {
e1.printStackTrace();
}
}
}
return oraConn;
}
}