Dynamically setting values for twitter configuration Mulesoft - mule

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.

Related

Mule Http Listner getting url parameter values

<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.

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.

How to capture an exception using the regex-filter filter in Mule ESB

Currently I have a flow that exposes a REST service with a string as input parameter . I am using a regex -filter to ensure the format parameter as follows :
<http:inbound-endpoint doc:name="HTTP"
connector-ref="ciuServiceHTTPConnector" ref="ciuServiceHTTPEndpoint"
exchange-pattern="request-response" />
<logger level="INFO" doc:name="Logger" message="epale1 #[payload]"/>
<regex-filter pattern="^/api/person/(V|E)[0-9]{8}$"
doc:name="Regex" />
<logger message="epale2 #[payload]" level="INFO" doc:name="Logger"/>
<jersey:resources doc:name="REST" >
<component class="...resource.CiudadanoResource"/>
</jersey:resources>
I need to send the customer a message "Invalid or missing parameter" . For this I use a choice-exception-strategy and catch-exception-strategy and then call a Subflow and perform http:response-builder.
How can I throw an exception(type) when the regex-filter do not match?. It is possible to incorporate this behavior or should I change my flow?
Thanks for your help;
Wrap it in a message-filter, like this:
<message-filter throwOnUnaccepted="true">
<regex-filter pattern="^/api/person/(V|E)[0-9]{8}$"
doc:name="Regex" />
</message-filter>
See the official documentation for further details:
Check the Throw On Unaccepted box to throw an exception if a message
or event is not handled. The default when not checked is to not throw
an exception.

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.

Get message inbound properties

im having trouble getting message inbound properties, somehow its coming as null, here is the code:
<scripting:transformer name="noopLoggingTransformer">
<scripting:script engine="groovy">
log.info "${message.getInboundProperty('user-agent')}"
muleContext.client.dispatch('vm://log-request.in', message)
message
</scripting:script>
</scripting:transformer>
<pattern:web-service-proxy name="service" transformer-refs="noopLoggingTransformer" inboundAddress="${serverName}/services/Logradouros/LogradouroServico" outboundAddress="${targetServer}/servicos/v2/service.svc" wsdlFile="LogradouroServicos.wsdl">
</pattern:web-service-proxy>
<jdbc-ee:postgresql-data-source name="WSA" user="${database.user}" password="${database.pass}" url="${database.url}" transactionIsolation="UNSPECIFIED" doc:name="PostgreSQL Data Source">
</jdbc-ee:postgresql-data-source>
<jdbc-ee:connector name="jdbcConnector" dataSource-ref="WSA" validateConnections="false" transactionPerMessage="true" queryTimeout="10" pollingFrequency="10000" doc:name="JDBC">
<jdbc-ee:query key="wsadb" value="insert into inbound_messages (payload, timestamp, agent, ip_from, endpoint, soap_operation) values ('', now(), #[groovy: return message.getInboundProperty('user-agent').toString()], #[groovy: return message.getInboundProperty('MULE_REMOTE_CLIENT_ADDRESS').toString()], #[groovy: return message.getInboundProperty('http.request').toString()], '');"></jdbc-ee:query>
</jdbc-ee:connector>
<flow name="log-request" doc:name="log-request">
<vm:inbound-endpoint path="log-request.in" />
<logger message="#[message.inboundProperties['user-agent']]" level="INFO" doc:name="Logger"/>
<jdbc-ee:outbound-endpoint exchange-pattern="one-way" queryKey="wsadb" responseTimeout="10000" queryTimeout="-1" connector-ref="jdbcConnector" doc:name="Persist raw message" />
</flow>
What it prints out is "null" and i dont know how to make it print the property from message...
No need to use Groovy:
<logger message="#[message.inboundProperties['user-agent']]" level="INFO" doc:name="Logger"/>
But your bigger issue is that you are not propagating the inbound properties to the outbound scope prior to dispatching to vm://log-request.in.
You need to propagate the properties you want to carry forward:
<scripting:transformer name="noopLoggingTransformer">
<scripting:script engine="groovy">
def props = [:]
props['User-Agent'] = message.getProperty('User-Agent', org.mule.api.transport.PropertyScope.INBOUND)
muleContext.client.dispatch('vm://log-request.in', payload, props)
message
</scripting:script>
</scripting:transformer>
Of course, you can iterate the inbound property names to copy them all.
Property name is User-Agent and as David pointed out, #message.inboundProperties['User-Agent']] is the MEL way to get it.
Did you make sure User-Agent property is set on the mule message when you're trying to access it. It's not always there
Remember inbound properties are not propagated unless you copy property manually like by
<copy-properties propertyName="*"/>