I need to get the following SOAP request into my controller.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<req:ResultMsg
xmlns:req="http://cps.huawei.com/cpsinterface/result"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Result>
<ResultType>0</ResultType>
<ResultCode>0</ResultCode>
<ResultDesc>The service request is processed successfully.</ResultDesc>
<OriginatorConversationID>S_X2013012921001</OriginatorConversationID>
<ConversationID>AG_20130129T102103</ConversationID>
<TranactionID>XD2013012923789234</TranactionID>
<ResultParameters></ResultParameters>
</Result>]]></req:ResultMsg>
</soapenv:Body>
</soapenv:Envelope>
I tried to set a POJO and a string for the CDATA part but not working.
Current implementation as below,
Interface:
#WebService(name = "VCashCallbackService",
targetNamespace = "http://cps.huawei.com/cpsinterface/result")
public interface VCashCallbackService {
#WebMethod(operationName = "ResultMsg")
#WebResult(name = "GetDataResponse")
GetDataResponse getData(#WebParam(name = "ResultMsg",
targetNamespace = "http://cps.huawei.com/cpsinterface/resul",
mode = WebParam.Mode.IN) Holder<String> searchResultDataXML);
}
Impl
#WebService(serviceName = "VCashCallbackService",
portName = "VCashCallbackServicePort",
endpointInterface = "com.argon.eightd.web.restful.mock.VCashCallbackService",
targetNamespace = "http://cps.huawei.com/cpsinterface/result")
#BindingType(value = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
#Service
public class VCashCallbackServiceImpl implements VCashCallbackService {
private static final Logger LOGGER = LoggerFactory.getLogger(VCashCallbackServiceImpl.class);
#Override
public GetDataResponse getData(Holder<String> searchResultDataXML) {
LOGGER.info("SOAP result: {}", searchResultDataXML.searchResultDataXML.value);
return new GetDataResponse();
}
}
Log
SOAP result: null
But this approach is getting the request as above in the WebMethod.
Thanks in advance.
Related
I have implemented below soap webservice. The xml response generated doesn't contain xml declaration (<?xml version="1.0" encoding="utf-8"?>). I have tried to implement SOAPHandler, and set below property, but no luck. Please suggest what am I missing?
context.getMessage().setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
Service:
#WebService(targetNamespace = "http://charginggw.org/")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
#HandlerChain(file= "/META-INF/handler.xml")
public interface LegacyService {
#WebMethod(operationName = "CheckBalance", action = "http://charginggw.org/CheckBalance")
#WebResult(name = "CheckBalanceResponse", targetNamespace = "")
CheckBalanceResponse checkBalance(#WebParam(name = "CheckBalance") CheckBalanceRequest checkBalanceRequest);
}
I'm trying to send a SOAP message via a FEIGN client. The problem is that when I send the java object, what is actually being sent is a request with an xml format, instead of a SOAP format.
The client is configured as follows:
#FeignClient(name = "calculatorServer", url = "http://www.dneonline.com/calculator.asmx")
public interface AEMWebServiceFeignClient{
#PostMapping(value = "", consumes = MediaType.TEXT_XML, produces = MediaType.TEXT_XML)
AddResponse calculate(#RequestBody Add addRequest);
}
Looking at the log I see that I am really sending this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Add xmlns="http://tempuri.org/">
<intA>2</intA>
<intB>0</intB>
</Add>
When I really should be sending the following message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:Add>
<tem:intA>2</tem:intA>
<tem:intB>0</tem:intB>
</tem:Add>
</soapenv:Body>
</soapenv:Envelope>
Any help is welcome, thanks!
You must define a custom Feign codec to use SOAP, as described in here.
To integrate it with FeignClient, you should define a custom configuration class for it, reference.
#FeignClient(
name = "calculatorServer",
url = "http://www.dneonline.com/calculator.asmx"
configuration = MySoapClientConfiguration.class)
public interface AEMWebServiceFeignClient{
#PostMapping(value = "", consumes = MediaType.TEXT_XML, produces = MediaType.TEXT_XML)
AddResponse calculate(#RequestBody Add addRequest);
}
#Configuration
public class MySoapClientConfiguration {
private static final JAXBContextFactory jaxbFactory = new JAXBContextFactory.Builder()
.withMarshallerJAXBEncoding("UTF-8")
.withMarshallerSchemaLocation("http://apihost http://apihost/schema.xsd")
.build();
#Bean
public Encoder feignEncoder() {
return new SOAPEncoder(jaxbFactory);
}
#Bean
public Decoder feignDecoder() {
return new SOAPDecoder(jaxbFactory);
}
}
It's works, but i had added:
Create package-info.java into package addRequest/AddResponse
#XmlSchema(
namespace = "http://tempuri.org/",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(prefix = "xsd", namespaceURI = "http://tempuri.org/")
}
)
package your.package.add;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Also, you need to add an interceptor to set content-type and soapAction:
import feign.RequestInterceptor;
import feign.RequestTemplate;
public class FeignRequestSoapInterceptor implements RequestInterceptor {
#Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("Content-Type", "text/xml");
requestTemplate.header("soapAction", "http://tempuri.org/Add");
}
}
In MySoapClientConfiguration, add the FeignRequestSoapInterceptor:
#Configuration
public class MySoapClientConfiguration {
private static final JAXBContextFactory jaxbFactory = new JAXBContextFactory.Builder()
.withMarshallerJAXBEncoding("UTF-8")
.build();
#Bean
public Encoder feignEncoder() {
return new SOAPEncoder(jaxbFactory);
}
#Bean
public Decoder feignDecoder() {
return new SOAPDecoder(jaxbFactory);
}
#Bean
public FeignRequestSoapInterceptor feignRequestSoapInterceptor() {
return new FeignRequestSoapInterceptor();
}
}
FeignClient:
#FeignClient(
name = "calculatorServer",
url = "http://www.dneonline.com/calculator.asmx"
configuration = MySoapClientConfiguration.class)
public interface AEMWebServiceFeignClient{
#PostMapping("/Add")
AddResponse calculate(#RequestBody Add addRequest);
}
Tell me how to read the header in the web server's response via the #WebMethod and #WebResult annotations. Of course, I can do this by SOAPConnection and parsing SOAPMessage, but there is a lot of functionality on javax.jws and I would like to unify everything. I need value from <osb:Backend/>.
Server response:
<soapenv:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<osb:Backend xmlns:osb="http://osb.emias.mos.ru/system">СКУУ</osb:Backend>
<ipaddr xmlns="https:/bis.skyy.soapHeader/">10.0.5.147</ipaddr>
<build xmlns="https:/bis.skyy.soapHeader/">1ec22a8</build>
</env:Header>
<env:Body xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<getEmployeePacketInfoResponse2 xmlns="http://emias.gov.ru/medempregisterservicetypes/1" xmlns:ns1="http://emias.gov.ru/types/1" xmlns:ns0="http://emias.gov.ru/servicetypes/1">
<EmployeeList>
.......
Interface declaration:
#WebResult(name = "Backend", targetNamespace = "http://emias.gov.ru/medempregisterservicetypes/1", partName = "getMedicalEmployeePacketInfo")
#WebMethod
public String getMedicalEmployeePacketInfo2(
#WebParam(partName = "getMedicalEmployeePacketInfoRequest", name = "getEmployeePacketInfoRequest", targetNamespace = "http://emias.gov.ru/medempregisterservicetypes/1")
GetEmployeePacketInfoRequest getMedicalEmployeePacketInfoRequest
) throws FaultMessage;
Request class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"requesterSystemCode",
"healthOrgID",
"employeeList"
})
#XmlRootElement(name = "getEmployeePacketInfoRequest")
public class GetEmployeePacketInfoRequest {
#XmlElement(name = "RequesterSystemCode", required = true)
protected String requesterSystemCode;
#XmlElement(name = "HealthOrgID")
protected String healthOrgID;
#XmlElement(name = "EmployeeList", required = true)
protected GetEmployeePacketInfoRequest.EmployeeList employeeList;
....
Request example:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://emias.gov.ru/medempregisterservicetypes/1">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>SPU/erz</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">emias_erz</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns:getEmployeePacketInfoRequest2>
<ns:RequesterSystemCode>SPU</ns:RequesterSystemCode>
<ns:HealthOrgID>10000430</ns:HealthOrgID>
<ns:EmployeeList>
<ns:EmployeeID>21426012</ns:EmployeeID>
</ns:EmployeeList>
</ns:getEmployeePacketInfoRequest2>
</soapenv:Body>
</soapenv:Envelope>
1. I haven't used jws, and haven't tried this, but it may help:
Try to add header option to your #WebResult annotation.
See https://docs.oracle.com/javaee/6/api/javax/jws/WebResult.html :
public abstract boolean header
"If true, the result is pulled from a message header rather then the message body."
But seems like in order to do so you have to write appropriate class for JAXB (I'm not sure).
2. Instead, I did it straightforward, and used this method:
Your business data is located inside message body - between <getEmployeePacketInfoRequest2/> tags. This is what JAXB creates your GetEmployeePacketInfoResponse class objects from. So, if you want to obtain anything outside this tags, you have to get it from the whole SOAP response. But you don't need to parse it manually - javax.xml.soap.SOAPMessage has inbuilt getSOAPHeader() method, which does what you need. Then just transform it to DOM, and do getElementsByTagName() or getElementsByTagNameNS().
implemented the second sentence
import lombok.val;
....
val soapPart = resp.getSOAPPart();
val soapEnvelope = soapPart.getEnvelope();
val soapHeader = soapEnvelope.getHeader();
val backendNode = soapHeader.getElementsByTagName("osb:Backend");
if (backendNode.getLength() > 0) {
backend = backendNode.item(0).getTextContent();
}
...
You need to use annotated parameter in your class method like this:
#WebResult(name = "Backend", targetNamespace = "http://emias.gov.ru/medempregisterservicetypes/1", partName = "getMedicalEmployeePacketInfo")
#WebMethod
public String getMedicalEmployeePacketInfo2(
#WebParam(partName = "header", name = "ipaddr", targetNamespace = "https:/bis.skyy.soapHeader/", header = true, mode = WebParam.Mode.IN)
String header,
...
#WebParam(partName = "getMedicalEmployeePacketInfoRequest", name = "getEmployeePacketInfoRequest", targetNamespace = "http://emias.gov.ru/medempregisterservicetypes/1")
GetEmployeePacketInfoRequest getMedicalEmployeePacketInfoRequest
) throws FaultMessage;
pay attention to header = true and mode = WebParam.Mode.IN
In my JAX-WS web service, I need to customize my SOAP Response Envelope.
At the moment, it is like this:
<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>
<methodResponse xmlns="http://interfaces.webservice.ucmdb.com">
<methodReturn>202</methodReturn>
</methodResponse >
</soapenv:Body>
</soapenv:Envelope>
And i need it to look like this:
<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:Header>
<code>123</code>
</soapenv:Header>
<soapenv:Body>
<getCIResponse xmlns="http://interfaces.webservice.ucmdb.com">
<getCIReturn>202</getCIReturn>
</getCIResponse>
</soapenv:Body>
</soapenv:Envelope>
So, how does one write the <soapenv:Header> part in a JAX-WS soap envelope?
Here is my WebMethod implementation (quite simple at the moment):
#WebMethod
public int operation(#WebParam(name="username", header=false)String id) {
return 202;
}
1.) In order to add a header to your SOAP message in JAX-WS you can implement the SOAPHandler interface. This will give you access to the SOAPMessage and you can use the SAAJ api to add/update the SOAP Header. Keep in mind this handler is bi-directional.
public class Handler1 implements SOAPHandler<SOAPMessageContext>{
#Override
public boolean handleMessage(SOAPMessageContext context) {
boolean isOutbound = (boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(isOutbound){
SOAPMessage msg = context.getMessage();
try {
//Grab the header
SOAPHeader header = msg.getSOAPHeader();
//Add whatever QName you need
header.addHeaderElement(new QName("code"));
//Save changes.
msg.saveChanges();
} catch (SOAPException e) {
e.printStackTrace();
}
}
//True continue, false halt.
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return false;
}
#Override
public void close(MessageContext context) {
}
#Override
public Set<QName> getHeaders() {
//Can also add a QName here.
return null;
}
}
2.) In order to register the Handler you need to add the handler via an xml handler configuration file that should be kept in the classpath.
<?xml version="1.0" encoding="UTF-8"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee">
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-class>com.calvinmmiller.service.Handler1</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
3.) This file can be added to the SEI(Service Endpoint Interface) with the annotation below:
import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
#WebService
#HandlerChain( file = "handlerFile.xml")
public class Service {
public int operation(String id){
return 202;
}
public static void main(String[] args){
Endpoint.publish("http://localhost:8080/soap", new Service());
}
}
I have a Webservice that returns an XML Payload.
In that Web Service Response - My GT brackets resolve to a real bracket - while the LT stays as < - i have no idea why.
Using
Weblogic 10.3
The Webservice is annotated as
#WebService(name = "MyService", portName = "MyServicePort", serviceName = "MyService", targetNamespace = "http://kwikksilva/myservice/ws")
#SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
The method like so
#WebMethod
#WebResult(name = "SyncResponse", targetNamespace = "http://kwikksilva/myservice/ws")
public SyncResponseTO processRequest(
It returns a TO with a payload
#XmlRootElement(name = "SyncResponse", namespace = "http://kwikksilva/myservice/ws")
#XmlAccessorType(XmlAccessType.FIELD)
public class SyncResponseTO implements Serializable {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The response. */
#XmlElement(name = "Payload", nillable = false, required = true)
private String payload;
I get a response back which looks like this
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:processSyncRequestResponse xmlns:ns2="http://kwikksilva/myservice/ws">
<ns2:SyncResponse>
<Payload xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
<Vbc>
<ApptEffDt>795243600000</ApptEffDt>
</Vbc>
</Payload>
</ns2:SyncResponse>
</ns2:processSyncRequestResponse>
</S:Body>
</S:Envelope>
Why would one encode to a bracket and not the other?
Has anyone got any ideas on this - i am confused....
take the payload and xml decode it. It should solve the problem.