Problem with unmarshalling name spaced SOAP XML parameter - java

I have a problem processing a SOAP request. I can read everything from the envelope but the name space decorated parameter (cs:measurand) cannot be parsed.
Here you can find the SOAP Envelope:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:cs="urn://Ocpp/Cs/2012/06/" xmlns:soap-enc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header>
<cs:identity>17083A00001101</cs:identity>
<a:From>
<a:Address>http://172.0.0.0:9080</a:Address>
</a:From>
<a:MessageID>urn:uuid:xxxxxxxxxxxx</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To>http://172.0.0.0:8080/ws/ocp</a:To>
<a:Action>/MValues</a:Action>
</soap:Header>
<soap:Body>
<cs:mValuesRequest>
<cs:id>1</cs:id>
<cs:transactionId>1881</cs:transactionId>
<cs:values>
<cs:timestamp>2019-03-07T13:41:52.405Z</cs:timestamp>
<cs:value cs:measurand="e.a.i.r" cs:unit="Wh">300</cs:value>
<cs:value cs:measurand="c.i" cs:unit="Amp">38.5</cs:value>
<cs:value cs:measurand="v" cs:unit="Volt">399.5</cs:value>
<cs:value cs:measurand="p.a.i" cs:unit="W">15380</cs:value>
<cs:value cs:measurand="t" cs:unit="Celsius">35</cs:value>
</cs:values>
</cs:mValuesRequest>
</soap:Body>
</soap:Envelope>
Here is the service which receive the request:
#Action("/MValues")
#ResponsePayload
public JAXBElement<MValuesResponse> receive(#RequestPayload MValuesRequest request,
MessageContext messageContext) {
....
}
And here is the MValuesRequest:
...
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ValuesRequest", propOrder = {
"id",
"transactionId",
"values"
})
public class MValuesRequest {
protected int id;
protected Integer transactionId;
protected List<MValue> values;
// getters setters...
}
Any your thoughts would be really appreciated.

try with this,
MValuesRequest.java
#XmlRootElement(name="cs:mValuesRequest")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name ="ValuesRequest", propOrder = { "id", "transactionId", "values" })
public class MValuesRequest {
#XmlElement(name="cs:id")
protected int id;
#XmlElement(name="cs:transactionId")
protected Integer transactionId;
#XmlElement(name="cs:values")
protected Values values;
// getters and setters...
}
Values.java
#XmlRootElement(name="cs:values")
public class Values{
#XmlElement(name="cs:timestamp")
protected String timestamp;
#XmlElement(name="cs:value")
protected List<Value> value;
// getters and setters...
}
Value.java
#XmlRootElement(name="cs:value")
public class value{
#XmlAttribute(name="measurand" namespace="http://www.w3.org/XML/1998/namespace")
protected String measurand;
#XmlAttribute(name="unit" namespace="http://www.w3.org/XML/1998/namespace")
protected String unit;
#XmlValue
protected String elementValue;
// getters and setters...
}

I finally could solve this is issue, big thanks to Rathnayake.
I didn't have to add #XmlRootElement but only add the namespace parameter to #XmlAttribute.
So currently my XML parameters look like this:
#XmlAttribute(name = "context", namespace="urn://Ocpp/Cs/2012/06/")
protected ReadingContext context;
#XmlAttribute(name = "format", namespace="urn://Ocpp/Cs/2012/06/")
protected ValueFormat format;
#XmlAttribute(name = "measurand", namespace="urn://Ocpp/Cs/2012/06/")
protected Measurand measurand;
#XmlAttribute(name = "location", namespace="urn://Ocpp/Cs/2012/06/")
protected Location location;
#XmlAttribute(name = "unit", namespace="urn://Ocpp/Cs/2012/06/")
protected UnitOfMeasure unit;
Just to remember here is my SOAP header:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:cs="urn://Ocpp/Cs/2012/06/" xmlns:soap-enc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
And I added as namespace="..." value xmlns:cs="..." from the header.

Related

Soap Message to Java Object

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:cs=\"urn:CardServices\" xmlns:ebppif1=\"urn:PaymentServer\" xmlns:el=\"urn:ExtListsServices\" xmlns:iiacs=\"urn:IIACardServices\" xmlns:lm=\"urn:Limits\">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Client</faultcode>
<faultstring></faultstring>
<detail>
<ebppif1:PaymentServerException>
<provider>RSW</provider>
<error>129</error>
<description>201433</description>
<screen>RSW129</screen>
</ebppif1:PaymentServerException>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
How to create java object using #XmlRootElement,#XmlElement.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Fault", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
#Data
public class FaultDto {
#XmlElement(name = "faultcode")
private String faultCode;
#XmlElement(name = "detail")
private DetailDto detail;
}
#XmlRootElement(name = "detail")
#XmlAccessorType(XmlAccessType.FIELD)
public class DetailDto {
#XmlElement(name = "PaymentServerException")
private PaymentExcepDto excepDto;
}
#XmlRootElement(name = "PaymentServerException")
#XmlAccessorType(XmlAccessType.FIELD)
public class PaymentExcepDto {
#XmlElement(name = "provider")
protected String provider;
#XmlElement(name = "error")
protected String error;
//others
}
I am getting this result : FaultDto(faultCode=SOAP-ENV:Client, detail=DetailDto(excepDto=null))
How to catch PaymentServerException ?

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 fix while converting xml to java object is response null

Hi guys i am trying to convert soap xml to java classes fields but response gives null values into targeted class fields. I haven't worked with soap before, I work with soap for the first time, so I did a bit of google in 2 days and tried to use it. Attached screenshots from intellij debug
It is a SOAP XML file. In fact this is the value of xml that comes to me as a response from another API because I got it via SOAPUI because I had a request for it. So I tried to convert this xml in a new project without working on a real project. I also mentioned the classes in this project below
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:queryTransactionHistoryResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:IssuingWS/binding">
<ResponseInfo>
<response_code>0</response_code>
<error_description xsi:nil="true"/>
<error_action xsi:nil="true"/>
<EXTERNAL_SESSION_ID>TEST111_20211111111111212201191210111511</EXTERNAL_SESSION_ID>
</ResponseInfo>
<Details>
<row>
<item>
<name>CARD_ACCT</name>
<value>0901095000004266</value>
</item>
<item>
<name>ACCOUNT_NO</name>
<value>8186</value>
</item>
<item>
<name>CL_ACCT_KEY</name>
<value>8096</value>
</item>
<item>
<name>CLIENT</name>
<value>00003660</value>
</item>
</row>
<row>
<item>
<name>CARD2_ACCT</name>
<value>0901095000004266</value>
</item>
<item>
<name>ACCOUNTSSO</name>
<value>8186</value>
</item>
<item>
<name>CL_ACCT_KEY22</name>
<value>8096</value>
</item>
<item>
<name>SOMENAME</name>
<value>00003660</value>
</item>
</row>
</Details>
</ns1:queryTransactionHistoryResponse>
</soapenv:Body>
</soapenv:Envelope>
It is rootclass parent class got it from the name after ns1 in the XML, but I don't know if the situation I'm using is correct and one of the things I don't understand is the xmlns.
package uz.paynet.test.Xml;
import lombok.ToString;
import javax.xml.bind.annotation.*;
#ToString
#XmlRootElement(namespace = "urn:IssuingWS/binding")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "queryTransactionHistoryResponse")
public class QueryTransactionHistoryResponse {
#XmlElement(name = "ResponseInfo", required = true,nillable = true)
private ResponseInfo responseInfo;
#XmlElement(name = "Details", required = true,nillable = true)
private Details details;
public QueryTransactionHistoryResponse() {
}
public QueryTransactionHistoryResponse(ResponseInfo responseInfo, Details details) {
this.responseInfo = responseInfo;
this.details = details;
}
public ResponseInfo getResponseInfo() {
return responseInfo;
}
public void setResponseInfo(ResponseInfo responseInfo) {
this.responseInfo = responseInfo;
}
public Details getDetails() {
return details;
}
public void setDetails(Details details) {
this.details = details;
}
}
it is my ResponseInfo class but this class get value you show on screenshop
package uz.paynet.test.Xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.FIELD)
public class ResponseInfo{
#XmlElement(name = "response_code")
private int responseCode;
#XmlElement(name = "error_description",nillable = true)
private String errorDescription;
#XmlElement(name="error-action",nillable = true)
private String errorAction;
#XmlElement(name = "EXTERNAL_SESSION_ID")
private String externalSessionId;
public ResponseInfo(int responseCode, String errorDescription, String errorAction, String externalSessionId) {
this.responseCode = responseCode;
this.errorDescription = errorDescription;
this.errorAction = errorAction;
this.externalSessionId = externalSessionId;
}
public ResponseInfo() {
}
public int getResponseCode() {
return responseCode;
}
public void setResponseCode(int responseCode) {
this.responseCode = responseCode;
}
public String getErrorDescription() {
return errorDescription;
}
public void setErrorDescription(String errorDescription) {
this.errorDescription = errorDescription;
}
public String getErrorAction() {
return errorAction;
}
public void setErrorAction(String errorAction) {
this.errorAction = errorAction;
}
public String getExternalSessionId() {
return externalSessionId;
}
public void setExternalSessionId(String externalSessionId) {
this.externalSessionId = externalSessionId;
}
}
this is Details class which Covers Row class
package uz.paynet.test.Xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import java.util.List;
#XmlAccessorType(XmlAccessType.FIELD)
public class Details{
#XmlElement(name = "row")
List<Row> rowList;
public Details() {
}
public Details(List<Row> rowList) {
this.rowList = rowList;
}
public List<Row> getRowList() {
return rowList;
}
public void setRowList(List<Row> rowList) {
this.rowList = rowList;
}
}
and last is Row class which covered value and name
which i need to get xml value and name
package uz.paynet.test.Xml;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(namespace = "urn:IssuingWS/binding")
public class Row {
#XmlElement(name = "name")
public String name;
#XmlElement(name = "value")
private String value;
public Row(String name, String value) {
this.name = name;
this.value = value;
}
public Row() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

How to add blank namespace in java using javax.xml.bind.annotation

I'm new to SOAP service, this is my output and java class detail.
How to add the blank xmlns in sub level class?
Out-Put Request:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sendEmail xmlns="http://ws.cns.channel.sendnotification.sdfsfds.com/">
<EmailNotificationRequest>
<requestHeader>
<channel>fsdfs</channel>
<subChannel>sdfds</subChannel>
<systemName>sdfsd</systemName>
<applicationName>dsfs</applicationName>
</requestHeader>
</EmailNotificationRequest>
</sendEmail>
Package Class
#javax.xml.bind.annotation.XmlSchema(namespace = "http://ws.cns.channel.sendnotification.sdfsfds.com/",
elementFormDefault = XmlNsForm.QUALIFIED
)
package com.etisalat.sendnotification.channel.cns.ws;
import javax.xml.bind.annotation.XmlNsForm;
Request Header Class
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "requestHeader", propOrder = {
"channel",
"subChannel",
"agentID",
"systemName",
"applicationName",
"hostID",
"requestDate"
})
public class RequestHeader {
#XmlElement(required = true)
protected String channel;
protected String subChannel;
protected String agentID;
#XmlElement(required = true)
protected String systemName;
protected String applicationName;
}
Required Input Request
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sendEmail xmlns="http://ws.cns.channel.sendnotification.sdfsfds.com/">
<EmailNotificationRequest>
<requestHeader xmlns="">
<channel>fsdfs</channel>
<subChannel>sdfds</subChannel>
<systemName>sdfsd</systemName>
<applicationName>dsfs</applicationName>
</requestHeader>
</EmailNotificationRequest>
</sendEmail>

Marshalling Java object to XML with JAXB returns unexpected output

I am having issues marshalling a bean into XML using JAXB. I have multiple REST API endpoints and I want to return a uniform response from all the endpoints, like the following:
<response>
<responseHeader> <!-- this will be same for all the end points -->
<status>OK</status>
<stausCode>AB-123<statusCode>
</responseHeader>
<responseBody>
<!-- contains end point specific data, could be differnet-->
</responseBody>
</response>
So what I did is created a generic response DTO:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "response")
public class GenericResponseDto implements Serializable {
#XmlElement(name="responseHeader")
private GenericResponseHeaderDto responseHeader;
#XmlAnyElement(name="responseBody")
private Object responseBody;
public GenericResponseHeaderDto getResponseHeader() {
return responseHeader;
}
public void setResponseHeader(GenericResponseHeaderDto responseHeader) {
this.responseHeader = responseHeader;
}
public Object getResponseBody() {
return responseBody;
}
public void setResponseBody(Object responseBody) {
this.responseBody = responseBody;
}
}
Where the response body field will be replaced by the following object for one of the endpoint responses:
#XmlRootElement(name = "responseBody")
#XmlAccessorType(XmlAccessType.FIELD)
public class Person implements Serializable {
#XmlElement(required = false)
private String phoneNumber;
#XmlElement(required = false)
private Integer personId;
public Integer getPersonId() {
return personId;
}
public void setPersonId(Integer personId) {
this.personId = personId;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
Here is my Jersey endpoint:
#POST
#Path("/myAPIFirstEndPoint")
#Produces({MediaType.APPLICATION_XML})
public GenericResponseDto myAPIFirstEndPoint(ABC abc) {
// some work and getting person dto
Person person = someWork.doWork();
GenericResponseDto genericResponseDto = new GenericResponseDto();
// not setting any responseHeader for now, so ignore
genericResponseDto.setResponseBody(row);
return genericResponseDto;
}
But it's not working as expected. The toString() method is being called on the Person object, instead of it being marshalled to XML. I'm getting the following incorrect response:
<?xml version="1.0" encoding="UTF-8" ?>
<response>
<responseBody>
path.to.package.Person#36af3690[phoneNumber=+123456789,personId=-1]
</responseBody>
</response>
Can you please tell me what I'm doing wrong? I am using Jersey and JAXB with Spring.
EDIT:
Introduced generics:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "response")
#XmlSeeAlso({Person.class})
public class GenericResponseDto<T> implements Serializable {
#XmlElement(name="responseHeader")
private GenericResponseHeaderDto responseHeader;
#XmlElement(name="responseBody")
private T responseBody;
public GenericResponseHeaderDto getResponseHeader() {
return responseHeader;
}
public void setResponseHeader(GenericResponseHeaderDto responseHeader) {
this.responseHeader = responseHeader;
}
public T getResponseBody() {
return responseBody;
}
public void setResponseBody(T responseBody) {
this.responseBody = responseBody;
}
}
changed Jersey endpoint as follows:
#POST
#Path("/myAPIFirstEndPoint")
#Produces({MediaType.APPLICATION_XML})
public GenericResponseDto<Person> myAPIFirstEndPoint(ABC abc) {
// some work and getting person dto
Person person = someWork.doWork();
GenericResponseDto<Person> genericResponseDto = new GenericResponseDto<Person>();
// not setting any responseHeader for now, so ignore
genericResponseDto.setResponseBody(row);
return genericResponseDto;
}
Still getting the same response as mentioned above.
Now getting this response, after adding #XmlSeeAlso({Person.class}) in GenericResponseDto
<?xml version="1.0" encoding="UTF-8" ?>
<response>
<responseBody xsi:type="Person">
<phoneNumber>+923454502dd0559</phoneNumber>
<personId>-1</personId>
<token />
</responseBody>
</response>

Categories

Resources