Search code examples
javahazelcastdistributed-cachingdistributed-cachehazelcast-imap

Need for custom serializers while using derivatives of ArrayList as value in Hazelcast


I have an IMAP whose key is a String and value is a derivative of ArrayList. I need to run EntryProcessor on a key of this map. Also note that Employee is a POJO which implements Serializable interface.

When I executed the code given below, the code prints "Why so !" and I got ClassCastException which mentioned that java.util.ArrayList cannot be cast to Employees in the process() method of ListValueEntryProcessor given below.

Q1. I learnt that I need to add custom serializer for my type (Employees) so that it could be serialized as Employees object and not as ArrayList object. I would like to know why is it mandatory to add a "custom serializer" for a built-in type like an ArrayList whose items are also marked Serializable ?

public class Employees extends ArrayList implements Serializable
{

    private static final long serialVersionUID = 1L;

   /**
   Constructs a new employees object
   */
   public Employees()
   {
      super();
   }
}

HazelcastInstance hazelcastInstance = HazelcastHelper.getHazelcastInstance();
IMap<String, Employees> empMap = hazelcastInstance.getMap("employeesMap");

Employees empList = new Employees();
Employee employee = new Employee();
empList.add(employee);
empMap.put("companyId", employees);
empMap.executeOnKey("companyId", new IncSalaryEntryProcessor()); 

public static class ListValueEntryProcessor extends AbstractEntryProcessor<String, Employees>
{

    private static final long serialVersionUID = 1L;

    @Override
    public Object process(Entry<String, Employees> arg0) 
    {
        if(! (arg0.getValue() instanceof Employees))
        {
            System.out.println("Why so !");
        }
        // ClassCastException thrown here.
        Employees empList = arg0.getValue();
        return true;
    }

}

Solution

  • This is a bug on our side. I created a bugreport:

    https://github.com/hazelcast/hazelcast/issues/6455

    The following code should resolve your problem for the time being:

    public class Main  {
    
    public static void main(String[] args){
        HazelcastInstance hz = Hazelcast.newHazelcastInstance();
        IMap<String,Employees> map = hz.getMap("foo");
        map.put("1", new Employees());
    
        Employees employees = map.get("1");
        System.out.println(employees);
    }
    
    static class Employees extends ArrayList implements DataSerializable {
        @Override
        public void writeData(ObjectDataOutput out) throws IOException {
            out.writeInt(size());
            for(Object item: this){
                out.writeObject(item);
            }
        }
    
        @Override
        public void readData(ObjectDataInput in) throws IOException {
            int size = in.readInt();
            for(int k=0;k<size;k++){
                add(in.readObject());
            }
        }
    }
    

    }