mule weird flow behavior - mule

I'm using mule 3.2.0 and
I'm invoking muleclient.send method in java-class which sends soap-request to a mule flow(not present here), which sends it to the http endpoint which receives request, logs it to my db with proxy pattern and propagates it to "ServiceFlow" which has Dispatcher transformer - java class, which uses invocation of MuleClient.send(String url, Object payload, Map messageProperties) method to dispatch one object of the payload array to an endpoint.
Then it gets processed by cxf:jax-ws-client, logged to a db once again and transferred to another instance of Dispatcher (where incoming payload is again of type Object[]). There I have http endpoint which does the service invocation. This part works okay.
But trouble appears at the receiving of the response. I've put Test1(2,3,4) transformers to print the invocation chain in my flows (They just do the System.out.println()), and saw that they're invoked in a weird sequence: I have it like 1,3 then TestTransformer (which is also the sysouter) then I get the error "NullPayload" in the caller of the main flow "Service flow" and then I receive the Test 4 and Test 2 outs. The responseTransformer-refs in patterns "1Proxy" are ignored, so as in "ServiceProxy". I've been looking for the solution for like a week now, and can't find it. In debugging, I can see that transformer called "TestTransformer" in has expected payload (Object[]) but when I receive it in my class caller, it appears as "NullPayload". I can see now that one of my endpoints has the path element instead of ref, not sure if this cause any impact on flow, but will check it. Also tried to use the "response" block to ensure my flow runs as expected. Any suggestions appreciated. Thanks
Here is what my config looks like:
<http:endpoint name="httpService" address="${service.soap}" exchange-pattern="request-response" responseTimeout="${timeout}" />
<vm:endpoint name="vmService" path="vmService" exchange-pattern="request-response"/>
<pattern:web-service-proxy
name="ServiceProxy"
inboundEndpoint-ref="httpService"
transformer-refs="to-string logging"
responseTransformer-refs="to-string logging"
outboundEndpoint-ref="vmService" />
<flow name="ServiceFlow" >
<inbound-endpoint ref="vmService"/>
<cxf:jaxws-service serviceClass="pkg.ServiceImpl" wsdlLocation="${service.wsdl}" enableMuleSoapHeaders="false" validationEnabled="true"/>
<custom-transformer class="pkg.Dispatcher">
<spring:property name="vmFlowPath" value="vm.logService"/>
</custom-transformer>
<custom-transformer name="TestTransformer" class="pkg.TestTransformer"/>
</flow>
<vm:endpoint name="vm1In" path="vm1In" exchange-pattern="request-response"/>
<vm:endpoint name="vm1Out" path="vm1Out" exchange-pattern="request-response"/>
<custom-transformer name="arrayGenerator" class="pkg.ArrayGenerator"/>
<custom-transformer name="objectExtractor" class="pkg.ObjectExtractor"/>
<custom-transformer name="faultChecker" class="pkg.FaultChecker"/>
<custom-transformer name="objectLogging" class="pkg.ObjectLogger">
<pattern:web-service-proxy
name="1Proxy"
inboundEndpoint-ref="vm1In"
transformer-refs="arrayGenerator objectLogging"
responseTransformer-refs="objectLogging objectExtractor faultChecker"
outboundEndpoint-ref="vm1Out" />
<flow name="logService">
<vm:inbound-endpoint path="vm.logService exchange-pattern="request-response"/>
<custom-transformer class="Test1"/>
<vm:outbound-endpoint ref="vm1In">
<cxf:jaxws-client
serviceClass="pkg.ServiceImpl"
operation="import"
enableMuleSoapHeaders="false"/>
<object-to-string-transformer/>
</vm:outbound-endpoint>
<object-to-xml-transformer>
<xm:xml-to-object-transformer returnClass="pkg.WSResponseClass"/>
<custom-transformer class="Test2"/>
</flow>
<flow name="DispatcherToServiceFlow">
<custom-transformer class="Test3"/>
<vm:inbound-endpoint path="vm1.Out"/>
<custom-transformer class="pkg.Dispatcher">
<spring:property name="vmFlowPath" value="vm.import"/>
</custom-transformer>
</flow>
<flow name="import">
<vm:inbound-endpoint path="vm.import" exchange-pattern="request-response"/>
<http:outbound-endpoint address="${importService}" responseTimeout="${timeout}" exchange-pattern="request-response" />
<object-to-string-transformer/>
<custom-transformer class="Test4"/>
</flow>

well, my problem really was the "path" element instead of referring to an existing vm endpoint with "ref" element like
<inbound-endpoint ref="vm1Out"/>

Related

Why until successful of Mule gets the response from the third party however never passes to the calling party

As you can see that I have used until successful at flow level and connector
level however the response does't comes back to the calling party however
the retries is successfully executed
<until-successful objectStore-ref="objectStore" maxRetries="2"
secondsBetweenRetries="60" doc:name="Until Successful">
<flow-ref name="xml-to-servlet" doc:name="xml-to-servlet"/>
</until-successful>
<sub-flow name="xml-to-servlet" doc:name="xml-to-servlet">
<custom-transformer class="MapToTemplate" doc:name="MapToTemplate">
<spring:property name="sessionBean" ref="SessionBean"/>
</custom-transformer>
<custom-transformer class="LogTime" doc:name="Logging">
<spring:property name="state" value="SEND_TIME"/>
</custom-transformer>
<http:outbound-endpoint exchange-pattern="request-response" method="POST"
address="http://localhost:8080/Xml_Servlet_Simulator/XmlServlet"
doc:name="HTTP" responseTimeout="60000" keep-alive="true">
<set-property propertyName="eig_requestId" value="#[sessionVars.REQUEST_ID]"/>
</http:outbound-endpoint>
<custom-transformer class="LogTime" doc:name="Logging">
<spring:property name="state" value="RECIEVE_TIME"/>
</custom-transformer>
<echo-component doc:name="Echo"/>
until-successful is asynchronous by default. So the rest of the calling flow will execute without waiting for the result of the until-successful regardless whether it was successful or not.
You can however configure it o be synchronous as documented here: http://www.mulesoft.org/documentation/display/current/Until+Successful+Scope#UntilSuccessfulScope-SynchronousUntil-Successful

How to get handle to original file from file:outbound-endpoint in mule

In a flow something like below:
<flow name="fileFlow">
<file:inbound-endpoint path="/inbound/ftp/sbc" pollingFrequency="30000" fileAge="30000" moveToDirectory="/inbound/ftp/sbc/archive">
<file:filename-wildcard-filter pattern="*.xml" caseSensitive="false"/>
</file:inbound-endpoint>
<logger message="Entering #[flow.name] flow" level="INFO"/>
<component class="com.abc.RequestFile"/>
<logger message="Payload after transformation is: #[payload] flow" level="INFO"/>
<vm:outbound-endpoint path="merge" />
<logger message="Exiting #[flow.name] flow" level="INFO"/>
</flow>
I get InputStream from file:inbound-endpoint which is passed to RequestFile component. This component is required to return a list of files of which one of this is the original one read and passed. I am seeking a solution other than manual copying InputStream to File in java component.
As explained in this answer https://stackoverflow.com/a/12397775/387927 you can get the java.io.File object instead of its content with this setting:
<file:connector name="fileConnector" streaming="false" autoDelete="false">
<service-overrides messageFactory="org.mule.transport.file.FileMuleMessageFactory" />
</file:connector>
Note that it is up to you to move / delete the file either before you start or once you've done processing it, otherwise Mule will poll it again and again.

Consume wsdl service using cfx:proxy-client in Mule ESB 3.3 - Could not find definition for service

I am attempting to consume a wsdl service using cfx:proxy-client in Mule ESB 3.3 but keep getting this error
org.apache.cxf.service.factory.ServiceConstructionException: Could not find definition for service {http://support.cxf.module.mule.org/}ProxyService.
at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:139)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromWSDL(ReflectionServiceFactoryBean.java:383)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:506)
Below is my simple flow:
<flow name="spider-middleware" doc:name="spider-middleware">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="salesforce" doc:name="HTTP"/>
<cxf:proxy-client operation="getCustomerByID"
payload="body"
wsdlLocation="http://localhost:4546/eplus-ws-fake/services/EplusCustomer/v1?wsdl"
enableMuleSoapHeaders="true"
doc:name="SOAP"/>
</flow>
The service is hardcoded to return a customer for getCustomerByID(1).
Please shed some lights on how do I get around the issue?
Thanks.
I got it working but only by providing a full SOAP envelope and not just the body, ie. using payload="envelope".
Also I removed the operation and wsdlLocation attributes, which are useless for the proxy-client. I also had to add SOAPAction and Content-Type properties, otherwise the test webservice I'm using chokes on the request.
This gives (using a test service from WebServiceX.net):
<flow name="pureCxfProxyClient">
<vm:inbound-endpoint path="test.in"
exchange-pattern="request-response" />
<set-property propertyName="SOAPAction"
value="http://www.webservicex.net/getACHByZipCode" />
<set-property propertyName="Content-Type" value="text/xml" />
<http:outbound-endpoint address="http://www.webservicex.net/FedACH.asmx"
exchange-pattern="request-response" >
<cxf:proxy-client payload="envelope" />
</http:outbound-endpoint>
</flow>
Note I used a VM endpoint, which allowed me to deal with the XMLStreamReader returned by the cxf:proxy-client.
In particular, I needed to do the following:
final XMLStreamReader xsr = (XMLStreamReader) result.getPayload();
xsr.nextTag();
to avoid crazy NPEs in org.mule.module.xml.stax.ReversibleXMLStreamReader.
All in all this is pretty intense... plus the cxf:proxy-client doesn't deliver much value when used standalone. You could actually just go with:
<flow name="pureCxfProxyClient">
<vm:inbound-endpoint path="test.in"
exchange-pattern="request-response" />
<set-property propertyName="SOAPAction"
value="http://www.webservicex.net/getACHByZipCode" />
<set-property propertyName="Content-Type" value="text/xml" />
<http:outbound-endpoint address="http://www.webservicex.net/FedACH.asmx"
exchange-pattern="request-response" />
</flow>
... and be freed of the XMLStreamReader part.

Mule 3.2 flow and cxf:jaxws-service

I am relatively new to mule and trying to define a mule flow which takes request XML via soap-based Web service. The XML is based on a complex schema and I have generated classes using WSDL2Java
After receiving the request cxf:jaxws-service executes the method submitOrder(SubmitOrderRequest parameters). After this method's execution I would like to transform the request XML to a little bit different format. Then this XML needs to be forwarded to another web service. The problem is that the mule message that comes out of ServiceImpl contains SubmitOrderResponse whereas I still want to work on SubmitOrderRequest.
<flow name="testService">
<http:inbound-endpoint address="http://localhost:62005/test"
exchange-pattern="request-response">
<cxf:jaxws-service serviceClass="com.test.ServicePortType" />
</http:inbound-endpoint>
<component class="com.test.ServiceImpl" />
<!-- transformer ref="MVIRequestTransformer" / -->
<!-- xm:object-to-xml-transformer / -->
<!-- logger message="XML payload is #[payload]" level="INFO" / -->
<!-- SEND TRASNFORMED MESSAGE TO ANOTHER SERVICE -->
</flow>
#WebService(endpointInterface = "com.pennmutual.services.mvi.MVIServicePort")
public class ServiceImpl implements ServicePortType {
...
#Override
public SubmitOrderResponse submitOrder(SubmitOrderRequest parameters) {
...
}
...
}
What are my options are. I can think of the following –
1. Put the request object somewhere in the context and retreive it later on for processing.
2. Change the return type of submitOrder to Object and return SubmitOrderRequest instead of SubmitOrderResponse.
Please suggest the best possible way to handle this situation. I am using mule 3.2.
I think there are two elegant way to do that (excluding the one that involves changing the webservice interface)
Store the request into a session variable and restore it afterwards.
Here is how your flow would look like:
<flow name="testService">
<http:inbound-endpoint address="http://localhost:62005/test" exchange-pattern="request-response">
<cxf:jaxws-service serviceClass="com.test.ServicePortType" />
</http:inbound-endpoint>
<message-properties-transformer scope="session">
<add-message-property value="payload" key="originalPayload" />
</message-properties-transformer>
<component class="com.test.ServiceImpl" />
</flow>
Use the enricher around the component to store the returned value into a variable so that it won't become the payload of your flow. Following an example of how to achieve this
<flow name="Echo" doc:name="Echo">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="6090" path="echo" encoding="UTF-8" />
<cxf:jaxws-service serviceClass="org.mule.example.echo.Echo" />
<enricher target="#[variable:echo]">
<component class="org.mule.example.echo.Echo" />
</enricher>
<logger level="ERROR" message="#[variable:echo]"/>
</flow>
You can find more informations on the enricher here

Mule flow request-response issue

In this flow the HTTP inbound is configured with request-response. But I still dont get the response as it is routed to the File outbound. How do I get a response for the HTTP endpoint and also route the response to File outbound.
<flow name="helloFlow1" doc:name="helloFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9095" doc:name="HTTP"/>
<custom-transformer class="com.uk.MyTransformer" doc:name="Java"/>
<component class="com.uk.MyComponent" doc:name="Java"/>
<echo-component doc:name="Echo"/>
<file:outbound-endpoint path="C:\" outputPattern="file#[function:datestamp]" doc:name="File"/>
You don't receive a response because nothing creates one: the file:outbound-endpoint is one-way per nature and doesn't generate a response event.
Assuming you want the same content written to the file to be also returned to the caller of the HTTP endpoint, one option consists in "detaching" the writing to the file in a parallel async flow so the main flow returns its current value to the caller:
<flow name="helloFlow1" doc:name="helloFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9095" doc:name="HTTP"/>
<custom-transformer class="com.uk.MyTransformer" doc:name="Java"/>
<component class="com.uk.MyComponent" doc:name="Java"/>
<echo-component doc:name="Echo"/>
<async>
<file:outbound-endpoint path="C:\" outputPattern="file#[function:datestamp]" doc:name="File"/>
</async>
</flow>