EJB and JNI - how does it actually work?

Hi

I need to call JNI from an EJB. I know that this cannot be done directly as it would break the EJB programming restrictions. I understand that you need to create a standalone Java program (outside the container), which can use JNI to call C functions in a dll, and that the EJB can look up the Java program through JNDI, and call its methods.

What I don't understand is how to structure this standalone Java program, and I was wondering whether anyone can help me with this.

Manythanks

Lyndsey

[536 byte] By [hairsinl] at [2007-9-26 2:08:47]
# 1
The stand alone program has to be a RMI server (for example). The EJB will invoke a RMI method on this server, and the method on the server will invoke the native method.
steflead at 2007-6-29 8:57:42 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 2

Thanks for your help. I am trying it out today, and getting there slowly. I have managed to load the dll and invoke the native method. However I am having problems getting a return value from my native method. The method should return a String, but I am getting the error:

RemoteException

java.rmi.UnmarshalException: error unmarshalling return;nested exception is: java.io.WriteAbortedException: Writing aborted by exception; java.io.NotSerializableException: java.lang.Object

If you can help at all, I'd be very grateful.

Thanks again.

hairsinl at 2007-6-29 8:57:42 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 3

Do this in two steps...

1. Test you jni alone as a java program. You should be able to run your program, printout results (if you want), etc. The java class that wraps your jni should implement java.io.Serializable. You can go ahead and test the class by writing the class with one program, and reading the class with another progam....the key thing is that all of the members of your class must be serializable or they must be declared transient.

2. run your rmi server that was throwing the not serializable...now you know that can't be now, because you have already tested your jni...you should be off to the races.

rmi uses the Seriliazable interface to pass the member references over the wire. If the members are not all serializable, you will get this exception.

lwfry@bbnow.net at 2007-6-29 8:57:42 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 4

Hi, thanks for your help. Unfortunately I am still getting the same exception. The java class that wraps the JNI is as follows - can you spot where I am going wrong? Many thanks...

************

import java.rmi.*;

import java.util.*;

import java.io.Serializable;

/**

*This is the implementation for the remote service

*/

public class CToolsImpl

extends java.rmi.server.UnicastRemoteObject implements CTools, java.io.Serializable

{

private CTCurve ct; //this is the JNI class

public CToolsImpl() throws RemoteException

{

super();

ct = new CTCurve();

}

public String getVersion() throws RemoteException

{

try

{

return ct.version();

}

catch (UnsatisfiedLinkError e)

{

throw new RemoteException(e.toString());

}

catch (Exception e)

{

throw new RemoteException(e.toString());

}

}

}

hairsinl at 2007-6-29 8:57:42 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 5
its that pesky jni class. It appears that this is your only member...if you do not this class with the serializable interface, this would do it.Try declaring this transiant ...private transient CTxxx ct;
lwfry@bbnow.net at 2007-6-29 8:57:42 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 6

I think I actually have a problem with the JNI part. As per your earlier suggestion I tried testing the JNi without the RMI - i.e. I created a test class with main(), in which I created an instance of the JNI class (CTCurve), and then called the version() method on this instance. It threw a horrible virtual machine exception along the lines of: EXCEPTION_ACCESS_VIOLATION, Function name = JVM_ArrayCopy, Library=C:\Program Files\JavaSoft\JRE\1.3.1\bin\hotspot\jvm.dll.

I am new to JNI and also C. My program can obviously load the dll, but does it need to see the C programs as well? Not sure how it works...

Any suggestions much appreciated - many thanks

hairsinl at 2007-6-29 8:57:42 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 7

Hi - I didn't manage to solve the previous problem, so I have been working on the JNDI bit. I am now having difficulties trying to bind the remote object to the WebSphere 3.5 JNDI naming service (com.ibm.ejs.jndi.CNInitialContext Factory). When I use ctx.bind(name object) I am getting a java.lang.ClassCastException. Here is my code:

CurveGenRemote c = new CurveGenImpl();

Hashtable env = new Hashtable();

env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,"com.ibm.ejs.ns.jndi.CNInitialContextFactory");

env.put(javax.naming.Context.PROVIDER_URL, "iiop://localhost:900");

InitialContext ctx = new InitialContext(env);

ctx.bind("CurveGenService",c);

Would be really grateful for any suggestions as this is driving me mad! Thanks in advance.

hairsinl at 2007-6-29 8:57:42 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 8
It's still the serialization problem. Your class should be serializable, otherwise it can't be bound to JNDIM
maozhoulu at 2007-6-29 8:57:42 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...