12/11/2007

Access Weblogic DataSource remotely from Java and JRuby client

In previous posts, I wrote how to access JBoss or Glassfish DataSource remotely from a java client (JBoss example and Glassfish example). Here is a simple program in Java and JRuby, how to do it in Weblogic 10, using the same appserver setup as Calling Weblogic EJB 3 from JRuby and java client.
package foo;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;

public class DataSourceClient {
public static void main(String[] args) throws Exception {
String sql = "SELECT id FROM MEDRECWLSTORE";
Context ic = new InitialContext();
DataSource dataSource =
(DataSource) ic.lookup("jdbc/MedRecGlobalDataSource");
System.out.println("lookup dataSource returned " + dataSource);
Connection connection = dataSource.getConnection();
System.out.println("Got connection: " + connection);

Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
System.out.print(rs.getString(1) + " ");
}
}
}
To do the equivalent in JRuby with less code (testDataSourceWeblogic.rb):
require 'java'
include_class 'javax.naming.InitialContext'

sql = "SELECT id FROM MEDRECWLSTORE"
ic = InitialContext.new
data_source = ic.lookup("jdbc/MedRecGlobalDataSource")
puts "lookup DataSource returned #{data_source}"
connection = data_source.getConnection
puts "Got connection #{connection}"
stmt = connection.createStatement
rs = stmt.executeQuery(sql)
while rs.next
print rs.getString(1) + " "
end
Set environment variable CLASSPATH for JRuby. Currently this is the only way to pass java classpath to JRuby (jruby1.0.2). Since I need to set CLASSPATH anyway, I will use it for compiling and running java client as well.
set CLASSPATH=%WL_HOME%\server\lib\weblogic.jar;%WL_HOME%\server\lib\api.jar;C:\simple-ejb3\classes
prepare jndi.properties somewhere in client classpath, e.g., simple-ejb3\classes directory:
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
java.naming.provider.url=t3://localhost:7011
7011 is the default port for t3, iiop, ldap and http for the sample MedRecServer. Your port number may be different.

Compile and run java client:
C:\simple-ejb3\classes > javac -d . ..\src\foo\DataSourceClient.java
C:\simple-ejb3\classes > java foo.DataSourceClient
Run JRuby client:
jruby testDataSourceWeblogic.rb
Both clients will produce the following output, if run successfully:
lookup DataSource returned ClusterableRemoteRef(-4637547633404831470S:localhost:[7011,7011,-1,-1,-1,-1,-1]:medrec:MedRecServer [-4637547633404831470S:localhost:[7011,7011,-1,-1,-1,-1,-1]:medrec:MedRecServer/286])/286
Got connection weblogic.jdbc.rmi.SerialConnection_weblogic_jdbc_rmi_internal_ConnectionImpl_weblogic_jdbc_wrapper_PoolConnection_com_pointbase_net_netJDBCConnection30_1001_WLStub@1
-1 1 2 3 4 5 6 7 8 9 10 134217727 268435454 402653181 536870908 671088635 805306362 939524089 1073741816 1207959543 1342177270 1476394997 1610612724 1744830451 1879048178 2013265905 214748363
Note that iiop protocol is not supported when accessing remote DataSource on Weblogic. Using iiop will cause the following failure:
Exception in thread "main" java.lang.ClassCastException: weblogic.jdbc.common.internal.ConnectionEnv cannot be cast to java.io.Serializable
at weblogic.iiop.InboundResponseImpl.unmarshalReturn(InboundResponseImpl.java:103)
at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:338)
at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:252)
at weblogic.jdbc.common.internal.RemoteDataSource_IIOP_WLStub.getConnection(Unknown Source)
at foo.DataSourceClient.main(DataSourceClient.java:12)
Caused by: java.lang.ClassCastException: weblogic.jdbc.common.internal.ConnectionEnv cannot be cast to java.io.Serializable
at weblogic.iiop.IIOPOutputStream.writeObject(IIOPOutputStream.java:2253)
Technorati Tags: , ,

2 comments:

Anonymous said...

Nice one! That helped with my migration from JBoss to Weblogic.

Anonymous said...

"Cannot use IIOP"?
But when you connect to weblogic using Context - don't you have to pass in "t3://host:port"?

how do u avoid connecting via iiop?