We exported an ESB service as a web service in the previous section. Let us now invoke that web service with another ESB service.
esbcontent/META-INF/jboss-esb.xml
file in Source mode.service
definition to the <services>
tag.<service category="Chapter8Sample" description="" name="Chapter8WSClient"> <listeners> <jms-listener busidref="Chapter8EsbChannel2" name="Chapter8EsbListener"/> </listeners> <actions mep="RequestResponse"> <action name="requestAction" class="org.jboss.soa.esb.samples.chapter8.MyRequestAction"/> <action class="org.jboss.soa.esb.actions.soap.SOAPClient" name="soapui-client-action"> <property name="wsdl" value="http://localhost:8080/Chapter8/ebws/Chapter8Sample/Chapter8Service?wsdl"/> <property name="SOAPAction" value="Chapter8ServiceOp"/> </action> </actions> </service>
src
folder, expand it till the SendEsbMessage.java
file is displayed in the tree. Now click Run | Run As | Java Application:INFO [STDOUT] (Thread-46) Progress: 1 - Caching definition from url [http://localhost:8080/Chapter8/ebws/Chapter8Sample/Chapter8Service?wsdl] ...
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'><env:Header></env:Header><env:Body><ns2:getAuthorsResponse xmlns:ns2='http://chapter8.samples.esb.soa.jboss.org/'><return>Charles Dickens</return><return>Sir Arthur Conan Doyle</return><return>Dan Brown</return><return>Amish Tripathi</return></ns2:getAuthorsResponse></env:Body></env:Envelope>
We deployed an ESB service with the ability to invoke an external web service. Note that the configuration of the pipeline contains a request mapper called MyRequestAction
, used to convert the incoming message into a Map
for populating the SOAP request template.
Have a look at the webservice_consumer1
quickstart. Examine the configuration and the usage of the MyRequestAction
class.
As mentioned previously the soapUI version of SOAPClient
generates a template based on the WSDL definition for the appropriate service operation, which is then populated from a set of parameters extracted from the current ESB message.
The SOAP parameters for the template are defined within a map that resides in the payload location of the ESB message, the keys of the map entries specifying the template location of their associated values. There are two choices when specifying values:
processOrder.order.id
would be used to populate the id
element nested within the order
and processOrder
elements.ProcessOrderRequest
, located within the parameter map with a key of processOrder
, would populate the order id by invoking the getOrder().getId()
methods and converting the result to a string.The naming convention used in each choice follows the notation defined as part of the Object-Graph Navigational Language (OGNL) expression language for accessing properties of java objects. See http://incubator.apache.org/ognl/ for more information.
The soapUI codebase creates a template based on the WSDL of the target web service which is then populated using the parameters extracted from the ESB message. This template, and its population, focus on the contents of the SOAP envelope's Body
element but do not support creation of elements within the SOAP envelope's Header
element.
In order to attach SOAP headers to the request it is necessary to transform the populated message before it is sent to the target web service. This can be achieved by including a Smooks transformation in the configuration of the action, using the smooksTransform
parameter.
An example of this configuration is as follows:
<action name="soapui-client-action"
class="org.jboss.soa.esb.actions.soap.SOAPClient">
<property name="wsdl" value="http://localhost:8080/Chapter8/ebws/Chapter8Sample/Chapter8Service?wsdl"/>
<property name="SOAPAction" value="getBooks"/>
<property name="smooksTransform" value="smooks-transform.xml"/>
</action>
Add a Smooks transformation to create SOAP headers as part of the request.
You can see the effect on the resulting request contents by specifying an extra entry into the parameter map, using the dumpSOAP
key. The existence of this key will cause the integration code to display the raw template and the populated template for the request on the server console.
The SOAP response from the web service can be processed in one of three ways, the result of which will be stored as the payload of the resulting ESB message:
In order to return a map containing the contents of the SOAP response message using the OGNL notation it is necessary to configure an additional property on the SOAPClient
action. This property, responseAsOgnlMap
, must be configured with the value true
.
The following is an example of receiving our sample's response as an OGNL map:
<action name="soapui-client-action"
class="org.jboss.soa.esb.actions.soap.SOAPClient">
<property name="wsdl" value="http://localhost:8080/Chapter8/ebws/Chapter8Sample/Chapter8Service?wsdl"/>
<property name="SOAPAction" value="Chapter8ServiceOp"/>
<property name="responseAsOgnlMap" value="true"/>
</action>
Go ahead and set the responseAsOgnlMap
property to true
and see how the response looks on the test Console. Take a look at the webservice_consumer2
quickstart and familiarize yourself with the OGNL notation. Change the request map of the quickstart so that it uses explicit locations instead of an object instance.
XStream (http://xstream.codehaus.org/) is an Open Source library which supports the serialization and deserialization of XML to and from Java Objects. When used through the SOAPClient
it supports the deserialization of the SOAP response into a Java object which is then returned through the ESB message payload.
In order to use the XStream functionality it is necessary to define a responseXStreamConfig
action property containing the appropriate mappings. Here is an example of how our getAuthorsResponse
SOAP envelope can be converted into a List<String>
object.
<action name="soapui-client-action" class="org.jboss.soa.esb.actions.soap.SOAPClient"> <property name="wsdl" value="http://localhost:8080/Chapter8/ebws/Chapter8Sample/Chapter8Service?wsdl"/> <property name="SOAPAction" value="Chapter8ServiceOp"/> <property name="responseXStreamConfig"> <alias name="getAuthorsResponse" class="java.util.ArrayList" namespace="http://chapter8.samples.esb.soa.jboss.org/"/> <alias name="return" class="java.lang.String" namespace=""/> </property> </action>
Go ahead and add the highlighted section above to the sample and see how it changes the response output.
The second SOAPClient
action is based on Wise (Wise Invokes Services Easily), a JBoss Open Source project (http://www.jboss.org/wise) which handles most of the necessary interactions of dealing with the JAX-WS APIs and proxies.
The goal of Wise is to make your life easier by automatically processing a web service's WSDL to generate the client-side proxy classes, select the appropriate services and endpoints, and enable the invocation of the operations by mapping an object model that you define to the JAX-WS objects needed to perform the operation. The result is that you can access a web service without having to generate the classes yourself.
A typical configuration sample would be like this:
<action name="soap-wise-client-action" class="org.jboss.soa.esb.actions.soap.wise.SOAPClient"> <property name="wsdl" value="http://localhost:8080/Chapter8/ebws/Chapter8Sample/Chapter8Service?wsdl"/> <property name="SOAPAction" value="getBooks"/> </action>