javax.xml.bind.UnmarshalException: unexpected element even if #XmlRootElement is added - java

In SoapUI I've got this exception
<faultstring>Unmarshalling Error: unexpected element (uri:"http://ws.soap.rd.pl", local:"User"). Expected elements are <{}User></faultstring>
I really do not know wy I've got this issue. I've tried trip gave in Stack but still cant find the answer. #XmlRootElement is added so I'm really confused.
request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.soap.rd.pl/" xmlns:ws1="http://ws.soap.rd.pl">
<soapenv:Header/>
<soapenv:Body>
<ws:updateUser>
<!--Optional:-->
<ws1:User>
<ID>?</ID>
<!--Optional:-->
<Imie>?</Imie>
<!--Optional:-->
<Nazwisko>?</Nazwisko>
<!--Optional:-->
<ws1:Adres>
<!--Optional:-->
<id>?</id>
<!--Optional:-->
<Ulica>?</Ulica>
<!--Optional:-->
<Miasto>?</Miasto>
</ws1:Adres>
</ws1:User>
</ws:updateUser>
</soapenv:Body>
</soapenv:Envelope>
my dto:
#XmlRootElement(name = "Adres", namespace = "http://ws.soap.rd.pl")
#XmlAccessorType(XmlAccessType.FIELD)
public class AddressDto {
#XmlElement(name = "id", required = false)
public Long id;
#XmlElement(name = "Ulica", required = false)
public String street;
#XmlElement(name = "Miasto", required = false)
public String city;
#Override
public String toString() {
return "AddressDto [street=" + street + ", city=" + city + "]";
}
}
and the second one:
#XmlRootElement(name = "User", namespace = "http://ws.soap.rd.pl")
#XmlAccessorType(XmlAccessType.FIELD)
public class UserDto {
#XmlElement(name = "ID")
public long id;
#XmlElement(name = "Imie", required = false)
public String firstName;
#XmlElement(name = "Nazwisko", required = false)
public String lastName;
#XmlElement(name = "Adres", required = false)
public AddressDto addressDto;
#Override
public String toString() {
return "UserDto [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", addressDto=" + addressDto + "]";
}
}
if you need my webService definition:
#WebService(endpointInterface = "userService", serviceName = "userService", name = "userServive")
public interface UserService {
#WebMethod
public void updateUser(#WebParam(name = "User") UserDto user);
}

Try adding the targetNamespace to your #WebParam:
#WebMethod
public void updateUser(
#WebParam(name = "User", targetNamespace = "http://ws.soap.rd.pl")
UserDto user);

Related

Soap Request and response to Java Objects

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
}

How to unmarshal an XML String contain diffgr to JAVA POJO

Hi I got a below XML string which contain diffgram
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Result xmlns="">
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<DT1 diffgr:id="DT11" msdata:rowOrder="0">
<TEST_NO>93481324345</TEST_NO>
<TEST_DESC>Description1</TEST_DESC>
</DT1>
<DT1 diffgr:id="DT12" msdata:rowOrder="1">
<TEST_NO>93481366454</TEST_NO>
<TEST_DESC>Description2</TEST_DESC>
</DT1>
<DT1 diffgr:id="DT13" msdata:rowOrder="2">
<TEST_NO>934813267783</TEST_NO>
<TEST_DESC>Description3</TEST_DESC>
</DT1>
</NewDataSet>
</diffgr:diffgram>
</Result>
How can I unmarshal this String to java POJO using JAXB ?
Below are the current POJO seems not able to bind by this way.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"diffgr",
"newDataSet",
"dt"
})
#XmlRootElement(name="Result")
public class Response {
#XmlElement(name = "diffgr:diffgram")
protected String diffgr;
#XmlElement(name = "NewDataSet")
protected String newDataSet;
#XmlElement(name = "DT1")
protected List<Response.DT> dt;
public String getDiffgr() {
return diffgr;
}
public void setDiffgr(String diffgr) {
this.diffgr = diffgr;
}
public String getNewDataSet() {
return newDataSet;
}
public void setNewDataSet(String newDataSet) {
this.newDataSet = newDataSet;
}
public List<Response.DT> getDt() {
if (dt == null) {
dt = new ArrayList<Response.DT>();
}
return this.dt;
}
public void setDt(List<Response.DT> dt) {
this.dt = dt;
}
#Override
public String toString() {
return "Response [diffgr=" + diffgr + ", newDataSet=" + newDataSet + ", dt=" + dt + "]";
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"testNo",
"testDesc"
})
public static class DT {
#XmlElement(name = "TEST_NO")
protected String testNo;
#XmlElement(name = "TEST_DESC")
protected String testDesc;
public String getTestNo() {
return testNo;
}
public void setTestNo(String testNo) {
this.testNo = testNo;
}
public String getTestDesc() {
return testDesc;
}
public void setTestDesc(String testDesc) {
this.testDesc = testDesc;
}
#Override
public String toString() {
return "DT [testNo=" + testNo + ", testDesc=" + testDesc + "]";
}
}
}
I'm using the below sample code to unmarshal the String
JAXBContext jaxbContext = JAXBContext.newInstance(Response.class);
Unmarshaller jaxbUnMarshaller = jaxbContext.createUnmarshaller();
Response response = (Response)jaxbUnMarshaller.unmarshal(new StringReader(xml));
When execute there is no any error throwing out while the POJO was empty.
How to unmarshal an XML String contain diffgr to JAVA POJO like this case?

java soap web service how to get a list from a xml request

I work with a SOAP web service. I want to recover the list productOrder from a java. My problem is that the list productOrder recovered from the java class is zero.
I dont't know how to recover this list from the java.
Below I explain my classes:
This is the request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://uciext.ws.hw3/wsdl">
<soapenv:Header/>
<soapenv:Body>
<wsdl:processOrder>
<!--Optional:-->
<arg0>
<vendorCode>330029</vendorCode>
<vendorName>My Shop</vendorName>
<orderNumber>1000339</orderNumber>
<!--1 or more repetitions:-->
<wsdl:productOrder>
<!--Optional:-->
<productSku>111</productSku>
<!--Optional:-->
<productName>Kindle Fire</productName>
<!--Optional:-->
<orderQuantity>5</orderQuantity>
</wsdl:productOrder>
</arg0>
</wsdl:processOrder>
</soapenv:Body>
</soapenv:Envelope>
I have the Order.java to parse this xml
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"vendorCode",
"vendorName",
"orderNumber",
"productOrder"
})
#XmlRootElement(name = "order")
public class Order {
#XmlElement(required = true)
protected String vendorCode;
#XmlElement(required = true)
protected String vendorName;
#XmlElement(required = true)
protected String orderNumber;
#XmlElement(required = true)
protected List<ProductOrder> productOrder;
public String getVendorCode() {
return vendorCode;
}
public void setVendorCode(String value) {
this.vendorCode = value;
}
public String getVendorName() {
return vendorName;
}
public void setVendorName(String value) {
this.vendorName = value;
}
public String getOrderNumber() {
return orderNumber;
}
public void setOrderNumber(String value) {
this.orderNumber = value;
}
public List<ProductOrder> getProductOrder() {
if (productOrder == null) {
productOrder = new ArrayList<ProductOrder>();
}
return this.productOrder;
}
}
I have a method processOrder in a interface and their implementation. This
is the interface
#WebService(targetNamespace = "http://uciext.ws.hw3/wsdl")
public interface OrderServiceWS {
#WebMethod
OrderConfirm processOrder(#WebParam(name="arg0", mode=Mode.IN) Order order) throws Exception;
}
processOrder is in the class
#XmlRootElement(name = "processOrder", namespace = "http://uciext.ws.hw3/wsdl")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "processOrder", namespace = "http://uciext.ws.hw3/wsdl")
public class ProcessOrder {
#XmlElement(name = "arg0", namespace = "")
private com.uciext.ws.hw3.service.model.order.Order arg0;
public com.uciext.ws.hw3.service.model.order.Order getArg0() {
return this.arg0;
}
public void setArg0(com.uciext.ws.hw3.service.model.order.Order arg0) {
this.arg0 = arg0;
}
}
This is the interface implementation where is called the method processOrder.
#WebService(
portName = "OrderPort",
serviceName = "OrderService",
targetNamespace = "http://uciext.ws.hw3/wsdl",
endpointInterface = "com.uciext.ws.hw3.service.OrderServiceWS")
public class OrderServiceWSImpl implements OrderServiceWS {
private InventoryManagerImpl manager = new InventoryManagerImpl();
#Override
public OrderConfirm processOrder(Order order) throws Exception {
Util.log("SOAP processOrder request [ order=" + order);
Util.log("OrderServiceWS start processOrder");
OrderDAO orderDAO = new OrderDAO();
List<ProductOrder> productOrderList = new ArrayList<ProductOrder>();
List<ProductOrderDAO> productOrderDAOList = new ArrayList<ProductOrderDAO>();
ProductOrderDAO productOrderDAO1 = null;
ProductDAO productDAO = null;
OrderConfirm orderConfirm = null;
ProductOrder productOrder = null;
ProductConfirm productConfirm = null;
List<ProductConfirm> productConfirmList = new ArrayList<ProductConfirm>();
Double totalPrice = 0.0;
Util.log("OrderServiceWS start processOrder vendorCode "+order.getVendorCode());
orderDAO.setVendorCode(order.getVendorCode());
orderDAO.setVendorName(order.getVendorName());
orderDAO.setOrderId(Long.parseLong(order.getOrderNumber()));
Util.log("OrderServiceWS processOrder before productOrderList ");
productOrderList = order.getProductOrder();
Util.log("OrderServiceWS processOrder before productOrderList size "+productOrderList.size());
The value of vendorCode is right but productOrderList.size() is cero

Parsed SOAP response is different with the received response

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>&lt;p&gt;&lt;b&gt;Property Location&lt;/b&gt; &lt;br /&gt;With a stay at Rydges World Square, you&apos;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&amp;cid=55505&amp;hotelID=150241&amp;mode=2&amp;numberOfRooms=1&amp;room-0-adult-total=2&amp;room-0-child-total=0&amp;arrivalMonth=5&amp;arrivalDay=18&amp;departureMonth=5&amp;departureDay=19&amp;showInfo=true&amp;locale=en_US&amp;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>

generating the right SOAP XML structure from a JAXB annotated class

Generated from the ProcessRequestBean class listed at the end,
This is what I get:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cel="http://www.myweb.com">
<soapenv:Header/>
<soapenv:Body>
<cel:processRequestOp>
<processReq>
<!--Optional:-->
<serviceID> 1 </serviceID>
<!--Zero or more repetitions:-->
<parameter>
<!--Optional:-->
<name> myname </name>
<!--Optional:-->
<value> myvalue </value>
</parameter>
</processReq>
</cel:processRequestOp>
</soapenv:Body>
</soapenv:Envelope>
But this is what I want:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cel="http://www.myweb.com">
<soapenv:Header/>
<soapenv:Body>
<cel:processRequestOp>
<!--Optional:-->
<serviceID>1</serviceID>
<!--Zero or more repetitions:-->
<parameter>
<!--Optional:-->
<name> myname </name>
<!--Optional:-->
<value> myvalue </value>
</parameter>
</cel:processRequestOp>
</soapenv:Body>
</soapenv:Envelope>
Note, the exta parent (processReq) element that is eliminated from this structure.
My SEI looks like this:
#WebService(name="QueryThirdParty", targetNamespace = "http://www.myweb.com")
#SOAPBinding(style = Style.RPC)
public interface QuerySEI {
public static final String targetNS = "http://www.myweb.com";
#WebMethod(operationName = "processRequestOp", action = "get_them")
#RequestWrapper(className = "biz.webservice.query3rdpartyaccount.ProcessRequestBean", localName = "localName", partName = "partName")
#ResponseWrapper(className = "biz.webservice.query3rdpartyaccount.ProcessResponseBean")
#WebResult(partName = "processResp", name = "processRequestResponse")
public ProcessResponseBean getAccountNumbers(#WebParam(partName = "processReq", name = "ProcessRequestBean", mode = Mode.IN) ProcessRequestBean request);
}
and ProcessRequestBean class looks like this:
#XmlRootElement(name = "processRequest") //the name of the XML root element
#XmlType(propOrder = {"serviceID", "parameter"})
public class ProcessRequestBean {
private String serviceID;
private List<RequestParameterElement> parameter;
public ProcessRequestBean(String serviceID, List<RequestParameterElement> parameter) {
this.serviceID = serviceID;
this.parameter = parameter;
}
public ProcessRequestBean() {
}
#XmlElement(name = "serviceId")//xml name of this property
public String getServiceID() {
return serviceID;
}
public void setServiceID(String serviceID) {
this.serviceID = serviceID;
}
#XmlElement(name = "parameter")
public List<RequestParameterElement> getParameter() {
return parameter;
}
public void setParameter(List<RequestParameterElement> parameter) {
this.parameter = parameter;
}
}
all help is appreciated
Please try following changes in ur SEI and ProcessRequestBean class,
SEI
#WebResult(partName = "processResp", name = "processRequestResponse")
public ProcessResponseBean getAccountNumbers(ProcessRequestBean request);
}
ProcessRequestBean class
get rid of #XmlRootElement(name = "processRequest") annotation..
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(propOrder = {"serviceID", "parameter"})
public class ProcessRequestBean {
private String serviceID;
private List<RequestParameterElement> parameter;
public ProcessRequestBean(String serviceID, List<RequestParameterElement> parameter) {
......
......
......
Let me know if it doesn't resolve ur prblm.

Categories

Resources