jaxb
  1. jaxb
  2. JAXB-1028

Unmarshaller sets the incorrect element as nil

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Cannot Reproduce
    • Affects Version/s: 2.2.6
    • Fix Version/s: 2.2.11
    • Component/s: runtime
    • Labels:
      None

      Description

      I have generated classes for the xml schema below using xjc. I have noticed that when unmarshalling an xml message like the one below where the UserReference element is nil the ResourceSpecification is marked a nil according to the object, even so the object is not null. If I then marshal the object into XML the ResourceSpecification is marked as nil and if I unmarshal it again back into an Object the ResourceSpecification is null.

      XSD

      <xs:schema elementFormDefault="qualified"
      targetNamespace="http://mycompany.com/CoreServices/Entities" xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/"
      xmlns:tns="http://mycompany.com/CoreServices/Entities" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:import namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
      <xs:complexType name="JobType">
      <xs:sequence>
      <xs:element name="JobReference" nillable="true" type="xs:string" />
      <xs:element name="CurrentResources" nillable="true"
      type="tns:ActualResourceAllocations" />
      </xs:sequence>
      </xs:complexType>
      <xs:element name="Job" nillable="true" type="tns:JobType" />
      <xs:complexType name="ActualResourceAllocations">
      <xs:sequence>
      <xs:element name="AllocatedResources" nillable="true"
      type="tns:ArrayOfResource" />
      </xs:sequence>
      </xs:complexType>
      <xs:complexType name="ArrayOfResource">
      <xs:sequence>
      <xs:element maxOccurs="unbounded" minOccurs="0" name="Resource"
      nillable="true" type="tns:Resource" />
      </xs:sequence>
      </xs:complexType>
      <xs:complexType name="Resource">
      <xs:sequence>
      <xs:element name="UserReference" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="ResourceSpecificationB"
      nillable="true" type="tns:ResourceSpecification" />
      </xs:sequence>
      </xs:complexType>
      <xs:complexType name="ResourceSpecification">
      <xs:sequence>
      <xs:element name="ResourceSpecificationId" type="xs:int" />
      <xs:element name="SpecUserReference" nillable="true" type="xs:string" />
      <xs:element name="Description" nillable="true" type="xs:string" />
      </xs:sequence>
      </xs:complexType>
      </xs:schema>

      Example XML

      <a:Job xmlns="http://mycompany.com/CoreServices" xmlns:a="http://mycompany.com/CoreServices/Entities"
      xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <a:JobReference>ESB234-TC015_LG</a:JobReference>
      <a:CurrentResources>
      <a:AllocatedResources>
      <a:Resource>
      <a:UserReference i:nil="true" />
      <a:ResourceSpecificationB>
      <a:ResourceSpecificationId>1</a:ResourceSpecificationId>
      <a:SpecUserReference>as</a:SpecUserReference>
      <a:Description>Default</a:Description>
      </a:ResourceSpecificationB>
      </a:Resource>
      </a:AllocatedResources>
      </a:CurrentResources>
      </a:Job>

      Example unit test
      package com.mycompany.xml;

      import java.io.File;
      import java.io.StringReader;
      import java.io.StringWriter;

      import javax.xml.bind.JAXBContext;
      import javax.xml.bind.JAXBElement;
      import javax.xml.bind.Marshaller;
      import javax.xml.bind.Unmarshaller;

      import org.junit.Test;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;

      import com.mycompany.ws.mywebservice.JobType;
      import com.mycompany.ws.mywebservice.Resource;

      /**

      • This is a test
        *
        */
        public class NilTest {

      private static final Logger LOG = LoggerFactory.getLogger(NilTest.class);

      @Test
      public void testNil() throws Exception {
      JAXBContext context = JAXBContext.newInstance(JobType.class);
      Unmarshaller unmarshaller = context.createUnmarshaller();
      Object a = unmarshaller.unmarshal(new File("src/test/resources/failingmessage.xml"));

      JAXBElement<JobType> jobTypeElement = (JAXBElement<JobType>) a;
      JobType jobType = jobTypeElement.getValue();
      for (Resource r : jobType.getCurrentResources().getAllocatedResources().getResource())

      { LOG.info("resource specification " + r.getResourceSpecificationB()); LOG.info("resource specification is nil " + r.getResourceSpecificationB().isNil()); LOG.info("Descriptor " + r.getResourceSpecificationB().getValue().getDescription()); }

      Marshaller marshaller = context.createMarshaller();
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
      StringWriter sw = new StringWriter();
      marshaller.marshal(a, sw);
      System.out.print(sw.toString());

      StringReader sr = new StringReader(sw.toString());
      a = unmarshaller.unmarshal(sr);

      jobTypeElement = (JAXBElement<JobType>) a;
      jobType = jobTypeElement.getValue();
      for (Resource r : jobType.getCurrentResources().getAllocatedResources().getResource())

      { LOG.info("resource specification " + r.getResourceSpecificationB()); LOG.info("resource specification is nil " + r.getResourceSpecificationB().isNil()); LOG.info("Descriptor " + r.getResourceSpecificationB().getValue().getDescription()); }

      }

      }

        Activity

        Hide
        kylape added a comment -

        I tested the reproducer posted, and it seems to work as reported.

        I created a (hopefully) simpler reproducer:

        <xs:schema xmlns:tns="http://jaxb.gss.redhat.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://jaxb.gss.redhat.com/">
          <xs:element name="team" type="tns:team"/>
          <xs:complexType name="team">
            <xs:sequence>
              <xs:element ref="tns:abstractName"/>
              <xs:element ref="tns:member"/>
            </xs:sequence>
          </xs:complexType>
          <xs:element abstract="true"  name="abstractName" nillable="false"/>
          <xs:element abstract="false" name="name"         nillable="true" substitutionGroup="tns:abstractName" type="xs:string"/>
          <xs:element abstract="true"  name="member"       nillable="false"/>
          <xs:element abstract="false" name="programmer"   nillable="true" substitutionGroup="tns:member" type="xs:string"/>
        </xs:schema>
        

        Code to test:

        package com.redhat.gss.jaxb;
        
        import java.net.URL;
        import javax.xml.bind.Unmarshaller;
        import javax.xml.bind.JAXBContext;
        import javax.xml.bind.JAXBElement;
        
        public class Test {
          private static JAXBContext ctx = null;
        
          public static void main(String[] args) throws Exception {
            ctx = JAXBContext.newInstance(ObjectFactory.class, Team.class, String.class);
            URL inputUrl = Test.class.getResource("/no-nil.xml");
            System.out.println("Non-nil test.");
            doTest(inputUrl);
            System.out.println("\nNil test.  Member should NOT be nil");
            inputUrl = Test.class.getResource("/nil.xml");
            doTest(inputUrl);
          }
        
          public static void doTest(URL inputUrl) throws Exception {
            Unmarshaller unm = ctx.createUnmarshaller();
            Object o = unm.unmarshal(inputUrl);
            Team team = ((JAXBElement<Team>)o).getValue();
            System.out.println("Name: " + team.getAbstractName().getValue());
            System.out.println("Name nil? " + (team.getAbstractName().isNil() ? "YES" : "NO"));
            System.out.println("Member: " + team.getMember().getValue());
            System.out.println("Member nil? " + (team.getMember().isNil() ? "YES" : "NO"));
          }
        }
        

        nil.xml:

        <team xmlns="http://jaxb.gss.redhat.com/">
          <name xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
          <programmer>Kyle</programmer>
        </team>
        

        no-nil.xml:

        <team xmlns="http://jaxb.gss.redhat.com/">
          <name>SEG</name>
          <programmer>Kyle</programmer>
        </team>
        
        Show
        kylape added a comment - I tested the reproducer posted, and it seems to work as reported. I created a (hopefully) simpler reproducer: <xs:schema xmlns:tns = "http://jaxb.gss.redhat.com/" xmlns:xs = "http://www.w3.org/2001/XMLSchema" version= "1.0" targetNamespace= "http://jaxb.gss.redhat.com/" > <xs:element name= "team" type= "tns:team" /> <xs:complexType name= "team" > <xs:sequence> <xs:element ref= "tns:abstractName" /> <xs:element ref= "tns:member" /> </xs:sequence> </xs:complexType> <xs:element abstract= "true" name= "abstractName" nillable= "false" /> <xs:element abstract= "false" name= "name" nillable= "true" substitutionGroup= "tns:abstractName" type= "xs:string" /> <xs:element abstract= "true" name= "member" nillable= "false" /> <xs:element abstract= "false" name= "programmer" nillable= "true" substitutionGroup= "tns:member" type= "xs:string" /> </xs:schema> Code to test: package com.redhat.gss.jaxb; import java.net.URL; import javax.xml.bind.Unmarshaller; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; public class Test { private static JAXBContext ctx = null ; public static void main( String [] args) throws Exception { ctx = JAXBContext.newInstance(ObjectFactory.class, Team.class, String .class); URL inputUrl = Test.class.getResource( "/no-nil.xml" ); System .out.println( "Non-nil test." ); doTest(inputUrl); System .out.println( "\nNil test. Member should NOT be nil" ); inputUrl = Test.class.getResource( "/nil.xml" ); doTest(inputUrl); } public static void doTest(URL inputUrl) throws Exception { Unmarshaller unm = ctx.createUnmarshaller(); Object o = unm.unmarshal(inputUrl); Team team = ((JAXBElement<Team>)o).getValue(); System .out.println( "Name: " + team.getAbstractName().getValue()); System .out.println( "Name nil? " + (team.getAbstractName().isNil() ? "YES" : "NO" )); System .out.println( "Member: " + team.getMember().getValue()); System .out.println( "Member nil? " + (team.getMember().isNil() ? "YES" : "NO" )); } } nil.xml: <team xmlns= "http://jaxb.gss.redhat.com/" > <name xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:nil= "true" /> <programmer> Kyle </programmer> </team> no-nil.xml: <team xmlns= "http://jaxb.gss.redhat.com/" > <name> SEG </name> <programmer> Kyle </programmer> </team>
        Hide
        kylape added a comment -
        Show
        kylape added a comment - Pull request: https://github.com/gf-metro/jaxb/pull/3
        Hide
        Iaroslav Savytskyi added a comment -

        Already fixed in 2.2.11

        Show
        Iaroslav Savytskyi added a comment - Already fixed in 2.2.11

          People

          • Assignee:
            Iaroslav Savytskyi
            Reporter:
            scottetech
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: