0

I am trying to parse an XML where I generate the DTOs using maven-jaxb2-plugin from xsd file. But I get this exception and don't know why, everything seems alright.

Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Publish_Date" (class com.compnay.package.SdnList$PublshInformation), not marked as ignorable (2 known properties: "publishDate", "recordCount"])
 at [Source: (PushbackInputStream); line: 4, column: 44] (through reference chain: com.compnay.package.SdnList["publshInformation"]->com.compnay.package.domain.SdnList$PublshInformation["Publish_Date"])

Jaxb execution for the relevant xsd

<execution>
  <id>tds</id>
  <goals>
    <goal>generate</goal>
  </goals>
  <configuration>
    <schemas>
      <schema>                              
        <url>xsd url</url>
      </schema>
  </schemas>                     
  <generatePackage>com.company.domain</generatePackage>
  <generateDirectory>${project.basedir}/domain/src/main/java</generateDirectory>
  <episode>false</episode>
  </configuration>
</execution>

Part of the XML file where I get the error.

<publshInformation>
  <Publish_Date>08/06/2021</Publish_Date>
  <Record_Count>9030</Record_Count>
</publshInformation>

Rest template Configuration

JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);

final XmlMapper xmlMapper = new XmlMapper(module);
xmlMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
// xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // Works when this is on

final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(xmlMapper);
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_XML));

        return new RestTemplateBuilder()
                .setReadTimeout(Duration.ofMillis(readTimeout))
                .setConnectTimeout(Duration.ofMillis(connectTimeout))
                .messageConverters(converter)
                .build();

Part of a Generated DTO

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "publshInformation",
    "sdnEntry"
})
@XmlRootElement(name = "sdnList")
public class SdnList {

    @XmlElement(required = true)
    protected SdnList.PublshInformation publshInformation;
    @XmlElement(required = true)
    protected List<SdnList.SdnEntry> sdnEntry;

    ........

    /**
     * <p>Java class for anonymous complex type.
     * 
     * <p>The following schema fragment specifies the expected content contained within this class.
     * 
     * <pre>
     * &lt;complexType&gt;
     *   &lt;complexContent&gt;
     *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
     *       &lt;sequence&gt;
     *         &lt;element name="Publish_Date" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt;
     *         &lt;element name="Record_Count" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/&gt;
     *       &lt;/sequence&gt;
     *     &lt;/restriction&gt;
     *   &lt;/complexContent&gt;
     * &lt;/complexType&gt;
     * </pre>
     * 
     * 
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "publishDate",
        "recordCount"
    })
    public static class PublshInformation {

        @XmlElement(name = "Publish_Date")
        protected String publishDate;
        @XmlElement(name = "Record_Count")
        protected Integer recordCount;
        ........
    }
}

I can make it work with using xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) but I don't want to lose other data. Can anyone help me figure it out why I get unrecognizedPropertyException? I will appreciate any pointers.

Dogukan Evcil
  • 313
  • 4
  • 15

1 Answers1

0

I guess you are doing something before the derealization which is making your input stream empty due to which you are getting this error. I used the provided XML and seems to work fine for me:

XML:

<publshInformation>
    <Publish_Date>08/06/2021</Publish_Date>
    <Record_Count>9030</Record_Count>
</publshInformation>

PublshInformation.class:

@XmlRootElement(name = "publshInformation")
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class PublshInformation {

    @XmlElement(name = "Publish_Date")
    private String Publish_Date;

    @XmlElement(name = "Record_Count")
    private Integer recordCount;

}

PublishMain.class:

public class PublishMain {
    public static void main(String[] args) throws JAXBException, XMLStreamException, IOException {
        final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream("publish.xml");
        final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
/*        final Unmarshaller unmarshaller = JAXBContext.newInstance(PublshInformation.class).createUnmarshaller();
        final PublshInformation publshInformation = unmarshaller.unmarshal(xmlStreamReader, PublshInformation.class).getValue();
        System.out.println(publshInformation.toString());

        Marshaller marshaller = JAXBContext.newInstance(PublshInformation.class).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(publshInformation, System.out);*/

        System.out.println(inputStream);
        final XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        PublshInformation jacksonPublish = xmlMapper.readValue(xmlStreamReader, PublshInformation.class);
        System.out.println(jacksonPublish);

        xmlMapper.writerWithDefaultPrettyPrinter().writeValue(System.out, jacksonPublish);

    }
}

This would produce the result:

java.io.BufferedInputStream@73a28541
PublshInformation(Publish_Date=null, recordCount=null)
<PublshInformation>
  <recordCount/>
  <publish_Date/>
</PublshInformation>

The above code works even by using the pure JAXB. If you uncomment then it will do it using the JAXB. I used the latest jackson-dataformat-xml 2.12.4

  1. Make your fields private.
  2. Use the latest version of the Jackson
  3. Ensure your input is not being used before which may become empty.

This should work I believe.

BATMAN_2008
  • 2,788
  • 3
  • 31
  • 98
  • 1
    Thanks for your input. I am using jackson 2.10. For the fields, I can't make them private as they are autogenerated but I am not using the input. I only call `restTemplate.getForEntity(this.url, SdnList.class);`. While debuging, In class `BeanPropertyMap` and at method `SettableBeanProperty find(String key)` for key `Publish_date` it matches with `recordCount` which is wrong. It might be a bug. – Dogukan Evcil Aug 09 '21 at 10:48
  • If that's the case maybe raise an issue request in the `Jackson Github` they can provide a better explanation and maybe some temporary workarounds. They are generally pretty quick in responding. – BATMAN_2008 Aug 10 '21 at 07:53
  • I figured that its not Jackson related. `jax2b-plugin` was generating bad DTO I believe when I wrote the DTO myself it worked. – Dogukan Evcil Aug 11 '21 at 06:30
  • cool to know you were able to figure it out – BATMAN_2008 Aug 11 '21 at 06:55