UnmarshallingFailureException: JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException
Asked Answered
T

1

1

I am trying to send a SOAP request and receive the response by WebServiceTemplate but I am receiving following exception:

The WSDL is here.

SEVERE: Servlet.service() for servlet [bb] in context with path [/Bb] threw 
exception [Request processing failed; nested exception is 
org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling 
exception; nested exception is javax.xml.bind.UnmarshalException: unexpected 
element (uri:"http://ticketmaster.productserve.com/v2/soap.php", 
local:"findEventsResponse"). Expected elements are <{}findEvents>,<{}request>,
<{}sortTicket>] with root cause

Request

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Request.class})
public class FindEvents {
    @XmlElement
    private Request request;

           getter / setter
}


@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({SortTicket.class})
public class Request {
    @XmlElement
    private String apiKey;
    @XmlElement
    private String country;
    @XmlElement
    private int resultsPerPage;
    @XmlElement
    private int currentPage;
    @XmlElement(name = "Sort")
    private SortTicket sort;
    @XmlElement
    private String[] filters;
    @XmlElement
    private String updatedSince;

           getters / setters
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class SortTicket {
    @XmlElement
    private String field;
    @XmlElement
    private String order;

           getters / setters
}

Response

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Return.class})
public class FindEventsResponse {
    @XmlElement
    private Return returnResult;

           getters / setters
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Details.class,Results.class})
public class Return {
    @XmlElement
    private Details details;
    @XmlElement
    private Results results;

           getters / setters
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Details {
    @XmlElement
    private int totalResults;
    @XmlElement
    private int totalPages;
    @XmlElement
    private int currentPage;
    @XmlElement
    private int resultsPerPage;

    getters / setters
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({ Artist.class, Venue.class })
public class Results {
    @XmlElement
    private long eventId;
    @XmlElement
    private String ticketmasterEventId;
    @XmlElement
    private String status;
    @XmlElement
    private String name;
    @XmlElement
    private String url;
    @XmlElement
    private String eventDate;
    @XmlElement
    private String onSaleDate;
    @XmlElement
    private String preSaleDate;
    @XmlElement
    private int categoyId;
    @XmlElement
    private String parentCategory;
    @XmlElement
    private int parentCategoryId;
    @XmlElement
    private Double minPrice;
    @XmlElement
    private Double maxPrice;
    @XmlElement(name = "Artists")
    private Artist artist;
    @XmlElement
    private Venue venue;

     getters / setters
}


@XmlRootElement(name = "Artists")
@XmlAccessorType(XmlAccessType.FIELD)
public class Artist {
    @XmlElement
    private long artistId;
    @XmlElement
    private long ticketMasterArtistId;
    @XmlElement
    private String name;
    @XmlElement
    private String url;
    @XmlElement
    private String imageUrl;
    @XmlElement
    private String category;
    @XmlElement
    private int categoryId;
    @XmlElement
    private String parentCategory;
    @XmlElement
    private int parentCategoryId;

           getters / setters
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Venue {
    @XmlElement
    private long venueId;
    @XmlElement
    private long ticketmasterVenueId;
    @XmlElement
    private String name;
    @XmlElement
    private String street;
    @XmlElement
    private String city;
    @XmlElement
    private String country;
    @XmlElement
    private String postcode;
    @XmlElement
    private String url;
    @XmlElement
    private String imageUrl;
    @XmlElement
    private String state;

    getters / setters
}

Configuration is as follows

<oxm:jaxb2-marshaller id="marshaller">
        <oxm:class-to-be-bound name="com.bb.tickets.ticketmaster.FindEvents"/>
    </oxm:jaxb2-marshaller>

    <bean id="webServiceTemplate" 
        class="org.springframework.ws.client.core.WebServiceTemplate">
        <property name="marshaller" ref="marshaller" />
        <property name="unmarshaller" ref="marshaller" />
        <property name="defaultUri"
            value="http://ticketmaster.productserve.com/v2/soap.php" />

    </bean>

The code to send the request and receive response

SortTicket sortTicket = new SortTicket();
Request request = new Request();
request.setApiKey("APIKEY");
request.setCountry("UK");
FindEvents findEvents = new FindEvents();
findEvents.setRequest(request);
FindEventsResponse response = (FindEventsResponse) 
webServiceTemplate.marshalSendAndReceive(findEvents);
System.err.println("response:"+ 
response.getReturnResult().getDetails().getCurrentPage());  
Thread answered 24/8, 2015 at 11:56 Comment(0)
M
1

From the stack trace, I understand that JAX-B received a findEventsResponse of type FindEventsResponse to marshall but it expected a FindEvents object.

The issue lies within your spring configuration. You only told Spring that the FindEvents class should be bound to your marshaller. You need to add the FindEventsResponse class too, using the classesToBeBound property :

<oxm:jaxb2-marshaller id="marshaller">
    <property name="classesToBeBound">
        <list>
            <value>com.bb.tickets.ticketmaster.FindEvents</value>
            <value>com.bb.tickets.ticketmaster.FindEventsResponse</value>
        </list>
    </property>
</oxm:jaxb2-marshaller>

You could also bound a package using the packageToScan property, check this question.

Hope that does it.

[Edit]: if it doesn't work simply try :

<oxm:jaxb2-marshaller id="marshaller">
    <oxm:class-to-be-bound name="com.bb.tickets.ticketmaster.FindEvents"/>
    <oxm:class-to-be-bound name="com.bb.tickets.ticketmaster.FindEventsResponse"/>
</oxm:jaxb2-marshaller>
Mohsen answered 24/8, 2015 at 12:35 Comment(5)
I used that but it returns following cvc-complex-type.2.4.a: Invalid content was found starting with element 'property'. One of '{"springframework.org/schema/oxm":class-to-be-bound}' is expected.Thread
I am using 4.1.5.RELEASEThread
That's strange, maybe there is an issue with you Spring config, check the documentation. My updated answer should work according to what I found in it.Mohsen
I will, I just used the second option but it returns Failed to convert property value of type 'java.util.ArrayList' to required type 'java.lang.Class[]' for property 'classesToBeBound'; nested exception is java.lang.IllegalArgumentException:Thread
Do you have exactly the same pojos as those shown in you question? Where does that ArrayList come from ?Mohsen

© 2022 - 2024 — McMap. All rights reserved.