Trying to run RMI example but facing the following exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: hejsan.RemoteBuffer
I have started the rmiregristry and it seems to be running fine. But the server is not running, it just builds and stops.
/Library/Java/JavaVirtualMachines/jdk1.7_45.jdk/Contents/Home/jre/bin/rmiregistry
Project name: hej
Package name: hejsan
Files: MyBuffer.java and RemoteBuffer.java
MyBuffer.java:
package hejsan;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.LinkedList;
#SuppressWarnings("serial")
public class MyBuffer extends UnicastRemoteObject implements RemoteBuffer {
LinkedList<Integer> list = new LinkedList<Integer>();
public MyBuffer() throws RemoteException, MalformedURLException {
super();
Naming.rebind("rmi://localhost/buffer", this);
}
public synchronized void put(Integer i) throws RemoteException {
list.addLast(i);
notifyAll();
}
public synchronized Integer get() throws RemoteException {
while (list.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return (Integer) list.removeFirst();
}
public static void main(String[] args) {
try {
new MyBuffer();
} catch (RemoteException re) {
System.out.println(re);
System.exit(1);
} catch (MalformedURLException me) {
System.out.println(me);
System.exit(1);
}
}
}
RemoteBuffer.java:
package hejsan;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteBuffer extends Remote {
void put(Integer i) throws RemoteException;
Integer get() throws RemoteException;
}
I discovered that I had to be on netbeans project path: ~/build/classes and runs the rmiregistry from while on that path.
The rmiregistry path can be found under Tools-> Java Platforms in netbeans. Caution! Change to jre instead of jdk following this below example:
/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/bin/rmiregistry
Related
we are trying to get RMI working over the Internet. What we tried:
Port forwarding (1099-1100) on Client and Serverside.
shut down firewall in windows and router
tried it with tunngle (www.tunngle.net/)
our RMI Interface:
import java.rmi.RemoteException;
public interface RMIInterface extends java.rmi.Remote {
public void helloWorld(int i) throws RemoteException;
}
our RMI Server Implementation:
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class RMIServerTest extends UnicastRemoteObject implements RMIInterface {
public RMIServerTest() throws RemoteException {
}
#Override
public void helloWorld(int i) throws RemoteException {
for (int j = 0; j < i; j++) {
System.out.println("Hello World");
}
}
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
}
catch (RemoteException ex) {
System.out.println(ex.getMessage());
}
try {
Naming.rebind("Server", new RMIServerTest());
} catch (MalformedURLException ex) {
System.out.println(ex.getMessage());
} catch (RemoteException ex) {
System.out.println(ex.getMessage());
}
}
}
and our Client:
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
public class RMIClient {
public static void main(String[] args) throws RemoteException, NotBoundException,MalformedURLException {
try {
RMIInterface serverObject = (RMIInterface) Naming.lookup("//externalServerAdress/Server");
serverObject.helloWorld(10);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
We're still getting this Error:
Connection refused to host: 192.168.0.13; nested exception is:
java.net.ConnectException: Connection timed out: connect
192.168.0.13 is the local IP-adress of the Server behind his router. We connect on client with the external IP of the router. like "2.246.133.155" = externalServerAdress.
So we have a connection. We connect over the external IP adress of the server (WAN IP) and error shows, it gets the local IP-adress of the server, but still refuse connection.
thx for any hint.
Connection refused to host: 192.168.0.13
That's not an Internet address. It is a private address that only exists behind your router. You need to use your public IP address, and arrange port forwarding via your router.
We are trying to create a system using Javas RMI. The problem is that a maintained list on the client cannot be accessed from the server using Java RMI. It seems that the RMI connection is handling a copy of the initialized list.
Below is a minimal example using an integer that the client increments every second until it equals 10. The server receives 0 all the time though.
Anyone have any idea what we are doing wrong?
Just run server and the client as a java application.
ServerDefaultImpl.java
package rmi;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class ServerDefaultImpl implements EIServerRemote, Runnable {
ClientRemote client;
private boolean running = true;
public ServerDefaultImpl() {
try {
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
ServerDefaultImpl server = this;
EIServerRemote stub = (EIServerRemote) UnicastRemoteObject.exportObject(server, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind("test", stub);
} catch (RemoteException e) {
e.printStackTrace();
}
new Thread(this).start();
}
public static void main(String[] args) {
new ServerDefaultImpl();
}
#Override
public void run() {
while (true == running) {
try {
Thread.sleep(1000);
if (null != client) { //Client not connected yet.
int test = client.test();
System.out.println(test);
running = test <= 10;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void attachClientListener(ClientRemote client) throws RemoteException {
this.client = client;
}
}
EIServerRemote.java
package rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface EIServerRemote extends Remote {
void attachClientListener(ClientRemote client) throws RemoteException;
}
ClientRemote.java
package rmi;
import java.io.Serializable;
import java.rmi.Remote;
public interface ClientRemote extends Remote,Serializable {
int test();
}
ClientDefaultImpl.java
package rmi;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class ClientDefaultImpl implements Runnable,
ClientRemote {
private static final long serialVersionUID = 4846141863099303590L;
protected EIServerRemote server = null;
public int test;
public boolean running = true;
public ClientDefaultImpl(String serverName) {
test = 0;
try {
connect(serverName);
} catch (RemoteException | NotBoundException e) {
e.printStackTrace();
}
new Thread(this).start();
}
public static void main(String[] args) {
new ClientDefaultImpl("test");
}
public void connect(String serverName) throws RemoteException,
NotBoundException {
Registry registry = LocateRegistry.getRegistry();
EIServerRemote s = (EIServerRemote) registry.lookup(serverName);
server = s;
s.attachClientListener((ClientRemote) this);
}
#Override
public void run() {
while (true == running) {
try {
Thread.sleep(1000);
System.out.println(test++);
running = test <= 10;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public int test() {
return test;
}
}
It seems that the RMI connection is handling a copy of the initialized list.
That's correct. The list isn't a remote object, so it is passed and returned via serialization.
============Server Interface:Server.java================
import java.rmi.*;
public interface Server extends Remote
{
void register (Client cl) throws RemoteException;
void broadcastCord () throws RemoteException;
}
=============Server Class:ServerImpl.java===============
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import java.net.*;
public class ServerImpl extends UnicastRemoteObject implements Server
{
public ServerImpl() throws RemoteException
{
}
public synchronized void register (Client cl) throws RemoteException
{
System.out.println("===>register Method of Process:");
cl.receiveInq();
}
//=========Broadcast Inquiry==================
public synchronized void broadcastCord () throws RemoteException
{
System.out.println("===>broadcastCord Method of Process:");
}
//==============Main Function===================
public static void main (String[] args)
{
try
{
System.out.println(InetAddress.getLocalHost().toString());
Naming.rebind("Server", new ServerImpl());
}
catch(Exception e)
{
System.err.println("Problem..."+e) ;
}
}
}
============Client InterfaceClient.java:=============
import java.rmi.*;
public interface Client extends Remote
{
void receiveInq() throws RemoteException;
void receiveGrt() throws RemoteException;
}
==============Client Class:ClientImpl.java==============
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
public class ClientImpl extends java.rmi.server.UnicastRemoteObject implements Client
{
private Server mycs;
public ClientImpl(Server cs) throws RemoteException
{
mycs=cs;
mycs.register(this);
}
//=====Greater List========
public synchronized void receiveGrt() throws RemoteException
{
System.out.println("===>recieveGRT Method of Process:");
}
//=====RECIEVE INQUIRY========
public synchronized void receiveInq () throws RemoteException
{
System.out.println("===>receiveInq Method of Process:");
mycs.broadcastCord();
}
public static void main(String args[])
{
String url = "rmi://localhost:1099/Server";
try{
Server cs= (Server) Naming.lookup(url);
new ClientImpl(cs);
}
catch(Exception e)
{
System.err.println("Problem..\n"+e) ;
}
}
}
it does not executes completely.......If we close the client program the execution
completes....but i don't know why its not executing properly....it does not throw any
exception
Remove 'synchronized'. You are deadlocked. RMI callbacks execute on a different thread from the original call.
I'm currently developing a system that loads classes via rmi. This system uses a classloader that communicates with the server in order to get the classes. The code is as follows.
Server:
import rocks.squareRock;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends UnicastRemoteObject
implements RemInterface {
public Server() throws RemoteException {
super();
}
public static void main(String argv[]) {
try {
Server serv = new Server();
Naming.rebind("RockServer", serv);
} catch (Throwable t) {
t.printStackTrace();
}
}
public Class<?> getRockClass(String type) {
if (type.equals("squareRock"))
return squareRock.class;
else
return null;
}
}
Client:
import rocks.Rock;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class Client {
RemInterface reminterface = null;
RockLoader rl = null;
public Client() {
String strName = "rmi://127.0.0.1/RockServer";
try {
reminterface = (RemInterface) Naming.lookup(strName);
rl = new RockLoader(reminterface);
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
}
loadRock("squareRock");
}
public Rock loadRock(String rock) {
try {
return (Rock) rl.loadClass(rock, false).newInstance();
} catch (Throwable t) {
return null;
}
}
}
Interface:
public interface RemInterface {
public Class<?> getRockClass(String type) throws RemoteException;
}
RockLoader:
import java.io.Serializable;
public class RockLoader extends ClassLoader implements Serializable {
private RemInterface reminterface = null;
public RockLoader(RemInterface reminterface) {
super();
this.reminterface = reminterface;
}
#Override
protected synchronized Class<?> loadClass(String className, boolean resolve)
throws ClassNotFoundException {
try {
return reminterface.getRockClass(className);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
The error I'm getting with this is (client-side):
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: SquareRock
This confuses me, as I'm not unmarshalling a SquareRock instance, but a Class. The only thought I have is that my classloader might be wrong.
It doesn't matter whether it's a Class or an object. The receiving JVM must have that class in its classpath, unless you are using the RMI codebase feature. What you are doing is basically trying to implement the codebase feature yourself. You can't do that.
I've been building an RMI application over the past week and I've hit a roadblock that no amount of googling can seem to help with.
The following code is used to send an object from the server to the client via RMI:
Server code:
import rocks.Rock;
import rocks.squareRock;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends UnicastRemoteObject
implements RemInterface {
public Server() throws RemoteException {
super();
}
public static void main(String argv[]) {
try {
Server serv = new Server();
Naming.rebind("RockServer", serv);
} catch (Throwable t) {
t.printStackTrace();
}
}
public Rock getRock() {
return new squareRock();
}
}
Client code:
import rocks.Rock;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class Client {
RemInterface reminterface = null;
public Client() {
String strName = "rmi://127.0.0.1/RockServer";
try {
reminterface = (RemInterface) Naming.lookup(strName);
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
public Rock loadRock() {
try {
return reminterface.getRock();
} catch (Throwable t) {
return null;
}
}
}
Interface:
public interface RemInterface {
public Rock getRock() throws RemoteException;
}
In this situation:
The "Rock" class is available in both the Client and Server classpath.
The "Rock" class implements serializable.
The "squareRock" extends class rock and is only available in the server's classpath.
The error I get when trying to call a method using a Rock from loadRock() on the client is as follows:
STDERR: java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: SquareRock
Any help would be appreciated.
You are returning an object of Type rocks.squareRock from the Server. During the de-serialization process at the client, this class will be required in order to create an instance of this class to represent the response from the server. As you've already indicated that the class is available only in the server's classpath, the failure to locate and load the said class causes the exception.
The resolution will be to make the rocks.squareRock class available in the client as well.