# RMI Registry



## rmacher (15. Dez 2013)

Hallo 

Ich habe mehrere RMI Applikationen, die auf einem Server laufen sollten. Ich kann für jede Applikation  jeweils eine Rmi-Registry Instanz (auf einem separaten Port) starten und dann funktioniert es. Jedoch würde ich gerne nur eine einzige RMI Registry Instanz laufen lassen und die RemoteObjects aus unterschiedlichen RMI-Applikationen bei der gleichen RMI Registry Instanz anmelden. 

*Ist das überhaupt möglich?* Alle meine Versuche waren bis jetzt erfolgslos!

Konkret habe ich zwei kleine Test-Applikationen implementiert: die erste liefert Datum (als String) und die zweite die Zeit (als String) zurück. 

*Die erste Applikation (Date):* 

```
// Interface
package date.server;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RmiDate extends Remote {
	String localDateAsString() throws RemoteException;
}

// Implementiertende Klasse 
package date.server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.SimpleDateFormat;
import java.util.Date;

public class RmiDateImpl extends UnicastRemoteObject implements RmiDate {

	private static final long serialVersionUID = 1L;

	public RmiDateImpl() throws RemoteException {

	}

	@Override
	public String localDateAsString() throws RemoteException {
		return new SimpleDateFormat("yyyy-MM-dd").format(new Date());
	}
}

// Server-Klasse 
package date.server;

import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.swing.JOptionPane;

public class RmiDateServer {

	public static void main(String[] args) {

		int port = 0;
		String remoteObjectName = "dateRO";
		Registry reg = null;

		if (args.length < 1) {
			System.out
					.println("\nusage: java server.RmiDateServer rmiPortNummer");
			System.exit(0);
		} else {

			try {

				port = Integer.valueOf(args[0]);

				System.setProperty("java.security.policy", "rmi.policy");

				if (System.getSecurityManager() == null) {
					System.setSecurityManager(new RMISecurityManager());
				}

				try {
					reg = LocateRegistry.createRegistry(port);
				} catch (Exception e) {
					reg = LocateRegistry.getRegistry(port);
				}

				if (reg != null) {

					RmiDate obj = new RmiDateImpl();

					Naming.rebind(remoteObjectName, obj);

					JOptionPane
							.showMessageDialog(
									null,
									"RMI Date-Server ist bereit für Anfragen von Clients.\n\nServer herunterfahren?",
									"RMI TimeServer ["
											+ InetAddress.getLocalHost()
													.getHostAddress() + ":"
											+ port + "]",
									JOptionPane.QUESTION_MESSAGE);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}
```

Die Policy-Datei ist (zum Testen) wie folgt:
[XML]
grant {
	permission java.security.AllPermission;
};
[/XML]

*Die zweite Applikation (Time): *

```
// Interface
package time.server;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RmiTime extends Remote {
	String localTimeAsString() throws RemoteException;
}


// Implementierende Klasse 
package time.server;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.SimpleDateFormat;
import java.util.Date;

public class RmiTimeImpl extends UnicastRemoteObject implements RmiTime,
		Serializable {

	private static final long serialVersionUID = 1L;

	public RmiTimeImpl() throws RemoteException {

	}

	@Override
	public String localTimeAsString() throws RemoteException {
		return new SimpleDateFormat("hh:mm:ss:SSSS").format(new Date());
	}
}

// Server-Klasse:
package time.server;

import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.swing.JOptionPane;

public class RmiTimeServer {

	public static void main(String[] args) {

		int port = 0;
		Registry reg = null;

		if (args.length < 1) {
			System.out
					.println("\nusage: java server.RmiTimeServer rmiPortNummer");
			System.exit(0);
		} else {
			try {
				port = Integer.valueOf(args[0]);

				System.setProperty("java.security.policy", "rmi.policy");

				if (System.getSecurityManager() == null) {
					System.setSecurityManager(new RMISecurityManager());
				}

				try {
					reg = LocateRegistry.createRegistry(port);
				} catch (Exception e) {
					reg = LocateRegistry.getRegistry(port);
				}

				if (reg != null) {

					RmiTime obj = new RmiTimeImpl();
					Naming.rebind("timeRO", obj);

					JOptionPane
							.showMessageDialog(
									null,
									"RMI Time-Server ist bereit für Anfragen von Clients.\n\nServer herunterfahren?",
									"RMI TimeServer ["
											+ InetAddress.getLocalHost()
													.getHostAddress() + ":"
											+ port + "]",
									JOptionPane.QUESTION_MESSAGE);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}
```

Die rmi.policy Datei ist wie bei der ersten Applikation (AllPermission) und steht auch zur Verfügung.


Ich kann eine (beliebige) Applikation starten, jedoch wenn ich die zweite Applikation starte *(mit der gleichen RMI Port-Nummer)*, wird die Ausnahme geworfen. 

Hier die Ausnahme: 

```
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: time.server.RmiTime
	at sun.rmi.server.UnicastServerRef.oldDispatch(Unknown Source)
	at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
	at sun.rmi.transport.Transport$1.run(Unknown Source)
	at sun.rmi.transport.Transport$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
	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.rebind(Unknown Source)
	at java.rmi.Naming.rebind(Unknown Source)
	at time.server.RmiTimeServer.main(RmiTimeServer.java:41)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: time.server.RmiTime
	at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
	at sun.rmi.server.UnicastServerRef.oldDispatch(Unknown Source)
	at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
	at sun.rmi.transport.Transport$1.run(Unknown Source)
	at sun.rmi.transport.Transport$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: time.server.RmiTime
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.rmi.server.LoaderHandler$Loader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Unknown Source)
	at sun.rmi.server.LoaderHandler.loadClassForName(Unknown Source)
	at sun.rmi.server.LoaderHandler.loadProxyInterfaces(Unknown Source)
	at sun.rmi.server.LoaderHandler.loadProxyClass(Unknown Source)
	at sun.rmi.server.LoaderHandler.loadProxyClass(Unknown Source)
	at java.rmi.server.RMIClassLoader$2.loadProxyClass(Unknown Source)
	at java.rmi.server.RMIClassLoader.loadProxyClass(Unknown Source)
	at sun.rmi.server.MarshalInputStream.resolveProxyClass(Unknown Source)
	at java.io.ObjectInputStream.readProxyDesc(Unknown Source)
	at java.io.ObjectInputStream.readClassDesc(Unknown Source)
	at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
	at java.io.ObjectInputStream.readObject0(Unknown Source)
	at java.io.ObjectInputStream.readObject(Unknown Source)
	... 13 more
```

Habe auch versucht, RMI Registry aus dem Commandprompt (als separaten Prozess) zu starten, jedoch kommt es gleich. 

*C:\Temp>rmiregistry 1099*

Wenn ich anschliessend z.B. die Date-Applikation starten versuche, bekomme ich wieder das Problem:


```
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: date.server.RmiDate
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:419)
	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:556)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:724)
	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.rebind(Unknown Source)
	at java.rmi.Naming.rebind(Unknown Source)
	at date.server.RmiDateServer.main(RmiDateServer.java:45)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: date.server.RmiDate
	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:556)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.ClassNotFoundException: date.server.RmiDate
	at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.rmi.server.LoaderHandler$Loader.loadClass(LoaderHandler.java:1206)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:270)
	at sun.rmi.server.LoaderHandler.loadClassForName(LoaderHandler.java:1219)
	at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:729)
	at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:673)
	at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:610)
	at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:646)
	at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311)
	at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:255)
	at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1556)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1512)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
	... 13 more
```

Meine Frage noch einmal: 
*Ist so etwas überhaupt möglich? Und falls ja, was mache ich hier falsch?*

Ich habe hier den vollständigen Code angegeben und hoffe, dass mir jemand helfen kann. Besten Dank für jeden Hinweis.

P.S.
Habe auch ohne Security-Manager versucht, jedoch das Problem bleibt weiterhin bestehen.


----------



## rmacher (15. Dez 2013)

Habe die Lösung gefunden: 

Enhancements in JDK 7


----------

