|
|
|
REST to SOAP extension
The REST to SOAP extension provides a way to make REST-style request to an external SOAP service using the Connection API.
When using the extension, the application can work with JSON-formatted request and response bodies and the REST to SOAP extension manages the conversion two and from SOAP. The SOAP request is then forwarded to the SOAP service using either HTTP or HTTPS.
To use the REST to SOAP extension, your application must include the zero.connection.soap dependency. This dependency includes a connection handler and soap protocol that can be configured for use with the connection infrastructure.
For an overview of the Connection API and related concepts, see Calling a remote resource.
Configuration
The following destination configuration contains an example configuration for the REST to SOAP extension.
/config/connection/destinations += [{
"name" : "/MyService/*",
"handlers" : [{
"class" : "zero.connection.soap.REST2SOAPHandler",
"config" : {
"endpointAddress" : "http://a.server/someSOAPService",
"SOAPVersion" : "1.2",
"r2sMapping" : [{
"RESTOperation" : "GET",
"URLMatch" : "/MyService/{id}",
"SOAPBodyTemplate" : "mySOAPBodyContents.gt",
"SOAPHeaderTemplate" : "mySOAPHeaderContents.gt",
"SOAPAction" : "http://some.action/"
}]
}
}]
}]
The following configuration properties are used in the above configuration:
- endpointAddress (required)
- Specifies the HTTP or HTTPS address URL of the SOAP service to be invoked.
- SOAPVersion (optional)
- Specifies the version of SOAP to be used when producing the SOAP message. Valid values are
1.1 and 1.2. If not specified, the version defaults to 1.1.
- r2sMapping (required)
- Specifies a list of REST to SOAP mapping configurations. Each entry may contain:
-
- RESTOperation (required)
- Specifies the REST operation being mapped;
GET, POST, PUT, DELETE or HEAD.
-
- URLMatch (optional)
- Defines a pattern to be used to match against the URL for the REST request. The success of the match, is used in conjunction with the
RESTOperation value to determine whether or not this r2sMapping should be used.
-
- SOAPBodyTemplate (required)
- Defines the name of the template to be used to render the contents of the SOAP request body.
-
- SOAPHeaderTemplate (optional)
- Defines the name of the template to be used to render the contents of the SOAP request headers.
-
- SOAPAction (optional)
- Defines the value of the
SOAPAction used in the SOAP request. If using SOAP 1.1 this value is sent using a SOAPAction HTTP header. If using SOAP 1.2, this value forms part of the HTTP Content-Type header.
The syntax for the URLMatch pattern is the same as the "==" condition operation (see Condition operators). The named groups, (e.g. {id}) are made available to the templates used to render the SOAP headers and body.
For more information about connection destination configuration and processing, see Configuring destinations.
Request processing
The REST to SOAP extension builds SOAP requests by rendering the named templates. Different templates can be used to producing the contents of the SOAP Body element and the SOAP Header element in the SOAP request envelope. The body template is required, the header template is optional.
The body template is responsible for producing the XML to go in the body of the SOAP envelope. It should not include the body element itself. Likewise, the header template should not include the header element. For example a SOAP 1.1 message is built up as follows:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
OUTPUT_FROM_HEADER_TEMPLATE_RENDERING
</soapenv:Header>
<soapenv:Body>
OUTPUT_FROM_BODY_TEMPLATE_RENDERING
</soapenv:Body>
</soapenv:Envelope>
</verbatim>
Accessing REST request information in the template
When the REST to SOAP extension renders the SOAP body or SOAP header templates, it makes data from the REST request available to the template via the GlobalContext. The following attributes are available:
| Key | Type | Description |
/connection/r2s/body | Map | If the body of the REST request is a JSON-formatted string, a Map representation of is available at this location. |
/connection/r2s/params | Map<String, String[]> | Includes parameters from query string, form-encoded parameters (POST) and named group matches from the URLMatch configuration. |
The following helper functions are also bound for Groovy scripts and Groovy templates:
| Method | Description |
r2s_getParam(String name) | Returns the value of the named parameter or null if the parameter does not exist. If more than one value exists for the named parameter, the first value is returned. |
r2s_getParam(String name, int n) | Returns the value at the index specified within the named parameter or null if such a value does not exist. The index is zero based. |
r2s_existsParam(String name) | Returns true if a parameter of the given name exists, false otherwise. |
r2s_countParam(String name) | Returns the number of values that exist for the named parameter. |
r2s_getJSONValue(String jsonPath) | Returns the value found at the given path within the JSON body. Returns null if no such value exists. |
r2s_existsJSONValue(String jsonPath) | Returns true if a value exists for the given path within the JSON body, false otherwise. |
r2s_countJSONValue(String jsonPath) | Returns the number of values that exist for the given path within the JSON body. |
Overriding configuration values in templates
The REST to SOAP extension supports users overriding certain configuration values during the processing of their body or header template. The following parameters can be overridden by adding code to your template that sets values for the specified keys in the global context:
Dealing with whitespace
When a template is rendered, unintentional whitespace can be introduced into the rendered output. To avoid problems with whitespace in the rendered SOAP message, the REST2SOAP mediation strips out all whitespace in the following way:
- Carriage return, line feed and tab characters are removed.
- A series of two or more whitespace characters found within an open or close element tag will be reduced to a single space character.
- Any whitespace found before or after a word/number/sentence within an element value is removed.
This is shown in the following example:
<ns0:Example xmlns:ns0="http://ns">
<A>Hello </A>
<B>
Goodbye</B>
</ns0:Example>
And this becomes:
<ns0:Example xmlns:ns0="http://ns"><A>Hello</A><B>Goodbye</B></ns0:Example>
If you have a requirement to maintain whitespace that would otherwise be removed, you can use the following markup in your template:
[- <i>any text</i> -]
All whitespace characters in the rendered template found between [- and -] are maintained. For example:
<ns0:Example xmlns:ns0="http://ns">
<A>[-Hello -]</A>
<B>Goodbye</B>
</ns0:Example>
The above example is rendered as:
<ns0:Example xmlns:ns0="http://ns"><A>Hello </A><B>Goodbye</B></ns0:Example>
Response processing
The REST to SOAP extension converts the XML from the body of the SOAP response into a JSON representation, using the JSON4J XMLtoJSONTransformer. The conversion converts XML elements and attributes to JSON parameters of the same name. Name space information is not included the resulting JSON text. Multiple elements of the same name are mapped to JSON array entries.
Example usage
This example demonstrates using the REST to SOAP extension in the invocation of the area conversion service hosted by WebserviceX.NET. It uses number of the parameter handling mechanisms mentioned above to give an idea of what is possible. In reality you would probably choose to include all the required data in just the JSON body or just the URL query string of the REST request for such a simple service.
The configuration
To begin with, let's look at the configuration we will use:
/config/connection/destinations += [{
"name" : "http://localhost:8080/Area/*",
"handlers" : [{ "class" : "zero.connection.soap.REST2SOAPHandler",
"config" : {
"endpointAddress" : "http://www.webservicex.net/ConvertArea.asmx",
"SOAPVersion" : "1.1",
"r2sMapping" : [{
"RESTOperation" : "POST",
"SOAPBodyTemplate" : "changeArea.gt",
"URLMatch" : "/Area/{toUnit}",
"SOAPAction" : "http://www.webserviceX.NET/ChangeAreaUnit"
}]
}
}]
}]
It is worth noting the following in this example:
- The destination
name value will result in requests with target URLs starting with http://localhost:8080/Area/ will be matched to this destination.
- The
URLMatch dictates that for the single r2sMapping to be matched, the target URL will need to be of the form http://localhost:8080/Area/<some_value> where <some_value> will be become the value of a parameter named toUnit.
The body template
In order to show the three types of REST data available to the templates ,this example uses a REST request URL of the form
http://localhost:8080/Area/<Unit_to_convert_to>?amount=<Amount_to_convert>
and requires that the body of the REST request be a JSON object containing an array named units which contains the names of units to convert to.
Given this request specification, we can construct a Groovy template for the SOAP body as follows:
<ChangeAreaUnit xmlns="http://www.webserviceX.NET/">
<AreaValue><%= r2s_getParam("amount") %></AreaValue>
<fromAreaUnit><%= r2s_getJSONValue("/units/2") %></fromAreaUnit>
<toAreaUnit><%= r2s_getParam("toUnit") %></toAreaUnit>
</ChangeAreaUnit>
This template uses REST request data in the following way:
| XML element | REST request data |
AreaValue | amount parameter from query string |
fromAreaUnit | The third unit value from the units array in the JSON body |
toAreaUnit | toUnit parameter matched from the REST request URL by URLMatch |
Invocation of the mediation
The following Goovy handler code demonstrates using the example mediation to convert 5 acres into hectares:
import zero.core.connection.*;
def onGET() {
String json = "{ \"units\": [ \"acre\", \"centaire\", \"hectare\", \"squaremeter\" ] }";
Connection conn = new Connection("http://localhost:8080/Area/acre?amount=5.0", Connection.Operation.POST);
conn.addRequestHeader("Content-Type", "application/json");
conn.setRequestBody(json);
Connection.Response response = conn.getResponse();
request.writer.println(response.getResponseBodyAsString());
}
The result of running this handler should be:
{"ChangeAreaUnitResponse":{"ChangeAreaUnitResult":"12.355269141746666"}}
Configuring the HTTP or HTTPS connection
The REST to SOAP extension introduces a soap protocol to the connection infrastructure and uses it to send a SOAP envelope using a HTTP or HTTPS connection.
The soap protocol supports the same configuration parameters as the http and https protocols used when making direct HTTP or HTTPS requests using the Connection API but must be configured separately. For more information on the protocol configuration parameters supported, see HTTP and HTTPS protocols.
For example, to consider the following REST to SOAP configuration which needs to contact the SOAP endpoint using the HTTPS protocol:
/config/connection/destinations += [{
"name" : "/MyService/*",
"handlers" : [{
"class" : "zero.connection.soap.REST2SOAPHandler",
"config" : {
"endpointAddress" : "https://a.server/someSOAPService",
"SOAPVersion" : "1.2",
"r2sMapping" : [{
"RESTOperation" : "GET",
"URLMatch" : "/MyService/{id}",
"SOAPBodyTemplate" : "mySOAPBodyContents.gt",
"SOAPHeaderTemplate" : "mySOAPHeaderContents.gt",
"SOAPAction" : "http://some.action/"
}]
}
}]
}]
A second destination configuration is used to configure the soap protocol for the https://a.server/someSOAPService destination, for example:
/config/connection/destinations += [{
"name" : "https://a.server/someSOAPService",
"connection" : {
"protocol" : "soap",
"config" : {
"httpsConfig" : "myHttpsConfigurationName"
}
}]
This configuration will allow the SOAP service endpoint to be contacted using the HTTPS configuration called myHttpsConfigurationName and configured under /config/connection/https.
|