RMI und Listener Serialisierung

Sandmann6

Grünschnabel
Hallo,
ich sitze nun schon Tage an einem Problem und komme einfach nicht weiter.
Problem:
Ich möchte über RMI JComponents übertragen. Das funktioniert soweit auch schon ganz gut. Wird nun jedoch ein Listener (oder natürlich auch mehrere) der JComponent zugeführt, so bekomme ich flgende Exception:

Code:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at java.awt.Container.readObject(Container.java:3599)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1945)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1869)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
	at javax.swing.event.EventListenerList.readObject(EventListenerList.java:255)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1945)
	at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:480)
	at javax.swing.JComponent.readObject(JComponent.java:5382)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	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.UnicastServerRef.dispatch(UnicastServerRef.java:290)
	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:535)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
	at java.lang.Thread.run(Thread.java:619)
	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
	at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
	at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
	at $Proxy0.buildGui2(Unknown Source)
	at client.ClientImpl.actionPerformed(ClientImpl.java:554)
	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)

Momentan sieht das Programm so aus, dass ich ein IF, welches Remote erweitert habe:
Code:
package service;

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

import javax.swing.JComponent;

public interface RMIServer extends Remote {

	public void buildGui(JComponent comp) throws RemoteException;
	
}

Ich weiß ja, dass ein EventListener nun ein Interface ist und nicht zu der abstrakten Klasse JComponent zugeordnet werden kann, aber wie kann ich bewerkstelligen, dass ich meine Listener an meinen Komponenten behalte?:confused:

Ich danke Euch schon mal im Voraus für Eure Ideen. Für weitere Fragen, wenn Ihr etwas konkreteres braucht stehe ich natürlich gerne zur Verfügung!
Gruß
 
Hallo,

also über RMI JComponents zu verschicken halte ich für ziemlichen Blödsinn,...
Anstatt die Listener zu verschicken würde ich eher die Events übers Netz verteilen. Hierbei wird dann nicht das original Event verschickt, sondern ein generisches Event welches mit genügend Information ausgestattet ist um das "original" Event in einem konkreten Client wieder erzeugen zu können.

Technologien hierzu wären:
http://www.terracottatech.com/
http://www.gigaspaces.com/
http://www.oracle.com/technology/products/coherence/index.html
http://labs.jboss.com/jbosscache/

Oder eben was selbst gebautes (Beispielsweise auf Basis von):
http://www.jgroups.org/javagroupsnew/docs/index.html

Gruß Tom
 
Hallo,
erstmal Danke für die schnelle Antwort. :p

Das mit den Events und den generischen Events habe ich mir ja schon in etwa so gedacht. Nur wo ich das Problem sehe ist in der Tatsache dass ich nicht weiß welche JComponent Elemente (können ja beliebig tief verschachtelt sein) einen Listener anhängen haben. Wenn ich nämlich nun auf jedes mögliche Event reagieren müsste(unddas sind viel z.B. mousePressed,MouseReleased,........) und dann überprüfe, ob auf ein solches Event reagiert werden muss, dann wird der Traffic übers Netzt doch bestimmt viel zu hoch.........
Sehe ich es richtig und ich muss noch irgendeine Datei mitverschicken. z.B. XML, so dass ich sehe, wo überall Listener hängen, so dass ich den Traffic-Overhead etwas eindämmen kann?
 
Hallo,

was willst du denn genau machen?
Sowas wie, wenn ein Benutzer in einer JComboBox xxx auswählt soll dieses bei allen anderen Clients auch ausgewählt werden...?

Gruß Tom
 
Hi,
Also es geht um ein konkretes System, das als GUI initial einen leeren JFrame besitzt-----> nennen wir dieses System einmal Hauptsystem. An dieses System werden kleinere Subsysteme angeschlossen, welche alle ihre eigene kleine GUI mitbringen. Das Hauptsystem lagert die kleineren GUI´s bei sich ein. Die Verarbeitung, wenn ein Benutzer auf einen Button im Hauptsystem drückt soll aber auf den jeweiligen Subsystemen ausgeführt werden.

Ich hoffe das Problem wird jetzt klarer. Dieses Vorhaben soll erst anhand von RMI entwickelt werden und danach auf Corba.......aber da bin ich noch Meilen davon entfernt :)

Also mein Haupt-Problem ist nun:
Wo hängen die Listener? Wenn ich diese Information in meinem Hauptsystem hätte, so wäre schon mal ein riesen Schritt zur Lösung dieses Problems getätigt! Mein Betreuer meinte ich sollte erstmal auf XML-basierte Lösungsansätze verzichten und erstmal schauen, ob ich so irgendwie auskomme(Begründung: Warum alles zuerst analysieren und in Datei schreiben und dann im Hauptsystem auch wieder analysieren und alles wieder aufbauen, wenn es vielleicht auch direkt geht!)
 
Ausgangspunkt des Problems:
Ich benötige ja das GUI-Objekt auf meiner Seite. D.h. ich brauche keine Referenz auf das GUI-Objekt, sondern die Visualisierung, also das GUI-Objekt selbst. Wenn man nun bei der Standard-Serialisierung ein Objekt übergibt, so können ja auch Referenzen auf andere Objekte bestehen. So ist dies auch in unserem Fall: Wir haben nämlich Referenzen auf EventListener. Die Serialisierung schreibt uns aber vor, dass alle referenzierten Objekte auch rekursiv zu serialisieren sind.

Jetzt folgender Einschub zu EventListener:

The event dispatching thread (EDT) is a background thread used in Java to process events from the Abstract Windowing Toolkit (AWT) graphical user interface event queue. These events are primarily update events that cause user interface components to redraw themselves, or input events from input devices such as the mouse or keyboard. The AWT uses a single-threaded painting model in which all screen updates must be performed from a single thread. The event dispatching thread is the only valid thread to update the visual state of visible user interface components. Updating visible components from other threads is the source of many common bugs in Java programs that use Swing [1].

Wir haben also jetzt auf dem EventListener eine Referenz und dies bindet uns ja an den Event-Dispatching-Thread.
Jetzt folgender Einschub zu Threads und Serialisierbarkeit:

9. Are there any plans to support the serialization of thread objects?
Threads will NOT be serializable. In the present implementation, if you attempt to serialize and then deserialize a thread, there is NO explicit allocation of a new native thread or stack; all that happens is that the object is allocated system resources with none of the native implementation. In short, it just won't work and will fail in unpredictable ways.
The difficulty with threads is that they have so much state which is intricately tied into the virtual machine that it is difficult or impossible to re-establish the context somewhere else. For example, saving the VM call stack is insufficient because if there were native methods that had called C procedures that in turn called code for the Java platform, there would be an incredible mix of Java programming language constructs and C pointers to deal with. Also, serializing the stack would imply serializing any object reachable from any stack variable.
If a thread were resumed in the same VM, it would be sharing a lot of state with the original thread, and would therefore fail in unpredictable ways if both threads were running at once, just like two C threads trying to share a stack. When deserialized in a separate VM, it's hard to tell what might happen.

Dies könnte ja meine Exception erklären, oder verstehe ich da jetzt etwas falsch?
Hier nochmal meine Exception:
Code:
java.lang.ClassCastException: server.TransferImpl_Stub cannot be cast to java.util.EventListener
	at javax.swing.event.EventListenerList.readObject(EventListenerList.java:255)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1945)
	at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:480)
	at javax.swing.JComponent.readObject(JComponent.java:5382)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1667)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
	at java.io.ObjectInputStream.access$300(ObjectInputStream.java:188)
	at java.io.ObjectInputStream$GetFieldImpl.readFields(ObjectInputStream.java:2107)
	at java.io.ObjectInputStream.readFields(ObjectInputStream.java:519)
	at java.awt.Container.readObject(Container.java:3584)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1667)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
	at java.io.ObjectInputStream.access$300(ObjectInputStream.java:188)
	at java.io.ObjectInputStream$GetFieldImpl.readFields(ObjectInputStream.java:2107)
	at java.io.ObjectInputStream.readFields(ObjectInputStream.java:519)
	at java.awt.Container.readObject(Container.java:3584)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1667)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
	at java.io.ObjectInputStream.access$300(ObjectInputStream.java:188)
	at java.io.ObjectInputStream$GetFieldImpl.readFields(ObjectInputStream.java:2107)
	at java.io.ObjectInputStream.readFields(ObjectInputStream.java:519)
	at java.awt.Container.readObject(Container.java:3584)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1667)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
	at java.io.ObjectInputStream.access$300(ObjectInputStream.java:188)
	at java.io.ObjectInputStream$GetFieldImpl.readFields(ObjectInputStream.java:2107)
	at java.io.ObjectInputStream.readFields(ObjectInputStream.java:519)
	at java.awt.Container.readObject(Container.java:3584)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
	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)
	at server.TransferImpl_Stub.getJFrame(TransferImpl_Stub.java:70)
	at client.TransferClient.main(TransferClient.java:24)

Was meint Ihr?
 
Zurück