Below is my soap request, I need to read the soap headers using spring boot java how can I do that.
Tried all possible scenarios I am able to read the headers without the target namespace but if I involve targetnamespace it gives me a null pointer exception error.Thanks for the help in advance.
Actual Requirement Which needs a Solution:
<soap11:Envelope xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
<soap11:Header>
<NS1:CUSTOMERNAME xmlns:NS1="http://www.example.org/EcCustom67ARequest/">XmasTree</NS1:CUSTOMERNAME>
<NS2:EMPID xmlns:NS2="http://www.example.org/EcCustom67ARequest/">kite123</NS2:EMPID>
</soap11:Header>
<soap11:Body>
<clientNS:EcCustom67A xmlns:clientNS="http://www.example.org/EcCustom67ARequest/">
<clientNS:PAYMENT_MODE>NEFT</clientNS:PAYMENT_MODE>
<clientNS:VAN>AUT1123456</clientNS:VAN>
<clientNS:AMOUNT>1000.00</clientNS:AMOUNT>
<clientNS:CREDIT_ACCOUNT_NUMBER>124236541582</clientNS:CREDIT_ACCOUNT_NUMBER>
<clientNS:CUSTOMER_CODE>AUT1</clientNS:CUSTOMER_CODE>
<clientNS:TRANSACTION_DATE>30-04-2021</clientNS:TRANSACTION_DATE>
<clientNS:ADD_INFO>Collection</clientNS:ADD_INFO>
</clientNS:EcCustom67A>
</soap11:Body>
</soap11:Envelope>
Able to do without targetnamespace:
<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"
xmlns:ns2 = "http://www.example.org/EcCustom67ARequest/" elementFormDefault="qualified">
<soapenv:Header>
<CUSTOMERNAME>XmasTree</CUSTOMERNAME>
<EMPID>kite123</EMPID>
</soapenv:Header>
<soapenv:Body>
<ns2:EcCustom67A soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" elementFormDefault="qualified">
<ns2:PAYMENT_MODE>NEFT</ns2:PAYMENT_MODE>
<ns2:VAN>ADAN12345678</ns2:VAN>
<ns2:AMOUNT>1000</ns2:AMOUNT>
<ns2:CREDIT_ACCOUNT_NUMBER>108328359093</ns2:CREDIT_ACCOUNT_NUMBER>
<ns2:CUSTOMER_CODE>ADAN</ns2:CUSTOMER_CODE>
<ns2:TRANSACTION_DATE>17-11-2020 13:10:12</ns2:TRANSACTION_DATE>
<ns2:ADD_INFO>Collection</ns2:ADD_INFO>
</ns2:EcCustom67A>
</soapenv:Body>
</soapenv:Envelope>
Working Code :
#Endpoint
public class EcCustom67AEndPoint {
private static final String NAMESPACE_URI = "http://www.example.org/EcCustom67ARequest/";
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "EcCustom67A")
#ResponsePayload
public EcCustom67AResponse getEcCustom67A(#RequestPayload EcCustom67A request,
#SoapHeader(value = "CUSTOMERNAME") SoapHeaderElement customerName,
#SoapHeader(value = "EMPID") SoapHeaderElement empid) throws JAXBException {
EcCustom67AResponse response = new EcCustom67AResponse();
String custName = customerName.getText();
String empID = empid.getText();
response.setAMOUNT(request.getAMOUNT().replaceAll(",", ","));
response.setCREDITACCOUNTNUMBER(request.getCREDITACCOUNTNUMBER());
response.setCUSTOMERCODE(request.getCUSTOMERCODE());
response.setVAN(request.getVAN());
response.setPAYMENTMODE(request.getPAYMENTMODE());
response.setTRANSACTIONDATE(request.getTRANSACTIONDATE());
response.setADDINFO(request.getADDINFO());
if (custName.equals("XmasTree") && empID.equals("kite123")) {
if (response.getAMOUNT() != null) {
if (Float.parseFloat(response.getAMOUNT().replaceAll(",", "")) >= 1000) {
response.setSTATUS("Success");
response.setREMARKS("Beneficiary Account Credited");
} else if (Float.parseFloat(response.getAMOUNT().replaceAll(",", "")) < 1000) {
response.setSTATUS("Reject");
response.setREMARKS("Transaction Failed");
}
} else {
response.setSTATUS("Reject");
response.setREMARKS("Transaction Failed");
}
} else{
response.setPAYMENTMODE(null);
response.setVAN(null);
response.setAMOUNT(null);
response.setCREDITACCOUNTNUMBER(null);
response.setCUSTOMERCODE(null);
response.setTRANSACTIONDATE(null);
response.setADDINFO(null);
response.setSTATUS("Reject");
response.setREMARKS("Invalid Authentication");
JAXBContext jc = JAXBContext.newInstance(IPValAllField219Response.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
}
return response;
}
}
Note: Working code does the job without targetname spce but if I include targetname spce it gives me Null Pointer Exception Please Help on the above issue and thanks in advance.
I'm using Spring Boot's #RestController and there's (at least) two ways I can think of doing this:
Your endpoint method has a param of type HttpServletRequest which Spring automatically populates for you. Then, if you called it request, in your code you can do things like request.getHeader(HttpHeaders.AUTHORIZATION).
Your endpoint method has a param annotated with #RequestHeader("My-Header-Name") String myHeaderName, then in your code read myHeaderName as you need.
Have you tried:
#SoapHeader("{http://www.example.org/EcCustom67ARequest/}CUSTOMERNAME") ...,
#SoapHeader("{http://www.example.org/EcCustom67ARequest/}EMPID") ...
?
It looks like the right approach to set namespace on soap headers:
https://docs.spring.io/spring-ws/docs/current/org/springframework/ws/soap/server/endpoint/annotation/SoapHeader.html
https://docs.oracle.com/javase/8/docs/api/javax/xml/namespace/QName.html?is-external=true#toString--
Related
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.
I am new using Spring SOAP W. I follow many tutorials and try to adapt my need to these examples, but never work, I had this message: No endpoint mapping found for [SaajSoapMessage {http://example/eFatura}documentRequest
Here is the endpoint
#PayloadRoot(namespace = "http://example/eFatura", localPart = "DocumentType")
#ResponsePayload
public DocumentReturnType sendDocument(#RequestPayload DocumentType request) {
DocumentReturnType response = new DocumentReturnType();
response.setHash("Hash-123");
response.setMsg("Mesaj-SemaDeneme");
return response;
}
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
I am trying to call a web service that as far as I know is implemented by Oracle. I need to get a date from this web service. The here is a part of code that is generated for web service client in NetBeans:
#WebMethod(operationName = "LASTENABLED", action = "LASTENABLED")
#WebResult(name = "LASTENABLEDOutput", targetNamespace = "Something",partName = "parameters")
public LASTENABLEDOutput lastenabled(
#WebParam(name = "SDATE-LASTENABLEDInput", targetNamespace = "Something", partName = "parameters")
SDATELASTENABLEDInput parameters);
and this is the code for LASTENABLEDOutput:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"_return"
})
#XmlRootElement(name = "LASTENABLEDOutput")
public class LASTENABLEDOutput {
#XmlElement(name = "RETURN", required = true)
#XmlSchemaType(name = "date")
protected XMLGregorianCalendar _return;
public XMLGregorianCalendar getRETURN() {
return _return;
}
public void setRETURN(XMLGregorianCalendar value) {
this._return = value;
}
}
And this is how I call this web service:
LASTENABLEDOutput output = webservice.lastenabled(input);
XMLGregorianCalendar xMLGregorianCalendar = output.getRETURN();
GregorianCalendar calendar = xMLGregorianCalendar.toGregorianCalendar();
Date date = calendar.getTime();
webservice.lastenabled(input) returns a LASTENABLEDOutput object but the value of output.getRETURN() in the code above is null. However, in soap UI, I tested the webservice and it returns a valid answer:
request:
<soapenv:Envelope xmlns:soapenv="a Url" xmlns:pkg="a URL">
<soapenv:Header/>
<soapenv:Body>
<pkg:SDATE-LASTENABLEDInput>
<pkg:TELNO-VARCHAR2-IN>some phone number</pkg:TELNO-VARCHAR2-IN>
<pkg:SERVICEID-NUMBER-IN>10</pkg:SERVICEID-NUMBER-IN>
<pkg:ENABLE-BOOLEAN-IN>true</pkg:ENABLE-BOOLEAN-IN>
</pkg:SDATE-LASTENABLEDInput>
</soapenv:Body>
</soapenv:Envelope>
response:
<soap:Envelope xmlns:soap="a URL">
<soap:Body>
<LASTENABLEDOutput xmlns="a URL">
<RETURN>07-JUL-15</RETURN>
</LASTENABLEDOutput>
</soap:Body>
</soap:Envelope>
It may be helpful to say that there are other methods in this web service with other return types that work correctly with the same way that I called this method. How can I solve this problem?
It sounds like 07-JUL-15 is not a valid format for your specified XML schema "date".
SUGGESTION:
If you're generating the return value yourself ... then output in the format YYYY-MM-DD.
Here is the request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soap="http://soap.ws.server.wst.fit.cvut.cz/">
<soapenv:Header>
<userId>someId</userId>
</soapenv:Header>
<soapenv:Body>
...
</soapenv:Body>
</soapenv:Envelope>
and I want to get that userId.
I tried this
private List<Header> getHeaders() {
MessageContext messageContext = context.getMessageContext();
if (messageContext == null || !(messageContext instanceof WrappedMessageContext)) {
return null;
}
Message message = ((WrappedMessageContext) messageContext).getWrappedMessage();
return CastUtils.cast((List<?>) message.get(Header.HEADER_LIST));
}
private String getHeader(String name) {
List<Header> headers = getHeaders();
if (headers != null) {
for (Header header : headers) {
logger.debug(header.getObject());
// return header by the given name
}
}
return null;
}
And it logs [userId : null]. How can I get the value and why is null there?
"[userId : null]" is generally the "toString" printout of a DOM element. Most likely if you do something like
logger.debug(header.getObject().getClass())
you will see that it is a DOM Element subclass of somesort. Thus, something like:
logger.debug(((Element)header.getObject()).getTextContent())
might print the text node.
import javax.xml.soap.*;
SOAPPart part = request.getSOAPPart();
SOAPEnvelope env = part.getEnvelope();
SOAPHeader header = env.getHeader();
if (header == null) {
// Throw an exception
}
NodeList userIdNode = header.getElementsByTagNameNS("*", "userId");
String userId = userIdNode.item(0).getChildNodes().item(0).getNodeValue();
You can get soap headers without Interceptors and without JAXB.
In your service_impl class add :
public class YourFunctionNameImpl implements YourFunctionName{
#Resource
private WebServiceContext context;
private List<Header> getHeaders() {
MessageContext messageContext = context.getMessageContext();
if (messageContext == null || !(messageContext instanceof WrappedMessageContext)) {
return null;
}
Message message = ((WrappedMessageContext) messageContext).getWrappedMessage();
List<Header> headers = CastUtils.cast((List<?>) message.get(Header.HEADER_LIST));
return headers;
}
...
Then in your function you can use:
List<Header> headers = getHeaders();
for(Iterator<Header> i = headers.iterator(); i.hasNext();) {
Header h = i.next();
Element n = (Element)h.getObject();
System.out.println("header name="+n.getLocalName());
System.out.println("header content="+n.getTextContent());
}
We can get SOAP header in server side by adding following code in CXF interceptor.
Create a class like
public class ServerCustomHeaderInterceptor extends AbstractSoapInterceptor {
#Resource
private WebServiceContext context;
public ServerCustomHeaderInterceptor() {
super(Phase.INVOKE);
}
#Override
public void handleMessage(SoapMessage message) throws Fault,JAXBException {
System.out.println("ServerCustomHeaderInterceptor handleMessage");
JAXBContext jc=null;
Unmarshaller unmarshaller=null;
try {
jc = JAXBContext.newInstance("org.example.hello_ws");
unmarshaller = jc.createUnmarshaller();
} catch (JAXBException e) {
e.printStackTrace();
}
List<Header> list = message.getHeaders();
for (Header header : list) {
ElementNSImpl el = (ElementNSImpl) header.getObject();
ParentNode pn= (ParentNode) el.getFirstChild();
//Node n1= (Node) pn;
//Node n1= (Node) el.getFirstChild();
CustomHeader customHeader=(CustomHeader) unmarshaller.unmarshal(el.getFirstChild());
}
}
After this we need to inject this as a interceptor like
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<bean class="org.example.hellows.soap12.ServerCustomHeaderInterceptor" />
</jaxws:inInterceptors>
in your server context xml.
We may need to change few lines as per your requirements. Basic flow will work like this.
Having a MessageContext messageContext, you can use this code:
HeaderList hl = (HeaderList) messageContext.get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);
which gives you access to all SOAP headers.