views:

59

answers:

5

Hi,

here's the code (simplified):

public abstract class PageBase implements Serializable {
     private static final long serialVersionUID = -31905358958878336L;
}

public abstract class ListPage extends PageBase {

    public Controller getController() {
         // Controller is a class
         // that implements Serializable and does have an def. constr.
         return new Controller() {
              @Override
              public void someMethod() {
                  // DoSomething
              }
         };
    }
}

public class ProjectList extends ListPage {
}

and through deserialization it throws:

java.io.InvalidClassException: de.edeka.plive.page.ListPage$1; no valid constructor

The deserialization is taking place somewhere in the IBM JSF-Code.

Any ideas? Thanks!

A: 

You are trying to serialize an abstract class which, by definition, cannot be instantiated. That is, with your definition of ListPage, you cannot do:

ListPage l = new ListPage();

Remove the abstract qualifier from ListPage and ProjectList, and everything will be ok.

Alessandro Baldoni
Thanks, but is it the only way? Are there any other options?
Mulmoth
Some Java serializers/deserializers DO need a default constructor for the objects being processed.Does your ProjectList class has a default ProjectList() constructor?
Alessandro Baldoni
None of these classes do have any constructor, this means they will have a default constructor, doesn't it?
Mulmoth
Well... for the compiler the answer is yes. Object serializers, however, have stronger requirements. Often, they use the reflection API to inspect objects and constructors not explicitely declared may not show up.You can always add a simple and empty constructor like PageList() {}Which serialization engine are you using?
Alessandro Baldoni
Ok, thanks... but it turns out to have something to do with inner classes - please see my edits.
Mulmoth
A: 

One serializes objects, not classes, no? All of the classes you've shown are abstract, so can't be instantiatiated, so what is it that you're (de)serializing?

The error references the class as "ListPage$1" -- an anonymous inner class. I think we'd need to see more of the code to understand what's going on.

Dave Costa
Thanks for the hints - please see my edits, 'ProjectList' actually isn't abstract.
Mulmoth
+2  A: 

de.edeka.plive.page.ListPage$1 will be an anonymous inner classes. Serialisaing nested classes isn't a good idea at the best of times (poor mapping to full JVM name and handling of "outer this" references).

The exception looks as if it is trying to find the no-arg constructor of the most derived non-Serializable base class, which must be accessible to the least derived Serializable class.

Tom Hawtin - tackline
Please see my edits - i have an inner class - thanks!
Mulmoth
+2  A: 

I'd suggest defining the anonymous Controller as a separate class.

Bozho
That's cool - please hold the line...
Mulmoth
Ok, it looked promising, i created the inner class ListPageController which inherits Controller, but i only get the (more obvious) 'java.io.InvalidClassException: ListPage$ListPageController; no valid constructor'
Mulmoth
(Although i provided a default constructor in ListPageController)
Mulmoth
@Mulmoth inner (non-static) classes don't have default constructors - they take an instance of the parent class as a constructor argument. Move it as a private class in the same file, if not a completely separate class
Bozho
Thanks Bozho, that's very interesting and answers my question.
Mulmoth
+1  A: 

I think that the problem is that subclass of Controller is a non-static inner class, and as such its constructor has an implicit argument that refers to the instance of the enclosing class. This makes the constructor unusable for object deserialization.

It is a bad idea to try to serialize these objects, but if you change the inner class so that it is static deserialization may work.

Stephen C
That answers my question, thanks. However i give it to Bozho, who was first.
Mulmoth