1
votes

we are on 7.1 EE and I've been tasked with designing a SOAP/WSDL web service running on Mule that could be consumed by the external clients. The WSDL is given as an input.

The MuleSoft's recommended way is to use CXF component for the purpose, generate java classes with wsdl2java and then add the WS logic to the java code. This of course works but it's more a java way of doing the task rather than Mule ESB way.

I would prefer an approach where Mule flow and message transforming components implement the WS logic rather than the java classes.

Actually, the APIKit is already working this way. Unfortunately, it doesn't support WSDL. So, what I'm looking for is the following:

  1. Getting the WS input as a POJO in the payload (after the schema been validated by CXF).
  2. Use DataMapper to transform the POJO to let's say some external VM input parameters
  3. Get the response from VM into DataMapper, put the values into the WS Response POJO.
  4. Letting the CXF to complete the task of returning the response to the caller.

This would be more Mule way of doing the task, IMHO.

Now, looking at the java code generated there are request and response POJOs already there and could be used in DataMapper.

I suspect that there could be actually a way of getting the WS request POJO in the Mule payload, transform it, populate the result POJO and somehow return it back to CXF.

Any ideas of how this could be implemented?

Pls note that I don't think that using CXF proxy mode is a good alternative. Because with this approach you effectively loosing a knowledge about the request/response format. And then you'll have to manually define the payload fields for the mapping... Effectively, this would be a manual SOAP parsing.

2

2 Answers

3
votes

Ok, actually, this was easy. Apparently, CXF is already working this way i.e. puts the request input POJO into the payload and expects the output POJO at the end. Easy.

I've been mislead by the MuleSoft docs and examples where all of them have Java component immediately after the CXF.

This is a small test that I've done. The DataMapper is from the Request POJO class generated to the Response POJO class.

<flow name="ws_callFlow">
    <http:listener config-ref="httpListenerConfig" path="/myws" doc:name="HTTP" allowedMethods="POST"/>
    <cxf:jaxws-service doc:name="CXF" configuration-ref="CXF_Configuration" serviceClass="ws.myws" validationEnabled="true"/>
    <data-mapper:transform config-ref="Pojo_To_Pojo" doc:name="Pojo To Pojo">
    </data-mapper:transform>
</flow>
1
votes

Did you try the xml-to-jabx object transformation to generate your pojo? I assume you have your own xml schema (xsd). You can use the generated pojo in your datamapper.

You can specify the location of your wsdl generated by your CXF provider in CXF consumer, so either you can generate WS service class from WSDL or using the wsdl2java tool.

Here is a sample WS provider:

<flow name="service-flow">
    <http:listener config-ref="HTTP_Listener_Configuration" path="/service" doc:name="HTTP" allowedMethods="POST"/>
    <cxf:jaxws-service doc:name="CXF" serviceClass="service.Service"/>
    <component doc:name="Java" class="service.ServiceImpl"/>
</flow>

Then here is the WS consumer:

<flow name="serviceconsumerFlow" processingStrategy="non-blocking">
    <outbound-endpoint
        address="http://${service.host}:${service.port}/service"
        doc:name="WS Consumer Service" exchange-pattern="request-response"
        mimeType="text/xml">
        <cxf:jaxws-client operation="executeOperation"
            clientClass="package.ServiceService"
            port="ServicePort" wsdlLocation="classpath:/service.wsdl"
            doc:name="CXF" />
    </outbound-endpoint>
    <byte-array-to-object-transformer returnClass="package.POJO" doc:name="Byte Array to Object"/>
</flow>

You'll notice from above that the CXF jaxws client is being wrapped in .