7

During the set up of a cluster I'm having an issue with WildFly/Infinispan attempting to serialize a number of classes which are fine to be recreated on each instance - although for whatever reason they seem determined to distribute across the cluster.

Initially I thought that the @Stateless annotation would have the effect I wanted, although it throws an issue from not having the correct constructors, so I don't believe this is what we are looking for.

What is the proper way to disable this, or overwrite the method of serialization, on a per-class basis?

Will
  • 810
  • 6
  • 21
  • What do you mean by "which are fine to remain completely stateful"? Also, putting the `@Stateful` turns the class into a stateful EJB, which is then automatically distributed across the cluster to provide fault-tolerance. – gcvt Jan 28 '16 at 12:27
  • You're right, I have been using the wrong annotation, I'll try it again now> I've worded it incorrectly, what I meant was that I don't want it clustered - I want each instance having it's own version. – Will Jan 28 '16 at 12:29
  • You should be able to use `@Stateless` or `@Singleton` for this, but in that case you'd need to add a no-args constructor to your class. – gcvt Jan 28 '16 at 12:32
  • Ok, thank you that makes sense. I'll start doing some re-writing to get rid of the constructors. I'll report back with progress – Will Jan 28 '16 at 12:34
  • Didn't have a measurable effect - it's still trying to serialize what is market with the @Stateless annotation. – Will Jan 28 '16 at 15:12
  • Why would you keep state in a @Stateless bean I wonder? – TT. Feb 02 '16 at 18:49
  • Could you add some details? which classes are being serialized? some EJB? or do you put objects in a clustered cache? maybe with their code? – user140547 Feb 02 '16 at 22:07
  • If you have been writing constructors then that implies that *you* are managing the object lifecycle for them and not the container. If you mark a class as @Stateless then it will be created by the container when you inject it into some other object. – Steve C Feb 03 '16 at 02:58
  • You mean Wildfly is serializing *instances* of the relevant classes, right? Not the class objects themselves? – John Bollinger Feb 08 '16 at 22:49
  • Are you passing bean instances as arguments to other beans' methods? If your beans really are stateless, then that should not be necessary. – John Bollinger Feb 08 '16 at 22:52
  • I dont believe so, they are all either autowired or retrieved by name from the beanmanager – Will Feb 09 '16 at 06:16

1 Answers1

1

The non-answer

Be careful with the approach of disabling serialisation for selected classes. Your application might not need to be 'clustered' and not needing replicated sesssions or stateful entities, when run locally or in some limited development environment. However once deployed to test or production it could be clustered. Then it's going to be broken, if you have prevented serialization.

Therefore the best cause of action is to ensure 'serializability' of your classes, rather than force-preventing it.

Serialization OFF answer

If you insist on disabling serialization, removing <distributable/> from your web.xml should do the trick.

Serializing non-serializables answer

By trying to make some classes serializable sometimes you will find that types of certain class members are simply non-serializable and you cannot swap the type for something similar, which would serialize. Then use the following trick, providing it is applicable:

public class ClassForcedToBeSerializable implements Serializable {

    transient private FileWriter writer; //FileWriter is not serializable!!!
    private final File file;

    public ClassForcedToBeSerializable(File file) throws IOException {
        this.file = file;
        this.writer = new FileWriter(file);
    }

    //FLESH AND BONES HERE

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        if (writer == null) {
            this.writer = new FileWriter(file);
        }
    }
}

As you can see the class includes field of FileWriter type. We ensured the object -> bytes serialization by marking it transient. However on the remote JVM when this class is being brought back from bytes, your FileWriter field field will be null. We avoid this problem by recreating it during deserialization (see readObject() method).

This example works only because the File field carries enough state for FileWriter to be successfully recreated.

diginoise
  • 7,352
  • 2
  • 31
  • 39