Serialization and JComponents with ActionListeners

Hi, I got a quick question:

Is there a chance to send JComponents which come with an ActionListener over the net for example via RMI?

I always get the following Exception:

java.lang.ClassCastException: server.ActionTryImpl_Stub cannot be cast to java.util.EventListener

java.lang.ClassCastException: server.ActionTryImpl_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.readObject(ObjectInputStream.java:351)

at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)

at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)

at server.ActionTryImpl_Stub.getJComponent(ActionTryImpl_Stub.java:56)

at client.TransferClient.main(TransferClient.java:33)

Please dont ask the sense of doing that, I just have to send them via RMI!

Is the only solution to analyse the JComponent at one side and put the information in an XML Document , then send this document via rmi over the net and rebuild the JComponent with Listeners on the other side?

Thanks for awnsering these questions!

[2650 byte] By [Sandmann6a] at [2007-11-27 10:29:22]
# 1

Sorry, I have to ignore your request and ask why you want to do it. A lot of people have some funny ideas about serialization, that leads them to try things that neither make sense nor actually solve their problem. Listeners should be stateless, so serializing them is pointless. I'm wondering what state of the object it is you're actually interested in. If you have the class bytes of your JComponent at the other end (and you have to, if you want to serialize it) you can already re-construct the JComponent (and listeners) without serializing it. If there's additional state you want to send across the wire (size of JComponent, other application data) you could put that all in a separate object and serialize that

But I doubt very much that what you're attempting is actually what you need to do. Can you give more info about what you're trying to achieve?

georgemca at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...
# 2

Of couse I can tell you the main problem I have.

OK:

I have a system on one side that on exists of an empty JFame.

The other sides are different components that all have their own GUI-elements with implemented listeners.

An nice example for something like zhat in reality would be:

You have an remote control with an initially empty screen. Now when you turn for example your DVD-Player on, you get the GUI that comes with your DVD player on the screen of your remote control. When you turn your TV on, you get the GUI element of the TV on your remote control. This should happen via RMI in my example.

I hope my problem gets a bit clearer now. Of course the GUI elements have (for example an JPanel with several JButtons) several Listeners and I want to react to the JButtons if they are pressed on my Remote Control.

The main problem I have know is to serialize for example an ActionListener. The JComponents are no problem, they can be send via RMI.......but the Listeners.

Its for a thesis on my university. And i need an answer pretty quick, because time is running out.

The main thing I have to know: THE WHY? Why are they not serializable? I have a very easy example: I have a class which implements ActionListener. If I want to send this ActionListener via RMI, I get the Exception shown above.

Thanks much for your help

Sandmann6a at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...
# 3

Ah, if I get you right, you want to basically remotely configure a JFrame with listeners. Ok, you've got a couple of options here. I

f you have a known set of Listeners, that is fixed, you have those classes at both ends, and part of the configuration for the component will include a list of strings which are the classnames of those listeners. You can easily serialize that and send it across the wire. At the other end, your component used a bit of reflection to instantiate the appropriate listeners and add them to itself.

If you want to add new types of listener without having to have them available on the other side of the wire up-front, you could have a custom classloader which pulls its class bytes over the wire, loads the class(es) then instantiates and adds them

The reason ActionListeners aren't serializable is that it doesn't really make sense to serialize them. They don't (typically) maintain state, so there's nothing other than the class bytes to be serialized, and class bytes are already serialized since they exist as, well, a stream of bytes

If that's not clear, do ask me to explain. I'm just in a bit of a rush at the moment!

georgemca at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...
# 4

Thanks a lot for your reply.

I would be very thankful for a detailed explanation, because I have to write it down in my work.

No problem if it takes you a few days, but at least I know that unknown Classes with ActionListeners are not serializable. Helps me a lot for the weekend.

You can also write to my Mail-adress: Sandmann6@freenet.de

Thank you, Jrg

Sandmann6a at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...
# 5

Other people can of course mail me, too. Im very interested in the reasons why Listeners are not serializable.

Sandmann6a at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...
# 6

I told you why they aren't, and I don't think you need them to be anyway. All you need to be able to do is construct an instance of one and add it to your component

georgemca at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...
# 7

Ok, lets look at a concrete example.

The Service Interface is something like that:

public interface ButtonTest extends Remote{

public JComponent getJComponent() throws RemoteException;

}

And then I have a class

public class Test implements ButtonTest, ActionListener{

public JComponent getJcomponent(){

JButton button = new JButton();

button.setText("TEST");

button.addActionListener(this);

return button;

}

public void actiuonperformed(Event e){

System.out.println("THIS IS A TEST");

}

}

Now I want this button on the other side with the same behaviour. Is there a direct way which makes this possible ? Im just geeting crazy because of that problem!

Message was edited by:

Sandmann6

Sandmann6a at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...
# 8

Well, yes. Write the action listener as a top-level class and have that class available at the remote end. When your JComponent needs that to be added as a listener, instantiate it and add. Serialization isn't the answer to this problem, you simply need to instantiate classes. ActionListeners don't generally maintain state, so there's nothing to be serialized

georgemca at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...
# 9

Hi,

You wont believe it, but it works.

If I put only the Listener and a JComponent in a seperate class (not in a UnicastRemoteObject) and send it over the net via RMI, I have the JComponent with the listener at the Client side.

I thought I tried this so many times and it didnt work, but now it does.....

So thank you so much. You will earn of course all the duke points for this topic!!!

Sandmann6a at 2007-7-28 17:57:04 > top of Java-index,Core,Core APIs...