Get dataHandler from a SOAP message - java

I need a way to change the dataHandler field to cid:generated cid
How do I get the dataHandler element from the SOAP message?
This approach doesn't work:
env.getBody().getElementByID("datahandler")
Any help?
String cid = _messageContext.addAttachment(
dispatchDocumentRequest8.getDataDescription().getDataHandler());
// create SOAP envelope with that payload
org.apache.axiom.soap.SOAPEnvelope env = null;
env = toEnvelope(getFactory(
_operationClient.getOptions().getSoapVersionURI()),
dispatchDocumentRequest8,
optimizeContent(
new javax.xml.namespace.QName(
"dmsSOAP.fiso.denue.fisglobal.com",
"dispatchDocument")));
env.getBody().getElementByID("datahandler"); // this is wrong
Envelope:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns1:dispatchDocumentRequest>
<dataDescription>
<dataHandler>HERE</dataHandler>
</dataDescription>
</ns1:dispatchDocumentRequest>
</soapenv:Body>
</soapenv:Envelope>

I think you should try it with camelCase, so instead of
COPYenv.getBody().getElementByID("datahandler")
Try the following:
COPYenv.getBody().getElementByID("dataHandler")
EDIT
According to your comment i think you should try:
COPYenv.getBody().getElementByID("dataHandler").setText("something")

Related

Java WS get SOAP request CDATA body

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.

How to Read SOAP API Request Headers Using Java Spring

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--

How to read the header in the web server 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

Axis2 Client Throws AxisFault: Must Understand check failed for header Security

I'm using Axis2-1.6.1 and have been able to successfully send a SOAP request. Here's an example of the request:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="true">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>***username***</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">***pass***</wsse:Password>
<wsse:Nonce Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">***nonce***</wsse:Nonce>
<wsu:Created Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">***datetime***</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
<wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://mysite/contract/users/v3/IUsers/EchoAuthenticated</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<ns6:EchoAuthenticated xmlns:ns6="http://mysite/contract/users/v3">
<ns6:value>success</ns6:value>
</ns6:EchoAuthenticated>
</soapenv:Body>
</soapenv:Envelope>
Upon receiving the response, this exception is thrown:
org.apache.axis2.AxisFault: Must Understand check failed for header http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd : Security
I'm under the impression, after doing some research, that there's something in the response that Axis2 doesn't like. Puzzled, I copied the above request and pasted it into SoapUI and fired it. It works, I receive the below response. I also confirmed, using Fiddler, that this is the same response I am getting when I send this request in Eclipse its just there's something about it that Axis2 doesn't like client-side, perhaps the mustUnderstand?
Here's the response:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://mysite/contract/users/v3/IUsers/EchoAuthenticatedResponse</a:Action>
<a:RelatesTo>urn:uuid:***guid***</a:RelatesTo>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>***datetime***</u:Created>
<u:Expires>***datetime***</u:Expires>
</u:Timestamp>
</o:Security>
</s:Header>
<s:Body>
<EchoAuthenticatedResponse xmlns="http://mysite/contract/users/v3">
<EchoAuthenticatedResult>This is the Users service answering back. The value you sent was: success</EchoAuthenticatedResult>
</EchoAuthenticatedResponse>
</s:Body>
</s:Envelope>
I'm limited in my ability to move to a more recent version of Axis2 as this is bundled with a product but I need to find out how I can get passed this error.
I found one solution which is to set mustUnderstand instances in the response to false
To accomplish this I've done the following:
Create a Handler class which extends *org.apache.axis2.handlers.AbstractHandler
MustUnderstandHandler.java
import java.util.Iterator;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
public class MustUnderstandHandler extends org.apache.axis2.handlers.AbstractHandler {
#Override
public InvocationResponse invoke(MessageContext messageContext) throws AxisFault {
try{
System.out.println("RemoveMustUnderstandAll: invoke " + messageContext);
SOAPEnvelope env = messageContext.getEnvelope();
SOAPHeader header = env.getHeader();
if(header != null){
for(Iterator<?> itr = header.getChildElements(); itr.hasNext();){
SOAPHeaderBlock headerBlock = (SOAPHeaderBlock) itr.next();
if(headerBlock.getMustUnderstand()){
headerBlock.setMustUnderstand(false);
System.out.println("RemoveMustUnderstandAll (" + messageContext + "): setMustUnderstand(false) to " + headerBlock.getQName());
}
}
}
}
catch(Exception e){
System.out.println(e.toString());
}
return InvocationResponse.CONTINUE;
}
}
Wire the AxisConfiguration to use the handler class
In the generated Stub (created from WSDL2Java) I've located instances where it's executing the client and before each of these lines I included the following:
MyStub.java
AxisConfiguration axisConfiguration = _messageContext.getConfigurationContext().getAxisConfiguration();
ArrayList arrayList = new ArrayList();
arrayList.add(new MustUnderstandHandler());
axisConfiguration.setInPhasesUptoAndIncludingPostDispatch(arrayList);
// execute the operation client
_operationClient.execute(true);

JAX-WS namespace in attribute, not prefix

is possible in JAX-WS to generate xmlns attributes instead of prefixes?
Example: Object A from package myns.a contains some objects B1, B2 from package myns.b. Generated SOAP message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="urn:myns/a" xmlns:b="urn:myns/b">
<soapenv:Header/>
<soapenv:Body>
<a:A1>
<b:B1>123456</b:B1>
<b:B2>abc</b:B2>
</a:A1>
</soapenv:Body>
</soapenv:Envelope>
However, i need to generate it this way (so prefix b should be removed and all objects from package myns.b should have xmlns attribute):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="urn:myns/a">
<soapenv:Header/>
<soapenv:Body>
<a:A1>
<B1 xmlns="urn:myns/b">123456</B1>
<B2 xmlns="urn:myns/b">abc</B2>
</a:A1>
</soapenv:Body>
</soapenv:Envelope>
Is there a simple way, how to handle this? For example on package-info.java level?
I solved this using custom SOAPHandler and removing prefixes from element in urn:myns/b namespace.
Simplified snippet:
#Override
public boolean handleMessage(SOAPMessageContext context) {
SOAPBody body = context.getMessage().getSOAPPart().getEnvelope().getBody();
//do recursivelly, this is just example
Iterator iter = body.getChildElements();
while (iter.hasNext()) {
Object object = iter.next();
if (object instanceof SOAPElement) {
SOAPElement element = (SOAPElement) object;
if("urn:myns/b".equals(element.getNamespaceURI())){
element.setPrefix("");
}
}
}

Categories