Search code examples
javaserializationenumshazelcast

How to implement Hazelcast PortableFactory for Portable enum


I have a Java enum A that I want to serialize with Hazelcast Portable interface.

To implement the PortableFactory associated with A I need to call an empty constructor to create an empty instance of A, but that is not possible when it comes to enum in Java.

What's the best way to implement a PortableFactory to serialize enum?

Here an example of what I'd like to achive:

public class MyPortableFactory implements PortableFactory {

    @Override
    public Portable create( int classId ) {
        if (Foo.ID == classId) {
            return new Foo(); //This is how you return normal class
        } else if(MyEnum.ID == classId) {
            return ???; //What should I return for the enum?
        } else {
            return null;
        }
    }
}

I have tried a workoround using a map to change the ids:

public enum MyEnum implements Portable { 

    Value1("1", "1", PortableIds.one),
    Value2("2", "2", PortableIds.two),
    Invalid("0", "0", PortableIds.InvalidID);


    private String first;
    private String second;
    private Integer portableId;

    public static final Map<Integer, MyEnum> mapPortableIdValues = new HashMap<>() {{
        for (MyEnum myEnum : MyEnum.values()) {
            put(myEnum.getPortableId(), myEnum);
        }
    }};

    @Override
    public int getFactoryId() {
        return MyPortableFactory.FACTORY_ID;
    }

    @Override
    public int getClassId() {
        return portableId;
    }

public class MyPortableFactory implements PortableFactory {

    public static final int FACTORY_ID = 2;

    @Override
    public Portable create(int classId) {
        if(mapPortableIdValues.containsKey(classId)){
            return mapPortableIdValues.get(classId);
        }
        return null;
    }
}
public interface PortableIds {

    Integer one = 100;
    Integer two = 101;
    Integer InvalidID = 106;
}

But when I run my application I get the following exception:

com.hazelcast.nio.serialization.HazelcastSerializationException: Wrong Portable type! Generic portable types are not supported! Expected class-id: 100, Actual class-id: 106
    at com.hazelcast.internal.serialization.impl.portable.DefaultPortableWriter.checkPortableAttributes(DefaultPortableWriter.java:174)
    at com.hazelcast.internal.serialization.impl.portable.DefaultPortableWriter.writePortable(DefaultPortableWriter.java:147)

Solution

  • I think this use case is not a good fit for the design of the Portable serialization. The mechanism of Portable serialization instantiates an instance of a class and fills the fields with readPortable method at runtime. This is not really possible with enums.

    I would suggest using a wrapper class to carry simply an integer enum tag or the name of the enum member as a string with Portable serialization.