i am tying to serially invoke Java RMI from server to other server ?
RMI Client 1 >--(1)--->RMI Server 1 >---(2)-----> RMI Server 2
Means on RMI Client 1 will invoke method on RMI Server 1 and that RMI server 1 will invoke method on Other RMI Server 2 acting client..for RMI Server 2 in same execution program
Exception : java.lang.ClassCastException: rmiserver1_Stub cannot be cast to interfc2
Please Help..
Code Here :
rmiserver1.java
import java.rmi.*;
import java.rmi.server.*;
import java.io.*;
import java.util.*;
class rmiserver1 extends UnicastRemoteObject implements interfc1
{
public rmiserver1() throws RemoteException
{
System.out.println("RMIServer 1 Constructor ");
}
public String remote1()
{
System.out.println("here Calling RMIServer2 method remote2 ");
try
{
//here is Exception
interfc2 obj2=(interfc2) Naming.lookup("rmi://localhost/rmiserver2");
String r2=obj2.remote2();
System.out.println("Result from rmiserver2 :"+r2);
}
catch(Exception e){e.printStackTrace();}
return "RMIServer1 remote 1 method return here....";
}
public static void main(String[] args)
{
System.out.println("RMIServer 1 Main method ");
try
{
rmiserver1 p1=new rmiserver1();
Naming.rebind("rmiserver1",p1);
System.out.println("RMIServer 1 rebinded ");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
interfc1.java
import java.rmi.*;
import java.io.*;
import java.util.*;
public interface interfc1 extends Remote
{
public String remote1() throws RemoteException;
}
interfc2.java
import java.rmi.*;
import java.io.*;
import java.util.*;
public interface interfc2 extends Remote
{
public String remote2() throws RemoteException;
}
rmiserver2.java
import java.rmi.*;
import java.rmi.server.*;
import java.io.*;
import java.util.*;
class rmiserver2 extends UnicastRemoteObject implements interfc2
{
public rmiserver2() throws RemoteException
{
System.out.println("RMIServer 2 Constructor ");
}
public String remote2()
{
return "RMIServer2 remote 2 method return here....";
}
public static void main(String[] args)
{
System.out.println("RMIServer 2 Main method ");
try
{
rmiserver1 p1=new rmiserver1();
Naming.rebind("rmiserver2",p1);
System.out.println("RMIServer 2 rebinded ");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
rmiclient1.java
import java.rmi.*;
import java.rmi.server.*;
import java.io.*;
import java.util.*;
class rmiclient1
{
public static void main(String[] args)
{
System.out.println("RMIClient 1 Main method");
try
{
interfc1 obj1=(interfc1) Naming.lookup("rmi://localhost/rmiserver1");
String r1=obj1.remote1();
System.out.println("Result from rmiserver1 :"+r1);
}
catch(Exception e){e.printStackTrace();}
}
}
Exception on rmiserver1 prompt :
java.lang.ClassCastException: rmiserver1_Stub cannot be cast to interfc2
at rmiserver1.remote1(rmiserver1.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:5
35)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTranspor
t.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport
.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExec
utor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor
.java:908)
at java.lang.Thread.run(Thread.java:619)
Please Help me.....
Your issue is in the main method of your class rmiserver2, you are binding rmiserver1 with the name "rmiserver2".
Your current code in the main method of rmiserver2
rmiserver1 p1=new rmiserver1();
Naming.rebind("rmiserver2",p1);
What you wanted was this :
rmiserver2 p2=new rmiserver2();
Naming.rebind("rmiserver2",p1);
Looks like a copy paste issue :)
Related
I'm trying to learn RMI. Managed to launch a simple example but I can't achieve dynamic loading of classes.
Hello.java
package com.example;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
String greet(String name) throws RemoteException;
}
HelloImpl.java
package com.example;
public class HelloImpl implements Hello {
public String greet(String name) {
System.out.println("Call from " + name);
return "Hello " + name + "!";
}
}
Server.java
package com.example;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends HelloImpl {
public Server() {}
public static void main(String args[]) {
System.setSecurityManager(new SecurityManager());
try {
HelloImpl greeter = new HelloImpl();
Hello stub = (Hello) UnicastRemoteObject.exportObject(greeter, 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
Client.java
package com.example;
import java.rmi.Naming;
public class Client {
private Client() {}
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager());
try {
Hello stub = (Hello) Naming.lookup("//localhost/Hello");
System.out.println(stub.greet(args[0]));
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
rmi.policy
grant {
permission java.security.AllPermission;
};
I started rmiregistry, web-server and executed java -Djava.security.policy=rmi.policy com.example.Server. When I try to start the client application with command
java -Djava.rmi.server.codebase=http://localhost:8000/ -Djava.security.policy=rmi.policy com.example.Client Hivemaster
web-server get request
127.0.0.1 - - [13/Dec/2017 14:06:45] "GET /com/example/Hello.class HTTP/1.1" 200
but program get exception
Exception in thread "main" java.lang.NoClassDefFoundError: com/example/Hello
at com.example.Client.main(Client.java:17)
Caused by: java.lang.ClassNotFoundException: com.example.Hello
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
Why?
If the client is using the Hello interface by name, it must be present on its classpath. Same as it does when compiling it.
The codebase feature is for classes derived from those mentioned in remote interfaces. In this case there is no apparent need to use the codebase feature at all: but if you do, the codebase property needs to be set at the JVM which is sending instances of those classes.
I am trying to write an RMI code for the very first time. The program performs a very simple function of getting the date from the server. I somehow managed to get the server running however at the client side exceptions occur:
Exception in thread "main" java.rmi.NotBoundException: //localhost/RemoteDatum
at sun.rmi.registry.RegistryImpl.lookup(RegistryImpl.java:166)
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:410)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:268)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$254(TCPTransport.java:683)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$1/1287360293.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:276)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:253)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:379)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at MyClient.main(MyClient.java:15)
My Interface "RemoteDatum" looks like this: (I copied the interface in server to the client Project folder and the stubs were generated by the RMI eclipse plugin)
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Date;
public interface RemoteDatum extends Remote{
public Date holeDatum() throws RemoteException; //holeDatum means getDate in german
}
RemoteDatumImpl: Implementation of Interface
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Date;
public class RemoteDatumImpl extends UnicastRemoteObject implements RemoteDatum {
protected RemoteDatumImpl() throws RemoteException {
super();
}
public Date holeDatum() throws RemoteException
{
return new Date();
}
}
The server:
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class MyServer extends UnicastRemoteObject {
protected MyServer() throws RemoteException {
super();
}
public static void main(String[] args) throws RemoteException, MalformedURLException
{
try
{
String name = "RemoteDatum";
Registry r = LocateRegistry.getRegistry();
MyServer service = new MyServer();
r.rebind(name, service);
}catch(Exception ex){ex.printStackTrace();}
}
}
My Client:
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class MyClient {
public static void main(String[] args) throws RemoteException, MalformedURLException, NotBoundException
{
Registry r = LocateRegistry.getRegistry();
String name = "//localhost/RemoteDatum";
RemoteDatum service = (RemoteDatum) r.lookup(name);
System.out.println(service.holeDatum());
}
}
I am using Eclipse RMI plugin to start RMI registry and don't know if that is relevant. I am using a Mac.
First:
Registry r = LocateRegistry.getRegistry();
Unless the client is running on the same host as the server, you need to get the server's Registry, not your own:
Registry r = LocateRegistry.getRegistry("serverhost);
Then:
String name = "//localhost/RemoteDatum";
RemoteDatum service = (RemoteDatum) r.lookup(name);
If you're using the Registry interface, you should not include the hostname in the lookup string. It should just be "RemoteDatum".
Alternatively, if you using the Naming class, you should include the hostname:
RemoteDatum service = (RemoteDatum)Naming.lookup("//serverhost/RemoteDatum");
I was learning rmi and I came up with a problem and I cannot solve it.
Here is the simple code
client code:
package rmi_test;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class client {
public static void main(String [] args) throws RemoteException, NotBoundException
{
Registry registry = LocateRegistry.getRegistry("127.0.0.1");
DNInterface s = (DNInterface) registry.lookup("DNInterface");
if (s.test())
System.out.println("Hello World");
}
}
Interface code:
package rmi_test;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface DNInterface extends Remote{
public boolean test() throws RemoteException;
}
Server Code:
package rmi_test;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class DataNodeImp implements DNInterface{
#Override
public boolean test() throws RemoteException {
System.out.println("test success");
return true;
}
public DataNodeImp()
{
super();
}
private static void boot() throws RemoteException
{
DNInterface d = new DataNodeImp();
DNInterface stub =
(DNInterface) UnicastRemoteObject.exportObject(d, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind("DNInterface", stub);
}
public static void main(String[] args) throws RemoteException
{
String name = "DNInterface";
boot();
}
}
Then I use the following commands to compile the code
javac -cp src: src/rmi_test/DNInterface.java
javac -cp src: src/rmi_test/DataNodeImp.java
javac -cp src: src/rmi_test/client.java
then i type
rmiregistry &
When I try to use
java -cp src: rmi_test.DataNodeImp to run the server
it said
Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: rmi_test.DNInterface
Is there anything wrong with the command I run the code?
Why I cannot find DNInterface.class?
Thank you very much!
The Registry doesn't have that class in its CLASSPATH.
The simplest solution is to use LocateRegistry.createRegistry() in the server JVM rather than rmiregistry.
I am learning RMI by myself now.I put all my files in the same directory and they are working well.But after I separate the server and client in different directory,there will be an error said
RemoteException
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: CalculatorImpl_Stub (no security manager: RMI class loader disabled).
I dont know how to fix it.and here is my code :
Server
import java.rmi.Naming;
public class CalculatorServer{
public CalculatorServer(){
try{
Calculator c = new CalculatorImpl();
Naming.rebind("rmi://localhost:1099/CalculatorService", c);
}catch(Exception e){
System.out.println("Trouble: "+ e);
}
}
public static void main(String args[]){
new CalculatorServer();
}
}
Client
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
public class CalculatorClient{
public static void main(String[] args){
try{
Calculator c = (Calculator)Naming.lookup("rmi://localhost/CalculatorService");
System.out.println(c.sub(4,3));
System.out.println(c.add(4,5));
System.out.println(c.mul(3,6));
System.out.println(c.div(9,3));
}catch(MalformedURLException murle){
System.out.println();
System.out.println("MalformedURLException");
System.out.println(murle);
}
....
}
You've over-separated. Some of the .class files are common to both the server and the client. The class mentioned in the exception is one of them, and so are any others that show up in subsequent such exceptions.
I have written a Java RMI chat application. There are four classes and two interfaces. Here they are:
ChatClient
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Scanner;
com.za.tutorial.rmi.server.ChatServerIF;
public class ChatClient extends UnicastRemoteObject implements ChatClientIF,Runnable {
private ChatServerIF chatServer;
private String name = null;
protected ChatClient(String name, ChatServerIF chatServer) throws RemoteException {
this.name = name;
this.chatServer = chatServer;
chatServer.registerChatClient(this);
}
public void retrieveMessage(String message) throws RemoteException {
// TODO Auto-generated method stub
System.out.println(message);
}
public void run() {
Scanner scanner = new Scanner(System.in);
String message;
while(true){
message = scanner.nextLine();
try {
chatServer.broadcastMessage(name + " : " + message);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
ChatClientDriver
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import com.za.tutorial.rmi.server.ChatServerIF;
public class ChatClientDriver {
public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
String chatServerURL = "rmi://localhost/RMIChatServer";
ChatServerIF chatServer = (ChatServerIF) Naming.lookup(chatServerURL);
new Thread(new ChatClient(args[0],chatServer)).start();
}
}
ChatClientInterface
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ChatClientIF extends Remote {
void retrieveMessage(String message) throws RemoteException;
}
ChatServer
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import com.za.tutorial.rmi.client.ChatClientIF;
public class ChatServer extends UnicastRemoteObject implements ChatServerIF {
private ArrayList<ChatClientIF> chatClients;
protected ChatServer() throws RemoteException {
chatClients = new ArrayList<ChatClientIF>();
}
public synchronized void registerChatClient(ChatClientIF chatClient)
throws RemoteException {
this.chatClients.add(chatClient);
}
public synchronized void broadcastMessage(String message) throws RemoteException {
int i = 0;
while(i < chatClients.size()){
chatClients.get(i++).retrieveMessage(message);
}
}
}
ChatServerDriver
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
public class ChatServerDriver {
public static void main(String[] args) throws RemoteException, MalformedURLException {
Naming.rebind("RMIChatServer", new ChatServer());
}
}
ChatServerInterface
import java.rmi.Remote;
import java.rmi.RemoteException;
import com.za.tutorial.rmi.client.ChatClientIF;
public interface ChatServerIF extends Remote {
void registerChatClient(ChatClientIF chatClient) throws RemoteException;
void broadcastMessage(String message) throws RemoteException;
}
When I run it on Commando, first of all I run rmic ChatClient and ChatServer, then rmiregistry. Then i run chatServerDriver which works completely fine. after that, when I run chatClientDriver with a name, I get the following error, I dont understand why :/ Can I get any solution for this?
Thanks :)
Exception in thread "main" java.rmi.NotBoundException: RMIChatServer
at sun.rmi.registry.RegistryImpl.lookup(RegistryImpl.java:136)
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:409)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
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 sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at java.rmi.Naming.lookup(Unknown Source)
at com.za.tutorial.rmi.client.ChatClientDriver.main(ChatClientDriver.java:15)
It also looks like you have a different address in Rebind to what is being used by the client to connect.
Naming.rebind("//localhost/RMIChatServer", new ChatServer());
There's an example implementation on the following Wikipedia page which may be worth comparing against your code.
http://en.wikipedia.org/wiki/Java_remote_method_invocation
Note that using Java 1.5+ you don't need to use rmic anymore see Do we really need to create Stub in java RMI?