I have a flow that takes a pair of dates inbound and then uses a message enricher to get a list of employees that worked on a specific job between those two dates. The result is a simple list of maps returned from a JDBC database. I got that saved into a flow variable without any trouble. The next enrichment is causing me trouble. I setup a for each loop that uses the employees list from the flow variable. This works great and I then need to execute another JDBC query for each of these employees to get all the time tickets they turned in between the two dates passed to the flow. The query works but I am having trouble defining the target expression to hold the result. I would like to see the target be a map with the employee id as the key and the tickets for the period (list of maps) be the value. Is there any way to do this? Is there a better way to save these results? After I get all the tickets, I need to summarize them in various ways and generate a report showing the detail as well as the analysis.
I am currently developing this in mule studio for the community runtime version 3.4.
Is this like something that you are looking for?
<set-variable variableName="maplistmap" value="#[new java.util.HashMap()]"/>
<foreach>
<jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="selekt" queryTimeout="-1" connector-ref="Database">
<jdbc-ee:query key="selekt" value="select * from mytable where id = #[payload]"/>
</jdbc-ee:outbound-endpoint>
<scripting:component>
<scripting:script engine="Groovy"><![CDATA[
flowVars["maplistmap"].put(payload[0].id, payload)
]]></scripting:script>
</scripting:component>
</foreach>
<logger message="#[flowVars.maplistmap]" level="INFO"/>
Related
I'm trying to connect to SQL Database with some configuration. But based on the input from the API we are supposed to hit different DB.
As of now, we have the code as
<choice doc:name="Check myFlag">
<when expression="#[flowVars.myFlag == 'true']">
<db:stored-procedure config-ref="Database_Configuration_1" doc:name="DB_config_1">
<db:dynamic-query><![CDATA[#[flowVars.callSPName]]]></db:dynamic-query>
</db:stored-procedure>
</when>
<otherwise>
<db:stored-procedure config-ref="Database_Configuration_2" doc:name="DB_config_2">
<db:dynamic-query><![CDATA[#[flowVars.callSPName]]]></db:dynamic-query>
</db:stored-procedure>
</otherwise>
</choice>
Instead of repeating <db:stored-procedure../> twice, is there a way where I can set a flow var with the DB config reference and use it?
Something like,
<db:stored-procedure config-ref="#[flowvars.db_config]" doc:name="DB_config_2">
<db:dynamic-query><![CDATA[#[flowVars.callSPName]]]></db:dynamic-query>
</db:stored-procedure>
In Mule 3, no. config-ref's are evaluated at application startup, not runtime.
In Mule 4 this is possible using Dynamic Configurations: https://docs.mulesoft.com/mule-sdk/1.1/static-dynamic-configs
Potential Mule 3 solutions documented here: https://help.mulesoft.com/s/article/How-to-configure-connector-with-dynamic-parameters
Put the DB call inside a sub-flow and call it from the rest of the flows with a <flow-ref>.
I have sfdc (salesforce connector) inside poller and enabled the watermarking for it after then getting data from sfdc and loading it to Database.
<flow name="loadData" processingStrategy="synchronous">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="2" timeUnit="MINUTES"/>
<watermark variable="timestamp" default-expression="#[server.dateTime.format("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")]" selector="MAX" selector-expression="#[payload.LastModifiedDate]" object-store-ref="sfdcStore"/>
<processor-chain doc:name="Processor Chain">
<logger message="poller started at #[server.dateTime]" level="INFO" doc:name="start"/>
<sfdc:query config-ref="svccloud_salesforce_configuration" query="SELECT Name, , Id, BillingStreet, BillingCity, BillingState, BillingCountry, BillingPostalCode, Phone, Pathway_Status__c FROM Account where LastModifiedDate < #[flowVars['timestamp']] and RecordTypeId IN (SELECT Id FROM RecordType where Name = 'Customer')" doc:name="Querying Customer Details"/>
</processor-chain>
</poll>
<logger message="process to DB" level="INFO"/>
</flow>
Data is getting and loading properly to DB but latest Date is not getting stored in the timestamp variable. I am getting below info message. If timestamp value is stored what is message we will get. Can you please help on this
INFO 2017-08-28 15:06:26,795 [pool-13-thread-1] org.mule.transport.polling.watermark.Watermark: Watermark value will not be updated since poll processor returned no results
The query doesn't actually select LastModifiedDate, so when the poll tries to update it, it will allways be null and will not update.
The query selects only records that are before the timestamp, meaning that the MAX watermark will never be updated.
You have to clear your application Data, to resolve this. If you run in studio, the watermark variable gets stored in Object store locally.
If you clear application data, it will work as expected.
Please follow below image to clear Application data.
Right click on project--> Run As --> Run Congiguration --> General Tab--> change Clear Application Data to Always(you need to scroll down to see this option).
enter image description here
Having a requirement to test a object store whether it contains a key or not in a choice router
<objectstore:config name="storeDownload" doc:name="ObjectStore" persistent="false" partition="test"/>
<choice>
<when expression="#[app.registry.storeDownload.contains('#[flowVars.startKey]').equals('false')]">
Getting an error
1. Expression Evaluator "registry" with expression "ON" returned null but a value was required. (org.mule.api.expression.ExpressionRuntimeException)
org.mule.expression.RegistryExpressionEvaluator:101 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/expression/ExpressionRuntimeException.html)
2. Failed to invoke store. Message payload is of type: byte[] (org.mule.api.MessagingException)
The main issue is that you are embedding MEL into MEL which can't work. Also the boolean-as-string comparison is dodgy.
Replace this:
#[app.registry.storeDownload.contains('#[flowVars.startKey]').equals('false')]
with that:
#[!(app.registry.storeDownload.contains(flowVars.startKey))]
My use case was a bit different to Nazar's I needed to monitor a long running process which can take up to four hours.
In the first flow I generate a key value with a time stamp in it as the payload and then use it to set the ProcessState to the static value 'Started' in an ObjectStore as shown below. After which I fire a Quartz Outbound Endpoint with a four hour delay.
<objectstore:store config-ref="MonitoredProcess" value-ref="Started" key="#[payload]" doc:name="ObjectStore"/>
<quartz:outbound-endpoint jobName="ProcessMonitor" responseTimeout="10000" doc:name="Quartz"
repeatInterval="0" repeatCount="0" startDelay="${process.monitor.event.start.delay}">
<quartz:scheduled-dispatch-job>
<quartz:job-endpoint address="vm://processMonitorQueue"/>
</quartz:scheduled-dispatch-job>
</quartz:outbound-endpoint>
And I got the same exception.
After scratching my head and lots of searches the name of the variable 'value-ref' in combination with David's answer above finally revealed my problem namely the MEL is always invoked for this ref field.
As soon as I changed the field to an expression #['Started'] that MEL could evaluate my problem went away.
<objectstore:store config-ref="MonitoredProcess" value-ref="#['Started']" key="#[payload]" doc:name="ObjectStore"/>
For completeness I've included the code that retrieves the ProcessState from the ObjectStore. Note the defaultValue-ref also needs to use MEL
<vm:inbound-endpoint exchange-pattern="one-way" path="processMonitorQueue" doc:name="VM" />
<objectstore:retrieve config-ref="MonitoredProcess" defaultValue-ref="#['DoesNotExist']" key="#[payload]" targetProperty="processState" doc:name="ObjectStore"/>
I have a flow that calls a MS SQL stored procedure which returns a value. The output that i get from the DB is {resultset1=[{id=30}]} i would like to store the value of id to flow variable
couldn't find a successful way to do this, Could somebody please help me in this
I'am using mule server 3.4.0 EE
Thank you in Advance
First place a json-to-object-transformer and then try the following :-
<json:json-to-object-transformer returnClass="java.util.HashMap" />
<set-variable variableName="id" value="#[payload.resultset1[0].id]" doc:name="Variable"/>
As of now ,when I poll the database with a query,It will fetch me multiple records during a specified duration.Problem is ,these multiple records will be pushed as a single message into the queue.How do I push every record from the set of records as an individual message?
As you have explained the JDBC endpoint is fetching a collection of records and sending them as one single message to the queue. Solution for this is two options.
Using Mule's For-Each message processor. This helps in iterating through the collection object and processes each item as one message.
Using Mule's collection splitter to iterate through the collection of records.
Solution for option 1 looks like as shown in the image below.
The code for this flow loks like this.
<flow name="JDBC-For-Each-JMS-Flow" >
<jdbc-ee:inbound-endpoint queryKey="SelectAll" mimeType="text/javascript" queryTimeout="500000" pollingFrequency="1000" doc:name="Database">
<jdbc-ee:query key="SelectAll" value="select * from users"/>
</jdbc-ee:inbound-endpoint>
<foreach doc:name="For Each" collection="#[payload]" >
<jms:outbound-endpoint doc:name="JMS"/>
</foreach>
<catch-exception-strategy doc:name="Catch Exception Strategy"/>
</flow>
Note: This is a sample flow.
Hope this helps.