Mule - session variables lost after sftp:outbound-endpoint - mule

Running the following config, I set a session variable before an sftp outbound endpoint and after it its not available anymore. I thought session variables were meant to be available across transport barriers? Am I doing something wrong?
<set-session-variable variableName="total" value="#[payload.size()]" />
<foreach>
<!-- Omitted for brevity -->
</foreach>
<sftp:outbound-endpoint encoding="UTF-8"
connector-ref="sftp-out" exchange-pattern="request-response" outputPattern="#[flowVars.filename]"
host="${sftp.host}" port="${sftp.port}" path="${sftp.output.path}" user="${sftp.username}"
responseTimeout="60000" identityFile="${app.home}/${sftp.keyPath}" passphrase="${sftp.passphrase}" />
<logger level="INFO" message="#[sessionVars.total]" />

Being available through transport barrier means that are still available when sending the message through a VM outbound endpoint, inside the same server (same app or different apps).
This is useful for sharing behaviour between flows, use transactions, make asynchronous processing or distribute load in a cluster.
Regards.

Related

Vars are getting wiped off while using vm connector in mule 4

mule doc says they have removed transport barrier so there is no need to have session vars in mule 4. when I am using a VM connector to publish and consume using VM vars are getting wiped off. I did cross check with mule 3.9 session vars will be persisted after reaching other flow irrespective of configured VM is one-way to req-res.
<vm:config name="vm">
<vm:queues>
<vm:queue queueName="publish" />
</vm:queues>
</vm:config>
<flow name="persistentVM">
<vm:listener queueName="publish" config-ref="vm"
numberOfConsumers="1">
<vm:response>
<vm:content><![CDATA[
]]></vm:content>
</vm:response>
</vm:listener>
<logger level="INFO" doc:name="Logger"
doc:id="1d624aa2-0aa4-4c5d-a258-0a8135a792ff" message="#[vars.test]" />
</flow>
<flow name="publish">
<http:listener doc:name="Listener"
doc:id="68f9601d-d31e-4de6-a448-98a43724de42" config-ref="HTTP_Listener_config"
path="/error" />
<set-variable value="#['My Message']" doc:name="Set Variable"
doc:id="861cc914-b1ad-4068-8753-a0fd1915bed4" variableName="test" />
<vm:publish doc:name="Publish" doc:id="153209cb-49f2-4f80-8305-56dcd046aa3c" config-ref="vm" queueName="publish"/>
`
Any comments on this is much helpful.
For Mule 4 session vars are removed and vars will not propagate across transport barriers. If you want the var in the other flow, you will either have to make it part of the payload and publish it using vm:content, persist it using the ObjectStore or use flows and flow-ref instead of the vm connector.

Read messages from different SQS queues in Mule

I have 2 separate Amazon SQS queues; Queue and ResponseQueue.
SQS configurations:
<sqs:config name="Amazon_SQS_Consumer" accessKey="XXX" secretKey="XXX" queueName="Queue" doc:name="Amazon SQS">
<sqs:connection-pooling-profile maxActive="10" maxIdle="10" exhaustedAction="WHEN_EXHAUSTED_GROW" maxWait="12000" minEvictionMillis="60000" evictionCheckIntervalMillis="30000" initialisationPolicy="INITIALISE_ONE"/>
<reconnect count="5" frequency="1000"/>
</sqs:config>
<sqs:config name="Amazon_SQS_Response" accessKey="XXX" secretKey="XXX" queueName="ResponseQueue" doc:name="Amazon SQS">
<sqs:connection-pooling-profile maxActive="100" maxIdle="10" exhaustedAction="WHEN_EXHAUSTED_GROW" maxWait="12000" minEvictionMillis="60000" evictionCheckIntervalMillis="30000" initialisationPolicy="INITIALISE_ONE"/>
<reconnect count="5" frequency="1000"/>
</sqs:config>
I have no problem receiving messages from the first queue (Queue) via:
<flow name="consumer" doc:name="consumer">
<sqs:receive-messages config-ref="Amazon_SQS_Consumer" preserveMessages="true" doc:name="Amazon SQS (Streaming)" visibilityTimeout="300" />
<logger level="INFO" message="#[payload]" />
</flow>
I need to also receive messages from the second queue (ResponseQueue):
<flow name="response" doc:name="response">
<sqs:receive-messages config-ref="Amazon_SQS_Response" preserveMessages="true" doc:name="Amazon SQS (Streaming)" visibilityTimeout="300" />
<logger level="INFO" message="#[payload]" />
</flow>
However, whenever the second sqs:receive-messages is added, I get the following error:
Exception in thread "Receiving Thread" java.lang.LinkageError: loader (instance of org/mule/module/launcher/plugin/MulePluginsClassLoader): attempted duplicate class definition for name: "com/amazonaws/services/sqs/QueueUrlHandler"
Is it possible to read messages from 2 different queues in the same project?
I'm using 3.4.0 CE Mule Server Runtime and 2.4.4 Amazon SQS Connector. I need to stay at these versions. If I switch to 3.5.0 EE Mule Server Runtime, there is no problem in having multiple sqs:receive-messages; it works just as expected. However, it leads to another issue.
Are you using the same credentials in both sqs:config elements? If yes, then you only need one config element and then specify the queue name on the sqs:receive-messages elements.
<sqs:receive-messages queueName="Queue"
preserveMessages="true"
visibilityTimeout="300" />
Refer to the user guide: http://mulesoft.github.io/sqs-connector/2.5.0/mule/sqs-config.html#receive-messages

mule asynchronous tls/ssl inbound endpoint

I'm working on a project where one of the requirements is to connect to a server using ssl/tls and subscribe to messages. I have setup a tls outbound-endpoint and can connect to the server. I have a spring bean that performs custom handshaking and part of that is subscribing to content from the server. Once subscribed I should receive messages asynchronously without having to poll for them. Is there a way to do this in Mule 3.3? Thanks for the help.
It seems you have a specific use case in which you can't use HTTPS. Mule does provide support for TCP connection, but I couldn't find the option to make the the secure TCP connection (which I beleive will be over SSL).
You can always write your custom endpoint connector code in a java component and call that java component using Quartz (for polling)
<flow name="polling-flow" doc:name="polling-flow">
<quartz:inbound-endpoint jobName="polling"
repeatInterval="5000" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job>
<quartz:payload>call-custom-component-to-poll-secure-tcp</quartz:payload>
</quartz:event-generator-job>
</quartz:inbound-endpoint>
<component doc:name="Java" class="com.company.CustomSecureTCPCode"></component>
<!-- do whatever you want to with the payload received from calling the endpoint -->
</flow>
I used a quartz inbound endpoint and setup an endpoint polling job and polled my endpoint. See the config below:
<flow name="QuartzPollingFlow">
<quartz:inbound-endpoint repeatCount="-1" repeatInterval="1000" jobName="myPoller">
<quartz:endpoint-polling-job>
<quartz:job-endpoint timeout="300" ref="SecureTcpEndpoint"/>
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
<flow-ref name="ProcessingFlow"/>
</flow>

Why won't a REST component not receive a call made internal to an app when multiple Global HTTP Connectors are Configured?

I'm struggling to configure and deploy to CloudHub an app with multiple Global HTTP Connectors and a REST component.
My application has two flows: one polls an RSS feed for news and posts a json representation of that feed to an http inbound endpoint in the same app (endpoint resides on second flow). The second flow receives that post, does some magic, including persisting the item to storage, and then notifies via an http outbound endpoint an external node.js web app to push the item via web sockets to active clients.
I have tried what feels like dozens of different configurations involving a variety of HTTP Global Connectors and http in and outbound endpoints, but I can't get everything to work. I currently have:
A Polling HTTP Connector
An HTTP endpoint referencing above polling http connector to get RSS Feed
One Global Connector (we'll call HTTP_ONE) to receive messages at localhost:${http.port}
An http oubound endpoint configured referencing HTTP_ONE and configured to post an activity to /api/v1/activity
An http inbound endpoint configured to receive messages for /api/v1 and a Jersey controller sitting just behind this endpoint which takes /activity.
Another Global Connector (HTTP_TWO) with an external host set as the proxy host name (e.g. somehost.somewhere.com).
An http outbound endpoint configured to post messages to somehost.somewhere.com
On my localhost, I've had to use various properties to allow for all of this activity on multiple ports on my laptop.
On CloudHub, I'm using localhost and ${http.port} everywhere except in the oubound endpoint that calls to an external web service.
I can get one flow or the other working, but not both.... My problem seems to be with the posting a given news item from the RSS feed to the Inbound HTTP Endpoint. It is sending the post to http://localhost:80/api/v1/activity, but the connector says that no such path exists (it only lists /api/v1 as an option), which makes me think that the call is not getting as far as the Jersey Controller which sits behind the Global Connector and the http inbound endpoint for /api/v1/activity. Is this behavior an inherent flaw in using the REST Component and multiple global http connectors? Also, why do we have to reference a Global HTTP Connector when making an outbound call? Why can't we use the default HTTP Connector? (Maybe the last two questions should go in a subsequent post...)
Here's most of the relevant config for the two flows:
Global Connectors
<http:polling-connector name="PollingHttpConnector" pollingFrequency="60000" doc:name="HTTP Polling" clientSoTimeout="10000" cookieSpec="netscape" receiveBacklog="0" receiveBufferSize="0" sendBufferSize="0" serverSoTimeout="10000" socketSoLinger="0" validateConnections="true"/>
<http:connector name="EduStream_HTTP" cookieSpec="netscape" validateConnections="true" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" proxyHostname="${edustream.host}" doc:name="HTTP\HTTPS" proxyPort="80"/>
<http:connector name="EduStreamESB_HTTP" cookieSpec="netscape" validateConnections="true" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" proxyHostname="localhost" proxyPort="${http.port}" doc:name="HTTP\HTTPS"/>
News RSS Feed Flow
<flow name="ucdNewsConsumer" doc:name="ucdNewsConsumer">
<http:inbound-endpoint address="http://news.ucdavis.edu/xml/getnews.php/rss/category/General%20Interest"
connector-ref="PollingHttpConnector" doc:name="HTTP" exchange-pattern="one-way"/>
<rss:feed-splitter/>
<rss:entry-last-updated-filter/>
<component class="edu.ucdavis.edustream.esb.news.rss.EntryReceiver" doc:name="Java"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="${http.port}" path="api/v1/activity" doc:name="HTTP" mimeType="application/json" connector-ref="EduStreamESB_HTTP" />
<logger message="Payload is: #[payload] Inbound Headers: #[headers:INBOUND:*] Outbound Headers: #[headers:OUTBOUND:*] Exception is: #[exception]" level="INFO" doc:name="Logger"/>
</flow>
Activity Publication Service -- Core Flow
<flow name="edustreamesbFlow1" doc:name="edustreamesbFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="${http.port}" doc:name="HTTP" contentType="application/json" mimeType="application/json" path="api/v1" connector-ref="EduStreamESB_HTTP"/>
<jersey:resources doc:name="REST">
<component class="edu.ucdavis.edustream.esb.activity.restapi.ActivityController"/>
</jersey:resources>
<component class="edu.ucdavis.edustream.esb.activity.restapi.JerseyResponseTransformer" doc:name="JerseyRespTrans"/>
<flow-ref name="PublishActivity" doc:name="Publish Activity"/>
</flow>
<sub-flow name="PublishActivity" doc:name="PublishActivity">
<component doc:name="ActivityService">
<spring-object bean="activityService"/>
</component>
<logger message="#[payload] #[message]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" host="${edustream.host}" port="80" path="api/v1/activity" mimeType="application/json" contentType="application/json" doc:name="HTTP" connector-ref="EduStream_HTTP"/>
</sub-flow>
I do not get why proxyHostname and proxyPort are configured on both EduStream_HTTP and EduStreamESB_HTTP connectors while the HTTP endpoints from these connectors target the same host/port as their destination address. This doesn't make any sense to me.
Are you really sure you need to use proxies?
For EduStreamESB_HTTP the answer is clearly no: you're calling CloudHub from CloudHub, so no need for a proxy.
For EduStreamESB_HTTP, maybe... but that still seems very strange.

Timed Mule Web Service Client Flow

I've searched the forums for an answer to this. I found one almost identical question, though the answer left me still wondering.
An almost identical post was found here:
Mule - Schedule a flow to consume a web service
This poster stated the problem I am having very well.
I am also new to Mule and am trying to do the very same thing. I didnt realize I needed a payload since I thought the operation specification was essentially the payload.
Notice that I have a flow that includes cxf:jaxws-client and that client specifies a URL for the service and an operation "listTest".
What other payload do i need to specify in order to actually execute the service request?
I tried to add a dummy payload to the event generator (as suggested in referenced post), and that doesnt make a difference.
When I execute the mule application, and monitor the "test auditor web service" (using wireshark) i see four requests go out for the wsdl, and i see that wsdl returned, but i dont actually see the listTest operation getting invoked.
My flow is:
<http:connector name="HTTP_HTTPS" cookieSpec="netscape"
validateConnections="true" sendBufferSize="0" receiveBufferSize="0"
receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000"
socketSoLinger="0" doc:name="HTTP\HTTPS" />
<flow name="TestAuditorClient_CheckerFlow1" doc:name="TestAuditorClient_CheckerFlow1">
<quartz:outbound-endpoint jobName="GetTestList"
repeatInterval="10000" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job jobGroupName="GetTestList" />
</quartz:outbound-endpoint>
<cxf:jaxws-client operation="listTest"
clientClass="server.TestService_Service" port="TestServicePort"
wsdlLocation="http://192.168.66.7:8080/TestAuditorWebApp/TestService?wsdl"
doc:name="SOAPY" />
<outbound-endpoint
address="http://192.168.66.7:8080/TestAuditorWebApp/TestService"
doc:name="HTTP" />
<logger message="Received HTTP Response #[payload]" level="INFO"
doc:name="Logger" />
<!-- <outbound-endpoint exchange-pattern="request-response" address="http://192.168.66.17:8080/TestAuditorWebApp/TestService"
doc:name="HTTP"/> -->
<file:outbound-endpoint path="C:\tmp"
outputPattern="#[function:datestamp:dd-MM-yy]_#[function:systime].txt"
responseTimeout="10000" doc:name="Output File" />
</flow>
I am not only new to mule, but as well to stack overflow. So if there was a better way for me to ask a related question, please advise and excuse.
Thanks in advance.
Instead of Quartz, you can use a poll message processor to generate the instances of ListTest you need.
Assuming this class FQDN is server.TestService.ListTest (you didn't tell), the following should work:
<flow name="TestAuditorClient_CheckerFlow1">
<poll frequency="10000">
<set-payload value="#[lt=new server.TestService.ListTest(); lt.aField='aValue'; lt]" />
</poll>
...
Notice how you can set values on the POJO directly from the expression that creates it.