Mule Http Listner getting url parameter values - mule

<flow..>
<http:listener-config name="HTTP_Listener_Configuration" host="${http.hostname}" port="${http.port}" basePath="${http.base.path}" doc:name="HTTP Listener Configuration"/>
<http:listener config-ref="HTTP_Listener_Configuration" path="store/*" doc:name="HTTP"/>
Old http end point
<!-- <http:inbound-endpoint address="http://${http.hostname}:${http.port}/${http.base.path}/store" doc:name="HTTP" exchange-pattern="request-response">
<object-to-string-transformer />
</http:inbound-endpoint> -->
<apikit:router config-ref="store-api-config" doc:name="APIkit Router" />
</flow>
<flow name="get:/rates/search:smartstore-api-config">
<logger message=" #[message.inboundProperties['referenceDate']]" level="INFO" doc:name="Log Request"/>
</flow>
When I try to invoke the url, I am getting null value in logger. If I enable old http end point point it is working fine.
http://localhost:8899/apis/myapp/myrates/search?referenceDate=2015-01-01
I have tried with this link, but didnot work.

1) #[message.inboundProperties.'http.query.params'.referenceDate]
2) #[message.inboundProperties.'http.query.params'.get('referenceDate')]
3) #[message.inboundProperties.get('http.query.params').get('referenceDate')]

try to use this line of code it works properly using MEL
#[message.inboundProperties.get('http.query.params').get('referenceDate')]
also you can set this value inside a variable and handle it in any way you want

When it comes to Java, to you read parameters like:
eventContext.getMessage().<Map<String,Object>>getInboundProperty("http.query.params").get("yourParam");
Hope it's usefull.

Related

How to import CSV files in Anypoint studio and convert them into JSON format?

I want to use HTTP Listener in my flows, and import csv files in Anypoint studio as input and convert them into JSON. Please help me.
you can just use a transform message and convert payload to json.
as you can see i am reading a file called address.csv.
in the transform message you can simple right
and in my logger you can see that contents of file converted to json
note -------------------------------------------------
if you want to pick a file in middle of a flow with a http listener you can always use Message-Requester module
here is how the code will look like
<file:connector name="file-connector-config" autoDelete="false" streaming="true" validateConnections="true" doc:name="File" />
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" basePath="/requester" doc:name="HTTP Listener Configuration" />
<flow name="muleRequester">
<http:listener config-ref="HTTP_Listener_Configuration" path="/requester" doc:name="HTTP" />
<logger message="Invoking Mule Requester" level="INFO" doc:name="Logger" />
<mulerequester:request resource="file://src/main/resources/in/ReadME.txt?connector=file-connector-config" doc:name="Retrieve File" returnClass="java.lang.String" />
<logger message="Payload after file requester #[payload]" level="INFO" doc:name="Logger" />
</flow>
refer link --> https://dzone.com/articles/mule-reading-file-in-the-middle-of-a-flow-using-mu
Maybe I'm misunderstanding the question, but if you'd like the http listener kick off the flow, then to load the file, you'll need a groovy script.
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[return new File("C:\test.csv").getText("UTF-8");]]></scripting:script>
</scripting:component>

Dynamically setting values for twitter configuration Mulesoft

Using mulesoft twitter connector an dynamically setting values for the twitter config parameters as shown below,
<twitter:config name="Twitter__Configuration" accessKey="#[flowVars.accessToken]" consumerKey="#[flowVars.consumerKey]" consumerSecret="#[flowVars.consumerSecret]" doc:name="Twitter: Configuration" accessSecret="#[flowVars.accessTokenSecret]"/>
<flow name="twitterFlow1">
<db:select config-ref="MySQL_Configuration" doc:name="Database">
<db:parameterized-query><![CDATA[select * from twittercredentials;]]></db:parameterized-query>
</db:select>
<set-variable variableName="consumerKey" value="#[message.payload[0]['consumerkey']]" doc:name="Variable" />
<set-variable variableName="consumerSecret" value="#[message.payload[0]['consumersecret']]" doc:name="Variable" />
<set-variable variableName="accessToken" value="#[message.payload[0]['accesstoken']]" doc:name="Variable" />
<set-variable variableName="accessTokenSecret" value="#[message.payload[0]['accesstokensecret']]" doc:name="Variable" />
</flow>
<flow name="twitterFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/twitterconnect" doc:name="HTTP"/>
<flow-ref name="twitterFlow1" />
<twitter:show-user config-ref="Twitter__Configuration" doc:name="Twitter"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
But I get an exception when invoking /twitterconnect,
Failed to connect/reconnect: Work Descriptor. Root Exception was: 401 response received, but no WWW-Authenticate header was p
resent. Type: class java.lang.IllegalStateException
Works fine with hard coded values in the twitter config. Any help please?
I think that won't work because you instance the twitter:config only one time and is empty.
You should find the way to create a new configuration and inject it to the twitter component.
Try This:
Create a properties file and write the AccessKey, AccessSecret, ConsumerKey, ConsumerSecret values in the properties file with references, and enter the details in the twitter connector as ${} and place the references inside the braces.

How to use Mule Expression in JMS:selector

I checked several previous discussions but couldnt find the answer.
I am trying to achieve synchronous communicaiton using JMS back-channel (http://www.whishworks.com/blog/synchronous-communication-using-jms-back-channel). Apart from the things mentioned in that site, I need to filter out the message from the inbound queue based on a dynamic Id.
Following are my mule flows:
<flow name="serverFlow" >
<jms:inbound-endpoint doc:name="REQUEST" queue="REQUEST.QUEUE" connector-ref="jmsConnector">
<jms:selector expression="MULE_CORRELATION_ID='#[sessionVars.myCorrelationId]'"/>
</jms:inbound-endpoint>
<set-payload value="#[payload] + Hello World from Receiver" doc:name="Set Payload" />
<jms:outbound-endpoint doc:name="REPLY" queue="REPLY.QUEUE" connector-ref="jmsConnector" />
</flow>
<flow name="mainFlow" >
<http:listener config-ref="HTTP_Listener_Configuration" path="/jms" allowedMethods="GET" doc:name="HTTP"/>
<set-session-variable variableName="myCorrelationId" value="#[System.currentTimeMillis().toString()]" doc:name="Set Correlation ID"/>
<set-payload value="New message sent from Mule - mainFlow at #[new Date()]" doc:name="Set Message"/>
<set-property propertyName="MULE_CORRELATION_ID" value="#[sessionVars.myCorrelationId]" doc:name="Property"/>
<request-reply doc:name="Request-Reply">
<jms:outbound-endpoint doc:name="REQUEST" connector-ref="jmsConnector" queue="REQUEST.QUEUE"/>
<jms:inbound-endpoint doc:name="REPLY" connector-ref="jmsConnector" queue="REPLY.QUEUE"/>
</request-reply>
<logger message="Reply to sender: #[message]" level="WARN" doc:name="Logger" />
</flow>
If I try a static value like "<jms:selector expression="MULE_CORRELATION_ID='12345'"/>", it works. But if I try a dynamic ID using MEL, its not working. The MEL inside the jms selector expression is not working. The message stays at the queue as Unread. I used logs to see what the MULE_CORRELATION_ID is while being set at mainFlow and found the same value is set in the message that is UNREAD in the queue. So, I guess nothing is wrong in the way the MULE_CORRELATION_ID is set. The only problem is that MEL is not working within jms:selector.
Could you please help how to get MEL working within JMS selector?
Thank you very much.
MEL is working fine in the selector but its usage is very limited. When the JMS selector is created, there's no in-flight event available to Mule so none of the event-bound data (including session) is available.
To select a very particular message, you need to use a JMS message requester, constructed with the desired selector, like:
jms://REQUEST.QUEUE?selector=MULE_CORRELATION_ID%3D'#[sessionVars.myCorrelationId]'
Here is the working solution based on David's suggestion. I am using wmq here (not jms).
<mulerequester:config name="Mule_Requester" doc:name="Mule Requester"/>
<flow name="mainFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" allowedMethods="GET" doc:name="HTTP"/>
<set-payload value="My Message" doc:name="Set Message"/>
<set-property propertyName="JMSCorrelationID" value="12345" doc:name="Property"/>
<set-session-variable variableName="myCorrelationId" value="ID:313233343500000000000000000000000000000000000000" doc:name="Set Correlation ID"/>
<!--313233343500000000000000000000000000000000000000 is the MQMD CorrelationId for 12345. This is set by IBM MQ -->
<logger message="The Message to REQUEST QUEUE: #[message]" level="WARN" doc:name="Logger"/>
<wmq:outbound-endpoint queue="REQUEST.QUEUE" connector-ref="wmqConnector" doc:name="OUT"/>
<mulerequester:request config-ref="Mule_Requester" resource="wmq://REPLY.QUEUE?selector=JMSCorrelationID%3D'#[sessionVars.myCorrelationId]'" doc:name="Mule Requester" timeout="120000"/>
<logger message="Final Response: #[message]" level="WARN" doc:name="Logger"/>
</flow>
Please note, I manually moved the message from Request queue to Reply queue using MQVE for my testing. In real time, it will be done by another program.

Error: unresolvable property or identifier: Base64

I'm trying to call a REST service that is protected by basic authentication and I can't get this work. Basically, I need to setup the authorization header as
"Authorization: Basic [base64 encoded user name and password]".
My flow looks like this:
<flow name="testjsonFlow1" doc:name="testjsonFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="testjson" doc:name="HTTP"/>
<set-property propertyName="Authorization" doc:name="Set Authentication Header" value="#["Basic " + Base64.encodeBase64String("username:password")]"/>
<http:outbound-endpoint exchange-pattern="request-response" host="<url>" port="80" path="Services/V1/testservices" method="POST" contentType="text/plain" doc:name="HTTP"/>
<echo-component doc:name="Echo"/>
</flow>
Invoking this flow results in the following error:
[Error: unresolvable property or identifier: Base64]
[Near : {... "Basic " + Base64.encodeBase64String("com ....}]
I see that the MuleStudio ships with commons-codec-1.3-osgi.jar while the Base64 API is not included and only comes with later version.
So my questions are:
Is this the right way to call a REST service that is protected with basic auth?
How can I resolve this issue?
How can I make the Mulestudio reference the commons-codec-1.9 jar instead of the commons-codec-1.3-osgi.jar?
Environment details: Windows 7 64 bit, Mule CE 3.4.
Any help is appreciated.
Update 1:
I made some updates to the script and it works now. Here is the updated script:
<flow name="testjsonFlow1" doc:name="testjsonFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="testjson" doc:name="HTTP" />
<set-variable variableName="uName" doc:name="Variable" value="domain\user"/>
<set-variable variableName="pwd" doc:name="Variable" value="P#ssword"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy">
<scripting:text><![CDATA[
def cred = message.getInvocationProperty("uName") + ":" + message.getInvocationProperty("pwd")
def credBytes = cred.bytes
def encodedCred = credBytes.encodeBase64().toString()
message.setProperty("credential",encodedCred)
return null;]]></scripting:text>
</scripting:script>
</scripting:component>
<set-property propertyName="Authorization" doc:name="Set Authentication Header" value="Basic #[header:OUTBOUND:credential]"/>
<logger level="INFO" doc:name="Logger"/>
<logger message="#[message.outboundProperties['Authorization']]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" host="myserver.com" port="80" path="Services/V1/service1/" method="POST" contentType="text/plain" doc:name="HTTP" />
</flow>
Answering your question to david in the comments above but hate pasting code into the comment editor.
You can add the user and pw to the endpoint and it'll base64 encode it like above.
<http:outbound-endpoint exchange-pattern="request-response"
host="foo.bar.com" port="80"
path="getFoo" method="GET"
user="username" password="password">
</http:outbound-endpoint>
<configuration>
<expression-language>
<import class="org.apache.commons.codec.binary.Base64" />
</expression-language>
</configuration>
or use the fully qualified class name in your expression.
But...
No, configure the username and password on the endpoint. See: http://www.mulesoft.org/documentation/display/current/Mule+Endpoint+URIs
Ditto.
Don't. Stick to the version provided by Mule. If you insist on using a most recent version, you'll need to package it with your application and use classloader override to ensure your application will use the packaged Commons Codec. See: http://www.mulesoft.org/documentation/display/current/Classloader+Control+in+Mule#ClassloaderControlinMule-Fine-GrainedClassloadingControl
Embedding user name and password on the http:outbound-endpoint didn't work as the password had a special character ('#') which was throwing a different exception. I made it work with a different approach and updated it in the question.

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>