Working Soap client example
To implement simple SOAP clients in Java, you can use the SAAJ framework (it is shipped with JSE 1.6 and above, but removed again in Java 11):
SOAP with Attachments API for Java (SAAJ) is mainly used for dealing directly with SOAP Request/Response messages which happens behind the scenes in any Web Service API. It allows the developers to directly send and receive soap messages instead of using JAX-WS.
See below a working example (run it!) of a SOAP web service call using SAAJ. It calls this web service.
import javax.xml.soap.*;
public class SOAPClientSAAJ {
// SAAJ - SOAP Client Testing
public static void main(String args[]) {
/*
The example below requests from the Web Service at:
http://www.webservicex.net/uszip.asmx?op=GetInfoByCity
To call other WS, change the parameters below, which are:
- the SOAP Endpoint URL (that is, where the service is responding from)
- the SOAP Action
Also change the contents of the method createSoapEnvelope() in this class. It constructs
the inner part of the SOAP envelope that is actually sent.
*/
String soapEndpointUrl = "http://www.webservicex.net/uszip.asmx";
String soapAction = "http://www.webserviceX.NET/GetInfoByCity";
callSoapWebService(soapEndpointUrl, soapAction);
}
private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
SOAPPart soapPart = soapMessage.getSOAPPart();
String myNamespace = "myNamespace";
String myNamespaceURI = "http://www.webserviceX.NET";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI);
/*
Constructed SOAP Request Message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myNamespace="http://www.webserviceX.NET">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<myNamespace:GetInfoByCity>
<myNamespace:USCity>New York</myNamespace:USCity>
</myNamespace:GetInfoByCity>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
*/
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("GetInfoByCity", myNamespace);
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("USCity", myNamespace);
soapBodyElem1.addTextNode("New York");
}
private static void callSoapWebService(String soapEndpointUrl, String soapAction) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), soapEndpointUrl);
// Print the SOAP Response
System.out.println("Response SOAP Message:");
soapResponse.writeTo(System.out);
System.out.println();
soapConnection.close();
} catch (Exception e) {
System.err.println("\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n");
e.printStackTrace();
}
}
private static SOAPMessage createSOAPRequest(String soapAction) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
createSoapEnvelope(soapMessage);
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", soapAction);
soapMessage.saveChanges();
/* Print the request message, just for debugging purposes */
System.out.println("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println("\n");
return soapMessage;
}
}
Yes, if you can acquire any WSDL file, then you can use SoapUI to create mock service of that service complete with unit test requests. I created an example of this (using Maven) that you can try out.
Calculator SOAP service test from SoapUI, Online SoapClient Calculator
Generate the SoapMessage
object form the input SoapEnvelopeXML
and SoapDataXml
.
SoapEnvelopeXML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<tem:Add xmlns:tem="http://tempuri.org/">
<tem:intA>3</tem:intA>
<tem:intB>4</tem:intB>
</tem:Add>
</soapenv:Body>
</soapenv:Envelope>
use the following code to get SoapMessage Object.
MessageFactory messageFactory = MessageFactory.newInstance();
MimeHeaders headers = new MimeHeaders();
ByteArrayInputStream xmlByteStream = new ByteArrayInputStream(SoapEnvelopeXML.getBytes());
SOAPMessage soapMsg = messageFactory.createMessage(headers, xmlByteStream);
SoapDataXml
<tem:Add xmlns:tem="http://tempuri.org/">
<tem:intA>3</tem:intA>
<tem:intB>4</tem:intB>
</tem:Add>
use below code to get SoapMessage Object.
public static SOAPMessage getSOAPMessagefromDataXML(String saopBodyXML) throws Exception {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
dbFactory.setIgnoringComments(true);
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
InputSource ips = new org.xml.sax.InputSource(new StringReader(saopBodyXML));
Document docBody = dBuilder.parse(ips);
System.out.println("Data Document: "+docBody.getDocumentElement());
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
SOAPMessage soapMsg = messageFactory.createMessage();
SOAPBody soapBody = soapMsg.getSOAPPart().getEnvelope().getBody();
soapBody.addDocument(docBody);
return soapMsg;
}
By getting the SoapMessage Object. It is clear that the Soap XML is valid. Then prepare to hit the service to get response. It can be done in many ways.
- Using Client Code Generated form WSDL.
java.net.URL endpointURL = new java.net.URL(endPointUrl);
javax.xml.rpc.Service service = new org.apache.axis.client.Service();
((org.apache.axis.client.Service) service).setTypeMappingVersion("1.2");
CalculatorSoap12Stub obj_axis = new CalculatorSoap12Stub(endpointURL, service);
int add = obj_axis.add(10, 20);
System.out.println("Response: "+ add);
- Using
javax.xml.soap.SOAPConnection
.
public static void getSOAPConnection(SOAPMessage soapMsg) throws Exception {
System.out.println("===== SOAPConnection =====");
MimeHeaders headers = soapMsg.getMimeHeaders(); // new MimeHeaders();
headers.addHeader("SoapBinding", serverDetails.get("SoapBinding") );
headers.addHeader("MethodName", serverDetails.get("MethodName") );
headers.addHeader("SOAPAction", serverDetails.get("SOAPAction") );
headers.addHeader("Content-Type", serverDetails.get("Content-Type"));
headers.addHeader("Accept-Encoding", serverDetails.get("Accept-Encoding"));
if (soapMsg.saveRequired()) {
soapMsg.saveChanges();
}
SOAPConnectionFactory newInstance = SOAPConnectionFactory.newInstance();
javax.xml.soap.SOAPConnection connection = newInstance.createConnection();
SOAPMessage soapMsgResponse = connection.call(soapMsg, getURL( serverDetails.get("SoapServerURI"), 5*1000 ));
getSOAPXMLasString(soapMsgResponse);
}
- Form HTTP Connection Classes
org.apache.commons.httpclient
.
public static void getHttpConnection(SOAPMessage soapMsg) throws SOAPException, IOException {
System.out.println("===== HttpClient =====");
HttpClient httpClient = new HttpClient();
HttpConnectionManagerParams params = httpClient.getHttpConnectionManager().getParams();
params.setConnectionTimeout(3 * 1000); // Connection timed out
params.setSoTimeout(3 * 1000); // Request timed out
params.setParameter("http.useragent", "Web Service Test Client");
PostMethod methodPost = new PostMethod( serverDetails.get("SoapServerURI") );
methodPost.setRequestBody( getSOAPXMLasString(soapMsg) );
methodPost.setRequestHeader("Content-Type", serverDetails.get("Content-Type") );
methodPost.setRequestHeader("SoapBinding", serverDetails.get("SoapBinding") );
methodPost.setRequestHeader("MethodName", serverDetails.get("MethodName") );
methodPost.setRequestHeader("SOAPAction", serverDetails.get("SOAPAction") );
methodPost.setRequestHeader("Accept-Encoding", serverDetails.get("Accept-Encoding"));
try {
int returnCode = httpClient.executeMethod(methodPost);
if (returnCode == HttpStatus.SC_NOT_IMPLEMENTED) {
System.out.println("The Post method is not implemented by this URI");
methodPost.getResponseBodyAsString();
} else {
BufferedReader br = new BufferedReader(new InputStreamReader(methodPost.getResponseBodyAsStream()));
String readLine;
while (((readLine = br.readLine()) != null)) {
System.out.println(readLine);
}
br.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
methodPost.releaseConnection();
}
}
public static void accessResource_AppachePOST(SOAPMessage soapMsg) throws Exception {
System.out.println("===== HttpClientBuilder =====");
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
URIBuilder builder = new URIBuilder( serverDetails.get("SoapServerURI") );
HttpPost methodPost = new HttpPost(builder.build());
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(5 * 1000)
.setConnectionRequestTimeout(5 * 1000)
.setSocketTimeout(5 * 1000)
.build();
methodPost.setConfig(config);
HttpEntity xmlEntity = new StringEntity(getSOAPXMLasString(soapMsg), "utf-8");
methodPost.setEntity(xmlEntity);
methodPost.setHeader("Content-Type", serverDetails.get("Content-Type"));
methodPost.setHeader("SoapBinding", serverDetails.get("SoapBinding") );
methodPost.setHeader("MethodName", serverDetails.get("MethodName") );
methodPost.setHeader("SOAPAction", serverDetails.get("SOAPAction") );
methodPost.setHeader("Accept-Encoding", serverDetails.get("Accept-Encoding"));
// Create a custom response handler
ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
@Override
public String handleResponse( final HttpResponse response) throws ClientProtocolException, IOException {
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status <= 500) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
}
return "";
}
};
String execute = httpClient.execute( methodPost, responseHandler );
System.out.println("AppachePOST : "+execute);
}
Full Example:
public class SOAP_Calculator {
static HashMap<String, String> serverDetails = new HashMap<>();
static {
// Calculator
serverDetails.put("SoapServerURI", "http://www.dneonline.com/calculator.asmx");
serverDetails.put("SoapWSDL", "http://www.dneonline.com/calculator.asmx?wsdl");
serverDetails.put("SoapBinding", "CalculatorSoap"); // <wsdl:binding name="CalculatorSoap12" type="tns:CalculatorSoap">
serverDetails.put("MethodName", "Add"); // <wsdl:operation name="Add">
serverDetails.put("SOAPAction", "http://tempuri.org/Add"); // <soap12:operation soapAction="http://tempuri.org/Add" style="document"/>
serverDetails.put("SoapXML", "<tem:Add xmlns:tem=\"http://tempuri.org/\"><tem:intA>2</tem:intA><tem:intB>4</tem:intB></tem:Add>");
serverDetails.put("Accept-Encoding", "gzip,deflate");
serverDetails.put("Content-Type", "");
}
public static void callSoapService( ) throws Exception {
String xmlData = serverDetails.get("SoapXML");
SOAPMessage soapMsg = getSOAPMessagefromDataXML(xmlData);
System.out.println("Requesting SOAP Message:\n"+ getSOAPXMLasString(soapMsg) +"\n");
SOAPEnvelope envelope = soapMsg.getSOAPPart().getEnvelope();
if (envelope.getElementQName().getNamespaceURI().equals("http://schemas.xmlsoap.org/soap/envelope/")) {
System.out.println("SOAP 1.1 NamespaceURI: http://schemas.xmlsoap.org/soap/envelope/");
serverDetails.put("Content-Type", "text/xml; charset=utf-8");
} else {
System.out.println("SOAP 1.2 NamespaceURI: http://www.w3.org/2003/05/soap-envelope");
serverDetails.put("Content-Type", "application/soap+xml; charset=utf-8");
}
getHttpConnection(soapMsg);
getSOAPConnection(soapMsg);
accessResource_AppachePOST(soapMsg);
}
public static void main(String[] args) throws Exception {
callSoapService();
}
private static URL getURL(String endPointUrl, final int timeOutinSeconds) throws MalformedURLException {
URL endpoint = new URL(null, endPointUrl, new URLStreamHandler() {
protected URLConnection openConnection(URL url) throws IOException {
URL clone = new URL(url.toString());
URLConnection connection = clone.openConnection();
connection.setConnectTimeout(timeOutinSeconds);
connection.setReadTimeout(timeOutinSeconds);
//connection.addRequestProperty("Developer-Mood", "Happy"); // Custom header
return connection;
}
});
return endpoint;
}
public static String getSOAPXMLasString(SOAPMessage soapMsg) throws SOAPException, IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapMsg.writeTo(out);
// soapMsg.writeTo(System.out);
String strMsg = new String(out.toByteArray());
System.out.println("Soap XML: "+ strMsg);
return strMsg;
}
}
@See list of some WebServices at http://sofa.uqam.ca/soda/webservices.php