7

I am receiving following error message, I have Status class but it is not being recognized. I've got no idea how to proceed and could not find an answer online.

Error

   org.springframework.http.converter.HttpMessageNotReadableException: Could 
   not read JSON: Unrecognized field "Status" (class 
   com.myproject.ticket.EventsResponse), not marked as ignorable (3 known 
   properties: "events", "status", "page"])
      ....
   Caused by: 
   com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: 
   Unrecognized field "Status" (class com.myproject.ticket.EventsResponse), 
   not marked as ignorable (3 known properties: "events", "status", "page"])

EventsResponse

@XmlRootElement(name = "EventsResponse")
@XmlAccessorType(XmlAccessType.FIELD)
public class EventsResponse {
    @XmlElement(name = "Status")
    private Status status;
    @XmlElement(name = "Paging")
    private Page page;
    @XmlElementWrapper(name="Events")
    @XmlElement(name = "Event")
    private List<Event> events;

    .....

Status

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Status {
    @XmlElement(name = "Version")
    private double version;
    @XmlElement(name = "TimeStampUtc")
    private Date timeStampUtc;
    @XmlElement(name = "Code")
    private int code;
    @XmlElement(name = "Message")
    private String message;
    @XmlElement(name = "Details")
    private String details;

Response

<EventsResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Status>
        <Version>2.0</Version>
        <TimeStampUtc>2016-06-11T09:32:21</TimeStampUtc>
        <Code>0</Code>
        <Message>Success</Message>
        <Details />
    </Status>
    <Paging>
        <PageNumber>1</PageNumber>
        <PageSize>50</PageSize>
        <PageResultCount>15</PageResultCount>
        <TotalResultCount>15</TotalResultCount>
        <TotalPageCount>1</TotalPageCount>
    </Paging>
    <Events>
        <Event>

I added following to Status but I am still receiving the same error.

@XmlElement(name = "Status")
@JacksonXmlProperty(localName = "Status")
private Status status;
Daniel Newtown
  • 2,873
  • 8
  • 30
  • 64

2 Answers2

3

I failed to reconstruct your issue.

I created a test project github here that has Jackson configuration and JAXB annotations that meet your needs.

I added dependencies to jackson-dataformat-xml and woodstox-core-asl as your Stax implementations (in my test project I am using Jackson 2.6.6. ,Spring 4.2.6)

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.6.6</version>
</dependency>
<dependency>
    <groupId>org.codehaus.woodstox</groupId>
    <artifactId>woodstox-core-asl</artifactId>
    <version>4.4.1</version>
</dependency>

Configure the Jackson2ObjectMapperBuilder to use both Jackson and JAXB annotations. This is a Spring-boot example to convert to Simple Spring-MVC look here

@SpringBootApplication
public class EventAppConfiguration {

  public static void main(String[] args) {
       SpringApplication.run(EventAppConfiguration.class, args);
  }

  @Bean
  public Jackson2ObjectMapperBuilder jacksonBuilder() {
      Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
      b.indentOutput(true)
      //Enable Introspects for both Jackson and JAXB annotation
     .annotationIntrospector(introspector())
      //Use CamelCase naming
     .propertyNamingStrategy(PropertyNamingStrategy.PASCAL_CASE_TO_CAMEL_CASE)
     .dateFormat(new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss"));
      return b;
  }
  @Bean
  public AnnotationIntrospector introspector(){
     AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
     AnnotationIntrospector secondary = new    JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
     AnnotationIntrospector pair =  AnnotationIntrospector.pair(primary, secondary);
    return pair;
 }
}

Note the use of

PropertyNamingStrategy.PASCAL_CASE_TO_CAMEL_CASE

it will save you the need to specify alternative naming for first letter capitalization and will require the use for JAXB annotation only for warping and renaming for example my EventsResponse will look like:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class EventsResponse {
       private Status status;
       @XmlElement(name = "Paging")
       private Page page;
       @XmlElementWrapper(name = "Events")
       @XmlElement(name = "Event")
       private List<Event> events;
    ...
}
Sevle
  • 3,109
  • 2
  • 19
  • 31
Haim Raman
  • 11,508
  • 6
  • 44
  • 70
1

You have two options, assuming you are using Jackson to deserialize your XML objects. The simplest is to use Jackson's own XML annotations instead of or as well as the JAXB @XmlElement annotations. For example:

@XmlElement(name = "Status")
@JacksonXmlProperty(localName = "Status")
private Status status;

(The @XmlElement annotation is in the jackson-dataformat-xml package in Maven - the version should match your other Jackson package versions.)

The alternative is to register an AnnotationIntrospector as part of your deserialization chain - ie. (from a unit test):

    XmlMapper mapper = new XmlMapper();
    AnnotationIntrospector aiJaxb = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
    mapper.setAnnotationIntrospector(aiJaxb);
    // EVENTS_RESPONSE is the incoming XML
    EventsResponse response = mapper.readValue(EVENTS_RESPONSE, EventsResponse.class);

This recognises the @XmlElement annotation. There are more details in this answer if you need to include this as part of a Spring configuration, for example.

(In order to use the JaxbAnnotationIntrospector class, you will need the jackson-module-jaxb-annotation module from Maven.)

Community
  • 1
  • 1
Matt Pearce
  • 484
  • 3
  • 7
  • thanks, I added the annotation you suggested but it seems I am using a different depenency to what you use. As the IDE says jacksonXmlProperty cannot be resolved to a type. Why does it my code recognize Status? why should I use JacksonXmlProperty? – Daniel Newtown Jun 12 '16 at 11:18
  • I've added some notes on the dependencies needed. Jackson 2.x doesn't support the default JAXB annotations out of the box - see their wiki page (http://wiki.fasterxml.com/JacksonJAXBAnnotations) for more details. – Matt Pearce Jun 12 '16 at 17:34
  • I followed your first solution but the code still returns following error. org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "Status" (class com.myproject.ticket.EventsResponse), not marked as ignorable (3 known properties: "events", "status", "page"]) Question is updated. – Daniel Newtown Jun 14 '16 at 12:11
  • I think, since you're using Spring, the second suggestion is more appropriate. In particular, adding the annotations from the linked answer should help (I don't use Spring, so can't verify that those annotations do what is needed - as such, I don't want to include them in my answer). – Matt Pearce Jun 14 '16 at 12:34
  • you'll have to register the jaxbannotationmodule in your object mapper using modules to install feature in jackson2objectmapperfactorbean to have jackson recognise jaxb annotations. – s7vr Jun 16 '16 at 05:23