I want to add the child element(Identifier) in the body of the Soap Request as below:
Expected Soap Request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="nsurl">
<soapenv:Header/>
<soapenv:Body>
<ns:GetRequest>
<ns:Identifier Type="x" Value="y"/>
</ns:GetRequest>
</soapenv:Body>
</soapenv:Envelope>
With my code I am able to add the child element(Identifier) as below:
Actual Soap Request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="nsurl">
<soapenv:Header/>
<soapenv:Body>
<ns:GetRequest>
<ns:Identifier>Type="x" Value="y"</ns:Identifier>
</ns:GetRequest>
</soapenv:Body>
</soapenv:Envelope>
And here is the java code:
private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
SOAPPart soapPart = soapMessage.getSOAPPart();
String myNamespace = "ns";
String myNamespaceURI = "nsurl";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI);
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("GetRequest", myNamespace);
SOAPElement soapBodyElem1 =soapBodyElem.addChildElement("Identifier", myNamespace);
soapBodyElem1.addTextNode("Type=\"x\" Value=\"y\"");
}
It appears that you are using SoapUI tool.
You could use Groovy Script test step with below script to change the same.
def xmlString = """ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="nsurl"> <soapenv:Header/> <soapenv:Body> <ns:GetRequest> <ns:Identifier>Type="x" Value="y"</ns:Identifier> </ns:GetRequest> </soapenv:Body> </soapenv:Envelope>"""
def xml = new XmlSlurper().parseText(xmlString)
//Get the Identifier node
def identifier = xml.'**'.find{it.name() == 'Identifier'}
//Create a map based on Identifier node value
def map = identifier.text().split(' ').collectEntries{ [(it.split('=')[0]) : it.split('=')[1].replace('"','')]}
//Remove the text value for Identifier node
identifier.replaceBody { '' }
//Set the attributes from the map
map.each{k,v -> identifier.#"$k" = v}
def newXml = groovy.xml.XmlUtil.serialize(xml)
log.info newXml
You can quickly try it online demo
In the expected request, Type and Value are attributes, not part of the content of the ns:Identifier element. Therefore you need to use SAAJ's addAttribute (or DOM's setAttributeNS) method to add them.
Related
I'm trying to get the desired customized header for my SOAP request:
What I need:
<soapenv:Header>
<urn:SessionHeader>
<urn:sessionId>abcdef1234</urn:sessionId>
</urn:SessionHeader>
</soapenv:Header>
But what I'm getting is:
<SOAP-ENV:Header>
<urn:sessionId xmlns:urn="www.dummy.com">
abcdef1234
</urn:sessionId>
</SOAP-ENV:Header>
I need to remove the xmlns from the childnode!
Below is the Java code I'm using:
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPHeaderElement messageId = soapMessage.getSOAPHeader().addHeaderElement(new QName("www.dummy.com", "sessionId","urn"));
messageId.setTextContent("urn:abcdef1234");
Any suggestions on how to deal with this?
Yes, I managed to get a solution and it is working fine! #JimmyB
//SOAP Header
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPHeaderElement sessionHeader = soapMessage.getSOAPHeader().addHeaderElement(new QName(serverM2M, "SessionHeader","urn"));
SOAPElement sessionID = sessionHeader.addChildElement(new QName(serverM2M, "sessionId","urn"));
sessionID.addTextNode(termTwo);
Which gives me an output:
<soapenv:Header>
<urn:SessionHeader>
<urn:sessionId>00D560000004Zxv!AQMAQGTYYqKa0NwwPNSY7QLnfn1aeyjsloOJQAvU4K53pJlPrGiI0rkdCfcEmN7va2c5caH3XmG.OvTxeU3hPAKwdlWxIlf8</urn:sessionId>
</urn:SessionHeader>
I tried to generate the below SOAP request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:loc="http://www.csapi.org/schema/parlayx/data/sync/v1_0/local">
<soapenv:Header/>
<soapenv:Body>
<loc:syncOrderRelationResponse>
<loc:result>0</loc:result>
<loc:resultDescription>OK</loc:resultDescription>
</loc:syncOrderRelationResponse>
</soapenv:Body>
</soapenv:Envelope>
And I'm using the following code:
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage outgoingMessage = messageFactory.createMessage();
SOAPPart soappart = outgoingMessage.getSOAPPart();
SOAPEnvelope envelope = soappart.getEnvelope();
envelope.setAttribute("xmlns:loc" , "http://www.csapi.org/s");
SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();
QName bodyName = new QName("", "syncOrderRelationResponse", "loc");
SOAPBodyElement purchaseLineItems = body.addBodyElement(bodyName);
QName childName = new QName("","result","loc");
SOAPElement product = purchaseLineItems.addChildElement(childName);
product.addTextNode("0");
childName = new QName("","resultDescription","loc");
SOAPElement product = purchaseLineItems.addChildElement(childName);
product.addTextNode("0");
When I execute the code I get no response,but when I put the namespaceURL I got the response.
could you please help me?
thanks for your support
You get an XML error because your use of namespaces is not coherent throughout your process, and ultimately results in an XML specification violation.
First things first :
envelope.setAttribute("xmlns:loc" , "http://www.csapi.org/s");
Means you add to your document a namespace prefix declaration (the loc prefix) that designates the namespace identified by http://www.csapi.org/s.
This implies that from now on, if you declare an XML element using this syntax <loc:tag>, then tag is an XML element that belongs to the http://www.csapi.org/s namespace.
When you subsenquently declare a QName this way
QName childName = new QName("","result","loc");
You are preparing an XML element that has 3 caracteristics :
It belongs to the empty namespace (first argument)
Its local name in the empty namespace is "result" (2nd argument)
You want its local name to be prefixed with "loc" (3rd argument)
Which is OK (at least, the implementation thinks so)... Untill you add this QName to your document : at this point in your XML document, the "loc" prefix does not designate the empty namespace. So you are, in effect, asking the XML implementation to redefine the "loc" prefix to mean "empty namespace" in order to comply with your statement. But the empty namespace is special in XML, it can not be prefixed (see http://www.w3.org/TR/REC-xml-names/#ns-using)
In a namespace declaration for a prefix (i.e., where the NSAttName is a PrefixedAttName), the attribute value MUST NOT be empty.
However, please note that, given your example, that's actually fortunate because "adding a <result> element from the empty namespace" is NOT what you want to do. What you want to do is add a result element from the "http://www.csapi.org/s" namespace.
Therefore, a consistent namespace handling provides you with the expected result :
String namespace = "http://www.csapi.org/s";
SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();
QName bodyName = new QName(namespace, "syncOrderRelationResponse");
SOAPBodyElement purchaseLineItems = body.addBodyElement(bodyName);
QName childName = new QName(namespace,"result");
SOAPElement product = purchaseLineItems.addChildElement(childName);
product.addTextNode("0");
childName = new QName(namespace,"resultDescription");
product = purchaseLineItems.addChildElement(childName);
product.addTextNode("0");
outgoingMessage.writeTo(System.out);
Outputs a valid representation of what you are seeking.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<syncOrderRelationResponse xmlns="http://www.csapi.org/s">
<result>0</result>
<resultDescription>0</resultDescription>
</syncOrderRelationResponse>
</SOAP-ENV:Body></SOAP-ENV:Envelope>
Although if you really want the namespace prefix to appear, you can do it so :
String namespace = "http://www.csapi.org/s";
String nsPrefix = "loc";
envelope.setAttribute("xmlns:" + nsPrefix , namespace);
SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();
QName bodyName = new QName(namespace, "syncOrderRelationResponse", nsPrefix);
SOAPBodyElement purchaseLineItems = body.addBodyElement(bodyName);
QName childName = new QName(namespace,"result", nsPrefix);
SOAPElement product = purchaseLineItems.addChildElement(childName);
product.addTextNode("0");
childName = new QName(namespace,"resultDescription", nsPrefix);
product = purchaseLineItems.addChildElement(childName);
product.addTextNode("0");
How can I get clientCode from requestHeader which is located under SOAP body?
<soapenv:Body>
<ser:GS>
<!--Optional:-->
<requestHeader>
<!--Optional:-->
<req:clientCode>KL7MU</req:clientCode>
<!--Optional:-->
<req:clientUsername>BLABLA</req:clientUsername>
</requestHeader>
</ser:GS>
</soapenv:Body>
I try to get but iterator.hasNext() returns false.
SOAPBody soapBody = context.getMessage().getSOAPBody();
java.util.Iterator iterator = soapBody.getChildElements();
while (iterator.hasNext()) {
SOAPBodyElement bodyElement = (SOAPBodyElement) iterator.next();
String val = bodyElement.getValue();
System.out.println("The Value is:" + val);
}
You can use wsdl to generate java class:
wsimport stock.wsdl -b stock.xml -b stock.xjb
wsimport -d generated http://example.org/stock?wsdl
Then you can call SOAP services as local methods.
Some other tools:
wsdl2javawizard: http://sourceforge.net/projects/wsdl2javawizard/
apache cxf: http://cxf.apache.org/docs/wsdl-to-java.html
instead of getting form SOAP message body
try the child elements form SOAP message header like context.getMessage().getSOAPPart().getEnvelope().getHeader();
details :http://www.mkyong.com/webservices/jax-ws/jax-ws-soap-handler-in-client-side/
You can get the values like in axiom,
SOAPEnvelope mes = messageContext.getEnvelope();
SOAPHeader mesh = mes.getHeader();
SOAPBody mesb = mes.getBody();
OMElement messageId = mesh.getFirstChildWithName(new QName("http://www.w3.org/2005/08/addressing","MessageID"));
String messageIDStr = messageId.getText();
OMElement bodyChild = mesb.getFirstElement();
OMElement remoteAddress = bodyChild.getFirstChildWithName(new QName(
"http://YourNameSpaceURI",
"remoteAddress"));
String remoteAddressStr = remoteAddress.getText();
I'm trying to use axis2, but there must be Security headers in message.
I tried to add PEWSClientHeaderHandler class from this example, but it doesn't work (it works with default sun implementation, but not with axis2). The formed SOAP message looks like this:
...
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"></wsse:Security>
</soapenv:Header>
...
UsernameToken, Username and Password tags are missing (but again, they are set in code and no exception when using sun).
Can anyone provide the simplest example of how such a header can be set in axis2?
Axis2 implementation has 1 little difference:
Standard Sun implementation:
SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
SOAPFactory soapFactory = SOAPFactory.newInstance();
SOAPHeader sh = envelope.addHeader();
SOAPElement wsSecHeaderElm = soapFactory.createElement("Security", AUTH_PREFIX, AUTH_NS);
SOAPElement userNameTokenElm = soapFactory.createElement("UsernameToken", AUTH_PREFIX, AUTH_NS);
SOAPElement userNameElm = soapFactory.createElement("Username", AUTH_PREFIX, AUTH_NS);
SOAPElement passwdElm = soapFactory.createElement("Password", AUTH_PREFIX, AUTH_NS);
userNameElm.addTextNode("username");
passwdElm.addTextNode("password");
userNameTokenElm.addChildElement(userNameElm);
userNameTokenElm.addChildElement(passwdElm);
wsSecHeaderElm.addChildElement(userNameTokenElm);
sh.addChildElement(wsSecHeaderElm);
Axis2 implementation:
// the same as above
userNameTokenElm.addChildElement(userNameElm);
userNameTokenElm.addChildElement(passwdElm);
SOAPElement el = sh.addChildElement(wsSecHeaderElm); // addChildElement returns new SOAPElement!
el.addChildElement(userNameTokenElm);
That's all
Hi trying to generate a security header in a Java Axis2 Client program in the format of.
<soapenv:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext>
<wsse:UsernameToken>
<wsse:Username>myUsername</wsse:Username>
<wsse:Password>myPassword</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
using the following code
SOAPHeaderElement wsseSecurity = new SOAPHeaderElement(new PrefixedQName("http://schemas.xmlsoap.org/ws/2002/04/secext","Security", "wsse"));
MessageElement usernameToken = new MessageElement("", "wsse:UsernameToken");
MessageElement username = new MessageElement("", "wsse:Username");
MessageElement password = new MessageElement("", "wsse:Password");
username.setObjectValue(myProps.getProperty("username"));
usernameToken.addChild(username);
password.setObjectValue(myProps.getProperty("password"));
usernameToken.addChild(password);
wsseSecurity.addChild(usernameToken);
BookingPort bp = bsl.getBooking();
((Stub) bp).setHeader(wsseSecurity);
Unfortunately its not generating quite what I wanted and I get.
<soapenv:Header>
<wsse:Security soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
<wsse:UsernameToken xmlns:wsse="">
<wsse:Username xmlns:wsse="">myUsername</wsse:Username>
<wsse:Password xmlns:wsse="">myPassword</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
The service on the other end doesn't seem to handle the extra bits, resulting in an error
faultDetail:
{http://xml.apache.org/axis/}stackTrace:com.ctc.wstx.exc.WstxParsingException: Non-default namespace can not map to empty URI (as per Namespace 1.0 # 2) in XML 1.0 documents
at [row,col {unknown-source}]: [1,450]
How do I generate the SOAPHeader to not print out all the extra empty bits?
Cheers
You're passing an empty string as the first argument to MessageElement, and you need to pass null. Note that null and the empty string ("") are not the same thing in Java. Also, you are really cheating by passing the namespace prefix to the local name (second) parameter of the MessageElement constructor...this is not what it is designed for. That being said, you can fix the problem by passing null as the namespace (first) parameter. If you try to pass it directly, you'll likely get an ambiguous constructor error, so do something like the following:
SOAPHeaderElement wsseSecurity = new SOAPHeaderElement(new PrefixedQName("http://schemas.xmlsoap.org/ws/2002/04/secext","Security", "wsse"));
String nullString = null;
MessageElement usernameToken = new MessageElement(nullString, "wsse:UsernameToken");
MessageElement username = new MessageElement(nullString, "wsse:Username");
MessageElement password = new MessageElement(nullString, "wsse:Password");
username.setObjectValue(myProps.getProperty("username"));
usernameToken.addChild(username);
password.setObjectValue(myProps.getProperty("password"));
usernameToken.addChild(password);
wsseSecurity.addChild(usernameToken);
BookingPort bp = bsl.getBooking();
((Stub) bp).setHeader(wsseSecurity);
I'd also recommend you use a different web service engine (not Axis2) if you have any choice in the matter.
Try this way to create custom header with Axis 1.* (The above code doesnt look like with Axis2)
import org.apache.axis.message.SOAPHeaderElement;
import javax.xml.soap.SOAPElement;
public void createCustomHeader(){
SOAPElement oHeaderElement;
SOAPElement oElement;
oHeaderElement = new SOAPHeaderElement("http://ws.mycompany.com", "securityHeader");
oHeaderElement.setPrefix("sec");
oHeaderElement.setMustUnderstand(false);
oElement = oHeaderElement.addChildElement("username");
oElement.addTextNode("myusername");
oElement = oHeaderElement.addChildElement("password");
oElement.addTextNode("mypassword");
// You can create client code something like this..
MySampleServiceServiceLocator service = new MySampleServiceServiceLocator();
service.setMySampleServiceEndpointAddress("endpointURL");
MySampleWebService serv = service.getMySampleService();
MySampleServiceSoapBindingStub stub = (MySampleServiceSoapBindingStub)serv;
// add this header to your stubs
stub.setHeader(oHeaderElement);
// Finally call your web service methid
serv.getMyClaimStatus("XYZ001");
}
//It creates the custom header like this:
<soapenv:Header>
<sec:securityHeader xmlns:sec="http://ws.mycompany.com"
soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0">
<sec:username>myusername</sec:username>
<sec:password>mypassword</sec:password>
</sec:securityHeader>
</soapenv:Header>