JeremyGStein
asked on
RMI callback with JBoss
I'm trying to call an EJB method on a JBoss server, passing it a reference to the client object so that I can receive a
callback. I used to have this working when we were using Weblogic, but I can't seem to get it to work for JBoss.
The EJB's interface includes a nested interface that extends Remote:
public interface TestEjb extends EJBObject {
public void register(Callback callback) throws RemoteException;
public interface Callback extends Remote {
public void send(String message) throws RemoteException;
}
}
My client implements that interface:
public class TestClient extends UnicastRemoteObject implements TestEjb.Callback {
...
public void send(String message) {
System.out.println("Messag e from server: '" + message + "'");
}
...
}
I expect to be able to pass "this" to TestEbj.register. However, I get an IllegalArgumentException from the server, claiming
that I am passing the wrong number of arguments.
Steps to reproduce:
1) Get the source files here: http://www.everybody.org/~jeremystein/code/CallbackTest.zip
2) Extract the zip file
3) The server directory contains the Test EJB. Deploy it on a JBoss server.
4) The EjbInterface.jar file contains these classes needed to compile the client.
- TestEjb$Callback.class
- TestEjb.class
- TestEjbHome.class
(You could create this jar yourself after compiling the EJB classes.)
5) Grab jbossall-client.jar from the jboss distribution (in the client directory). Put it in the client directory.
6) CD to the client directory.
7) javac -d . -classpath EjbInterface.jar;jbossall- client.jar TestClient.java
8) rmic -classpath .;EjbInterface.jar;jbossal l-client.j ar com.elementk.client.TestCl ient
9) java -classpath .;EjbInterface.jar;jbossal l-client.j ar com.elementk.client.TestCl ient
Detailed exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.ServerException: RuntimeException; nested exception is:
java.lang.IllegalArgumentE xception: wrong number of arguments
at sun.rmi.server.UnicastServ erRef.disp atch(Unica stServerRe f.java:292 )
at sun.rmi.transport.Transpor t$1.run(Tr ansport.ja va:148)
at java.security.AccessContro ller.doPri vileged(Na tive Method)
at sun.rmi.transport.Transpor t.serviceC all(Transp ort.java:1 44)
at sun.rmi.transport.tcp.TCPT ransport.h andleMessa ges(TCPTra nsport.jav a:460)
at sun.rmi.transport.tcp.TCPT ransport$C onnectionH andler.run (TCPTransp ort.java:7 01)
at java.lang.Thread.run(Threa d.java:534 )
at sun.rmi.transport.StreamRe moteCall.e xceptionRe ceivedFrom Server(Unk nown Source)
at sun.rmi.transport.StreamRe moteCall.e xecuteCall (Unknown Source)
at sun.rmi.server.UnicastRef. invoke(Unk nown Source)
at org.jboss.invocation.jrmp. server.JRM PInvoker_S tub.invoke (Unknown Source)
at org.jboss.invocation.jrmp. interfaces .JRMPInvok erProxy.in voke(JRMPI nvokerProx y.java:135 )
at org.jboss.invocation.Invok erIntercep tor.invoke (InvokerIn terceptor. java:96)
at org.jboss.proxy.Transactio nIntercept or.invoke( Transactio nIntercept or.java:46 )
at org.jboss.proxy.SecurityIn terceptor. invoke(Sec urityInter ceptor.jav a:45)
at org.jboss.proxy.ejb.Statel essSession Intercepto r.invoke(S tatelessSe ssionInter ceptor.jav a:100)
at org.jboss.proxy.ClientCont ainer.invo ke(ClientC ontainer.j ava:85)
at $Proxy2.register(Unknown Source)
at com.elementk.client.TestCl ient.main( TestClient .java:25)
Caused by: java.rmi.ServerException: RuntimeException; nested exception is:
java.lang.IllegalArgumentE xception: wrong number of arguments
at org.jboss.ejb.plugins.LogI nterceptor .handleExc eption(Log Intercepto r.java:361 )
at org.jboss.ejb.plugins.LogI nterceptor .invoke(Lo gIntercept or.java:19 5)
at org.jboss.ejb.plugins.Prox yFactoryFi nderInterc eptor.invo ke(ProxyFa ctoryFinde rIntercept or.java:12 2)
at org.jboss.ejb.StatelessSes sionContai ner.intern alInvoke(S tatelessSe ssionConta iner.java: 331)
at org.jboss.ejb.Container.in voke(Conta iner.java: 700)
at sun.reflect.NativeMethodAc cessorImpl .invoke0(N ative Method)
at sun.reflect.NativeMethodAc cessorImpl .invoke(Na tiveMethod AccessorIm pl.java:39 )
at sun.reflect.DelegatingMeth odAccessor Impl.invok e(Delegati ngMethodAc cessorImpl .java:25)
at java.lang.reflect.Method.i nvoke(Meth od.java:32 4)
at org.jboss.mx.capability.Re flectedMBe anDispatch er.invoke( ReflectedM BeanDispat cher.java: 284)
at org.jboss.mx.server.MBeanS erverImpl. invoke(MBe anServerIm pl.java:54 6)
at org.jboss.invocation.jrmp. server.JRM PInvoker.i nvoke(JRMP Invoker.ja va:367)
at sun.reflect.NativeMethodAc cessorImpl .invoke0(N ative Method)
at sun.reflect.NativeMethodAc cessorImpl .invoke(Na tiveMethod AccessorIm pl.java:39 )
at sun.reflect.DelegatingMeth odAccessor Impl.invok e(Delegati ngMethodAc cessorImpl .java:25)
at java.lang.reflect.Method.i nvoke(Meth od.java:32 4)
at sun.rmi.server.UnicastServ erRef.disp atch(Unica stServerRe f.java:261 )
at sun.rmi.transport.Transpor t$1.run(Tr ansport.ja va:148)
at java.security.AccessContro ller.doPri vileged(Na tive Method)
at sun.rmi.transport.Transpor t.serviceC all(Transp ort.java:1 44)
at sun.rmi.transport.tcp.TCPT ransport.h andleMessa ges(TCPTra nsport.jav a:460)
at sun.rmi.transport.tcp.TCPT ransport$C onnectionH andler.run (TCPTransp ort.java:7 01)
at java.lang.Thread.run(Threa d.java:534 )Caused by: java.lang.IllegalArgumentE xception: wrong number of arguments
at sun.reflect.NativeMethodAc cessorImpl .invoke0(N ative Method)
at sun.reflect.NativeMethodAc cessorImpl .invoke(Na tiveMethod AccessorIm pl.java:39 )
at sun.reflect.DelegatingMeth odAccessor Impl.invok e(Delegati ngMethodAc cessorImpl .java:25)
at java.lang.reflect.Method.i nvoke(Meth od.java:32 4)
at org.jboss.ejb.StatelessSes sionContai ner$Contai nerInterce ptor.invok e(Stateles sSessionCo ntainer.ja va:683)
at org.jboss.resource.connect ionmanager .CachedCon nectionInt erceptor.i nvoke(Cach edConnecti onIntercep tor.java:1 85)
at org.jboss.ejb.plugins.Stat elessSessi onInstance Intercepto r.invoke(S tatelessSe ssionInsta nceInterce ptor.java: 72)
at org.jboss.ejb.plugins.Abst ractTxInte rceptor.in vokeNext(A bstractTxI nterceptor .java:84)
at org.jboss.ejb.plugins.TxIn terceptorC MT.runWith Transactio ns(TxInter ceptorCMT. java:267)
at org.jboss.ejb.plugins.TxIn terceptorC MT.invoke( TxIntercep torCMT.jav a:128)
at org.jboss.ejb.plugins.Secu rityInterc eptor.invo ke(Securit yIntercept or.java:11 8)
at org.jboss.ejb.plugins.LogI nterceptor .invoke(Lo gIntercept or.java:19 1)
... 21 more
If no one can tell me what's wrong with my code, perhaps someone can point me to a COMPLETE example of RMI callback that works with JBoss.
callback. I used to have this working when we were using Weblogic, but I can't seem to get it to work for JBoss.
The EJB's interface includes a nested interface that extends Remote:
public interface TestEjb extends EJBObject {
public void register(Callback callback) throws RemoteException;
public interface Callback extends Remote {
public void send(String message) throws RemoteException;
}
}
My client implements that interface:
public class TestClient extends UnicastRemoteObject implements TestEjb.Callback {
...
public void send(String message) {
System.out.println("Messag
}
...
}
I expect to be able to pass "this" to TestEbj.register. However, I get an IllegalArgumentException from the server, claiming
that I am passing the wrong number of arguments.
Steps to reproduce:
1) Get the source files here: http://www.everybody.org/~jeremystein/code/CallbackTest.zip
2) Extract the zip file
3) The server directory contains the Test EJB. Deploy it on a JBoss server.
4) The EjbInterface.jar file contains these classes needed to compile the client.
- TestEjb$Callback.class
- TestEjb.class
- TestEjbHome.class
(You could create this jar yourself after compiling the EJB classes.)
5) Grab jbossall-client.jar from the jboss distribution (in the client directory). Put it in the client directory.
6) CD to the client directory.
7) javac -d . -classpath EjbInterface.jar;jbossall-
8) rmic -classpath .;EjbInterface.jar;jbossal
9) java -classpath .;EjbInterface.jar;jbossal
Detailed exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.ServerException: RuntimeException; nested exception is:
java.lang.IllegalArgumentE
at sun.rmi.server.UnicastServ
at sun.rmi.transport.Transpor
at java.security.AccessContro
at sun.rmi.transport.Transpor
at sun.rmi.transport.tcp.TCPT
at sun.rmi.transport.tcp.TCPT
at java.lang.Thread.run(Threa
at sun.rmi.transport.StreamRe
at sun.rmi.transport.StreamRe
at sun.rmi.server.UnicastRef.
at org.jboss.invocation.jrmp.
at org.jboss.invocation.jrmp.
at org.jboss.invocation.Invok
at org.jboss.proxy.Transactio
at org.jboss.proxy.SecurityIn
at org.jboss.proxy.ejb.Statel
at org.jboss.proxy.ClientCont
at $Proxy2.register(Unknown Source)
at com.elementk.client.TestCl
Caused by: java.rmi.ServerException: RuntimeException; nested exception is:
java.lang.IllegalArgumentE
at org.jboss.ejb.plugins.LogI
at org.jboss.ejb.plugins.LogI
at org.jboss.ejb.plugins.Prox
at org.jboss.ejb.StatelessSes
at org.jboss.ejb.Container.in
at sun.reflect.NativeMethodAc
at sun.reflect.NativeMethodAc
at sun.reflect.DelegatingMeth
at java.lang.reflect.Method.i
at org.jboss.mx.capability.Re
at org.jboss.mx.server.MBeanS
at org.jboss.invocation.jrmp.
at sun.reflect.NativeMethodAc
at sun.reflect.NativeMethodAc
at sun.reflect.DelegatingMeth
at java.lang.reflect.Method.i
at sun.rmi.server.UnicastServ
at sun.rmi.transport.Transpor
at java.security.AccessContro
at sun.rmi.transport.Transpor
at sun.rmi.transport.tcp.TCPT
at sun.rmi.transport.tcp.TCPT
at java.lang.Thread.run(Threa
at sun.reflect.NativeMethodAc
at sun.reflect.NativeMethodAc
at sun.reflect.DelegatingMeth
at java.lang.reflect.Method.i
at org.jboss.ejb.StatelessSes
at org.jboss.resource.connect
at org.jboss.ejb.plugins.Stat
at org.jboss.ejb.plugins.Abst
at org.jboss.ejb.plugins.TxIn
at org.jboss.ejb.plugins.TxIn
at org.jboss.ejb.plugins.Secu
at org.jboss.ejb.plugins.LogI
... 21 more
If no one can tell me what's wrong with my code, perhaps someone can point me to a COMPLETE example of RMI callback that works with JBoss.
ASKER
mayankeagle, no doubt that's true. I wish there was a way to turn on logging in the sun.rmi.server.UnicastServ erRef class to see what arguments it was using with my method. The client is calling testEjb.register(this). I suspect that RMI is somehow unable to pass the remote object and so it leaves it off the argument list? I don't know how to tell what's really happening.
Does your class implement Serializable?
ASKER
mayankeagle,
No, as you can see above, it implements TestEjb.Callback, which means it implements Remote.
No, as you can see above, it implements TestEjb.Callback, which means it implements Remote.
Oh, right. I didn't read the whole of your question properly. How do you obtain a reference to the EJB (where you call the method)? Can you show that part of your code?
ASKER
OK, here's the whole client. It's also available from the zip file here: http://www.everybody.org/~jeremystein/code/CallbackTest.zip
TestClient.java:
package com.elementk.client;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import javax.ejb.*;
import javax.naming.*;
import com.elementk.server.*;
public class TestClient extends UnicastRemoteObject implements TestEjb.Callback {
private static String EJB_NAME = "com.elementk.server.TestE jb";
private static String SERVER_URL = "localhost:1101";
public TestClient() throws RemoteException {
super();
}
public void send(String message) {
System.out.println("Messag e from server: '" + message + "'");
}
public static void main(String args[]) {
try {
TestClient client = new TestClient();
getEjb().register(client);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
private static TestEjb getEjb() throws NamingException, CreateException, RemoteException {
Context context = getContext();
TestEjbHome testEjbHome = (TestEjbHome)context.looku p(EJB_NAME );
return testEjbHome.create();
}
private static Context getContext() throws NamingException {
Properties p = new Properties();
p.put(Context.INITIAL_CONT EXT_FACTOR Y, "org.jnp.interfaces.Naming ContextFac tory");
p.put(Context.URL_PKG_PREF IXES, "jboss.naming:org.jnp.inte rfaces");
p.put(Context.PROVIDER_URL , SERVER_URL);
return new InitialContext(p);
}
}
TestClient.java:
package com.elementk.client;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import javax.ejb.*;
import javax.naming.*;
import com.elementk.server.*;
public class TestClient extends UnicastRemoteObject implements TestEjb.Callback {
private static String EJB_NAME = "com.elementk.server.TestE
private static String SERVER_URL = "localhost:1101";
public TestClient() throws RemoteException {
super();
}
public void send(String message) {
System.out.println("Messag
}
public static void main(String args[]) {
try {
TestClient client = new TestClient();
getEjb().register(client);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
private static TestEjb getEjb() throws NamingException, CreateException, RemoteException {
Context context = getContext();
TestEjbHome testEjbHome = (TestEjbHome)context.looku
return testEjbHome.create();
}
private static Context getContext() throws NamingException {
Properties p = new Properties();
p.put(Context.INITIAL_CONT
p.put(Context.URL_PKG_PREF
p.put(Context.PROVIDER_URL
return new InitialContext(p);
}
}
>> jboss.naming:org.jnp.inter faces
Should this be: org.jboss.naming:org.jnp.i nterfaces ?
Should this be: org.jboss.naming:org.jnp.i
Have a look at this: http://nemesisit.rdsnet.ro/opendocs/simplearch/simplejboss.html
ASKER
mayankeagle,
Changing jboss.naming to org.jboss.naming didn't make a difference, although perhaps the latter is more correct.
The link is interesting, but I think it's more geared toward getting through a firewall. I'm not having that problem. The article doesn't mention callbacks or passing remote objects. Thanks.
Changing jboss.naming to org.jboss.naming didn't make a difference, although perhaps the latter is more correct.
The link is interesting, but I think it's more geared toward getting through a firewall. I'm not having that problem. The article doesn't mention callbacks or passing remote objects. Thanks.
Can you describe here what you want to achieve? Perhaps there is a better way to do it.
Passing this of a remote and expecting the server to understand it needs to get the stub sounds fishy to me.
Passing this of a remote and expecting the server to understand it needs to get the stub sounds fishy to me.
ASKER
vzilka,
There are plenty of reasons for callbacks. When I had this working with Weblogic, I used it for a couple of purposes:
1) The server could decide whether it needed further data and request it as necessary. For large chunks of data that were only sometimes required by the server, this allowed me to pass that data as necessary.
2) Logging. The server would send a message to the callback object with logging information. In my case, I don't have access to the server's production log. By sending logging information back to me, I can diagnose problems more easily.
With RMI, you're supposed to be able to pass either a serializable or a remote object. I can get a serializable object to be passed, but not a remote object. I think the fact that the remote object happens to be "this" shouldn't be important.
There are plenty of reasons for callbacks. When I had this working with Weblogic, I used it for a couple of purposes:
1) The server could decide whether it needed further data and request it as necessary. For large chunks of data that were only sometimes required by the server, this allowed me to pass that data as necessary.
2) Logging. The server would send a message to the callback object with logging information. In my case, I don't have access to the server's production log. By sending logging information back to me, I can diagnose problems more easily.
With RMI, you're supposed to be able to pass either a serializable or a remote object. I can get a serializable object to be passed, but not a remote object. I think the fact that the remote object happens to be "this" shouldn't be important.
I am sorry, I did not explain my self correctly.
Of course sending a remote reference from the client is useful.
However, I find it hard to believe it will work. I don't think it is the this usage. I think that the server expects to recieve a stub, and how will this stub be transferred? WHo will create an object of the skeleton to listen to it?
I can think of other solutions, but it depends on your architecture.
Is your client app running in a J2EE container?
Of course sending a remote reference from the client is useful.
However, I find it hard to believe it will work. I don't think it is the this usage. I think that the server expects to recieve a stub, and how will this stub be transferred? WHo will create an object of the skeleton to listen to it?
I can think of other solutions, but it depends on your architecture.
Is your client app running in a J2EE container?
ASKER
I haven't abandoned the problem. I'm still trying to get this to work.
You should've replied to vzilka.
ASKER
vzilka,
I knew that RMI callback is supposed to work, but it took me a long time to find a good example online. Here is such an example:
http://java.sun.com/developer/onlineTraining/rmi/RMI.html#RMIClientSideCallbacks
I believe most of your questions are addressed in the article.
My client is NOT running in a J2EE container.
I knew that RMI callback is supposed to work, but it took me a long time to find a good example online. Here is such an example:
http://java.sun.com/developer/onlineTraining/rmi/RMI.html#RMIClientSideCallbacks
I believe most of your questions are addressed in the article.
My client is NOT running in a J2EE container.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> java.lang.IllegalArgumentE
Perhaps some method is receiving the wrong number of arguments.