How to add child element in soap header in java - java

How to add child element in soap header in java spring webservice.
I have tried two approach but nothing is working please suggest me what need to be done?
first approach :-
soapHeaderString.append("<tem:Culture>en_Us</tem:Culture><tem:AgentCode>PumpkinSafari</tem:AgentCode><tem:PartnerID></tem:PartnerID><tem:Password>PMP22#in</tem:Password>");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// Here we create a Source Tree
StringSource stringSource = new StringSource(soapHeaderString.toString());
transformer.transform(stringSource, soapHeader.getResult());
but it is giving me error
The prefix "tem" for element "tem:Culture" is not bound.
2nd Approach :-
SoapHeaderElement headerElement=soapMessage.getSoapHeader().addHeaderElement(new QName("http://tempuri.org/", "SOAPHeaderAuth","tem"));
headerElement.setText(soapHeaderString.toString());
It produce unescaped sequqnce so service provider give error as it was not able to understand the request.
Please help me what need to be done to solve the problem.

Yes, in my case too it prompts the same error, The prefix "username" for element "wsse:username" is not bound. I tried doing everything to add namespace declaration. But, it doesn't worked!
"Finally", I was able to do it last night with a workaround, converting some way from Spring org.springframework.ws.soap.SoapHeader to javax.xml.soap.SOAPHeader. And no issues now!
SOAPMessage soapMessage = ((SaajSoapMessage) message).getSaajMessage();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPHeaderElement security = header.addHeaderElement(new QName(SCHEMA, "Security", SCHEMA_PREFIX));
SOAPElement usernameToken = security.addChildElement("UsernameToken", SCHEMA_PREFIX);
SOAPElement usernameElement = usernameToken.addChildElement("Username", SCHEMA_PREFIX);
SOAPElement passwordElement = usernameToken.addChildElement("Password", SCHEMA_PREFIX);
usernameElement.setTextContent(username);
passwordElement.setTextContent(password);
Through this I was able to add namespace declarations to spring soap header child elements!

JAX-WS Users
I would recommend using a message handler:
http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client
Spring Web Services Users
A similar concept exists:
http://arcanetechnotes.blogspot.com/2008/12/modifying-soap-headers-with-spring-web.html
The question states that it cannot understand the tem namespace, so perhaps register the namespace in the header:
soapHeader.addNamespaceDeclaration("tem", "http://whatever.namespace.com/");

Use "header=true" property in webparam
Like
#WebMethod(operationName = "someMethod")
public String someMethod(#WebParam(name = "yourBeanObj") YourBeanObjClass yourBeanObj,
#WebParam(header = true, mode = WebParam.Mode.IN, name = "username") String userName,
#WebParam(header = true, mode = WebParam.Mode.IN, name = "password") String pwd) {
//todo stuff
}
As per above example "yourBeanObj" wil be added into soap body, "username" and "password" are add in soap header.

Related

Get parameters from soap request

my app receive a soap request; this is an example:
<SOAP-ENV:Body>
<ns1:authorize>
<params>AppSender</params>
<params>url.appsender.local</params>
<params>GET /applic/ HTTP/1.1</params>
<params>2017-01-4T09:38:00.601Z#NCODER08F839F#myapp.sch</params>
<params>/applic/</params>
<params>2.0.00</params>
<params></params>
<params>d1c714fe-cae1-4150-934f-bb3e61ad85f2</params>
<params>Authentication-Instant</params><params>2017-01-</params>
<params>fiscalCode</params><params>NTSDNT80R085454</params>
<params>userName</params><params>user</params>
<params>levelVerification</params><params>10</params>
<params>AuthenticationType</params><params>BASIC</params>
</ns1:authorize>
Can i have an example that i take this request and i set the value of the tag "params" in a JavaBean???
Thank you
You must process the request with some java library for XML processing.
Example:
org.w3c.dom.Document doc = null;
doc = builder.parse(request);
doc.getDocumentElement().normalize();
org.w3c.dom.Node nodeRoot = doc.getFirstChild();
if(nodeRoot.getNodeName().equals("authorize")) {
... doc.getElementsByTagName("params")...;
You can do it with JAXB, here you have more info ...
http://theopentutorials.com/examples/java/jaxb/generate-java-class-from-xml-schema-in-eclipse-ide/

How is a SOAP response treated different in Java 8 vs Java 6?

Have some legacy code that works with Java 6 but not fully with Java 8. It sends a SOAP request and reads the response. When using Java 8, the response is not correctly parsed and the code returns a failed result.
Here is a simplified version of the code, I have cut out most of the request building code and changed server names and the like. Please pardon any typos.
try {
// Init the factories
SOAPConnectionFactory SOAPConnFac = SOAPConnectionFactory.newInstance();
SOAPFactory SOAPFac = SOAPFactory.newInstance();
MessageFactory MessageFac = MessageFactory.newInstance();
// Create the SOAP Connection
SOAPConnection SOAPConn = SOAPConnFac.createConnection();
// Build the SOAP request message
SOAPMessage SOAPRequestMsg = MessageFac.createMessage();
// Add info to the MIME header for .NET compatibility
MimeHeaders hd = SOAPRequestMsg.getMimeHeaders();
hd.addHeader("SOAPAction", "http://www.mysever.com/respond");
// Remove the SOAP message header, it is not needed in this case
SOAPHeader SOAPRequestHeader = SOAPRequestMsg.getSOAPHeader();
SOAPRequestHeader.detachNode();
// Build the SOAP body main element CheckIt
SOAPBody SOAPRequestBody = SOAPRequestMsg.getSOAPBody();
javax.xml.soap.Name nameRequestBody = SOAPFac.createName("CheckIt", "", "http://www.myserver.com/");
SOAPBodyElement sbeRequestBodyEle = SOAPRequestBody.addBodyElement(nameRequestBody);
// Add all child elements to the CheckIt element
SOAPElement seNameNode = sbeRequestBodyEle.addChildElement("Name");
seNameNode.addChildElement("FirstName").addTextNode("mary");
seNameNode.addChildElement("LastName").addTextNode("smith");
sbeRequestBodyEle.addChildElement("ID").addTextNode("3423");
URL urlWebService = new URL ("http://webserver/BGC/");
// Send the SOAP request message and get back the SOAP response message
SOAPMessage SOAPResponseMsg = SOAPConn.call(SOAPRequestMsg, urlWebService);
SOAPConn.close();
// Pull out the SOAP response body
SOAPBody SOAPResponseBody = SOAPResponseMsg.getSOAPBody();
// Check for SOAP faults
if (SOAPResponseBody.hasFault()) {
SOAPFault newFault = SOAPResponseBody.getFault();
strStatus = "SOAP FAULT:<br>";
strStatus += "<br>code = " + newFault.getFaultCodeAsName();
strStatus += "<br>message = " + newFault.getFaultString();
strStatus += "<br>actor = " + newFault.getFaultActor()+"<br>";
boolOK = false;
} else {
// Pull the CheckProspectResponse element out of the SOAP response body
javax.xml.soap.Name nameResponseBody = SOAPFac.createName("CheckResponse", "", "http://www.mysever.com/");
Iterator iterElement = SOAPResponseBody.getChildElements(nameResponseBody);
if (iterElement.hasNext()){
SOAPBodyElement sbeResponseBodyEle = (SOAPBodyElement) iterElement.next();
// Check for success or failure
String strResultMsg = ((sbeResponseBodyEle.getValue() == null) ? sbeResponseBodyEle.toString() : sbeResponseBodyEle.getValue());
strStatus = "Check response came back from webserver as *" + strResultMsg + "*<br>";
boolOK = (strResultMsg.trim().toUpperCase().indexOf("SUCCESS") > 0);
} // End if (iterElement.hasNext())
} // End if (SOAPResponseBody.hasFault())
} catch(Exception e) {
strStatus = "Error : "+((e.getMessage() != null) ? e.getMessage() : e.toString());
boolOK = false;
} // End try
It seems that when pulling elements out of the response, it gets an empty set.
Iterator iterElement = SOAPResponseBody.getChildElements(nameResponseBody);
Returns a set of null elements. Not a null itself, the set has at least one member but that member is null. It should have a value of "SUCCESS" but it's null. I have looked at the full response and it looks fine, everything is there and it works with Java 6, just not with Java 8. A typical, successful response looks like this:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<CheckResponse xmlns="http://www.mysever.com/">
<CheckResult>SUCCESS</CheckResult>
</CheckResponse>
</soap:Body>
</soap:Envelope>
UPDATE
I have found a way around my problem, using getTextContent I get the correct data, or at least the data I expect to get. Given the above SOAP response, Java 8 returns the following for the given method call:
getValue = null
getNodeValue = null
getLocalName = CheckResponse
getNodeName = CheckResponse
getNamespaceURI = http://www.mysever.com/
getPrefix = null
getTextContent = SUCCESS
Acording to both Java 6 and Java 8 docs, the returned value for getValue should be "SUCCESS" in this case. Which is true for Java 6 but false for Java 8.
Any ideas on why this method works with Java 6 but not with Java 8? Is this a bug?

PolicyException: None of the policy alternatives can be satisfied in WCF Service Call

I have created web service client using Apache axis 1.4. The wcf service i am accessing is STS service which required AppliesTo Parameter and its return SAML token. I have go through various blog and website while searching and some how i came to this kanbancoding Part 3
So i go through it and do the changes in my code but now i am getting org.apache.cxf.ws.policy.PolicyException: None of the policy alternatives can be satisfied. My
Well after lot of try and error i figure out what exactly i need to call WCF STS Service. While goggling i found a document on Docs.Oasis OOasis WS Trust 1.3 which explain in details what data need to be send in a soap Message and yes with the help of kanbancoding this is my method to call the STS
private static void getSecurityToken() {
try {
// Use the empty constructor – no need to specify wsdl
SecurityTokenService src = new SecurityTokenService();
// Pull the class used to negotiate WS Trust directly from the
// SecurityTokenService
IWSTrust13Sync trust = src.getBasicHttpBindingIWSTrust13Sync();
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(IWSTrust13Sync.class);
factory.setAddress(ServiceURL);
IWSTrust13Sync service = (IWSTrust13Sync) factory.create();
// Obtain a reference to the CXF endpoint using the ClientProxy helper:
Client client = ClientProxy.getClient(service);
// Set up logging if desired
client.getOutInterceptors().add(new LoggingOutInterceptor());
client.getInInterceptors().add(new LoggingInInterceptor());
client.getRequestContext().put("com.sun.xml.ws.connect.timeout", 1 * 60 * 1000);
client.getRequestContext().put("com.sun.xml.ws.request.timeout", 5 * 60 * 1000);
// Specify the user we want to authenticate
client.getRequestContext().put("ws-security.username", UserName);
client.getRequestContext().put("ws-security.password", Password);
HTTPConduit http = (HTTPConduit) client.getConduit();
http.getAuthorization().setUserName(UserName);
http.getAuthorization().setPassword(Password);
http.getClient().setConnectionTimeout(36000);
http.getClient().setAllowChunking(false);
RequestSecurityTokenType token = new RequestSecurityTokenType();
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element tokenType = document.createElementNS("http://docs.oasis-open.org/ws-sx/ws-trust/200512",
"TokenType");
tokenType.setTextContent("http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0");
token.getAny().add(tokenType);
Element requestType = document.createElementNS("http://docs.oasis-open.org/ws-sx/ws-trust/200512",
"RequestType");
requestType.setTextContent("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue");
token.getAny().add(requestType);
Document appliesTodoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element appliesTo = appliesTodoc.createElementNS("http://schemas.xmlsoap.org/ws/2004/09/policy",
"AppliesTo");
Element endPoint = appliesTodoc.createElementNS("http://schemas.xmlsoap.org/ws/2004/08/addressing",
"EndpointReference");
Element address = appliesTodoc.createElementNS("http://schemas.xmlsoap.org/ws/2004/08/addressing",
"Address");
address.setTextContent("http://localhost");
endPoint.appendChild(address);
appliesTo.appendChild(endPoint);
token.getAny().add(appliesTo);
//Now specify what claims we want back.
Document claimsDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element claims = claimsDoc.createElementNS("http://docs.oasis-open.org/ws-sx/ws-trust/200512", "Claims");
claims.setAttribute("Dialect", "http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice");
// Add claims to token request
//token.getAny().add(claims);
RequestSecurityTokenResponseCollectionType result = service.trust13Issue(token);
//parseResponse(result);
List<RequestSecurityTokenResponseType> response = result.getRequestSecurityTokenResponse();
Iterator<RequestSecurityTokenResponseType> itr = response.iterator();
while (itr.hasNext()) {
RequestSecurityTokenResponseType obj = itr.next();
List<Object> responseObject = obj.getAny();
Iterator<Object> ObjItr = responseObject.iterator();
while (ObjItr.hasNext()) {
System.out.println("Result " + ObjItr.next());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
But not fully succeeded in what i want but yes something i am getting in response In Apache CFX Log not in result object.

Get elements of SOAP response

When I send a SOAP request using SAAJ API, I would receive a large SOAP response, in which I need to search for some nodes.
I am using following code but it just show the name of first node of body (HotelListResponse which has many children) and I have noticed that the loop just iterates once, (as shown in commented section).
In short: I need to know how to search for some nodes (preferably by their name) in a variable which its type is SOAPMessage. Thanks
SOAPMessage sm = response; //this is the response
sm.writeTo(System.out); //response is shown successfully in console
SOAPBody ReBody = sm.getSOAPBody();
Iterator sentIt = ReBody.getChildElements(); //create an iterator on elements
int counter=0;
while(sentIt.hasNext())
{
SOAPBodyElement sentSBE = (SOAPBodyElement)sentIt.next();
Iterator sentIt2 = sentSBE.getChildElements();
SOAPElement sentSE = (SOAPElement)sentIt2.next();
String sentID = sentSE.getNodeName(); //result is HotelListResponse
counter++;
//System.out.println("sentID:"+sentID);
}
System.out.println("counter"+counter); //result is 1

Java SOAP - Need help on Body and ChildElement manipulation

I'm trying to write some code in java to learn more about coding with WSDL and SOAP.
For example given :'<'to:checkAccount xmlns:to="http://foo">
'<'to:id> test '<'/to:id>
'<'to:password> test '<'/to:password>
'<'to:checkAccount >"
'<'element name="checkAccountResponse">
'<'complexType>
'<'sequence>
'<'element name="checkAccountReturn" type="impl:account"/>
'<'/sequence>
'<'/complexType>
'<'/element>
'<'complexType name="account">
'<'sequence>
'<'element name="active" type="xsd:boolean"/>
'<'element name="name" type="xsd:string"/>
'<'/sequence>
'<'/complexType>
my code looks like this at the moment:
//create the message
String endpoint = "http://foo/someAPI";
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPHeader header = message.getSOAPHeader();
//adding to the body
SOAPBody body = message.getSOAPBody();
SOAPFactory soapFactory = SOAPFactory.newInstance();
Name bodyName = soapFactory.createName("checkAccount","to","http://foo");
SOAPElement bodyElement = body.addBodyElement(bodyName);
//add the ID child elements
soapFactory = SOAPFactory.newInstance();
Name childName = soapFactory.createName("id","to","http://foo");
SOAPElement symbol = bodyElement.addChildElement(childName);
symbol.addTextNode("test");
//add password child element
soapFactory = SOAPFactory.newInstance();
childName = soapFactory.createName("password","to","http://foo");
symbol = bodyElement.addChildElement(childName);
symbol.addTextNode("test");
//call and get the response
SOAPMessage response = sc.call(message,endpoint);
//print the response
SOAPBody responseBody = response.getSOAPBody();
java.util.Iterator iterator = responseBody.getChildElements(bodyName);
.
.
.
//the response is blank so trying to iterate through it gives the exception
I run this and i get nothing in return , just blank. I know my endpoint is correct , as well as the checkAccount ,id and password since I've tested it in xmlSpy and it returns account status.
It has to be the way I'm trying to get the response. Can someone please give me a hint?
This is how I would do it.
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
SOAPBody body = message.getSOAPBody();
SOAPElement checkAccEl = body
.addChildElement("checkAccount", "to", "http://foo");
SOAPElement idEl = checkAccEl
.addChildElement("id", "to", "http://foo");
idEl.addTextNode("test");
SOAPElement passwordEl = checkAccEl
.addChildElement("password", "to", "http://foo");
passwordEl.addTextNode("test");
// print out the SOAP Message. How easy is this?!
ByteArrayOutputStream out = new ByteArrayOutputStream();
message.writeTo(out);
System.out.println(out.toString());
The first time you use the namespace 'to=http://foo' it is automatically declared on the element - checkAccount in this case. When you use the same namespace again, the XML won't need to declare it again, but will use the prefix.
The output looks like:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<to:checkAccount xmlns:to="http://foo">
<to:id>test</to:id>
<to:password>test</to:password>
</to:checkAccount>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Which is what you want I think

Categories