Publishing a SOAP API
Mule runtime engine version 3.8 reached its End of Life on November 16, 2021. For more information, contact your Customer Success Manager to determine how to migrate to the latest Mule version. |
Mule runtime leverages the Apache open-source CXF framework to build APIs. You can create a CXF API in Studio by configuring a CXF component in your Mule flow to perform any of the following CXF operations related to publishing a SOAP API:
-
publish a simple service
-
publish a JAX-WS service
-
proxy a published service
Using the Mule CXF Component, you can also enable WS-security, specify data bindings, and add interceptors to your CXF API.
When sending requests to an external web service, using the Web Service Consumer instead of the CXF Module is recommended.
Basic Anatomy
Exposing a SOAP API through a Mule application requires these elements:
-
An endpoint that receives requests and sends responses
-
A CXF Component that references and exposes the WSDL file
-
A component or a combination of components that performs the operations the API supports, such as retrieving data and updating data in a database.
Endpoint Element
The endpoint receives requests and sends responses, both containing XML SOAP envelopes. Typically, the endpoint is HTTP, HTTPS, JMS, or VM.
CXF component
A SOAP API needs to expose its contract through a WSDL file. Access the contents of this file by adding ?wsdl
to the API’s URL when performing a request.
Through CXF, you present a WSDL contract using one of the following methods:
-
WSDL-first: start with a WSDL file that you created yourself, import it into your Mule project, then reference its location from the CXF component.
-
Code-first: start with an annotated Java class, then have JAX-WS compile a WSDL file based upon it.
The CXF component is implemented as annotations on Java classes. There is a direct relationship between the WSDL structure and the Java annotations needed. When you use a WSDL, Java POJOs are generated with the correct annotations. You can also force an existing Java POJO to adhere to a WSDL spec. Studio can also create flows to act as SOAP clients.
Regardless of the method you use, you can instruct the CXF component to verify the validity of incoming requests against the WSDL.
Through the CXF component you select one of the following operation types:
-
Proxy Service: Using this service, you deal with XML directly in your flow. Using a proxy service performs fewer transformations and responds faster than alternative operation types. Use it under the following conditions:
-
To edit the XML directly.
-
To use with XSLT.
-
To use with DataMapper to map fields.
-
You click the CXF component and select Proxy service in the Operations drop-down of the property editor.
-
JAX-WS: Converts the payload into a POJO. You can access attributes in the POJO in your flow. Use it under the following conditions:
-
You are comfortable working with Java objects.
-
You need to construct POJO or JSON outputs.
-
You are using Community runtime and can’t employ Dataweave.
-
You want to present the WSDL through a Code-first approach (the proxy service uses only WSDL-first).
-
The third option, Simple service, can be used if you are using a simple service pattern that is not covered here.
One or More Processing Components
With the other two components in place, the flow is ready to process requests and perform the business logic that makes up your API. The API could potentially fit into a single Java class, but more likely includes the use of several elements, such as flow controls, transformers, and HTTP calls to Web services.
Building a WSDL-First Proxy Service API
To build a WSDL-First Proxy Service API you need to create the WSDL you intend to use for your SOAP API. Some of the steps involved in building this service are:
Studio
-
Import a WSDL file into your project.
-
Select File > Import.
-
Select General > File System.
-
Select the WSDL file from your file system, then, in the Into Folder field, select
src/main/resources
. -
Click Finish.
-
-
Drag and drop an HTTP listener and a CXF component into a new flow on your canvas.
-
In the HTTP Listener’s properties, create a new configuration element for it. Accept the default port value 8081, and set the host to localhost.
-
Configure the CXF component as per the image and table below.
Field Value Operation
Proxy service
Port
Specify the port to which you wish to bind the WSDL
Payload
body
The output of this component is a byte array. The array content depends upon the value you set in the Payload field.
-
If you select envelope, then the message remains wrapped within the envelope in which it was originally received
-
If you select body, then the message contains only the body, without its envelope
-
-
Configure the Advanced settings as per the image and table below.
Field Value WSDL Location
Filepath of the WSDL in your Mule project
Soap 1.1
OR
Soap 1.2Version of SOAP you want to use
-
Drop a Flow Reference after your CXF component. This reference will redirect the requests to another flow, where the actual business logic of your API will be carried out. Keep in mind that whatever happens in this second flow, the returned output must match the output declared by the WSDL.
As stated earlier, rather than fitting into a single Java class, your API’s business logic may involve the use of several elements, such as flow controls, transformers, HTTP calls to Web services, and so on. If this is the case, you do not need to include a Java class; you can model, then configure your flow to perform the operations your SOAP API must support.
-
If you want direct access to the payload in your business logic flow, you must pass the message through an Dataweave (recommended) or XML-to-DOM transformer.
Otherwise, you can use Xpath expressions to parse parts of the payload when needed. For example, suppose that you only want to alter the message when a condition is met, you can implement a choice router that evaluates the condition based on an Xpath expression.
-
Create a new flow: Drag the Flow component onto the canvas below the existing flow.
-
Configure the Flow Reference component in the flow above this flow, specifying a Flow Name that matches the name of the new flow.
-
Use other Mule runtime components to build your business logic inside this flow.
After adding business logic and running the API as a Mule application, you can access the API by sending requests to the HTTP listener. Include a SOAP envelope in the body.
To make SOAP requests to send to your SOAP API, use a free service such as SoapUI which automatically provides the SOAP message structure you need for each kind of request to the API.
Alternatively, you can use a browser extension such as Postman (Google Chrome), or the curl command line utility to send SOAP requests. To use these, you must know the required structure of the requests.
Standalone XML
-
Import a WSDL file into your project:
-
Select File > Import.
-
Select General > File System.
-
Select the WSDL File from your file system, then, in the Into Folder field, select
src/main/resources.
-
Click Finish.
-
-
Create an` http:listener `in a new flow.
<http:listener config-ref="listener-config" path="/" doc:name="HTTP Connector"/>
Attribute Value config-ref
listener-config
path
/
doc:name
HTTP Connector
-
Create a global configuration element for the HTTP listener, outside the flow
<http:listener-config name="listener-config" host="localhost" port="8081"/>
Attribute Value name
listener-config
host
localhost
port
8081
-
Add a
cxf:proxy-service
element after the HTTP listener.<cxf:proxy-service doc:name="SOAP" payload="body" port="myAPI" service="myAPI" wsdlLocation="myAPI.wsdl"/>
Attribute Value wsdlLocation
The filepath of your WSDL in the Mule project
service
myAPI
port
myAPI
payload
body
The output of this component is a byte array who’s content depends upon the value you set for the
payload
attribute.-
If you select envelope, then the message remains wrapped within the envelope in which it was originally received
-
If you selected body, then the message contains only the body, without its envelope
-
-
Create a
flow-ref
after your CXF component. This reference redirects the requests to another flow, where the actual business logic of your API is carried out. Keep in mind that whatever happens in this second flow, the returned output must match the output declared by the WSDL.<flow-ref name="business-logic_flow" doc:name="Flow Reference"/>
Attribute Value name
business-logic_flow
doc:name
Flow Reference
As stated earlier, rather than fitting into a single Java class, your API business logic may involve the use of several elements, such as flow controls, transformers, HTTP calls to Web services, etc. Through these elements, you can model, then configure your flow to perform the operations your SOAP API must support.
<flow name="business-logic_flow" doc:name="business-logic_flow"> <!-- your business logic here --> </flow>
-
Create a new flow and name it the same as the
flow-ref
attribute Flow Name. Then use other Mule components to build your business logic inside this flow. -
If you want direct access to the payload in your business-logic flow, you must pass the message through a
mulexml:xml-to-dom-transformer
.<mulexml:xml-to-dom-transformer doc:name="XML to DOM"/>
Otherwise, you can use Xpath expressions to parse parts of the payload when needed. For example, suppose that you only want to alter the message when a condition is met, you can implement a choice router that evaluates the condition based on an Xpath expression.
-
Run your Mule project. Access the API by sending requests to the HTTP listener. Include a SOAP envelope in the body.
To make SOAP requests to send to your SOAP API, use a free service such as SoapUI which automatically provides the SOAP message structure you need for each kind of request to the API.
Alternatively, you can use a browser extension such as Postman (Google Chrome), or the curl command line utility to send SOAP requests. To use these, you must know the required structure of the requests.
Incomplete WSDL-First Example
To execute this code, you must include:
-
a WSDL file
-
unique business logic in the business logic flow
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd">
<http:listener-config name="listener-config" host="localhost" port="8081"/>
<flow name="SOAP_flow" doc:name="SOAP_flow">
<http:listener config-ref="listener-config" path="/" doc:name="HTTP Connector"/>
<cxf:proxy-service doc:name="SOAP" payload="body" port="myAPI" service="myAPI" wsdlLocation="myAPI.wsdl"/>
<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
<flow-ref name="business-logic_flow" doc:name="Flow Reference"/>
</flow>
<flow name="business-logic_flow" doc:name="business-logic_flow">
<!-- your business logic here -->
</flow>
</mule>