# Was kann man alles serialisieren?



## Björn K. (10. Jul 2007)

Hallo,
habe da nur ne kleine Frage, die wahrscheinlich sehr schnell beantwortet ist. 

Wenn ich jetzt diese Interfaces bei RMI erstellt habe, was dürfen meine Methoden denn da alles zurückgeben? Nur Klassen (d.h. konkrete und abstrakte Klassen, oder auch Interfaces?)

Wenn ich jetzt z.B. so etwas hötte:


```
public interface Komponente1 extends Remote {
	
	public EventListener getListener() throws RemoteException;
	
}
```

Weil ein EventListener ist ja ein Interface und keine konkrete Klasse.

Wenn so etwas nicht funktioniert, welche abstrakte Klasse müsste man denn im konkreten Fall dieses Eventlisteners dann nehmen, wenn ich z.B. konkrete EventListener-Klassen übertragen will. Gibt es da  eine allgemeinere abstrakte Klasse, die ich benutzen könnte?
Danke,
Gruß
Björn


----------



## SlaterB (10. Jul 2007)

du kannst weder Klassen noch abstracte Klassen noch Interfaces übergeben
sondern nur Objekte,
und Objekte haben immer eine Klasse, von daher gibts in der Hinsicht keinerlei Probleme,

alle Objekte die das Interface implementieren, können übertragen werden
(evtl. nur sofern serialisierbar)


----------



## Guest (10. Jul 2007)

Dann muss mein Fehler irgendwo anders liegen.
Ich arbeite mit folgendem Szenario:

Ich bekomme eine java.rmi.UnmarshalException mit dem Auslöser java.lang.ClassNotFoundException der Klasse server.ButtonAction2

Ich weiß dass es typischerweise an der codebase-Einstellung liegt, aber wo mein Fehler liegt....keine Ahnung

Ich arbeite zur Zeit zu Hause mit 2 Rechnern in einem Netzwerk. Nennen wir diese typischerweise mal Client und Server 

Mein Remote IF sieht folgendermaßen aus:

```
public interface Komponente1 extends Remote {
	
	public ActionListener getListener() throws RemoteException;
	
}
```

Dieses liegt ja typischerweise auf beiden Seiten.

Auf Server-Seite liegt noch folgende Klasse, um Service bei der Registry zu registrieren:


```
package server;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.EventListener;

import javax.swing.JButton;
import javax.swing.JComponent;

import service.Komponente1;

public class GUIKomponenten implements ActionListener,Serializable,Komponente1 {
	

	/**
	 * 
	 */
	private static final long serialVersionUID = 2736594069802458000L;
	public GUIKomponenten(){
		try {
			Komponente1 stub2 = (Komponente1) UnicastRemoteObject.exportObject(this,
					0);
			Registry registry = LocateRegistry.getRegistry("192.168.0.3", 1099);
			registry.rebind("SERVERSERVICE2", stub2);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	public void actionPerformed(ActionEvent e) {
		System.out.println("ANDERE VARIANTE(VOM SERVER GETRENNT) FUNKTIONIERT!");
		
	}

	public JButton getComponent() throws RemoteException {
		JButton button = new JButton();
		//button.addActionListener(this);
		button.setText("Neue Variante");
		return button;
	}
	public ActionListener getListener() throws RemoteException {
		ActionListener listener= new ButtonAction2();
		return listener;
	}

}
```

Wie ihr seht, arbeite ich schon mit dynamischen Stubs.

Hier jetzt die Klasse ButtonAction2


```
package server;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;

import javax.swing.JButton;
import javax.swing.JComponent;

public class ButtonAction2 implements ActionListener,Serializable{ 

	/**
	 * 
	 */
	private static final long serialVersionUID = -3882810878233908450L;
	JComponent component = null;
	public ButtonAction2(JComponent comp){
		component=comp;
	}
	public ButtonAction2(){
		
	}
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==component){
			System.out.println("AUF WELCHER SEITE BIN ICH DENN?");
								
		}
		
		
		
	}

	

}
```

Der Client versucht nun über getListener einen ActionListener zu übertragen(der Sinn warum man das macht ist ja erstmal egal ). Aber dann kommt immer diese oben genannte Exception. Meine Argumente, die ich beim Server-Start übergebe sind:

-Djava.rmi.server.ignoreStubClasses=true 
-Djava.rmi.server.codebase=file:/C:/RMINORMICEXAMPLE/SERVER/SERVER/bin/
-Djava.security.policy=security.policy


Irgendwelche Ideen?


----------



## SlaterB (10. Jul 2007)

versuche auf Empfänger-Seite nahe an der Stelle, an der die Exception auftritt, mit
new ButtonAction2();
manuell ein solches Objekt zu erzeugen,
wenn das ebenso schiefläuft, dann ist eindeutig gezeigt, dass die Klasse einfach nicht da ist..,
Classpath-Problem oder so


----------



## Guest (10. Jul 2007)

Hallo,
Ich glaube ich habe mich etwas unklar ausgedrückt.
Der Client möchte den Listener ja haben und nicht selbst verschicken(also er möchte ihn geschickt bekommen).

Die Codebase bekommt der Client ja aber erst,wenn er einen RMI-Call auf den Server macht. Hier die konkrete Exception im Client:

```
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
	java.lang.ClassNotFoundException: server.ButtonAction2
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:178)
	at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
	at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
	at $Proxy1.getListener(Unknown Source)
	at client.ClientImpl.actionPerformed(ClientImpl.java:458)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.Component.processMouseEvent(Component.java:6038)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
	at java.awt.Component.processEvent(Component.java:5803)
	at java.awt.Container.processEvent(Container.java:2058)
	at java.awt.Component.dispatchEventImpl(Component.java:4410)
	at java.awt.Container.dispatchEventImpl(Container.java:2116)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
	at java.awt.Container.dispatchEventImpl(Container.java:2102)
	at java.awt.Window.dispatchEventImpl(Window.java:2429)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
Caused by: java.lang.ClassNotFoundException: server.ButtonAction2
	at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:247)
	at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:434)
	at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
	at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
	at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
	at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
	at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)
	... 29 more
```

Die CodeBase des Servers ist jawie oben angegeben das bin Verzeichnis. In diesem Verzeichnis ist der Ordner server und darin liegt die Class Datei von ButtonAction2. 
Aber die Exception sagt mir dass server.ButtonAction2 nicht gefunden wird ?
Bin irgendwie total ratlos.........


----------



## Guest (10. Jul 2007)

d.h.
Die Klasse ButtonActon2 existiert beim Client gar nicht!!!!


----------



## Björn K. (10. Jul 2007)

Das war noch ne Anmerkung von mir....also keine qualifizierte Antwort ;-)


----------



## SlaterB (10. Jul 2007)

wer nun Client oder Server ist ist egal,
der Empfänger will das Objekt haben und braucht dafür die Klasse,
wie man das Vorhandensein der Klasse einfach testen kann habe ich gesagt,

damit hat das ganze nun nichts mehr mit RMI zu tun sondern allein mit der Konfiguration des Programms,
z.B. Classpath,

dazu könntest du ja noch mehr Infos angeben falls du welche hast,
mir fällt aber spontan nix interessantes ein


----------



## Gast (10. Jul 2007)

mmmh....vielleicht stehe ich eben auch gerade voll auf dem Schlauch.
Situation ist so:
2 Notebooks in meinem privatem Netzwerk zu Hause.
Auf Client-Notebook ist die Class-Datei neines Listeners nicht vorhanden. Der Client möchte den Listener vom Server-Notebook bekommen. Ich dachte an das Vorgehen wie in folgender Grafik:
http://www.oio.de/m/jboss/rmi-dynamic-stub.htm

Beim Lookup sollte mein Client-Notebook ja erst wissen wo dieser Listener zu finden ist. 
Ausserdem wie gebe ich einen Classpath im Netzwerk ein, um diesen auf einen entfernten Labtop zu setzen. Nehmen wir mal an, dass das Server-Notebook die IP 192.168.0.3 hätte und meine Class Dateien im Verzeichnis:
C:\RMINORMICEXAMPLE\SERVER\SERVER\bin\server
liegen?????
Hatte vorher noch nicht so viel Erfahrung mir RMI. Vielleicht muss mein Listener ja auch noch irgendwie modifiziert werden, so dass dieser verschickt werden kann?!? Die Klasse ButtonAction implementiert ja ActionListener und Serializable; erweitert aber nicht UnicastRemoteObject.
Ich hab keinen Plan, wo der Fehler liegen könnte!

Danke auf jeden Fall schon mal für Dein Interesse und Deine Hilfe zur Lösung des Problems! Ist echt Klasse!


----------



## SlaterB (10. Jul 2007)

hmm, ok das ist ein neues Thema,
du willst also das Objekt allgemein nach Interface übertragen mit dynamischen Stub auf Empfängerseite
(wäre ne interessante Info im ersten Post gewesen..)

mag sein, dass das bei RMI möglich ist, dazu kann ich nix weiter sagen,
UnicastRemoteObject kenne ich z.B. auch nicht,

hast du keine allgemeine Tutorials/ Beispiele?


----------



## Gast (10. Jul 2007)

Vielleicht verrenne ich mich da gerade in irgendetwas......
Versuche jetzt mal einen anderen Weg, so dass Komponenten gleich geschickt werden und nicht durch Client angefordert werden müssen. d.h. der Server bringt den Stein ins Rollen und übergibt Komponenten.......mal sehen, ob das besser funktioniert!


----------

