2

Note: I changed the question title to be more precise

Here is my question: When using RMI to communicate between a client and a server, does the client needs to have the Stub in his classpath, or does this Stub should only be on server side?


Note, the "full" story:

I am currently working on a web-application that calls a calculation engine. The communication between these 2 elements is made using RMI.

Here is Maven structure of the project:

my-project
 +- core
 +- web-application
 +- engine

Both web-application and engine have a dependency on core.

In core module, I've defined an interface:

public interface MyEngine extends java.rmi.Remote {

    MyResults calculate() throws RemoteException;

}

In engine module (which is the server on the RMI point of view), I define the implementation of this interface:

public class MyEngineImpl extends UnicastRemoteObject implements MyEngine {

    public MyResults calculate() throws RemoteException {
        ...
    }

    public static void main(String... args) {
        MyEngine engine = new MyEngineImpl();
        Registry registry = LocateRegistry.createRegistry(1418);
        registry.rebind("my-engine", engine);
    }

}

Finally, on the web-application, I wrote a class that calls the engine module, using the interface of core:

public class RemoteEngineFacade {

    public MyResults callCalculate() throws RemoteException {
        Registry localisation = LocateRegistry.getRegistry("url-of-engine", 1418);
        MyEngine engine = (LiquidityEngine) localisation.lookup("my-engine");
        return engine.calculate();
    }

}

The RMI compilation is made by the rmic Maven plugin:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>rmic-maven-plugin</artifactId>
    <version>1.1</version>
    <executions>
        <execution>
            <id>rmi compilation</id>
            <goals>
                <goal>rmic</goal>
            </goals>
            <configuration>
                <outputDirectory>target/classes</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

(note that this plugin definition is made on each module)

Now, after deploying the application, when the web-application is calling the engine, I get the following error on the web-application logs:

2012-03-12 09:42:37 ERROR [xxx.RemoteEngineFacade] Engine is unable to respond to the request
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
    java.lang.ClassNotFoundException: xxx.MyEngineImpl_Stub (no security manager: RMI class loader disabled)
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at xxx.RemoteEngineFacade.callCalculate(RemoteEngineFacade.java:50)
    ...

I don't get why it is looking for the Stub on the web-application side, as normally the Stub has only to be located on the RMI server (the engine in my context).

Do you have any idea where is my problem?

Thanks.


Edit: Setting a security manager, as explained in Riddhish.Chaudhari answer did solve the issue. The only difference is that I don't have the no security manager: RMI class loader disabled message in the stacktrace anymore...


Edit 2: If I copy the engine.jar in my WEB-INF/lib, then the communication is made correctly. But I should not have to add the engine library in my web-application...

Romain Linsolas
  • 79,475
  • 49
  • 202
  • 273
  • possible duplicate of [RMI ClassNotFoundException](http://stackoverflow.com/questions/7387031/rmi-classnotfoundexception) – user207421 Mar 12 '12 at 09:04
  • It seems to be the same problem, but in the other question, no answer was accepted, and the user indicates that it was just a configuration issue... – Romain Linsolas Mar 12 '12 at 09:10
  • and that's exactly what it is, a configuration issue. The class named is not available at the client. It has to be there so the client can use it. That's what it's *for.* Unless you are using dynamic stubs, which you aren't, or you wouldn't be getting that error message. – user207421 Mar 13 '12 at 01:18

2 Answers2

2

I finally solved my problem. In this page, it is said that

As of the J2SE 5.0 release, stub classes for remote objects no longer need to be pregenerated using the rmic stub compiler, unless the remote object needs to support clients running in pre-5.0 VMs

As I am working with Java 6, I decided to simply remove the rmic tasks in my pom.xml files... and it worked!

Maybe the presence of a Stub in the server (my engine) creates some confusion for the JVM, which produces the error I got...

Romain Linsolas
  • 79,475
  • 49
  • 202
  • 273
-2

You are not using a security manager:

Have you got a policy file (mypolicy.policy):

grant {
  permission java.security.AllPermission;
};

and run your program using

java -Djava.security.manager -Djava.security.policy=/some/path/myplicy.policy MyClass

Use below link to for complete example of how to use security policy permission

http://www.javacoffeebreak.com/articles/javarmi/javarmi.html

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
Riddhish.Chaudhari
  • 833
  • 1
  • 8
  • 24
  • Ok, thanks. I will check that. Do I need to also add in my code the `System.setSecurityManager(new RMISecurityManager());` line ? – Romain Linsolas Mar 12 '12 at 09:11
  • -1. None of this would make any difference unless he also started using the codebase feature. Not an answer. – user207421 Jul 21 '12 at 10:11