users@glassfish.java.net

Re: JAXB behaves differently on Glassfish 4

From: Iaroslav Savytskyi <iaroslav.savytskyi_at_oracle.com>
Date: Mon, 10 Feb 2014 23:53:37 +0100

Hi, Andreas,

You are absolutely right. The behaviour was changed because we fixed a bug when setter was called 2 times.

Fix:
I expect Menu class has some ID field. Mark setter for this field with @XmlID and setParent with @XmlIDREF. After this JAXB will set dependencies by itself. So you can remove redundant code from setChildren method.

If you have other questions regarding JAXB you can ask on JAXB mailing lists: https://java.net/projects/jaxb/lists/


Best regards,
Iaroslav


On 10 Feb 2014, at 15:11, Andreas Junius <andreas.junius_at_gmail.com> wrote:

> 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: *********************************
>
>
>