Solved

RMI callback with JBoss

Posted on 2004-03-29
18
4,046 Views
Last Modified: 2013-12-22
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("Message 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;jbossall-client.jar com.elementk.client.TestClient
9) java -classpath .;EjbInterface.jar;jbossall-client.jar com.elementk.client.TestClient

Detailed exception:

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
        java.rmi.ServerException: RuntimeException; nested exception is:
        java.lang.IllegalArgumentException: wrong number of arguments
        at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:292)
        at sun.rmi.transport.Transport$1.run(Transport.java:148)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.Transport.serviceCall(Transport.java:144)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701)
        at java.lang.Thread.run(Thread.java:534)
        at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
        at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
        at sun.rmi.server.UnicastRef.invoke(Unknown Source)
        at org.jboss.invocation.jrmp.server.JRMPInvoker_Stub.invoke(Unknown Source)
        at org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxy.invoke(JRMPInvokerProxy.java:135)
        at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:96)
        at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:46)
        at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:45)
        at org.jboss.proxy.ejb.StatelessSessionInterceptor.invoke(StatelessSessionInterceptor.java:100)
        at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:85)
        at $Proxy2.register(Unknown Source)
        at com.elementk.client.TestClient.main(TestClient.java:25)
Caused by: java.rmi.ServerException: RuntimeException; nested exception is:
        java.lang.IllegalArgumentException: wrong number of arguments
        at org.jboss.ejb.plugins.LogInterceptor.handleException(LogInterceptor.java:361)
        at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195)
        at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
        at org.jboss.ejb.StatelessSessionContainer.internalInvoke(StatelessSessionContainer.java:331)
        at org.jboss.ejb.Container.invoke(Container.java:700)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:324)
        at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284)
        at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:546)
        at org.jboss.invocation.jrmp.server.JRMPInvoker.invoke(JRMPInvoker.java:367)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:324)
        at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:261)
        at sun.rmi.transport.Transport$1.run(Transport.java:148)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.Transport.serviceCall(Transport.java:144)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701)
        at java.lang.Thread.run(Thread.java:534)Caused by: java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:324)
        at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:683)
        at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185)
        at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:72)
        at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:84)
        at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267)
        at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:128)
        at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:118)
        at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191)
        ... 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.
0
Comment
Question by:JeremyGStein
  • 8
  • 6
  • 2
18 Comments
 
LVL 30

Expert Comment

by:Mayank S
ID: 10711682
It says:

>> java.lang.IllegalArgumentException: wrong number of arguments

Perhaps some method is receiving the wrong number of arguments.
0
 

Author Comment

by:JeremyGStein
ID: 10713157
mayankeagle, no doubt that's true.  I wish there was a way to turn on logging in the sun.rmi.server.UnicastServerRef 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.
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 10713326
Does your class implement Serializable?
0
 

Author Comment

by:JeremyGStein
ID: 10713354
mayankeagle,
No, as you can see above, it implements TestEjb.Callback, which means it implements Remote.
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 10713459
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?
0
 

Author Comment

by:JeremyGStein
ID: 10713487
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.TestEjb";
    private static String SERVER_URL = "localhost:1101";

    public TestClient() throws RemoteException {
        super();
    }

    public void send(String message) {
        System.out.println("Message 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.lookup(EJB_NAME);
        return testEjbHome.create();
    }

    private static Context getContext() throws NamingException {
        Properties p = new Properties();
        p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
        p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
        p.put(Context.PROVIDER_URL, SERVER_URL);

        return new InitialContext(p);
    }
}
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 10713523
>> jboss.naming:org.jnp.interfaces

Should this be: org.jboss.naming:org.jnp.interfaces ?
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 10713541
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

Author Comment

by:JeremyGStein
ID: 10714325
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.
0
 
LVL 9

Expert Comment

by:vzilka
ID: 10716771
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.
0
 

Author Comment

by:JeremyGStein
ID: 10716827
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.
0
 
LVL 9

Expert Comment

by:vzilka
ID: 10716898
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?
0
 

Author Comment

by:JeremyGStein
ID: 10871940
I haven't abandoned the problem.  I'm still trying to get this to work.
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 10876683
You should've replied to vzilka.
0
 

Author Comment

by:JeremyGStein
ID: 10962221
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.
0
 

Accepted Solution

by:
JeremyGStein earned 0 total points
ID: 10990646
I have found the answer.  The client stub was not available to the server.  Once I put the client stub on the server, it worked.
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Unable to start eclipse ? 17 134
Groovy:unable to resolve class error 2 70
JList custom Cell Renderer refresh 15 53
object oriented programming comparison 5 57
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now