In addition to using the CXF Component to expose a SOAP Web Service, we can also use the APIkit SOAP together with a WSDL file to do this in the Mule ESB. How is it in details? Let’s find out in this tutorial.
First, I will also create a Mule Maven project as an example:
The WSDL file defined for the SOAP Web Service we use in this example is as simple as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://muleesbcxfsoapexpose.huongdanjava.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="HelloWorldServiceService" targetNamespace="http://muleesbcxfsoapexpose.huongdanjava.com/"> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://muleesbcxfsoapexpose.huongdanjava.com/" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://muleesbcxfsoapexpose.huongdanjava.com/"> <xs:element name="hello" type="tns:hello"/> <xs:element name="helloResponse" type="tns:helloResponse"/> <xs:complexType name="hello"> <xs:sequence> <xs:element name="name" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="helloResponse"> <xs:sequence> <xs:element name="result" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:element name="clientId" nillable="true" type="xs:string"/> </xs:schema> </wsdl:types> <wsdl:message name="helloResponse"> <wsdl:part element="tns:helloResponse" name="result"> </wsdl:part> <wsdl:part element="tns:clientId" name="clientId"> </wsdl:part> </wsdl:message> <wsdl:message name="hello"> <wsdl:part element="tns:hello" name="parameters"> </wsdl:part> <wsdl:part element="tns:clientId" name="clientId"> </wsdl:part> </wsdl:message> <wsdl:portType name="HelloWorldService"> <wsdl:operation name="hello"> <wsdl:input message="tns:hello" name="hello"> </wsdl:input> <wsdl:output message="tns:helloResponse" name="helloResponse"> </wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="HelloWorldServiceServiceSoapBinding" type="tns:HelloWorldService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="hello"> <soap:operation soapAction="" style="document"/> <wsdl:input name="hello"> <soap:header message="tns:hello" part="clientId" use="literal"> </soap:header> <soap:body parts="parameters" use="literal"/> </wsdl:input> <wsdl:output name="helloResponse"> <soap:header message="tns:helloResponse" part="clientId" use="literal"> </soap:header> <soap:body parts="result" use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="HelloWorldServiceService"> <wsdl:port binding="tns:HelloWorldServiceServiceSoapBinding" name="HelloWorldServicePort"> <soap:address location="http://localhost:8081/hello"/> </wsdl:port> </wsdl:service> </wsdl:definitions> |
This WSDL defines a SOAP Web Service with an operation named “hello” that allows the user to send a SOAP message containing the name of someone in the <Body> section (for example, my name, Khanh). The <Header> section of the request message will contain the clientId information of the device sending the message. Implementation of the response section, which we will use the ESAP SOAP APIkit to do, is because of us. I will build to respond to the message “Hello, Khanh” for simplicity.
I will put this file into the /src/main/wsdl directory of the project.
In fact, this /src/main/wsdl directory is actually available when we create a new Mule Maven project but by default, it is not included as the project’s resource folder so you don’t see it. You can use the Builder Helper Maven Plugin plugin which is being declared in the pom.xml file of this project to include the wsdl folder as a resource folder as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>1.7</version> <executions> <execution> <id>add-resource</id> <phase>generate-resources</phase> <goals> <goal>add-resource</goal> </goals> <configuration> <resources> <resource> <directory>src/main/app/</directory> </resource> <resource> <directory>src/main/api/</directory> </resource> <resource> <directory>mappings/</directory> </resource> <resource> <directory>src/main/wsdl/</directory> </resource> </resources> </configuration> </execution> </executions> </plugin> |
Then you will see the wsdl directory included as the source folder of the project.
Please put our wsdl file into this folder.
OK, now let’s go to the main topic of this tutorial.
To use the APIkit SOAP in Mule ESB, first, we need to declare its dependencies. There are 3 dependencies we need to declare for the APIkit SOAP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<dependency> <groupId>org.mule.modules</groupId> <artifactId>mule-module-apikit-soap</artifactId> <version>1.0.3</version> </dependency> <dependency> <groupId>org.mule.modules</groupId> <artifactId>mule-module-apikit-soap-common</artifactId> <version>1.0.3</version> </dependency> <dependency> <groupId>org.mule.modules</groupId> <artifactId>mule-module-apikit-soap-metadata</artifactId> <version>1.0.3</version> </dependency> |
Currently, I could not find the Maven repository that contains these three dependencies on the internet, so there is only one way that we will go to the plugins folder of Anypoint Studio and look for the org.mule.tooling.soapkit.contribution_1.1.4/lib directory
to get these files, then install them into the Local Maven repository. You can see the guideline for installing dependencies into the Local Maven repository here.
OK, after adding the dependencies, right-click on the hello.wsdl file in the example project and select Mule, then select Generate Flows from WSDL.
At this point, a window will appear:
allow us to choose the Mule Configuration file to generate Mule Flows.
You can leave the defaults and click the OK button.
You will see that Mule Flows is generated as follows:
As you can see, Anypoint Studio has generated Mule Flows using the APIkit SOAP with an api-main Mule flow will receive requests from the client, each SOAP Web Service operation will be generated as a Mule Flow. Our task is to implement the Mule flow for each operation.
By default, the flow mule for each operation has only one endpoint Set Payload. The content of this Set Payload endpoint depends on the operation of the SOAP Web Service, which will have different content. In this example, the content of the Set Payload endpoint is as follows:
1 2 3 4 |
<soap:Fault xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <faultcode>soap:Server</faultcode> <faultstring>Operation [hello:/HelloWorldServiceService/HelloWorldServicePort/api-config] not implemented</faultstring> </soap:Fault> |
You can remove this Set Payload endpoint to implement this flow in your own way but must conform to the definition of your WSDL file.
Here, I will delete this Set Payload endpoint and add a Transform Message Component to build the SOAP response message back to the client as follows:
1 2 3 4 5 6 7 8 9 10 11 12 |
%dw 1.0 %output application/xml %namespace ns0 http://muleesbcxfsoapexpose.huongdanjava.com/ --- { ns0#helloResponse: { return: "Hello, " ++ payload.ns0#hello.name } } |
Similar to the Web Service Consumer connector, the Payload part of the Mule Message will automatically convert the <Body> element of the SOAP response message.
To build the <Header> section for the response, we need to take another step, which is to build a Mule Message Property with a name that begins with “soap.”
To do this, in the Transform Message window, next to the Output of Payload, click on the new Target button:
A new window will appear:
Please select Output and enter Variable name as above.
Click the OK button to start building the Mule Message Property “soap.header”:
DataWeave content of the Message Property section “soap.header” will look like this:
1 2 3 4 5 6 7 8 9 10 |
%dw 1.0 %output application/xml %namespace ns0 http://muleesbcxfsoapexpose.huongdanjava.com/ --- { ns0#clientId : inboundProperties."soap.clientId".ns0#clientId } |
You will now see the endpoint of the HTTP Listener Connector being corrupted. The cause is that after generating from the WSDL file, the Global Configuration of this connector has not been created. Please configure it, can see the guideline here.
Here, I configured the Global Configuration for the HTTP Listener Connector as follows:
Change the configuration of the HTTP Listener Connector to the correct definition of the WSDL file:
Here we have completed a simple example using the SOAP API to expose the SOAP Web Service, but to get our application running, you need to take more step to bring the SOAP API library into our application when running it with Mule Runtime. If you do not do this, you will get an error regarding the SOAP API’s mule-apikit-soap.xsd. With this last step, you need to open the pom.xml file and find the mule-app-maven-plugin plugin to include the SOAP API libraries as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<plugin> <groupId>org.mule.tools.maven</groupId> <artifactId>mule-app-maven-plugin</artifactId> <version>${mule.tools.version}</version> <extensions>true</extensions> <configuration> <copyToAppsDirectory>true</copyToAppsDirectory> <inclusions> <inclusion> <groupId>org.mule.modules</groupId> <artifactId>mule-module-apikit-soap</artifactId> </inclusion> <inclusion> <groupId>org.mule.modules</groupId> <artifactId>mule-module-apikit-soap-common</artifactId> </inclusion> <inclusion> <groupId>org.mule.modules</groupId> <artifactId>mule-module-apikit-soap-metadata</artifactId> </inclusion> </inclusions> </configuration> </plugin> |
OK, that’s all, let run our application now.
Results when running with SOAPUI:
Satya Prasad B
@hemanth, you can create WSDL file from manually in eclipse IDE easily.
blah
Suppose, I have a HTTP Request connector after Transform message. And in case the target URL is down, I want to catch that exception and form a custom SOAP fault and send it back to the SOAPUI. How do I achieve this?
Khanh Nguyen
I think you can use Catch Exception Strategy to catch the exception and build the SOAP Fault Message to return to client.
Ayesha
How can you apply xml threat protection policy to this soap resource from api manager?
Raj
POC1:
(Create Salesforce developer account; Any point account)
Implement a SOAP API with two resources. One is to get account detail from salesforce by account id & another one is to delete.
Implement a REST API which should act as a wrapper / pass through service for SOAP.
Should accept account id in path parameter
Use appropriate HTTP method for resources
Should return JSON response
i. Account detail for get operation
ii. and delete confirmation message for delete operation.
Implement proper exception handling
Please let me know how to implement a soap web service as per the above requirement?
Khanh Nguyen
You should use Salesforce connector for calling and manipulating with Salesforce. Let define REST API with APIkit Router and implement the calling to SF for each resource. You should research more about SF to understand about it.
Best regards,
Gowtham
HI Khanh Nguyen, i was trying to create a Mule project to expose a soap service as above and while deploying the project i’m getting an error as below. I’m using Mule 3.9.0 Run-time.
org.mule.module.launcher.DeploymentException: Failed to deploy artifact [helloservicesoapkit]
at org.mule.module.launcher.DefaultArtifactDeployer.deploy(DefaultArtifactDeployer.java:85) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.DefaultArchiveDeployer.deployArtifact(DefaultArchiveDeployer.java:547) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.DefaultArchiveDeployer.deployArtifact(DefaultArchiveDeployer.java:325) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.DefaultArchiveDeployer.deployPackagedArtifact(DefaultArchiveDeployer.java:185) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.DefaultArchiveDeployer.deployPackagedArtifact(DefaultArchiveDeployer.java:274) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.DefaultArchiveDeployer.deployPackagedArtifact(DefaultArchiveDeployer.java:80) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.DefaultArchiveDeployer.deployPackagedArtifact(DefaultArchiveDeployer.java:577) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.DeploymentDirectoryWatcher.deployPackedApps(DeploymentDirectoryWatcher.java:283) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.DeploymentDirectoryWatcher.start(DeploymentDirectoryWatcher.java:155) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.MuleDeploymentService.start(MuleDeploymentService.java:135) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.module.launcher.MuleContainer.start(MuleContainer.java:172) ~[mule-module-launcher-3.9.1.jar:3.9.1]
at org.mule.tooling.server.application.ApplicationDeployer.main(ApplicationDeployer.java:15) ~[tooling-support-3.9.1.jar:?]
Caused by: java.lang.NoClassDefFoundError: org/mule/module/soapkit/metadata/api/FaultMetaDataResolver
here is my wsdl file
WSDL File for HelloService
and my implementation is as below
Please help me to resolve this issue
Khanh Nguyen
Can you please share your project?
klik
Did you manage to solve this issue? I’m having the same here.
Suneel
Remove your api kit soap metadata and common dependencies from your POM file. It should work.
hemant
Thanks for the Article. Like RAML for Rest, do we have anything apart from Java code to prepare a wsdl file ??
Khanh Nguyen
No problem Hemant,
Without Java code, you can create the WSDL file manually, but in this case, you must have knowledge about the structure of a WSDL file.