Consuming SOAP WebService with Java issue - java

I was reading a lot of tutorials and similar questions on stackoverflow, but I still have a problem connecting to my SOAP service.
I am trying to call a SOAP web service using Java. I found a nice answer here: https://stackoverflow.com/a/15942217/2145530
The example works perfectly as is but when I change it to another wsdl file it no longer works:
public static void main(String args[]) throws Exception {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
String url = "http://192.168.200.165/soap/server.php";
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// print SOAP Response
System.out.print("Response SOAP Message:");
soapResponse.writeTo(System.out);
soapConnection.close();
}
private static SOAPMessage createSOAPRequest() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "urn:BoardSOAP";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("soap", serverURI);
System.out.println(envelope.getNamespaceURI());
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "getBoardStatus");
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}
As you can see I changed those lines:
String url = "http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx";
String serverURI = "http://ws.cdyne.com/";
headers.addHeader("SOAPAction", serverURI + "ReturnCodes");
String url = "http://192.168.200.165/soap/server.php";
String serverURI = "urn:BoardSOAP";
headers.addHeader("SOAPAction", serverURI + "getBoardStatus");
Here is my wsdl file:
Full output:
http://schemas.xmlsoap.org/soap/envelope/
Request SOAP Message:<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="urn:BoardSOAP"><SOAP-ENV:Header/><SOAP-ENV:Body/></SOAP-ENV:Envelope>
Response SOAP Message:<?xml version="1.0" encoding="ISO-8859-1"?><SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body><SOAP-ENV:Fault><faultcode xsi:type="xsd:string">SOAP-ENV:Client</faultcode><faultactor xsi:type="xsd:string"></faultactor><faultstring xsi:type="xsd:string">Operation &apos;&apos; is not defined in the WSDL for this service</faultstring><detail xsi:type="xsd:string"></detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
WSDL file isn't corrupted, I can communicate with it via SoupUI with no problem.

In the answer you cite, the soapAction for ReturnCodes is http://ws.cdyne.com/ReturnCodes, which is constructed by the line headers.addHeader("SOAPAction", serverURI + "ReturnCodes");
However, in your WSDL, since you are using not a URL but a URN for your namespace identifier, the soapAction for getBoardStatus is urn:server#getBoardStatus. If you use the same concatenation scheme, you will be missing the # and you will be using urn:BoardSoap instead of urn:server.
Try using `headers.Header("SOAPAction", "urn:server#getBoardStatus").

This way also worked for me:
saajSoapMessage.setSoapAction("urn:server#getBoardStatus");

Related

How do I make a java client to call a soap WebService method with parameters?

How do I make a java client to call a soap WebService method with parameters?
I've tried this class for a java client
import javax.xml.soap.*;
public class SOAPClientSAAJ {
public static void main(String args[]) throws Exception {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
String url = "http:localhost:8080/myproject/mywebservice?wsdl";
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// print SOAP Response
System.out.print("Response SOAP Message:");
soapResponse.writeTo(System.out);
soapConnection.close();
}
private static SOAPMessage createSOAPRequest() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String namespace= "http://wsnamespace/";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("example", namespace);
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("Login", "example");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("username", "example");
SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("password", "example");
soapBodyElem1.addTextNode("email#example.com");
soapBodyElem2.addTextNode("1234");
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", namespace + "Login");
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}
}
with this java webservice method
#WebMethod(operationName="Login")
public boolean Login(#WebParam(name = "username") String username,
#WebParam(name = "password") String password) {
System.out.print(username + "-" + password);
}
but username and password are always null so the output when the method is called is "null-null", I would like to know how call this method sending the paramaters correctly.
thanks!
You can make a HTTPClient call and pass SOAP request as string parameter.
There are better way to do this that internally does the above for example using Apache AXIS2, CXF, JAX-WS etc.
I prefer to use CXF by generating stubs of WSDL file and calling the service through JAVA.
Refer examples:
https://rathinasaba.wordpress.com/2013/02/01/call-webservice-wsdl-based-using-apache-httpconnection/
How to call a SOAP webservice with a simple String (xml in string format)

Java SOAP request string in POST data

I am not familiar with SOAP requests so I have been reading up on it. The examples and tutorials I've looked at construct the request in an xml format in the SOAP envelope.
example:
private static SOAPMessage createSOAPRequest() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://ws.cdyne.com/";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("example", serverURI);
/*
Constructed SOAP Request Message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:example="http://ws.cdyne.com/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<example:VerifyEmail>
<example:email>mutantninja#gmail.com</example:email>
<example:LicenseKey>123</example:LicenseKey>
</example:VerifyEmail>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
*/
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("VerifyEmail", "example");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("email", "example");
soapBodyElem1.addTextNode("mutantninja#gmail.com");
SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("LicenseKey", "example");
soapBodyElem2.addTextNode("123");
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "VerifyEmail");
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message = ");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}
but the example request that was given to me by the organization with the server is a single line with the request in the URL:
http://sdmdataaccess.nrcs.usda.gov/Spatial/SDMNAD83Geographic.wfs?Service=WFS&Version=1.0.0&Request=GetFeature&OutputFormat=GML3&TypeName=MapunitPoly&FILTER=<Filter><Intersect><PropertyName>Geometry</PropertyName><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-95.1852448111,43.0186163988 -95.1853350008,43.0183961223 -95.1854898978,43.0183055981 -95.1858276893,43.0182603358 -95.1861146851,43.0183087828 -95.1862558373,43.0184050072 -95.186496397,43.0188380162 -95.1867287441,43.018969948 -95.1871860608,43.0190950058 -95.1872413814,43.0192924831 -95.1869109659,43.0195048805 -95.1863026073,43.019660449 -95.1860721056,43.0196581015 -95.185922908,43.0195072276 -95.1857936581,43.0191228335 -95.1853686954,43.0188252761 -95.1852448111,43.0186163988 -95.1852448111,43.0186163988</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></Intersect></Filter>
Here it is again but wrapped and indented for easier reading:
http://sdmdataaccess.nrcs.usda.gov/Spatial/SDMNAD83Geographic.wfs?
Service=WFS&
Version=1.0.0&
Request=GetFeature&
OutputFormat=GML3&
TypeName=MapunitPoly&
FILTER=<Filter>
<Intersect>
<PropertyName>Geometry</PropertyName>
<gml:Polygon>
<gml:outerBoundaryIs>
<gml:LinearRing>
<gml:coordinates>
-95.1852448111,43.0186163988
-95.1853350008,43.0183961223
-95.1854898978,43.0183055981
-95.1858276893,43.0182603358
-95.1861146851,43.0183087828
-95.1862558373,43.0184050072
-95.186496397,43.0188380162
-95.1867287441,43.018969948
-95.1871860608,43.0190950058
-95.1872413814,43.0192924831
-95.1869109659,43.0195048805
-95.1863026073,43.019660449
-95.1860721056,43.0196581015
-95.185922908,43.0195072276
-95.1857936581,43.0191228335
-95.1853686954,43.0188252761
-95.1852448111,43.0186163988
-95.1852448111,43.0186163988
</gml:coordinates>
</gml:LinearRing>
</gml:outerBoundaryIs>
</gml:Polygon>
</Intersect>
</Filter>
I'm not sure how to either modify this to handle the single line request or to modify the request to fit into this system. Any information would be helpful.
That's not SOAP. That's a simple GET request, in which one parameter is an XML document. As such, you can simply issue a GET request using Apache Http Components or similar.
Note that if you take the above URL and request it via your browser (a GET) you'll get an XML response back (which you'll need to parse appropriately)

Server did not recognize the value of HTTP Header SOAPAction:

I'm trying to call a SOAP webservice using SAAJ for this WSDL. I submitted the request for this WSDL here http://www.webservicex.net/ws/WSDetails.aspx?WSID=64and it generated the following SOAP requests..
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetGeoIP xmlns="http://www.webservicex.net/">
<IPAddress>string</IPAddress>
</GetGeoIP>
</soap:Body>
</soap:Envelope>
Using SAAJ I generated the same SOAP requests and submitted it but get this error - Server did not recognize the value of HTTP Header SOAPAction: .
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><SOAP-ENV:Header/>
<SOAP-ENV:Body>
<GetGeoIP xmlns="http://www.webservicex.net/">
<IPAddress>SUNW</IPAddress>
</GetGeoIP>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Java Code:
package newpackage;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
public class SOAPClientSAAJ {
public static void main(String args[]) throws Exception {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
String url = "http://www.webservicex.net/geoipservice.asmx";
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// print SOAP Response
System.out.print("Response SOAP Message:");
soapResponse.writeTo(System.out);
soapConnection.close();
}
private static SOAPMessage createSOAPRequest() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://www.w3.org/2001/XMLSchema";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("xsd", serverURI);
SOAPBody body = soapMessage.getSOAPBody();
QName bodyName = new QName("http://www.webservicex.net/", "GetGeoIP" );
SOAPBodyElement bodyElement = body.addBodyElement(bodyName);
QName name = new QName("IPAddress");
SOAPElement symbol = bodyElement.addChildElement(name);
symbol.addTextNode("SUNW");
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}
}
Add
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", "http://www.webservicex.net/" + "GetGeoIP");
If you are using Marshelling and Unmarsheling, Just implement WebseviceMessageCallback interface like:
public class SOAPConnector extends WebServiceGatewaySupport
{
public Object callWebService( String url, Object request )
{
return getWebServiceTemplate().marshalSendAndReceive( url, request,
webServiceMessage -> {
(( SoapMessage )webServiceMessage).setSoapAction(
"https://www.w3schools.com/xml/CelsiusToFahrenheit" );
} );
}
}
Otherwise proceed with: https://stackoverflow.com/a/26253141/6097074

How to request from a SOAP webservice, convert the SOAP response to XML and compare it to another SOAP response, in JAVA

i am completely new in doing this 3 steps, so can you please help me step by step. (I understand Java language, did couple of scripts here and there but never touched SOAP stuff).
I need to do this:
1) Request from two SOAP services and store the responses in two objects.
2) Transform the response in XML(maybe, maybe not, depends if the output is in the form
< tag>< /tag>
then no transformation required, but if it is
< n32:tag>< n32:tag>
then i will want to get rid of "n32".
3) Compare those two responses and see where is the difference at node/tag and maybe inside tag level (maybe using XMLUnit)
4) Report the differences, in console.(not as an error in JUnit).
Thanks!
Since you have the webservice endpoint, I sugest you to create webservice clients for each service.
You can do it with wsimport, that already comes with JDK:
wsimport.bat -d "D:\WS" -keep -verbose endpoint_ws.wsdl
pause
After this command, you will have java objects to access the webservice.
Put these objects in your project and access the webservice.
Here a reference on how to do:
JAXWS
Now that you have objects of the responses, you could code and compare each property.
If there's a need to transform these objects into xml again for comparison (I say again because the SOAP message is already xml), you could use xstream (http://x-stream.github.io/tutorial.html).
EDITED
If you don't need to deal with the java client objects, you could follow this post:
How to do a SOAP Web Service call from Java class?
In the second part of the post, is shown how to interact directly with the request/response messages:
import javax.xml.soap.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class SOAPClientSAAJ {
/**
* Starting point for the SAAJ - SOAP Client Testing
*/
public static void main(String args[]) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
String url = "http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx";
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// Process the SOAP Response
printSOAPResponse(soapResponse);
soapConnection.close();
} catch (Exception e) {
System.err.println("Error occurred while sending SOAP Request to Server");
e.printStackTrace();
}
}
private static SOAPMessage createSOAPRequest() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://ws.cdyne.com/";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("example", serverURI);
/*
Constructed SOAP Request Message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:example="http://ws.cdyne.com/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<example:VerifyEmail>
<example:email>mutantninja#gmail.com</example:email>
<example:LicenseKey>123</example:LicenseKey>
</example:VerifyEmail>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
*/
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("VerifyEmail", "example");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("email", "example");
soapBodyElem1.addTextNode("mutantninja#gmail.com");
SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("LicenseKey", "example");
soapBodyElem2.addTextNode("123");
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "VerifyEmail");
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message = ");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}
/**
* Method used to print the SOAP Response
*/
private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Source sourceContent = soapResponse.getSOAPPart().getContent();
System.out.print("\nResponse SOAP Message = ");
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
}
}
EDITED
To create a soap message directly from a string, first create a InputStream
InputStream is = new ByteArrayInputStream(send.getBytes());
SOAPMessage request = MessageFactory.newInstance().createMessage(null, is);
More info:
How to convert a string to a SOAPMessage in Java?

Error during parsing of SOAP header when calling PI service

I have to call a Webservice with SOAP. I have made a client in Java that produces the following SOAPMessage:
<?xml version="1.0" encoding="utf-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:abc="http://company.com/SAMPLE/ABC">
<SOAP-ENV:Header />
<SOAP-ENV:Body>
<abc:genXX>
<ServiceRequestID>111</ServiceRequestID>
<Code>328630962</Code>
</abc:genXX>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
That call produces Error during parsing of SOAP when I call it inside my application:
<SOAP:Header>
</SOAP:Header>
<SOAP:Body>
<SOAP:Fault xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<faultcode>SOAP:Client</faultcode>
<faultstring>Error during parsing of SOAP header</faultstring>
<faultactor>http://sap.com/xi/XI/Message/30</faultactor>
<detail>
<SAP:Error SOAP:mustUnderstand="1"
xmlns:SAP="http://sap.com/xi/XI/Message/30">
<SAP:Category>XIProtocol</SAP:Category>
<SAP:Code area="PARSER" />
<SAP:P1 />
<SAP:P2 />
<SAP:P3 />
<SAP:P4 />
<SAP:AdditionalText />
<SAP:Stack>System error in parser
</SAP:Stack>
</SAP:Error>
</detail>
</SOAP:Fault>
</SOAP:Body>
</SOAP:Envelope>
But when I call it with the same computer with SOAP UI the webservice responds well. The client in my application is made this way:
public void callWebservice(String serviceRequestID, String code) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory =
SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
URLEndpoint url = new URLEndpoint ("http://company.com:50000/");
SOAPMessage soapResponse = soapConnection.call(
createSOAPRequest(serviceRequestID, code), url);
{...}
soapConnection.close();
} catch (Exception e) {
//
}
private SOAPMessage createSOAPRequest(String serviceRequestID,
String code) throws SOAPException{
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://company.com/SAMPLE/ABC";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("abc", serverURI);
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("genXXX", "abc");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("ServiceRequestID");
SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("Code");
soapBodyElem1.addTextNode(serviceRequestID);
soapBodyElem2.addTextNode(code);
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI );
String loginPassword = "USER:PASSWORD";
headers.addHeader("Authorization", "Basic " + new
String(Base64.encodeBase64(loginPassword.getBytes())));
soapMessage.saveChanges();
return soapMessage;
}
}
I have checked header and authentication and it is right. If I change the user or password the Webservice respondos with a 401 Unauthorized so I think the header is sent as expected.
Do you have any clue on what's causing the error inside my application?
You are calling a web service in SAP PI (SAP Process Integration). I work as a PI developer and it is possible to use a SAP proprietary protocol over SOAP called XI protocal that is useful in SAP-SAP scenarios. If this service should be accessed by a non SAP system it should probably be changed to regular SOAP 1.1 protocol. Talk to the PI team.
A couple of years late to the party, but because I ran into pretty much the same issue today, here's the solution:
In order to communicate via SOAP 1.1 protocol as Richard L suggested, change your "SOAPAction" header to "http://sap.com/xi/WebService/soap1.1"
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", "http://sap.com/xi/WebService/soap1.1");
That did the trick for me.

Categories