web-dev-qa-db-fra.com

Problème d'objet de connexion Apache Commons DBCP, Fil: exception ClassCastException dans org.Apache.Tomcat.dbcp.dbcp.PoolingDataSource $ PoolGuardConnectionWrapper

J'utilise Apache Commons DBCP (commons-dbcp.jar) Pool de connexions.

Une fois que j'ai obtenu une connexion du pool, celle-ci est encapsulée dans la Class org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.

Mon exigence est de passer un tableau de chaînes à la procédure stockée pl/sql dans Oracle.

Voici ce que je fais dans l'extrait de code suivant:

Connection dbConn = ConnectionManager.ds.getConnection();
//The above statement returns me an connection wrapped in the class
//org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.

org.Apache.commons.dbcp.DelegatingConnection del = new org.Apache.commons.dbcp.DelegatingConnection(dbConn.getConnection());
con = del.getInnermostDelegate();

cs = con.prepareCall("call SP_NAME(?,?,?,?)");
Oracle.sql.ArrayDescriptor arDesc= Oracle.sql.ArrayDescriptor.createDescriptor("ARRAY_NAME", (OracleConnection) con);

CallableStatement c_stmt = conn.prepareCall("begin update_message_ids_ota
(:x); end;" );
c_stmt.setArray( 1, array_to_pass );
c_stmt.execute();

En exécutant le code ci-dessus, j'obtiens l'exception suivante:

Exception Java.lang.ClassCast: org.Apache.commons.dbcp.PoolingDataSource $ PoolGuardConnectionWrapper ne peut pas être converti en Oracle.jdbc.OracleConnection à Oracle.sql.ArrayDescriptor.createDescriptor

J'ai essayé de trouver une solution à ce problème en parcourant presque tous les sites et forums, mais je n'ai pas pu obtenir la réponse ou la solution satisfaisante.

25
Prodigy

Par défaut, DBCP n'autorise pas l'accès à la "vraie" instance de connexion à la base de données sous-jacente, vous ne pouvez donc pas accéder à la classe Oracle.

Lorsque configuration le pool, vous pouvez définir

accessToUnderlyingConnectionAllowed = true

et puis ça marche.

La valeur par défaut est false, il s’agit d’une opération potentiellement dangereuse et les programmes qui se comportent mal peuvent avoir des effets néfastes. (fermer le sous-jacent ou continuer à l'utiliser lorsque la connexion protégée est déjà fermée) Soyez prudent et utilisez-le uniquement lorsque vous avez besoin d'un accès direct à des extensions spécifiques au pilote.

REMARQUE: ne fermez pas la connexion sous-jacente, mais uniquement celle d'origine.

23
Thilo

Si vous utilisez une connexion JDBC compatible Java 6, vous pouvez utiliser un code similaire à celui-ci:

OracleConnection oracleConnection = null;
try {
    if (connection.isWrapperFor(OracleConnection.class)) {
        oracleConnection = connection.unwrap(OracleConnection.class);
    }
} catch (SQLException ex) {
    // do something
}
return oracleConnection;

À partir de là, utilisez oracleConnection au lieu de connection d'origine.

Voir http://docs.Oracle.com/javase/6/docs/api/Java/sql/Wrapper.html

16
Jeff Olson

Vu ce post, je peux obtenir OracleConnection avec ce code:

DataSource ds1 = // get the org.Apache.commons.dbcp.PoolingDataSource
org.Apache.Tomcat.dbcp.dbcp.DelegatingConnection del = new org.Apache.Tomcat.dbcp.dbcp.DelegatingConnection(cds1.getConnection());
OracleConnection con = (OracleConnection) del.getInnermostDelegate();

rappelez-vous que neons pas commons-dbcp-1.4.jar doit être dans le chemin de classe

5
Leonardo Eloy

Hmmm , J'ai rencontré la même solution que vous. Je pense qu'il faut mentionner deux positions . 1.Config Connection pool set accessToUnderlyingConnectionAllowed = "true"; 2. Le cauchemar concerné par le projet open source La conceration terrable. Dans ce cas, cela Est 

org.Apache.commons.dbcp.DelegatingConnection 

n'est pas égal à 

org.Apache.Tomcat.dbcp.dbcp.DelegatingConnection

alors que par défaut Apache common-dbcp.jar, vous ne trouverez jamais la classe suivante. Mais seule la classe est la clé. Nous devons donc trouver la classe quelque part. Je trouve enfin le paquet Tomcat-dbcp .jar. Vous pouvez l’obtenir de http://www.docjar.com/ Après 

import org.Apache.Tomcat.dbcp.dbcp.DelegatingConnection

, vous pouvez forcer votre dbConn à vous lancer et obtenir la connexion sous-jacente

Oracle.jdbc.driver.OracleConnection delConn = 

(Oracle.jdbc.driver.OracleConnection) 

((org.Apache.Tomcat.dbcp.dbcp.DelegatingConnection)c_stmt.getConnection()).getDelegate();

Ensuite, nous pouvons utiliser delConn pour obtenir le ArrayDescriptor Rappelez-vous une chose, dans ce document, nous n’avons pas besoin du

org.Apache.commons.dbcp.DelegatingConnection Class

C'est une chose tellement étrange, mais un vrai travail pour le cas.

4
Rui Zha

Je propose ceci ici pour que toute personne à la recherche de conseils soit au courant de la solution ultime:

Si vous êtes obligé d'utiliser la version non intégrée du gestionnaire de persistance (car un ancien référentiel utilise toujours cette structure incompatible avec la présentation intégrée), voici ce que vous pouvez faire, la solution est très simple:

Téléchargez les sources de Jackrabbit Core (vous pouvez les obtenir à partir du site Web Jackrabbit) Ouvrez la classe OraclePersistenceManager et recherchez la ligne de code suivante:

Object blob = createTemporary.invoke(null,
                new Object[]{con, Boolean.FALSE, durationSessionConstant});

(Autour de la ligne 377 - peut également vérifier le StackTrace pour référence)

ConnectionFactory contient une méthode statique qui permet de décompresser une connexion qui correspond exactement à ce dont vous avez besoin:

Object blob = createTemporary.invoke(null,
                new Object[]{org.Apache.jackrabbit.core.util.db.ConnectionFactory
                        .unwrap(con), Boolean.FALSE, durationSessionConstant});

Vous aurez besoin de Maven 2+ pour compiler les sources. Je l’ai fait et n’avais aucun problème de dépendance. Notez que j’ai compilé la version 2.2.10 de Jackrabbit.

Je me suis également assuré de consigner un bogue contre Jackrabbit 2.2.11 (version actuelle qui pose toujours le problème): https://issues.Apache.org/jira/browse/JCR-3262

J'espère que cela t'aides!

2

Nous utilisons des tableaux dans nos appels aux procédures stockées Oracle et utilisons une api propriétaire d'Oracle pour construire des tableaux. Cette petite vérification a résolu le problème pour nous lorsque nous utilisons les fonctionnalités d'applications autonomes utilisant commons-dbcp.

    if (conn instanceof org.Apache.commons.dbcp.DelegatingConnection)
    {
        log.debug("detected Apache commons dbcp datasource");
        conn = ((org.Apache.commons.dbcp.DelegatingConnection) conn).getInnermostDelegate();
    }

Vous aurez cependant besoin de commons-dbcp dans le classpath/dependecies.

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
        <scope>provided</scope>
    </dependency>
1
chinto

J'avais rencontré le même problème. Nous utilisions spring et il existe une classe appelée NativeJdbcExtractor. Il a de nombreuses implémentations et la suivante fonctionne pour Tomcat. Il existe des implémentations spécifiques pour Websphere, serveurs d'applications Weblogic.

<bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"></bean>

Dans votre DAO, vous pouvez injecter le haricot et utiliser la méthode suivante

protected NativeJdbcExtractor jdbcExtractor;
Connection conn=jdbcExtractor.getNativeConnection(oracleConnection);
1
Sherin Syriac

Pour ceux qui cherchent, getDelegate() et getInnermostDelegate() renvoient NULL dans mon code. Cependant, à partir du débogueur, j'ai trouvé OracleConnection comme ci-dessous. Nous utilisons Spring JdbcTemplate dans l’ensemble de l’application, dans laquelle la source de données est injectée. Nous sommes sur spring-jdbc-4.1.5.RELEASE.jar et ojdbc6.jar.

Connection conn = getJdbcTemplate().getDataSource().getConnection();

OracleConnection oracleConnection = ( OracleConnection ) conn.getMetaData().getConnection();
0
Severus Snape

Je travaille avec Tomcat 8.5.8 et je faisais face à ce problème.
La solution ci-dessous a fonctionné à merveille.


Le code:

Delegating Connection delegate_conn = new Delegating Connection(connection)
conn = delegate_conn.getInnermostDelegate();
Oracle.sql.ArrayDescriptor desc = Oracle.sql.ArrayDescriptor.createDescriptor("TABLE_VIEW", conn);

La solution:

Ajouter une dépendance pour Tomcat-dbcp 8.5.8.__ et ajouter le même fichier jar dans le dossier lib de Tomcat.
Semble Tomcat a différents jar pour différentes versions à partir de 7.0 (référence: https://mvnrepository.com/artifact/org.Apache.Tomcat/tomcat-dbcp ).

J'espère que ça aide quelqu'un.

0
ashutosh singh

dans votre définition de contexte, ajoutez les balises ci-dessous à votre définition XML existante.

factory="Oracle.jdbc.pool.OracleDataSourceFactory
scope="Shareable"
type="Oracle.jdbc.pool.OracleDataSource"

.

0
ibrahimbayer