I am sending a request to a webservice but it seems the request is invalid. I am sending a similar request using SoapUI and the webservice accepts it. I need to change my request to what SoapUI sends. How can I add namespaces to my request? WSDL is here.
I visited following pages but could not find a solution yet. 1,2,3
Code
SearchFlights
#XmlRootElement(name = "SearchFlights")
#XmlAccessorType(XmlAccessType.FIELD)
public class SearchFlights {
#XmlElement(name = "SoapMessage")
private SoapMessage soapMessage;
getter and setter
SoapMessage
#XmlRootElement(name = "SoapMessage")
#XmlAccessorType(XmlAccessType.FIELD)
public class WegoloSoapMessage {
#XmlElement(name = "Username")
private String username;
#XmlElement(name = "Password")
private String password;
#XmlElement(name = "LanguageCode")
private String languageCode;
#XmlElement(name = "Request")
private Request request;
getters and setters
Request
#XmlRootElement(name = "Request")
#XmlAccessorType(XmlAccessType.FIELD)
public class Request {
#XmlElement(name = "Departure")
private String departure;
#XmlElement(name = "Destination")
private String destination;
#XmlElement(name = "DepartureDate")
private String departureDate;
#XmlElement(name = "ReturnDate")
private String returnDate;
#XmlElement(name = "NumADT")
private int numADT;
#XmlElement(name = "NumINF")
private int numInf;
#XmlElement(name = "NumCHD")
private int numCHD;
#XmlElement(name = "CurrencyCode")
private String currencyCode;
#XmlElement(name = "WaitForResult")
private boolean waitForResult;
#XmlElement(name = "NearByDepartures")
private boolean nearByDepartures;
#XmlElement(name = "NearByDestinations")
private boolean nearByDestinations;
#XmlElement(name = "RROnly")
private boolean rronly;
#XmlElement(name = "MetaSearch")
private boolean metaSearch;
getters and setters
jaxb.index
SearchFlights
Flight
Flights
Leg
Legs
Outbound
Request
Response
WegoloSoapMessage
Code to send request
try {
SaajSoapMessageFactory soapMsgFac = new SaajSoapMessageFactory(
MessageFactory.newInstance());
soapMsgFac.afterPropertiesSet();
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(
soapMsgFac);
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.myprojet.flights.wegolo");
marshaller.afterPropertiesSet();
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.setUnmarshaller(marshaller);
webServiceTemplate.afterPropertiesSet();
Response response = (Response) webServiceTemplate
.marshalSendAndReceive(
"http://www5v80.elsyarres.net/service.asmx",
searchFlights,
new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message)
{
((SoapMessage)message).setSoapAction("ElsyArres.API/SearchFlights");
}
}
);
Response msg = (Response) response;
System.err.println("Wegolo >>>"
+ msg.getFlights().getFlight().size());
} catch (Exception s) {
s.printStackTrace();
}
}
My Request
SoapUI request
In your request there is no namesapce before elements like in request from SoapUI.
For example your element:
<SearchFlights>
SoupUI element:
<els:SearchFlights>
You should add namespace xmlns:els="ElsyArres.API" and prefix before all elements using code form here or here or here.
Related
I need help to convert the soap request and response to Java Object. So that I can marshal and un-marshal it.
Note: I am new to soap services and tried built in tool but not able to convert into Java Object.
Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sen="http://schemas.xmlsoap.org/sendSmsMSDP" xmlns:met="http://schemas.xmlsoap.org/soap/MetaInfoReq">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>ravi</wsse:Username>
<wsse:Password>more</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<sen:SendSmsMSDPRequest>
<sen:MetaInfo>
<met:ConsumerReqInfo>
<met:circleId>1</met:circleId>
<met:serviceName>sendSmsMSDP_SV</met:serviceName>
<met:channelName>CG</met:channelName>
<met:segment>PREPAID</met:segment>
<met:key>345</met:key>
<met:version>1.0</met:version>
</met:ConsumerReqInfo>
</sen:MetaInfo>
<sen:SRVsendSmsMSDPReq>
<sen:requestType>SMSSubmitReq</sen:requestType>
<sen:userName>usernME</sen:userName>
<sen:password>PASSWORD</sen:password>
<sen:mobileNumber>XXXXXXXXXX</sen:mobileNumber>
<sen:message>hello</sen:message>
<sen:originAddress>0987</sen:originAddress>
<sen:type>0</sen:type>
</sen:SRVsendSmsMSDPReq>
</sen:SendSmsMSDPRequest>
</soapenv:Body>
</soapenv:Envelope>
Response:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sen="http://schemas.xmlsoap.org/soap/envelope/" xmlns:met="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<sen:SendSmsMSDPResponse>
<sen:MetaInfo>
<met:ConsumerReqInfo>
<met:circleId>123</met:circleId>
<met:serviceName>sendSmsMSDP_SV</met:serviceName>
<met:channelName>cc</met:channelName>
<met:segment>pre</met:segment>
<met:key>345</met:key>
<met:version>1.0</met:version>
</met:ConsumerReqInfo>
<met:StatusInfo>
<met:errorCode>WWI00000I</met:errorCode>
<met:errorStatus>0</met:errorStatus>
<met:errorDesc>The Request has been processed Successfully</met:errorDesc>
<met:errorCategory>SUCCESS</met:errorCategory>
</met:StatusInfo>
</sen:MetaInfo>
</sen:SendSmsMSDPResponse>
</soapenv:Body>
</soapenv:Envelope>
Also, if you know some resources for soap services that will be really helpful.
Thanks for your time.
**For Response **
Here is my classes but its failing.
#XmlRootElement(name = "SendSmsMSDPResponse")
#XmlAccessorType(XmlAccessType.FIELD)
public class SendSmsMSDPResponse {
#XmlElement(name = "MetaInfo")
private MetaInfo MetaInfo;
public MetaInfo getMetaInfo() {
return MetaInfo;
}
public void setMetaInfo(MetaInfo metaInfo) {
MetaInfo = metaInfo;
}
}
#XmlRootElement(name = "MetaInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class MetaInfo {
#XmlElement(name = "ConsumerReqInfo")
private ConsumerReqInfo ConsumerReqInfo;
#XmlElement(name = "StatusInfo")
private StatusInfo StatusInfo;
public ConsumerReqInfo getConsumerReqInfo() {
return ConsumerReqInfo;
}
public void setConsumerReqInfo(ConsumerReqInfo consumerReqInfo) {
ConsumerReqInfo = consumerReqInfo;
}
public StatusInfo getStatusInfo() {
return StatusInfo;
}
public void setStatusInfo(StatusInfo statusInfo) {
StatusInfo = statusInfo;
}
}
#XmlRootElement(name = "ConsumerReqInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class ConsumerReqInfo {
#XmlElement(name = "circleId")
private String circleId;
#XmlElement(name = "serviceName")
private String serviceName;
#XmlElement(name = "channelName")
private String channelName;
#XmlElement(name = "segment")
private String segment;
#XmlElement(name = "key")
private String key;
#XmlElement(name = "version")
private String version;
//setters and getters
}
#XmlRootElement(name = "StatusInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class StatusInfo {
#XmlElement(name = "errorCode")
private String errorCode;
#XmlElement(name = "errorStatus")
private String errorStatus;
#XmlElement(name = "errorDesc")
private String errorDesc;
#XmlElement(name = "errorCategory")
private String errorCategory;
// setters and getters
}
I have this soap response below and I need to parse it to a java object ...But all the fields are returning null when I print it. Below the classes that I am using to interpret the response.
I have been trying to use jaxb to unmarshall the content but none of my tries went right.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:consultarPosicaoCotistaOnOfflineFundoResponse>
<ns2:listCotistaFundo>
<ns2:cotistaFundo>
<ns2:cdFundo>014588</ns2:cdFundo>
<ns2:nmCliente>BRADESCO FIC FIM GAVEA MACRO</ns2:nmCliente>
<ns2:dtPosicao>2021-02-18</ns2:dtPosicao>
<ns2:vlCota>1.3121393</ns2:vlCota>
<ns2:qtdCotas>43650.7211055</ns2:qtdCotas>
<ns2:vlCorrigido>57275.83</ns2:vlCorrigido>
<ns2:vlIr>221.1</ns2:vlIr>
<ns2:vlIof>0</ns2:vlIof>
<ns2:vlLiquidoResg>57054.73</ns2:vlLiquidoResg>
<ns2:vlContaCorrente>57054.73</ns2:vlContaCorrente>
<ns2:vlContaInvestimento>57054.73</ns2:vlContaInvestimento>
<ns2:noCnpjFundo>28428211000149</ns2:noCnpjFundo>
<ns2:icAfPosicao>F</ns2:icAfPosicao>
<ns2:vlAplicacao>49069.11</ns2:vlAplicacao>
<ns2:qtCotasBloqueadas>0</ns2:qtCotasBloqueadas>
<ns2:vlBrutoBloqueado>0</ns2:vlBrutoBloqueado>
<ns2:vlLiquidoBloqueado>0</ns2:vlLiquidoBloqueado>
<ns2:vlAplicacaoNaoCotizada>0</ns2:vlAplicacaoNaoCotizada>
<ns2:vlResgateNaoCotizado>0</ns2:vlResgateNaoCotizado>
</ns2:cotistaFundo>
</ns2:listCotistaFundo>
<ns3:responseMessages>
<ns3:message>
<ns3:code>EJCOT-0000</ns3:code>
<ns3:desc>Operação Concluída</ns3:desc>
</ns3:message>
</ns3:responseMessages>
</ns2:consultarPosicaoCotistaOnOfflineFundoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Unmarshaller unmarshaller = JAXBContext.newInstance(ConsultarPosicaoCotistaOnOfflineFundoResponse.class).createUnmarshaller();
response = (ConsultarPosicaoCotistaOnOfflineFundoResponse) unmarshaller.unmarshal(soapMessage.getSOAPBody().extractContentAsDocument());
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "consultarPosicaoCotistaOnOfflineFundoResponse",
namespace = "http://totvs.cot.webservices")
public class ConsultarPosicaoCotistaOnOfflineFundoResponse implements Serializable {
private ListCotistaFundo[] listCotistaFundo;
public ListCotistaFundo[] getCotistaFundo() {
return listCotistaFundo;
}
#XmlElement(name ="listCotistaFundo",
namespace = "http://totvs.cot.webservices")
public void setCotistaFundos(ListCotistaFundo[] listCotistaFundo) {
this.listCotistaFundo = listCotistaFundo;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
public class ListCotistaFundo {
#XmlElement(name = "cdFundo")
private String cdFundo;
#XmlElement(name = "nmCliente")
private String nmCliente;
#XmlElement(name = "dtPosicao")
private Date dtPosicao;
#XmlElement(name = "vlCota")
private BigDecimal vlCota;
#XmlElement(name = "qtdCotas")
private BigDecimal qtdCotas;
#XmlElement(name = "vlCorrigido")
private BigDecimal vlCorrigido;
#XmlElement(name = "vlIr")
private BigDecimal vlIr;
#XmlElement(name = "vlIof")
private BigDecimal vlIof;
#XmlElement(name = "vlLiquidoResg")
private BigDecimal vlLiquidoResg;
#XmlElement(name = "vlContaCorrente")
private BigDecimal vlContaCorrente;
#XmlElement(name = "vlContaInvestimento")
private BigDecimal vlContaInvestimento;
#XmlElement(name = "noCnpjFundo")
private double noCnpjFundo;
#XmlElement(name = "icAfPosicao")
private String icAfPosicao;
#XmlElement(name = "vlAplicacao")
private BigDecimal vlAplicacao;
#XmlElement(name = "qtCotasBloqueadas")
private BigDecimal qtCotasBloqueadas;
#XmlElement(name = "vlBrutoBloqueado")
private BigDecimal vlBrutoBloqueado;
#XmlElement(name = "vlLiquidoBloqueado")
private BigDecimal vlLiquidoBloqueado;
#XmlElement(name = "vlAplicacaoNaoCotizada")
private BigDecimal vlAplicacaoNaoCotizada;
#XmlElement(name = "vlResgateNaoCotizado")
private BigDecimal vlResgateNaoCotizado;
Getters and Setters ...
Does anyone have a tip in how to convert the response in Java object?
It could be an issue with namespace since I dont see namespaces declared in the XML. You could try setting the namespace as empty in both #XmlRootElement and #XmlElement as follows :
#XmlRootElement(name = "consultarPosicaoCotistaOnOfflineFundoResponse",
namespace = "")
#XmlElement(name ="listCotistaFundo", namespace = "")
When I send a SOAP request to the server it returns following error. I am not sure how I can configure unmarshaller, I am going to send SOAP requests to multiple webservices. WSDL is here.
I visited following pages but could not find a solution yet. 1,2,3
java.lang.IllegalStateException: No unmarshaller registered. Check configuration of WebServiceTemplate.
at org.springframework.ws.client.core.WebServiceTemplate$3.extractData(WebServiceTemplate.java:406)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:598)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:539)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:386)
Code
SearchFlights
#XmlRootElement(name = "SearchFlights")
#XmlAccessorType(XmlAccessType.FIELD)
public class SearchFlights {
#XmlElement(name = "SoapMessage")
private SoapMessage soapMessage;
getter and setter
SoapMessage
#XmlRootElement(name = "SoapMessage")
#XmlAccessorType(XmlAccessType.FIELD)
public class SoapMessage {
#XmlElement(name = "Username")
private String username;
#XmlElement(name = "Password")
private String password;
#XmlElement(name = "LanguageCode")
private String languageCode;
#XmlElement(name = "Request")
private Request request;
getters and setters
Request
#XmlRootElement(name = "Request")
#XmlAccessorType(XmlAccessType.FIELD)
public class Request {
#XmlElement(name = "Departure")
private String departure;
#XmlElement(name = "Destination")
private String destination;
#XmlElement(name = "DepartureDate")
private String departureDate;
#XmlElement(name = "ReturnDate")
private String returnDate;
#XmlElement(name = "NumADT")
private int numADT;
#XmlElement(name = "NumINF")
private int numInf;
#XmlElement(name = "NumCHD")
private int numCHD;
#XmlElement(name = "CurrencyCode")
private String currencyCode;
#XmlElement(name = "WaitForResult")
private boolean waitForResult;
#XmlElement(name = "NearByDepartures")
private boolean nearByDepartures;
#XmlElement(name = "NearByDestinations")
private boolean nearByDestinations;
#XmlElement(name = "RROnly")
private boolean rronly;
#XmlElement(name = "MetaSearch")
private boolean metaSearch;
getters and setters
jaxb.index
SearchFlights
Flight
Flights
Leg
Legs
Outbound
Request
Response
SoapMessage
Code to send request
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
......
// populate searchFlights and other classes to create request
try {
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(
MessageFactory.newInstance());
messageFactory.afterPropertiesSet();
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(
messageFactory);
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.myproject.flights.wegolo");
marshaller.afterPropertiesSet();
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.afterPropertiesSet();
Response response = (Response) webServiceTemplate
.marshalSendAndReceive( <<< ERROR is on this line
"http://www5v80.elsyarres.net/service.asmx",
searchFlights,
new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message)
{
((SoapMessage)message).setSoapAction("http://www5v80.elsyarres.net/searchFlights");
}
}
);
Response msg = (Response) response;
System.err.println("Wegolo >>>"
+ msg.getFlights().getFlight().size());
} catch (Exception s) {
s.printStackTrace();
}
It seems that you didn't set the unmarshaller on your webServiceTemplate.
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.setUnmarshaller(marshaller);
I am trying to parse a SOAP response. I can show the full response using following line.
System.out.println("Response: " + out.toString());
However when I parse the response and marshall the parsed response, it shows a wrong response.
package-info.java
#XmlSchema(
namespace = "http://v3.hotel.wsapi.ean.com/",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.ean;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
My Code
#XmlRootElement(name="getListResponse")
#XmlAccessorType(XmlAccessType.FIELD)
public class GetListResponse {
#XmlElement(name="HotelListResponse")
private HotelListResponse hotelListResponse;
public GetListResponse() {
this.hotelListResponse = new HotelListResponse();
}
…getter and setter
}
#XmlRootElement(name ="HotelListResponse")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelListResponse {
#XmlElement(name = "customerSessionId")
String customerSessionId;
#XmlElement(name = "numberOfRoomsRequested")
int numberOfRoomsRequested;
#XmlElement(name = "moreResultsAvailable")
boolean moreResultsAvailable;
#XmlElement(name = "cacheKey")
String cacheKey;
#XmlElement(name="cacheLocation")
String cachLocation;
#XmlElement(name = "HotelList")
HotelList hotelList;
public HotelListResponse() {
this.hotelList = new HotelList();
}
… getters and setters…
}
#XmlRootElement(name ="HotelList")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelList {
#XmlAttribute(name = "size")
int size;
#XmlAttribute(name = "activePropertyCount")
int activePropertyCount;
#XmlElement(name = "HotelSummary")
List <HotelSummary> hotelSummaries;
public HotelList() {
this.hotelSummaries = new ArrayList();
}
… getters and setters…
}
#XmlRootElement(name = "HotelSummary")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelSummary {
#XmlAttribute(name = "order")
int order;
#XmlElement(name = "hotelId")
int hotelId;
#XmlElement(name = "name")
String name;
#XmlElement(name = "address1")
String address1;
#XmlElement(name = "city")
String city;
#XmlElement(name = "stateProvinceCode")
String stateProvinceCode;
#XmlElement(name = "postalCode")
int postalCode;
#XmlElement(name = "countryCode")
String countryCode;
#XmlElement(name = "airportCode")
String airportCode;
#XmlElement(name = "supplierType")
String supplierType;
#XmlElement(name = "propertyCategory")
int propertyCategory;
#XmlElement(name = "hotelRating")
float hotelRating;
#XmlElement(name = "confidenceRating")
int confidenceRating;
#XmlElement(name = "amenityMask")
int amenityMask;
#XmlElement(name = "tripAdvisorRating")
float tripAdvisorRating;
#XmlElement(name = "locationDescription")
String locationDescription;
#XmlElement(name = "shortDescription")
String shortDescriptionl; //change amp to &
#XmlElement(name = "highRate")
String highRate;
#XmlElement(name = "lowRate")
float lowRate;
#XmlElement(name = "rateCurrencyCode")
String rateCurrencyCode;
#XmlElement(name = "latitude")
float latitude;
#XmlElement(name = "longitude")
float longitude;
#XmlElement(name = "proximityDistance")
float proximityDistance;
#XmlElement(name = "proximityUnit")
String proximityUnit;
#XmlElement(name = "hotelInDestination")
boolean hotelInDestination;
#XmlElement(name = "thumbNailUrl")
String thumbNailUrl;
#XmlElement(name = "deepLink")
String deepLink;
#XmlElement(name = "RoomRateDetailsList")
RoomRateDetailsList roomRateDetailsList;
public HotelSummary() {
this.roomRateDetailsList = new RoomRateDetailsList();
}
… getters and setters…
}
#XmlRootElement(name = "RoomRateDetailsList")
#XmlAccessorType(XmlAccessType.FIELD)
public class RoomRateDetailsList {
#XmlElement(name="RoomRateDetails")
List<RoomRateDetails> roomRateDetails;
public RoomRateDetailsList() {
this.roomRateDetails = new ArrayList();
}
.. getter and setter..
}
#XmlRootElement(name = "RoomRateDetails")
#XmlAccessorType(XmlAccessType.FIELD)
public class RoomRateDetails {
#XmlElement(name="roomTypeCode")
int roomTypeCode;
#XmlElement(name="rateCode")
int rateCode;
#XmlElement(name="maxRoomOccupancy")
int maxRoomOccupancy;
#XmlElement(name="quotedRoomOccupancy")
int quotedRoomOccupancy;
#XmlElement(name="minGuestAge")
int minGuestAge;
#XmlElement(name="roomDescription")
String roomDescription;
#XmlElement(name="promoId")
int promoId;
#XmlElement(name="promoDescription")
String promoDescription;
#XmlElement(name="currentAllotment")
int currentAllotment;
#XmlElement(name="propertyAvailable")
boolean propertyAvailable;
#XmlElement(name="propertyRestricted")
boolean propertyRestricted;
#XmlElement(name="expediaPropertyId")
int expediaPropertyId;
#XmlElement(name="rateKey")
String rateKey;
#XmlElement(name="RateInfo")
RateInfo rateInfo;
#XmlElement(name="ValueAdds")
ValueAdds valueAdds;
public RoomRateDetails() {
this.rateInfo = new RateInfo();
this.valueAdds = new ValueAdds();
}
… getters and setters…
}
#XmlRootElement(name = "RoomInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class RateInfo {
#XmlAttribute(name="priceBreakdown")
boolean priceBreakdown;
#XmlAttribute(name="promo")
boolean promo;
#XmlAttribute(name="rateChange")
boolean rateChange;
#XmlElement(name="ChargeableRateInfo")
ChargeableRateInfo chargeableRateInfo;
public RateInfo() {
this.chargeableRateInfo = new ChargeableRateInfo();
}
.. getters and setters…
}
#XmlRootElement(name = "ChargeableRateInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class ChargeableRateInfo {
#XmlAttribute(name="averageBaseRate")
float averageBaseRate;
#XmlAttribute(name="averageRate")
float averageRate;
#XmlAttribute(name="commissionableUsdTotal")
float commissionableUsdTotal;
#XmlAttribute(name="currencyCode")
String currencyCode;
#XmlAttribute(name="maxNightlyRate")
float maxNightlyRate;
#XmlAttribute(name="nightlyRateTotal")
float nightlyRateTotal;
#XmlAttribute(name="total")
float total;
#XmlElement(name="NightlyRatesPerRoom")
NightlyRatesPerRoom nightlyRatesPerRoom;
public ChargeableRateInfo() {
this.nightlyRatesPerRoom = new NightlyRatesPerRoom();
}
… getters and setters…
}
#XmlRootElement(name = "NightlyRatesPerRoom")
#XmlAccessorType(XmlAccessType.FIELD)
public class NightlyRatesPerRoom {
#XmlAttribute(name="size")
int size;
#XmlElement(name="NightlyRate")
NightlyRate nightlyRate;
public NightlyRatesPerRoom() {
this.nightlyRate = new NightlyRate();
}
… getters and setters…
}
#XmlRootElement(name = "NightlyRate")
#XmlAccessorType(XmlAccessType.FIELD)
public class NightlyRate {
#XmlAttribute(name="baseRate")
float baseRate;
#XmlAttribute(name="rate")
float rate;
#XmlAttribute(name="promo")
float promo;
public NightlyRate() {
}
… getters and setters…
}
#XmlRootElement(name = "ValueAdds")
#XmlAccessorType(XmlAccessType.FIELD)
public class ValueAdds {
#XmlAttribute(name="size")
private int size;
#XmlElement(name="ValueAdd")
private List<ValueAdd> valueAdd;
public ValueAdds() {
this.valueAdd = new ArrayList();
}
… getters and setters…
}
#XmlRootElement(name = "ValueAdd")
#XmlAccessorType(XmlAccessType.FIELD)
public class ValueAdd {
#XmlAttribute(name="id")
private int id;
#XmlElement(name="description")
private String description;
public ValueAdd() {
}
… getters and setters…
}
Code
try {
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection connection = soapConnectionFactory.createConnection();
SOAPFactory soapFactory = SOAPFactory.newInstance();
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
SOAPHeader header = message.getSOAPHeader();
header.detachNode();
SOAPBody body = message.getSOAPBody();
Name bodyName;
bodyName = soapFactory.createName("getList",
"v3", "http://v3.hotel.wsapi.ean.com/");
SOAPBodyElement getList
= body.addBodyElement(bodyName);
Name childName = soapFactory.createName("HotelListRequest");
SOAPElement HotelListRequest = getList.addChildElement(childName);
……Here, I add child nodes of the request…...
message.writeTo(System.out); //show message details
URL endpoint = new URL("http://dev.api.ean.com/ean-services/ws/hotel/v3");
SOAPMessage response = connection.call(message, endpoint);
connection.close();
SOAPMessage sm = response;
System.err.println("Response:");
ByteArrayOutputStream out = new ByteArrayOutputStream();
sm.writeTo(out);
System.err.println(">>>" + out.toString());
System.err.println(">>>>>>>>>>>parse:");
SOAPBody sb = response.getSOAPBody();
DOMSource source = new DOMSource(sb);
HotelListResponse results = new HotelListResponse();
results = (HotelListResponse) JAXB.unmarshal(source, HotelListResponse.class);
JAXBContext context = JAXBContext.newInstance(HotelListResponse.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
System.err.println("Response *******");
m.marshal(results, System.out);
System.err.println("116872:" + results.getHotelList().getHotelSummaries().get(0).getHotelId());
} catch (Exception ex) {
ex.printStackTrace();
}
Actual Respose
Response:
Response:>>><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getListResponse xmlns:ns2="http://v3.hotel.wsapi.ean.com/">
<HotelListResponse>
<customerSessionId>0ABAAA95-28B2-5914-7952-0331AC9069EA</customerSessionId>
<numberOfRoomsRequested>1</numberOfRoomsRequested>
<moreResultsAvailable>true</moreResultsAvailable>
<cacheKey>-41118b29:146950321ac:-69e1</cacheKey>
<cacheLocation>10.176.160.143:7300</cacheLocation>
<HotelList size="25" activePropertyCount="119">
<HotelSummary order="0">
<hotelId>150241</hotelId>
<name>Rydges World Square</name>
<address1>389 Pitt Street</address1>
<city>Sydney</city>
<stateProvinceCode>NW</stateProvinceCode>
<postalCode>2000</postalCode>
<countryCode>AU</countryCode>
<airportCode>SYD</airportCode>
<supplierType>E</supplierType>
<propertyCategory>1</propertyCategory>
<hotelRating>4.5</hotelRating>
<confidenceRating>52</confidenceRating>
<amenityMask>1343491</amenityMask>
<tripAdvisorRating>3.5</tripAdvisorRating>
<locationDescription>Near Darling Harbour</locationDescription>
<shortDescription><p><b>Property Location</b> <br />With a stay at Rydges World Square, you'll be centrally located in Sydney, steps from World Square Shopping Centre and minutes from Capitol Theatre. This 4.5-star</shortDescription>
<highRate>218.64</highRate>
<lowRate>218.64</lowRate>
<rateCurrencyCode>USD</rateCurrencyCode>
<latitude>-33.8766</latitude>
<longitude>151.20752</longitude>
<proximityDistance>0.5492472</proximityDistance>
<proximityUnit>MI</proximityUnit>
<hotelInDestination>true</hotelInDestination>
<thumbNailUrl>/hotels/1000000/570000/565000/564969/564969_91_t.jpg</thumbNailUrl>
<deepLink>http://travel.ian.com/index.jsp?pageName=hotAvail&cid=55505&hotelID=150241&mode=2&numberOfRooms=1&room-0-adult-total=2&room-0-child-total=0&arrivalMonth=5&arrivalDay=18&departureMonth=5&departureDay=19&showInfo=true&locale=en_US&currencyCode=USD</deepLink>
<RoomRateDetailsList>
<RoomRateDetails>
<roomTypeCode>200156055</roomTypeCode>
<rateCode>202768754</rateCode>
<maxRoomOccupancy>2</maxRoomOccupancy>
<quotedRoomOccupancy>2</quotedRoomOccupancy>
<minGuestAge>0</minGuestAge>
<roomDescription>Special: Deluxe King - Check-In from 8:30pm</roomDescription>
<promoId>201528081</promoId>
<promoDescription>Sale! Save 25% on this Stay.</promoDescription>
<currentAllotment>10</currentAllotment>
<propertyAvailable>true</propertyAvailable>
<propertyRestricted>false</propertyRestricted>
<expediaPropertyId>564969</expediaPropertyId>
<rateKey>0ABAAA85-18B2-9914-6952-0351AC9069DF</rateKey>
<RateInfo priceBreakdown="true" promo="true" rateChange="false">
<ChargeableRateInfo averageBaseRate="218.64" averageRate="218.64" commissionableUsdTotal="218.64" currencyCode="USD" maxNightlyRate="218.64" nightlyRateTotal="218.64" total="218.64">
<NightlyRatesPerRoom size="1">
<NightlyRate baseRate="218.64" rate="218.64" promo="false"/>
</NightlyRatesPerRoom>
</ChargeableRateInfo>
</RateInfo>
<ValueAdds size="1">
<ValueAdd id="2048">
<description>Free Wireless Internet</description>
</ValueAdd>
</ValueAdds>
</RoomRateDetails>
<RoomRateDetails>
...
>>>>>>>>>>>parse:
Response *******
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<HotelListResponse xmlns="http://v3.hotel.wsapi.ean.com/">
<numberOfRoomsRequested>0</numberOfRoomsRequested>
<moreResultsAvailable>false</moreResultsAvailable>
<HotelList size="0" activePropertyCount="0"/>
</HotelListResponse>
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at com.expedia.Engine.retrieveHotels(Engine.java:135)
at com.hotelsdotcom.App.main(App.java:17)
How to Fix Things
Unmarshal at the Right Level
Currently you are unmarshalling the XML node that corresponds to the soap:Body element, instead you need to navigate down to the HotelListResponse element and unmarshal that.
You could try the following:
DOMSource source = new DOMSource(sb.getFirstChild().getFirstChild());
Watch your Namespace Qualification
In the XML that you have marshalled all the elements appear qualified with the http://v3.hotel.wsapi.ean.com/, the document that you are trying to unmarshal doesn't have this namespace qualification so you should remove the #XmlSchema annotation from the package-info class.
Use Unmarshaller instead of JAXB.unmarshal
Instead of doing the following:
results = (HotelListResponse) JAXB.unmarshal(source, HotelListResponse.class);
I would recommend doing:
JAXBContext jc = JAXBContext.newInstance(HotelListResponse.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
results = unmarshaller.unmarshal(source, HotelListResponse.class).getValue();
What is Happening Now
When you use an unmarshal method that takes a class parameter, you are telling JAXB what class that XML corresponds to instead of having it automatically determined by the root element.
results = (HotelListResponse) JAXB.unmarshal(source, HotelListResponse.class)
Because the level of the XML document is wrong JAXB isn't able to match any of it to your domain model. Therefore only the default values are populated. This is why the result is full of values that are 0 or false.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<HotelListResponse xmlns="http://v3.hotel.wsapi.ean.com/">
<numberOfRoomsRequested>0</numberOfRoomsRequested>
<moreResultsAvailable>false</moreResultsAvailable>
<HotelList size="0" activePropertyCount="0"/>
</HotelListResponse>
I am trying to parse the XML response to an object but it throws exception.
The link of response is this:
<response>
<meta>
<per_page>10</per_page>
<total>20</total>
<geolocation>None</geolocation>
<took>8</took>
<page>1</page>
</meta>
<events>
<event>
...
</event>
<event>
...
</event>
....
</events>
</response>
Code
queryString = queryString.replaceAll(" ", "%20");
try {
URL page = new URL(queryString);
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
InputStreamReader in = new InputStreamReader(conn.getInputStream(),Charset.forName("UTF-8"));
this.response = (Response) JAXB.unmarshal(in, Response.class);
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
Exception
javax.xml.bind.DataBindingException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 40
counts of IllegalAnnotationExceptions
Class has two properties of the same name "events"
this problem is related to the following location:
....
Object classes
#XmlRootElement(name = "Response")
public class Response {
#XmlElement(name="per_page")
private int per_page;
#XmlElement(name="total")
private int total;
#XmlElement(name="geolocation")
private String geolocation;
#XmlElement(name="took")
private int took;
#XmlElement(name="page")
private int page;
#XmlElement(name="events")
private List<Event> events = null;
**getters and setters**
Objects
#XmlRootElement(name="event")
public class Event {
#XmlElement(name = "links")
private String link;
#XmlElement(name = "id")
private int id;
#XmlElement(name = "stats")
private Stats stats;
#XmlElement(name = "title")
private String title;
#XmlElement(name = "announce_date")
private String announce_date;
#XmlElement(name = "score")
private float score;
#XmlElement(name = "date_tbd")
private boolean date_tbd;
#XmlElement(name = "type")
private String type;
#XmlElement(name = "datetime_local")
private String datetime_local;
#XmlElement(name = "visible_until_utc")
private String visible_util_utc;
#XmlElement(name = "time_tbd")
private boolean time_tbd;
#XmlElement(name = "taxonomies")
private List<Taxonomie> taxonomies;
#XmlElement(name = "performers")
private List<Performer> performers;
#XmlElement(name = "url")
private String url;
#XmlElement(name = "created_at")
private String created_at;
#XmlElement(name = "venue")
private Venue venue;
#XmlElement(name = "short_title")
private String short_title;
#XmlElement(name = "datetime_utc")
private String datetime_utc;
#XmlElement(name = "datetime_tbd")
private boolean datetime_tbd;
**getters and setters**
By default JAXB implementations treat public fields and properties as mapped. When you annotate a non-public field it also becomes mapped. Then if you have a mapped field an property with the same name you will get this exception.
When you annotate fields you need to annotate your class with #XmlAccessorType(XmlAccessType.FIELD).
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
Note:
You are currently adding more annotations on your model than you need to. Since JAXB is configuration by exception you only need to add annotations where you want the XML representation to differ from the default.
http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html