users@glassfish.java.net

JAXB behaves differently on Glassfish 4

From: Andreas Junius <andreas.junius_at_gmail.com>
Date: Tue, 11 Feb 2014 00:41:13 +1030

Hi all,

I encountered a problem with JAXB on Glassfish 4. It is about a type
"Menu" that can be used to create a tree structure. Some code:


The type:

...

@XmlAccessorType ( XmlAccessType.NONE )
public class Menu implements Iterable<Menu> {

...

@XmlElementWrapper ( name = "subMenu" )
@XmlElement ( name = "item" )
public void setChildren ( List<Menu> children ) {
        System.out.println("set children for menue " + this.getCaption() + "
list " + children);
        if (children != null) {
                for (Menu item : children) {
                        // set parent relationship into child
                        item.setParent(this);
                        System.out.println("child " + item.getCaption() + " gets parent " +
item.getParent());
                }
        }
        this.childrenProperty = children;
}

...


code for reading in the xml file:

...

JAXBContext context = JAXBContext.newInstance(Menu.class);
Unmarshaller um = context.createUnmarshaller();
InputStream fileInputStream = new FileInputStream(file);
inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
result = (Menu)um.unmarshal(inputStreamReader);

...






This code works fine in plain Java, e.g. unit-tests and it works fine on
Glassfish 3. As you can see from the output below, the method
"setChildren" gets called twice in both the unit test and on Glassfish
3. First with an empty list, then with a list of child nodes. It doesn't
look efficient and I assume that was the reason to optimise that for
Glassfish 4. Unfortunately it does now only the first call with the
empty list. Funny enough, the tree structure is complete regardless of
that. It's just that the child nodes don't have the parent relationship
set, because they got probably injected using different means, not the
setChildren method provided.

Is there anything I can do to influence how the xml gets unmarshalled
into the object? Or is this simply a bug?


Cheers,

        Andreas







Output showing the difference:

Glassfish 3

2014-02-11T00:02:28.104+1030|INFO: set children for menue Yakka list []
2014-02-11T00:02:28.105+1030|INFO: set children for menue B list []
2014-02-11T00:02:28.105+1030|INFO: set children for menue B list [[Menu
- getPath()=/home/b/subb1/, getCaption()=Sub B1, getChildren()=null],
[Menu - getPath()=/home/b/subb2/, getCaption()=Sub B2, getChildren()=null]]
2014-02-11T00:02:28.106+1030|INFO: child Sub B1 gets parent [Menu -
getPath()=/home/b/, getCaption()=B, getChildren()=[[Menu -
getPath()=/home/b/subb1/, getCaption()=Sub B1, getChildren()=null],
[Menu - getPath()=/home/b/subb2/, getCaption()=Sub B2, getChildren()=null]]]
2014-02-11T00:02:28.106+1030|INFO: child Sub B2 gets parent [Menu -
getPath()=/home/b/, getCaption()=B, getChildren()=[[Menu -
getPath()=/home/b/subb1/, getCaption()=Sub B1, getChildren()=null],
[Menu - getPath()=/home/b/subb2/, getCaption()=Sub B2, getChildren()=null]]]
2014-02-11T00:02:28.106+1030|INFO: set children for menue Yakka list
[[Menu - getPath()=/home/b/, getCaption()=B, getChildren()=[[Menu -
getPath()=/home/b/subb1/, getCaption()=Sub B1, getChildren()=null],
[Menu - getPath()=/home/b/subb2/, getCaption()=Sub B2,
getChildren()=null]]], [Menu - getPath()=/home/c/, getCaption()=C,
getChildren()=null]]
2014-02-11T00:02:28.106+1030|INFO: child B gets parent [Menu -
getPath()=/home/, getCaption()=Yakka, getChildren()=[[Menu -
getPath()=/home/b/, getCaption()=B, getChildren()=[[Menu -
getPath()=/home/b/subb1/, getCaption()=Sub B1, getChildren()=null],
[Menu - getPath()=/home/b/subb2/, getCaption()=Sub B2,
getChildren()=null]]], [Menu - getPath()=/home/c/, getCaption()=C,
getChildren()=null]]]
2014-02-11T00:02:28.107+1030|INFO: child C gets parent [Menu -
getPath()=/home/, getCaption()=Yakka, getChildren()=[[Menu -
getPath()=/home/b/, getCaption()=B, getChildren()=[[Menu -
getPath()=/home/b/subb1/, getCaption()=Sub B1, getChildren()=null],
[Menu - getPath()=/home/b/subb2/, getCaption()=Sub B2,
getChildren()=null]]], [Menu - getPath()=/home/c/, getCaption()=C,
getChildren()=null]]]
2014-02-11T00:02:28.107+1030|INFO: *********************************
2014-02-11T00:02:28.107+1030|INFO: [Menu - getPath()=/home/,
getCaption()=Yakka, getChildren()=[[Menu - getPath()=/home/b/,
getCaption()=B, getChildren()=[[Menu - getPath()=/home/b/subb1/,
getCaption()=Sub B1, getChildren()=null], [Menu -
getPath()=/home/b/subb2/, getCaption()=Sub B2, getChildren()=null]]],
[Menu - getPath()=/home/c/, getCaption()=C, getChildren()=null]]]
2014-02-11T00:02:28.107+1030|INFO: *********************************

Unit Test

loading menu
set children for menue Yakka list []
set children for menue B list []
set children for menue B list [[Menu - getPath()=/home/b/subb1/,
getCaption()=Sub B1, getChildren()=null], [Menu -
getPath()=/home/b/subb2/, getCaption()=Sub B2, getChildren()=null]]
child Sub B1 gets parent [Menu - getPath()=/home/b/, getCaption()=B,
getChildren()=[[Menu - getPath()=/home/b/subb1/, getCaption()=Sub B1,
getChildren()=null], [Menu - getPath()=/home/b/subb2/, getCaption()=Sub
B2, getChildren()=null]]]
child Sub B2 gets parent [Menu - getPath()=/home/b/, getCaption()=B,
getChildren()=[[Menu - getPath()=/home/b/subb1/, getCaption()=Sub B1,
getChildren()=null], [Menu - getPath()=/home/b/subb2/, getCaption()=Sub
B2, getChildren()=null]]]
set children for menue Yakka list [[Menu - getPath()=/home/b/,
getCaption()=B, getChildren()=[[Menu - getPath()=/home/b/subb1/,
getCaption()=Sub B1, getChildren()=null], [Menu -
getPath()=/home/b/subb2/, getCaption()=Sub B2, getChildren()=null]]],
[Menu - getPath()=/home/c/, getCaption()=C, getChildren()=null]]
child B gets parent [Menu - getPath()=/home/, getCaption()=Yakka,
getChildren()=[[Menu - getPath()=/home/b/, getCaption()=B,
getChildren()=[[Menu - getPath()=/home/b/subb1/, getCaption()=Sub B1,
getChildren()=null], [Menu - getPath()=/home/b/subb2/, getCaption()=Sub
B2, getChildren()=null]]], [Menu - getPath()=/home/c/, getCaption()=C,
getChildren()=null]]]
child C gets parent [Menu - getPath()=/home/, getCaption()=Yakka,
getChildren()=[[Menu - getPath()=/home/b/, getCaption()=B,
getChildren()=[[Menu - getPath()=/home/b/subb1/, getCaption()=Sub B1,
getChildren()=null], [Menu - getPath()=/home/b/subb2/, getCaption()=Sub
B2, getChildren()=null]]], [Menu - getPath()=/home/c/, getCaption()=C,
getChildren()=null]]]
*********************************
[Menu - getPath()=/home/, getCaption()=Yakka, getChildren()=[[Menu -
getPath()=/home/b/, getCaption()=B, getChildren()=[[Menu -
getPath()=/home/b/subb1/, getCaption()=Sub B1, getChildren()=null],
[Menu - getPath()=/home/b/subb2/, getCaption()=Sub B2,
getChildren()=null]]], [Menu - getPath()=/home/c/, getCaption()=C,
getChildren()=null]]]
*********************************


Glassfish 4

2014-02-11T00:04:26.880+1030|INFO: set children for menue Yakka list []
2014-02-11T00:04:26.880+1030|INFO: set children for menue B list []
2014-02-11T00:04:26.881+1030|INFO: *********************************
2014-02-11T00:04:26.881+1030|INFO: [Menu - getPath()=/home/,
getCaption()=Yakka, getChildren()=[[Menu - getPath()=/home/b/,
getCaption()=B, getChildren()=[[Menu - getPath()=/home/b/subb1/,
getCaption()=Sub B1, getChildren()=null], [Menu -
getPath()=/home/b/subb2/, getCaption()=Sub B2, getChildren()=null]]],
[Menu - getPath()=/home/c/, getCaption()=C, getChildren()=null]]]
2014-02-11T00:04:26.881+1030|INFO: *********************************