How to include Websphere plugin jars in WAS classp

2019-09-04 07:12发布

问题:

I am facing classpath issue related to jars in WAS plugins folder. My application had IBM specific code to get compiled using the com.ibm.ws.runtime jar as mentioned below.

Location : C:\Program Files\IBM\Websphere\AppServer\Plugins

Source code:

Object obj = ((com.ibm.ws.rsadapter.jdbc.WSJdbcUtil.getNativeConnection((com.ibm.ws.rsadapter.jdbc.WSJdbcConnection)connect)));

Both classes are available in com.ibm.ws.runtime

Compiled successfully by including IBM runtime.jar in classpath of build process but after the deployment in WAS, i am getting ClassNotFoundException. Could any one please let me know, how to include that plugins folder in classpath of WAS, so that i wont get ClassNotFoundException. I have added only runtime.jar in JVM classpath but it is throwing error as it is dependent on other jars of IBM.

Error : Caused by: java.lang.ClassNotFoundException: com.ibm.ws.rsadapter.jdbc.WSJdbcConnection

Updated: Currently it is working perfectly with Jboss server. Code below. My aim is to proivide the same provision with Webpshere.

Calling method:

Connection connect = null;
connect = mDataSrc.getConnection();
unlockJDBC(connect);

private void unlockJDBC(Connection connect)
{
//This bit is JBoss specific but we are trying to avoid importing JBoss JAR files so we use reflection instead.

if (connect.getClass().getName().equals("org.jboss.resource.adapter.jdbc.WrappedConnection") || connect.getClass().getSuperclass().getName().equals("org.jboss.resource.adapter.jdbc.WrappedConnection"))
{
Method method = null;
try{
    method = connect.getClass().getMethod("getUnderlyingConnection",null);
    Connection conn = (Connection)method.invoke(connect, null);
    if (conn != null){
        connect = conn;
    }
}
catch (InvocationTargetException e){
    mLogger.severe(e.getTargetException().getMessage());
}
catch (Exception e){
    mLogger.severe(e.toString());
}
}
if (connect instanceof ExtEmbeddedConnection){
ExtEmbeddedConnection embConnect = (ExtEmbeddedConnection)connect;
try{
    embConnect.unlock("unlock");
}
catch (Exception e){
    mLogger.severe(e.toString());
}
 }

回答1:

The recommended way to get underlaying connection is to use proper JDBC API and unwrap it, like this (not using WebSphere internall classes):

Context ic = new InitialContext();
DataSource ds = (DataSource)ic.lookup("jdbc/OracleDS");
Connection conn = ds.getConnection();

// Returns true if this either implements the interface argument
// or is directly or indirectly a wrapper for an object that does.
if (conn.isWrapperFor(oracle.jdbc.OracleConnection.class)) {
    // Returns an object that implements the given interface to
    // allow access to non-standard methods, or standard methods
    // not exposed by the proxy.
    oracle.jdbc.OracleConnection oraCon = conn.unwrap(oracle.jdbc.OracleConnection.class);
    // Do some Oracle-specific work here.
}

For more details check the WebSphere Application Server and the JDBC 4.0 Wrapper Pattern

UPDATE
In response to comments. I do not recommend this, although it works perfectly fine in WAS 8.5.5, so please fix your classpath and remove any WebSphere related jars you added there or packed with application:

        Connection connection = myDs.getConnection();
        System.out.println("connection: " + connection.getClass().getName());
        WSJdbcConnection conn = null;
        if(connection instanceof WSJdbcConnection) {
            System.out.println("WSJdbcConnection");
            conn = (WSJdbcConnection) connection;
            Object obj = WSJdbcUtil.getNativeConnection(conn);
            System.out.println("native: " + obj.getClass().getName());
        }

with output:

[8/11/15 16:55:10:165 CEST] 0000009a SystemOut     O connection: com.ibm.ws.rsadapter.jdbc.WSJccSQLJPDQConnection
[8/11/15 16:55:10:165 CEST] 0000009a SystemOut     O WSJdbcConnection
[8/11/15 16:55:10:165 CEST] 0000009a SystemOut     O native: com.ibm.db2.jcc.am.ef


回答2:

Websphere uses OSGI to limit visibility of internal classes to applications. That could be what's happening here. OSGI probably wasn't in play when you compiled it, but it is when you try to run it. If I do this in a servlet in v7,

ps.println("trying to new up a WSJdbcConnection");
Object o = com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.class.newInstance();
ps.println("got it")

I get an IllegalAccessException, so it's not visible.

As Gas said, if you can use something that's not an internal, you should be able to access it. Generally, com.ibm.websphere - api, com.ibm.wsspi - spi, com.ibm.ws - internal