2

I've noticed a strange behavior, when using double brace initialization, the initialized object serialization fails :

queueVO.setUser(new UserVO() {{setIndex("admin");}});

result in the following error when sending the object to a JMS queue :

javax.jms.JMSException: Failed to serialize object
at org.hornetq.jms.client.HornetQObjectMessage.setObject(HornetQObjectMessage.java:139)

whereas everything is running fine otherwise

queueVO.setUser(new UserVO());
queueVO.getUser().setIndex("admin");

I know that this syntactic sugar lead to the creation of an anonymous class but i don't understand why it breaks the serializable contract.

Can someone explain me what's happening here ?

Gab
  • 7,869
  • 4
  • 37
  • 68
  • 3
    Double brace initialisation is a dirty hack and can cause all sorts of unexpected problems. It should never be used. It's not a language feature; it's an abuse of anonymous classes. As no why serialization fails - can your API serialize other arbitrary anonymous classes? How do you expect it to de-serialize them at the other end? – Boris the Spider Mar 31 '15 at 07:50
  • the underlying cause is a java.io.NotSerializableException, wrapped by the hornetQ implementation it seems that my user is now of type MyTestClassType$1 which is indeed not serializable – Gab Mar 31 '15 at 07:57
  • 1
    No, `MyTestClassType$1` inherits `Serializable` from its super class but the anonymous inner class is, as the name suggests, *an inner class* and has a reference to its outer instance. When the inner class instance gets serialized, it will attempt to serialize the outer instance as well. Maybe you now get the point why “Double Brace Initialization” is an anti-pattern. That hidden reference might also cause memory leaks… – Holger Mar 31 '15 at 08:10
  • No MyTestClassType is the type of my test class not the VO one and is not serializable so the inner class does inherit nothing. Seems that the double brace create an anonymous class inner to the class in which is written the code – Gab Mar 31 '15 at 08:32

1 Answers1

3

The created anonymous class is not static, so has a <SurroundingClass>.this, which would be serialized too, or worse become null after the object will be reloaded.

One solution would be to let the setter return this, instead of being void. Then you can chain setters.

UserVO vo = new UserVO().setIndex("admin");
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • Indeed `SurroundingClass` seems to by my test class type, something I don't really understand. I already know about fluent syntax, thanks – Gab Mar 31 '15 at 07:58
  • 1
    @Gab [this](http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class) might be of help. – Boris the Spider Mar 31 '15 at 08:00