-
-
Save luisbandalap/21698dd3197f01e0527b28dbab6d889b to your computer and use it in GitHub Desktop.
A simple SOAP Client class to send request body to a SOAP Server. Useful when you want to test a SOAP server and you don't want to generate all SOAP client class from the WSDL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.kdstudio.snippets.soap.client; | |
import java.io.ByteArrayInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import javax.xml.parsers.DocumentBuilderFactory; | |
import javax.xml.parsers.ParserConfigurationException; | |
import javax.xml.soap.MessageFactory; | |
import javax.xml.soap.MimeHeaders; | |
import javax.xml.soap.SOAPBody; | |
import javax.xml.soap.SOAPConnection; | |
import javax.xml.soap.SOAPConnectionFactory; | |
import javax.xml.soap.SOAPConstants; | |
import javax.xml.soap.SOAPElement; | |
import javax.xml.soap.SOAPEnvelope; | |
import javax.xml.soap.SOAPException; | |
import javax.xml.soap.SOAPHeader; | |
import javax.xml.soap.SOAPMessage; | |
import javax.xml.soap.SOAPPart; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import org.w3c.dom.Document; | |
import org.xml.sax.SAXException; | |
/** | |
* This is an example of a simple SOAP Client class to send request body to a | |
* SOAP Server. | |
* | |
* Useful when you want to test a SOAP server and you don't want to generate all | |
* SOAP client class from the WSDL. | |
* | |
* @author kdelfour | |
* @modified luisbandalap | |
*/ | |
public final class ASimpleSOAPClient { | |
// Default logger | |
private static final Logger LOGGER = LoggerFactory.getLogger(ASimpleSOAPClient.class); | |
private static final SOAPConnectionFactory SOAPCONNECTIONFACTORY; | |
private static final String AGENT_HEADER_NAME = "User-Agent"; | |
private static final String SOAPACTION_HEADER_NAME = "SOAPAction"; | |
private static final String AGENT_STRING = "Java/ASimpleSOAPClient-2.0"; | |
static { | |
try { | |
synchronized (ASimpleSOAPClient.class) { | |
SOAPCONNECTIONFACTORY = SOAPConnectionFactory.newInstance(); | |
} | |
} catch (UnsupportedOperationException | SOAPException ex) { | |
LOGGER.error("Error when connection factory was created", ex); | |
throw new RuntimeException("Error when connection factory was created", ex); | |
} | |
} | |
// The SOAP server URI | |
private final String uriSOAPServer; | |
private final String uriSOAPAction; | |
private final String SOAPProtocol; | |
// The SOAP connection | |
private final SOAPConnection soapConnection; | |
// Factories | |
private final MessageFactory messageFactory; | |
private final DocumentBuilderFactory builderFactory; | |
// Custom namespaces and headers definitions | |
private final Map<String, String> envelopeNamespaces; | |
private final Map<String, String> headerNamespaces; | |
private final Map<String, String> bodyNamespaces; | |
private final Map<String, List<String>> defaultHttpHeaders; | |
/** | |
* A constructor who create a SOAP connection | |
* | |
* @param url the SOAP server URI | |
*/ | |
public ASimpleSOAPClient(final String url) { | |
this(url, null, null); | |
} | |
/** | |
* A constructor who create a SOAP connection | |
* | |
* @param url the SOAP server URI | |
* @param operation the SOAP Action | |
*/ | |
public ASimpleSOAPClient(final String url, final String operation) { | |
this(url, operation, null); | |
} | |
/** | |
* A constructor who create a SOAP connection | |
* | |
* @param url the SOAP server URI | |
* @param operation the SOAP Action | |
* @param soapProtocol the SOAP protocol version | |
*/ | |
public ASimpleSOAPClient(final String url, final String operation, final String soapProtocol) { | |
//We set properties | |
this.uriSOAPServer = url; | |
this.uriSOAPAction = operation; | |
this.envelopeNamespaces = new HashMap<>(); | |
this.headerNamespaces = new HashMap<>(); | |
this.bodyNamespaces = new HashMap<>(); | |
this.defaultHttpHeaders = new HashMap<>(); | |
final String settedProtocol = soapProtocol != null ? soapProtocol : SOAPConstants.SOAP_1_1_PROTOCOL; | |
switch (settedProtocol) { | |
case SOAPConstants.SOAP_1_1_PROTOCOL: | |
case SOAPConstants.SOAP_1_2_PROTOCOL: | |
SOAPProtocol = settedProtocol; | |
break; | |
default: | |
throw new RuntimeException(soapProtocol + " is not a valid SOAP protocol version"); | |
} | |
//We create the XML document factory | |
builderFactory = DocumentBuilderFactory.newInstance(); | |
builderFactory.setNamespaceAware(true); | |
//We create the SOAP Connection and the Message Factory | |
try { | |
soapConnection = SOAPCONNECTIONFACTORY.createConnection(); | |
messageFactory = MessageFactory.newInstance(this.SOAPProtocol); | |
} catch (Exception e) { | |
LOGGER.error("Error when endpoint was created", e); | |
throw new RuntimeException("Error when endpoint was created", e); | |
} | |
} | |
/** | |
* Send a SOAP request for a specific operation | |
* | |
* @param xmlRequestBody the body of the SOAP message | |
* @param xmlRequestHeader the header for your SOAP message | |
* @param operation the operation from the SOAP server invoked | |
* @param customHttpHeaders | |
* @return a response from the server | |
* @throws SOAPException | |
* @throws ParserConfigurationException | |
* @throws IOException | |
* @throws SAXException | |
*/ | |
public SOAPMessage sendMessageToSOAPServer(final String xmlRequestBody, final String xmlRequestHeader, final String operation, final Map<String, List<String>> customHttpHeaders) | |
throws SOAPException, SAXException, IOException, ParserConfigurationException { | |
// Send SOAP Message to SOAP Server | |
final SOAPElement soapBody = stringToSOAPElement(xmlRequestBody); | |
final SOAPElement soapHeader = xmlRequestHeader != null ? stringToSOAPElement(xmlRequestHeader) : null; | |
final SOAPMessage soapRequest = createSOAPRequest(soapBody, soapHeader, operation, customHttpHeaders); | |
final SOAPMessage soapResponse = soapConnection.call(soapRequest, uriSOAPServer); | |
// Print SOAP Response | |
LOGGER.info("Response SOAP Message : " + soapResponse.toString()); | |
return soapResponse; | |
} | |
public SOAPMessage sendMessageToSOAPServer(String xmlRequestBody, String xmlRequestHeader, final Map<String, List<String>> customHttpHeaders) | |
throws SOAPException, SAXException, IOException, ParserConfigurationException { | |
return sendMessageToSOAPServer(xmlRequestBody, xmlRequestHeader, uriSOAPAction, customHttpHeaders); | |
} | |
public SOAPMessage sendMessageToSOAPServer(final Document bodyDocument, final Document headerDocument, final String operation, final Map<String, List<String>> customHttpHeaders) | |
throws SOAPException, SAXException, IOException, ParserConfigurationException { | |
// Send SOAP Message to SOAP Server | |
final SOAPElement soapBody = documentToSOAPElement(bodyDocument); | |
final SOAPElement soapHeader = headerDocument != null ? documentToSOAPElement(headerDocument) : null; | |
final SOAPMessage soapRequest = createSOAPRequest(soapBody, soapHeader, operation, customHttpHeaders); | |
final SOAPMessage soapResponse = soapConnection.call(soapRequest, uriSOAPServer); | |
// Print SOAP Response | |
LOGGER.info("Response SOAP Message : " + soapResponse.toString()); | |
return soapResponse; | |
} | |
public SOAPMessage sendMessageToSOAPServer(final Document bodyDocument, final Document bodyHeader, final Map<String, List<String>> customHttpHeaders) | |
throws SOAPException, SAXException, IOException, ParserConfigurationException { | |
return sendMessageToSOAPServer(bodyDocument, bodyHeader, uriSOAPAction, customHttpHeaders); | |
} | |
/** | |
* Create a SOAP request | |
* | |
* @param body the body of the SOAP message | |
* @param header the header for your SOAP message | |
* @param operation the operation from the SOAP server invoked | |
* @return the SOAP message request completed | |
* @throws SOAPException | |
*/ | |
private SOAPMessage createSOAPRequest(final SOAPElement body, final SOAPElement header, final String operation, final Map<String, List<String>> customHttpHeaders) | |
throws SOAPException { | |
final SOAPMessage soapMessage = messageFactory.createMessage(); | |
final SOAPPart soapPart = soapMessage.getSOAPPart(); | |
// SOAP Envelope | |
final SOAPEnvelope soapEnvelope = soapPart.getEnvelope(); | |
if (envelopeNamespaces != null && !envelopeNamespaces.isEmpty()) { | |
for (final String prefixKey : envelopeNamespaces.keySet()) { | |
final String namespace = envelopeNamespaces.get(prefixKey); | |
soapEnvelope.addNamespaceDeclaration(prefixKey, namespace); | |
} | |
} | |
// SOAP Header | |
final SOAPHeader soapHeader = soapEnvelope.getHeader(); | |
if (headerNamespaces != null && !headerNamespaces.isEmpty()) { | |
for (final String prefixKey : headerNamespaces.keySet()) { | |
final String namespace = headerNamespaces.get(prefixKey); | |
soapHeader.addNamespaceDeclaration(prefixKey, namespace); | |
} | |
} | |
if (header != null) { | |
soapHeader.addChildElement(header); | |
} | |
// SOAP Body | |
final SOAPBody soapBody = soapEnvelope.getBody(); | |
if (bodyNamespaces != null && !bodyNamespaces.isEmpty()) { | |
for (final String prefixKey : bodyNamespaces.keySet()) { | |
final String namespace = bodyNamespaces.get(prefixKey); | |
soapBody.addNamespaceDeclaration(prefixKey, namespace); | |
} | |
} | |
soapBody.addChildElement(body); | |
// Mime Headers | |
final MimeHeaders headers = soapMessage.getMimeHeaders(); | |
for (final String headKey : defaultHttpHeaders.keySet()) { | |
final List<String> headValues = defaultHttpHeaders.get(headKey); | |
if (headers.getHeader(headKey) != null && headers.getHeader(headKey).length > 0) { | |
headers.removeHeader(headKey); | |
} | |
for (final String headValue : headValues) { | |
headers.addHeader(headKey, headValue); | |
} | |
} | |
if (customHttpHeaders != null && !customHttpHeaders.isEmpty()) { | |
for (final String headKey : customHttpHeaders.keySet()) { | |
final List<String> headValues = customHttpHeaders.get(headKey); | |
if (headers.getHeader(headKey) != null && headers.getHeader(headKey).length > 0) { | |
headers.removeHeader(headKey); | |
} | |
for (final String headValue : headValues) { | |
headers.addHeader(headKey, headValue); | |
} | |
} | |
} | |
//We set operation if it is not set from http headers | |
if (operation != null) { | |
if (headers.getHeader(SOAPACTION_HEADER_NAME) != null && headers.getHeader(SOAPACTION_HEADER_NAME).length > 0) { | |
headers.removeHeader(SOAPACTION_HEADER_NAME); | |
} | |
headers.addHeader(SOAPACTION_HEADER_NAME, operation); | |
} | |
//We set user-agent if it is not set from http headers | |
if (!defaultHttpHeaders.containsKey(AGENT_HEADER_NAME)) { | |
headers.removeHeader(AGENT_HEADER_NAME); | |
headers.addHeader(AGENT_HEADER_NAME, AGENT_STRING); | |
} | |
soapMessage.saveChanges(); | |
return soapMessage; | |
} | |
/** | |
* Transform a String to a SOAP element | |
* | |
* @param xmlRequestBody the string body representation | |
* @return a SOAP element | |
* @throws SOAPException | |
* @throws SAXException | |
* @throws IOException | |
* @throws ParserConfigurationException | |
*/ | |
private SOAPElement stringToSOAPElement(final String xmlRequestBody) | |
throws SOAPException, SAXException, IOException, ParserConfigurationException { | |
// Load the XML text into a DOM Document | |
try (final InputStream stream = new ByteArrayInputStream(xmlRequestBody.getBytes());) { | |
final Document doc = builderFactory.newDocumentBuilder().parse(stream); | |
// This returns the SOAPBodyElement that contains ONLY the Payload | |
return documentToSOAPElement(doc); | |
} | |
} | |
private SOAPElement documentToSOAPElement(final Document document) | |
throws SOAPException, SAXException, IOException, | |
ParserConfigurationException { | |
// Use SAAJ to convert Document to SOAPElement | |
// Create SoapMessage | |
final SOAPMessage message = messageFactory.createMessage(); | |
final SOAPBody soapBody = message.getSOAPBody(); | |
// This returns the SOAPBodyElement that contains ONLY the Payload | |
return soapBody.addDocument(document); | |
} | |
public String getUriSOAPServer() { | |
return uriSOAPServer; | |
} | |
public String getUriSOAPAction() { | |
return uriSOAPAction; | |
} | |
public Map<String, String> getEnvelopeNamespaces() { | |
return envelopeNamespaces; | |
} | |
public Map<String, String> getHeaderNamespaces() { | |
return headerNamespaces; | |
} | |
public Map<String, String> getBodyNamespaces() { | |
return bodyNamespaces; | |
} | |
public Map<String, List<String>> getDefaultHttpHeaders() { | |
return defaultHttpHeaders; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>com.dkstudio</groupId> | |
<artifactId>snippets</artifactId> | |
<version>0.0.2-SNAPSHOT</version> | |
<name>Simple SOAP Client</name> | |
<description>A simple SOAP Client class to send request body to a SOAP Server. | |
Useful when you want to test a SOAP server and you don't want to generate all SOAP client class from the WSDL.</description> | |
<developers> | |
<developer> | |
<id>delfour.k</id> | |
<name>Kevin DELFOUR</name> | |
<email>[email protected]</email> | |
<organization>DK</organization> | |
<organizationUrl>http://kevin.delfour.eu</organizationUrl> | |
</developer> | |
</developers> | |
<organization> | |
<name>DK</name> | |
<url>http://kevin.delfour.eu</url> | |
</organization> | |
<properties> | |
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
<project.build.sourceVersion>1.7</project.build.sourceVersion> | |
</properties> | |
<dependencies> | |
<dependency> | |
<groupId>log4j</groupId> | |
<artifactId>log4j</artifactId> | |
<version>1.2.17</version> | |
</dependency> | |
</dependencies> | |
</project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Now it's not that simple but i'll cover some generic usage like adding custom http headers and namespaces.