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?
Related
I am trying to run the rmi tutorial on oracles' website. I am able to run the server, but I receive an error running the client. The error I receive when try to run the client is a NotBoundException exception. How do I fix this error?
Below is the code and exception
Exception
Exception in thread "main" java.rmi.NotBoundException: Server
at java.rmi/sun.rmi.registry.RegistryImpl.lookup(RegistryImpl.java:234)
at java.rmi/sun.rmi.registry.RegistryImpl_Skel.dispatch(RegistryImpl_Skel.java:133)
at java.rmi/sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:468)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:298)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:832)
at java.rmi/sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:303)
at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:279)
at java.rmi/sun.rmi.server.UnicastRef.invoke(UnicastRef.java:380)
at java.rmi/sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:123)
at rmi.Client.main(Client.java:13)
I use Server and Client with different project at Port 1212
here is Server
package De_1;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws RemoteException, AlreadyBoundException {
Registry r = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
ProductDAO productDAO = new ProductDAOImpl();
r.bind("Server", productDAO);
}
}
and here is Client
package rmi;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Client {
public static void main(String[] args) throws RemoteException, NotBoundException {
Registry r = LocateRegistry.getRegistry(1212);
ProductDAO productDAO = (ProductDAO) r.lookup("Server");
System.out.println("Hay nhap");
Scanner sc = new Scanner(System.in);
while (true) {
String command = sc.nextLine();
StringTokenizer stringTokenizer = new StringTokenizer(command);
String request = stringTokenizer.nextToken();
System.out.println(request);
switch (request) {
case "HELLO": {
productDAO.addProduct();
}
default:
break;
}
}
}
}
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.
Here is my Program and,
package myapp;
import java.rmi.RemoteException;
import visad.DataImpl;
import visad.VisADException;
import visad.data.hdf5.HDF5Form;
import ncsa.hdf.hdf5lib.*;
public final class hfAdapter2
{
String filePath;
String path;
public hfAdapter2() throws VisADException, RemoteException
{
filePath="F:\\Devanshi\\Input\\xyz.h5";
System.load("F:\\Devanshi\\Projects\\MyApp\\Lib\\jhdf.dll");
System.load("F:\\Devanshi\\Projects\\MyApp\\Lib\\jhdf5.dll");
HDF5Form h=new HDF5Form();
DataImpl ncData=h.open(filePath);
}
public static void main(String[] args)
throws RemoteException, VisADException, IOException
{
new hfAdapter2();
}
}
The exception I got is :
Exception in thread "main" java.lang.UnsatisfiedLinkError:
ncsa.hdf.hdf5lib.H5.H5Fopen(Ljava/lang/String;II)I
at ncsa.hdf.hdf5lib.H5.H5Fopen(Native Method)
at visad.data.hdf5.hdf5objects.HDF5File.<init>(HDF5File.java:85)
at visad.data.hdf5.HDF5FileAdapted.<init>(HDF5FileAdapted.java:70)
at visad.data.hdf5.HDF5Form.open(HDF5Form.java:102)
at myapp.hfAdapter2.<init>(hfAdapter2.java:46)
at myapp.hfAdapter2.main(hfAdapter2.java:96)
I have tried to solve this by
-Dncsa.hdf.hdf5lib.H5.hdf5lib=F:\DLL\hdf5_ij_plugin\lib\win32
-Djava.library.path=F:\DLL\hdf5_ij_plugin\lib\win32
and also this:
-Dncsa.hdf.hdf5lib.H5.hdf5lib=F:\DLL\hdf5_ij_plugin\lib\win32\jhdf5.lib
-Djava.library.path=F:\DLL\hdf5_ij_plugin\lib\win32\jhdf5.lib
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 :)