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
Related
I try to get the big data from FRED (Federal Reserve Economic Data) using java but there are some problems. Belows are the sample codes.
for(US_STATE state : US_STATE.values()) { // for every us-states loop
String fredUrl = "https://api.stlouisfed.org/fred/series/search?search_text=Unemployment Rate in " + state.toString() + &api_key=**********&file_type=json";
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(new URL(fredUrl)); // request url in this line
Thread.sleep(500); // insert sleep line to avoid the http errors
ArrayNode nodeSeriess = (ArrayNode)rootNode.get("seriess");
// I make the jsonnode stream , extract series_id from rootNode and make another url string
Stream<JsonNode> elementStream = StreamSupport.stream(nodeSeriess.spliterator(), false);
elementStream.flatMap(pojo -> {
String observUrl = "https://api.stlouisfed.org/fred/series/observations?series_id=" + pojo.getSeriesId() + "&api_key=***********&file_type=json";
// I request url again in the stream
JsonNode nodeValue = mapper.readTree(new URL(observUrl));
Thread.sleep(500); // insert sleep line to avoid the http errors
ArrayNode nodeValueObserv = (ArrayNode)nodeValue.get("observations");
...... // processing data from this line
});
As you see, my codes execute too much Java URL api. So I think I face the HTTP response code: 504 for URL.
I found with googling that the 504 error is not related with client codes, but when I execute too much Java URL, I always receive this error. I want to know how to avoid this error programmatically. I am afraid my Java program calls the Java URL too much in for loop.
Below is the java program i have written in the client side to receive & encrypt part of the XML message that is sent in the SOAP interface.
SOAPBindingMessageContext soapbindingmessagecontext = (SOAPBindingMessageContext) iContext;
javax.xml.soap.SOAPMessage soapMessage = soapbindingmessagecontext.getRequestMessage();
Iterator iterator = soapMessage.getMimeHeaders().getAllHeaders();
while (iterator.hasNext()) {
MimeHeader header = (MimeHeader) iterator.next();
System.out.println(header.getName());
System.out.println(header.getValue().toString());
if (header.getName().equalsIgnoreCase("SOAPAction")) {
System.out.println("The soapAction is : " + header.toString());
operationName = header.getValue().replaceAll("\"", "");
}
}
if (debug) {
System.out.println(operationName);
}
However it looks like the operationName (soapAction in the WSDL) is null & not being extracted from the SOAP Message. I have confirmed from the logs that other MIME-headers can be extracted. Just the soapAction i am not able to extract. I have also confirmed from the soapUI that the soapAction is really sent and is not null when sending. Below is the snap of same. Could you please help me to understand where i am doing wrong ?
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?
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.
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.