Mule Quartz Connector terminates abruptly after running for hours - mule

My Mule Quartz Connector runs for several hours then terminates abruptly. I want the job to run continuously every 30 minutes past the hour. However, after running for several hours it suddenly terminates. I suspect it is related to the cronExpression but I am not sure which part will cause that to happen. I feel that the cronExpression has something that is making this happen, as it simply shuts the application down terminating the process.
Please help!!
Here is the quartz configuration:
<quartz:connector name="updateQuartzConnector" validateConnections="true" doc:name="Quartz">
<receiver-threading-profile maxThreadsActive="1"/>
<quartz:factory-property key="org.quartz.scheduler.instanceName" value="updateQuartzScheduler"/>
<quartz:factory-property key="org.quartz.threadPool.class" value="org.quartz.simpl.SimpleThreadPool"/>
<quartz:factory-property key="org.quartz.threadPool.threadCount" value="1"/>
<quartz:factory-property key="org.quartz.scheduler.rmi.proxy" value="false"/>
<quartz:factory-property key="org.quartz.scheduler.rmi.export" value="false"/>
<quartz:factory-property key="org.quartz.jobStore.class" value="org.quartz.simpl.RAMJobStore"/>
</quartz:connector>
And here is the flow using the quartz configuration above:
<flow name="processClientData" tracking:enable-default-events="true" processingStrategy="synchronous">
<quartz:inbound-endpoint responseTimeout="10000" doc:name="30 minutes past hour" cronExpression="0 30/30 0/1 * * ?"
jobName="ProcessClientUpdates" repeatInterval="0" connector-ref="updateQuartzConnector">
<quartz:event-generator-job/>
</quartz:inbound-endpoint>
<flow-ref name="process.client.data" />
</flow>
I show part of the flow, although this part works fine:
<flow name="process.client.data" processingStrategy="synchronous">
<db:select config-ref="ORACLE_CONFIG" doc:name="Check Customer existence in Database">
<db:parameterized-query><![CDATA[SELECT first_name,last_name,email FROM contact
WHERE email=#[payload.email]]]></db:parameterized-query>
</db:select>
<enrich source="#[payload.size() > 0]" target="#[recordVars['exists']]"/>
<enrich source="#[payload]" target="#[recordVars['dbRecord']]"/>
.......
</flow>
Please help this issue is just perplexing

The cron expression should be 0 30/30 * * *?

Related

How to set a Max number of parallel VM flows

I have a request-response flow that starts with VM. Is there a way to restrict a number of the requests that could be processed in parallel by the flow? I'm on 3.7. Thanks.
Ps. I've tried using maxThreadsActive in VM connector but it still runs in the "source" thread. This is how the VM connector in defined:
<vm:connector name="myvm" validateConnections="true" doc:name="VM">
<receiver-threading-profile maxThreadsActive="1"/>
<vm:queue-profile>
<default-in-memory-queue-store/>
</vm:queue-profile>
</vm:connector>
and then in the flow:
<vm:inbound-endpoint exchange-pattern="request-response" path="myqueue" connector-ref="myvm" doc:name="getevent">
<vm:transaction action="NONE"/>
</vm:inbound-endpoint>
This is how it's called from the "source" flow:
<vm:outbound-endpoint exchange-pattern="request-response" path="myqueue" connector-ref="myvm" doc:name="VM">
<vm:transaction action="NONE"/>
</vm:outbound-endpoint>
You can configure the number of receiver threads for the connector or your inbound-endpoint to one:
<vm:connector name="VM" validateConnections="true">
<receiver-threading-profile maxThreadsActive="1"/>
</vm:connector>
<flow name="testFlow1">
<vm:inbound-endpoint path="in" connector-ref="VM"/>
<echo-component/>
</flow>
You can control this with the threading profiles. For example:
<configuration >
<default-threading-profile maxBufferSize="100" maxThreadsActive="20" maxThreadsIdle="10" threadTTL="60000" poolExhaustedAction="RUN" />
</configuration>
You can read more here: https://docs.mulesoft.com/mule-user-guide/v/3.7/tuning-performance

Issues with Mule ESB collection-aggregator processing

A simplified version of the process I am trying to accomplish is that I will have sets of files which should be processed, in order, and only as complete sets. For proof of concept, I have created a flow to collect a set of two files named as "File1*YYMMDD*.txt" and "File2*YYMMDD*.txt" which will constitute a set for date YYMMDD. I use a file inbound-endpoint to watch for files and use the date portion of the name to define a correlation ID. A collection-aggregator then groups these into a set of 2 and a file outbound then dispatched the files from the set:
<configuration>
<default-threading-profile doThreading="false" />
</configuration>
<flow name="Aggregator">
<file:inbound-endpoint path="G:/SourceDir" moveToDirectory="G:/SourceDir/Archive"
responseTimeout="10000" doc:name="get-working-files"
pollingFrequency="5000" fileAge="600000">
<file:filename-regex-filter pattern="File1(.*).txt|File2(.*).txt" caseSensitive="false"/>
<message-properties-transformer>
<add-message-property key="MULE_CORRELATION_GROUP_SIZE" value="2" />
<add-message-property key="MULE_CORRELATION_ID"
value="#[message.inboundProperties
.originalFilename
.substring(5, message.inboundProperties.originalFilename.lastIndexOf('.'))]" />
</message-properties-transformer>
</file:inbound-endpoint>
<collection-aggregator timeout="86400000" failOnTimeout="false" doc:name="Collection Aggregator">
</collection-aggregator>
<foreach doc:name="For Each">
<logger message="Processing: #[message.inboundProperties.originalFilename]" level="INFO"
doc:name="Some process"/>
<file:outbound-endpoint responseTimeout="10000" doc:name="Destination"
outputPattern="#[function:datestamp:yyyyMMdd.HHmmss].#[message.inboundProperties.originalFilename]"
path="G:/DestDir"/>
</foreach>
</flow>
The issues I have are two-fold.
1) If I have only one file from the set, say File2150102.txt, the flow correctly identifies the set is incomplete and waits. After about 1 minute, the file again has a lock put on it and is accepted as the second file in the collection. The file is processed through the outbound endpoint and archived, and then this process is attempted again for the file a second time and fails as the file has already been removed:
INFO 2015-07-14 11:19:51,205 [[fileset].connector.file.mule.default.receiver.01] org.mule.transport.file.FileMessageReceiver: Lock obtained on file: G:\SourceDir\File2150102.txt
INFO 2015-07-14 11:21:01,241 [[fileset].connector.file.mule.default.receiver.01] org.mule.transport.file.FileMessageReceiver: Lock obtained on file: G:\SourceDir\File2150102.txt
INFO 2015-07-14 11:21:01,273 [[fileset].connector.file.mule.default.receiver.01] org.mule.api.processor.LoggerMessageProcessor: Processing: File2150102.txt
INFO 2015-07-14 11:21:01,304 [[fileset].connector.file.mule.default.receiver.01] org.mule.lifecycle.AbstractLifecycleManager: Initialising: 'connector.file.mule.default.dispatcher.452370795'. Object is: FileMessageDispatcher
INFO 2015-07-14 11:21:01,304 [[fileset].connector.file.mule.default.receiver.01] org.mule.lifecycle.AbstractLifecycleManager: Starting: 'connector.file.mule.default.dispatcher.452370795'. Object is: FileMessageDispatcher
INFO 2015-07-14 11:21:01,320 [[fileset].connector.file.mule.default.receiver.01] org.mule.transport.file.FileConnector: Writing file to: G:\DestDir\20150714.112101.File2150102.txt
WARN 2015-07-14 11:21:01,336 [[fileset].connector.file.mule.default.receiver.01] org.mule.transport.file.ReceiverFileInputStream: Failed to move file from G:\SourceDir\File2150102.txt to G:\SourceDir\archive\File2150102.txt
INFO 2015-07-14 11:21:01,336 [[fileset].connector.file.mule.default.receiver.01] org.mule.api.processor.LoggerMessageProcessor: Processing: File2150102.txt
INFO 2015-07-14 11:21:01,336 [[fileset].connector.file.mule.default.receiver.01] org.mule.transport.file.FileConnector: Writing file to: G:\DestDir\20150714.112101.File2150102.txt
WARN 2015-07-14 11:21:01,476 [[fileset].connector.file.mule.default.receiver.01] org.mule.transport.file.FileMessageReceiver: Failure trying to remove file G:\SourceDir\File2150102.txt from list of files under processing
I can find no setting which is controlling this iteration of grabbing the file again, my polling frequency is set at 5 seconds, I require a file age of 10 minutes, and gave the collection timeout a very long period of 10 days so it should sit and wait until another file is found, but I do not want it picking up the same file a second time.
2) In a more complex case, I have files: File1150201.txt, File2150201.txt, File1150202.txt, File1150203.txt, and File2150203.txt in the directory. The flow starts grabbing files, correctly finds and processes the set for "150201" and dispatches it. It finds the file for 150202, recognizes it needs the second file and does not process it. It then finds the complete set for "150203" and does process it. I need for it to not process this set until the "150202" set has been processed. Can someone tell me how to get it to wait on the incomplete set and not continue with other sets? I have the correct processing order, just not the ability to wait for the missing file and keep sets in sequence if there is an incomplete set.
I am not sure whether I understand it correctly, but for your issue 1, the matching (and waiting for the incomplete sets) is working for me with the below test flow --
<file:connector name="File" autoDelete="false" streaming="false" validateConnections="true" doc:name="File">
<file:expression-filename-parser />
</file:connector>
<file:connector name="File1" autoDelete="false" outputAppend="true" streaming="false" validateConnections="true" doc:name="File"/>
<vm:connector name="VM" validateConnections="true" doc:name="VM">
<receiver-threading-profile maxThreadsActive="1"></receiver-threading-profile>
</vm:connector>
<flow name="fileaggreFlow2" doc:name="fileaggreFlow2">
<file:inbound-endpoint path="C:\InFile" moveToDirectory="C:\InFile\Archive" responseTimeout="10000" connector-ref="File" doc:name="File">
</file:inbound-endpoint>
<message-properties-transformer overwrite="true" doc:name="Message Properties">
<add-message-property key="MULE_CORRELATION_ID" value="#[message.inboundProperties.originalFilename.substring(5,13)]"/>
<add-message-property key="MULE_CORRELATION_GROUP_SIZE" value="2"/>
<add-message-property key="MULE_CORRELATION_SEQUENCE" value="#[message.inboundProperties.originalFilename.substring(0,5)]"/>
</message-properties-transformer>
<vm:outbound-endpoint exchange-pattern="one-way" path="Merge" doc:name="VM" connector-ref="VM"/>
</flow>
<flow name="fileaggreFlow1" doc:name="fileaggreFlow1" processingStrategy="synchronous">
<vm:inbound-endpoint exchange-pattern="one-way" path="Merge" doc:name="VM" connector-ref="VM"/>
<logger level="INFO" doc:name="Logger"/>
<processor-chain doc:name="Processor Chain">
<collection-aggregator timeout="1000000" failOnTimeout="true" storePrefix="#[MULE_CORRELATION_ID]" doc:name="Collection Aggregator"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<foreach doc:name="For Each">
<logger message="Processing: #[message.inboundProperties.originalFilename]" level="INFO" doc:name="Some process"/>
<file:outbound-endpoint path="C:\TestFile" outputPattern="#[message.inboundProperties.originalFilename.substring(5,17)]" responseTimeout="10000" connector-ref="File1" doc:name="Destination"/>
</foreach>
</processor-chain>
</flow>
It would help if you could post the complete flow. My file names are File120150107.txt (and so on...)
I think your issue is just because you made the failOnTimeout = 'false'. Make it as 'True'
<collection-aggregator timeout="86400000" failOnTimeout="true" doc:name="Collection Aggregator">
.
It will wait for the files ( 2 or 3 files, based on your requirement) until it reached the specific time ( Here, 86400000). Once it exceed, it will fail.
In your case( FailOnTime= 'False'), for example. If you try sending some 4 files. Within the time if only 2 files are received. Incomplete file will be processed ( It wont wait for remaining 2 files).
Try to check how many files you are planning to process, and how long it will take to process ( example:4 files), adjust the time accordingly.

Using Quartz with Mule in Clustered Environment

I have a scenario where , I am trying to read data from Yelp API and want to put it into a ActiveMQ queue after certain intervals, So I am using quartz scheduler for the same.My quartz scheduler runs after every 10 minutes and pushes the data to queue,
All is fine till here,
Now I want this to work in a clustered environment, where I will have 2 instances deployed and listening to same Yelp Endpoint , Now what is happening is, my quartz scheduler from 2 instances are executing at same instance and they extract same information from Yelp ,causing same messages to land up in ActiveMQ queue, that is DUPLICATES,(I want to use clustered environment for High availability purposes, i.e. if any node fails other node can takeover.)
So is there any configuration, in Mule which can promote one node as master and other as failover node.
Thanks for all the help!
This will trigger by the cron expression 0/10 * * * * ? (each 10th second) for one of all nodes running the same application and that connects to the same database (MySQL in this case). The Quartz setup is a bit messy. You need to configure the database etc, but I leave you studying the Quartz docs for that. You should look at version 1.8.x and not 2.x.
It's pretty much a budget alternative of clustering endpoints in Mule EE. It's useful when you do not want to cluster your EE nodes or need to run CE nodes.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:quartz="http://www.mulesoft.org/schema/mule/quartz" xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.6.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/quartz http://www.mulesoft.org/schema/mule/quartz/current/mule-quartz.xsd">
<quartz:connector name="quartzConnector" validateConnections="true" doc:name="Quartz">
<quartz:factory-property key="org.quartz.scheduler.instanceName" value="QuartzScheduler" />
<quartz:factory-property key="org.quartz.scheduler.instanceId" value="AUTO" />
<quartz:factory-property key="org.quartz.jobStore.isClustered" value="true" />
<quartz:factory-property key="org.quartz.scheduler.jobFactory.class" value="org.quartz.simpl.SimpleJobFactory" />
<quartz:factory-property key="org.quartz.threadPool.class" value="org.quartz.simpl.SimpleThreadPool" />
<quartz:factory-property key="org.quartz.threadPool.threadCount" value="3" />
<quartz:factory-property key="org.quartz.scheduler.rmi.proxy" value="false" />
<quartz:factory-property key="org.quartz.scheduler.rmi.export" value="false" />
<quartz:factory-property key="org.quartz.jobStore.class" value="org.quartz.impl.jdbcjobstore.JobStoreTX" />
<quartz:factory-property key="org.quartz.jobStore.driverDelegateClass" value="org.quartz.impl.jdbcjobstore.StdJDBCDelegate" />
<quartz:factory-property key="org.quartz.jobStore.dataSource" value="quartzDataSource" />
<quartz:factory-property key="org.quartz.jobStore.tablePrefix" value="QRTZ_" />
<quartz:factory-property key="org.quartz.dataSource.quartzDataSource.driver" value="com.mysql.jdbc.Driver" />
<quartz:factory-property key="org.quartz.dataSource.quartzDataSource.URL" value="jdbc:mysql://localhost:3306/qrtz" />
<quartz:factory-property key="org.quartz.dataSource.quartzDataSource.user" value="root" />
<quartz:factory-property key="org.quartz.dataSource.quartzDataSource.password" value="" />
<quartz:factory-property key="org.quartz.dataSource.quartzDataSource.maxConnections" value="8" />
</quartz:connector>
<flow name="cFlow1">
<quartz:inbound-endpoint jobName="job1" cronExpression="0/10 * * * * ?" repeatInterval="0" connector-ref="quartzConnector" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job>
<quartz:payload>Job Trigger</quartz:payload>
</quartz:event-generator-job>
</quartz:inbound-endpoint>
<logger level="INFO" message="Got message" doc:name="Logger"/>
</flow>
</mule>
We use 3.5.2-Enterprise edition but not sure if there is restriction on the community edition as such. Can you try the following way and see if that works:
<!-- Quart Connector with one thread to ensure that we don't have duplicate processing at any point of time -->
<quartz:connector name="QuartzConnector" validateConnections="true">
<receiver-threading-profile maxThreadsActive="1" />
</quartz:connector>
Then refer this in your flow wherever you are planning to trigger this action.
<flow name="test">
<quartz:inbound-endpoint jobName="myQuartzJob" cronExpression="${my.job.cron.expression}" repeatInterval="${my.job.repeat.interval}" responseTimeout="${my.job.response.timeout}" connector-ref="QuartzConnector">
<quartz:event-generator-job>
<quartz:payload>blah</quartz:payload>
</quartz:event-generator-job>
</quartz:inbound-endpoint>
</flow>
Hope that works.

Error when creating multiple file transfer flows in mule

I have a need to have three different scheduled jobs for picking up and transferring files to an SFTP server. Using examples I was able to create a single working flow. However, when I replicate that flow and adjust the configuration, I get an error complaining about 2 connectors matching protocol file.
It asks me to specify these, however, I have specified which endpoint should be used for each flow.
Does anyone have any ideas about what I'm doing wrong, or what Mule is looking for?
Flow definitions:
<file:endpoint name="partsDataConnector" path="${partsDataOriginFilePath}" pollingFrequency="5000" doc:name="partsDataFile"/>
<flow name="partsDataTransfer">
<quartz:inbound-endpoint jobName="partsDataTransfer"
repeatInterval="10000" responseTimeout="10000" doc:name="Quartz">
<quartz:endpoint-polling-job>
<quartz:job-endpoint ref="partsDataConnector"/>
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
<sftp:outbound-endpoint host="${destinationFileServerIp}" port="${destinationFileServerPort}"
path="${partsDataDestinationPath}" tempDir="${partsDataDestinationTempDir}"
user="${destinationFileServerUser}" password="${destinationFileServerPassword}"
outputPattern="#[header:originalFilename]" />
</flow>
<file:endpoint name="imageDataConnector" path="${imageDataOriginFilePath}" pollingFrequency="5000" doc:name="partsDataFile"/>
<flow name="imageDataTransfer">
<quartz:inbound-endpoint jobName="imageDataTransfer"
repeatInterval="10000" responseTimeout="10000" doc:name="Quartz">
<quartz:endpoint-polling-job>
<quartz:job-endpoint ref="imageDataConnector"/>
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
<sftp:outbound-endpoint host="${destinationFileServerIp}" port="${destinationFileServerPort}"
path="${imageDataDestinationPath}" tempDir="${imageDataDestinationTempDir}"
user="${destinationFileServerUser}" password="${destinationFileServerPassword}"
outputPattern="#[header:originalFilename]" />
</flow>
<file:endpoint name="customerDataConnector" path="${customerDataOriginFilePath}" pollingFrequency="5000" doc:name="partsDataFile"/>
<flow name="customerDataTransfer">
<quartz:inbound-endpoint jobName="customerDataTransfer"
repeatInterval="10000" responseTimeout="10000" doc:name="Quartz">
<quartz:endpoint-polling-job>
<quartz:job-endpoint ref="customerDataConnector" />
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
<sftp:outbound-endpoint host="${destinationFileServerIp}" port="${destinationFileServerPort}"
path="${customerDataDestinationPath}" tempDir="${customerDataDestinationTempDir}"
user="${destinationFileServerUser}" password="${destinationFileServerPassword}"
outputPattern="#[header:originalFilename]" />
</flow>
Stacktrace:
2014-04-09 06:46:44,924 INFO [org.quartz.core.JobRunShell] Job mule.quartz://customerDataTransfer threw a JobExecutionException:
org.quartz.JobExecutionException: org.mule.transport.service.TransportFactoryException: There are at least 2 connectors matching protocol "file", so the connector to use must be specified on the endpoint using the 'connector' property/attribute. Connectors in your configuration that support "file" are: connector.file.mule.default, connector.file.mule.default.1, (java.lang.IllegalStateException) [See nested exception: org.mule.transport.service.TransportFactoryException: There are at least 2 connectors matching protocol "file", so the connector to use must be specified on the endpoint using the 'connector' property/attribute. Connectors in your configuration that support "file" are: connector.file.mule.default, connector.file.mule.default.1, (java.lang.IllegalStateException)]
at org.mule.transport.quartz.jobs.EndpointPollingJob.doExecute(EndpointPollingJob.java:176)
at org.mule.transport.quartz.jobs.AbstractJob.execute(AbstractJob.java:36)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:534)
The error message is asking you to declare explicit file:connector components. Now you have just file:endpoint components.
If you haven't defined a file connecotr. Try declaring one and add a connector-reference on each of the file endpoints.
<file:connector name="myFileConnector" ></file:connector>
Add the Connector reference on each of the file endpoints as below. Add the reference for all the three file endpoints.
<file:endpoint name="imageDataConnector" connector-ref="myFileConnector" path="${imageDataOriginFilePath}" pollingFrequency="5000" doc:name="partsDataFile"/>
Hope this helps.

Mule: Processing messages in intervals. Delayed message processing

How do I create a delayed JMS message processor in Mule 3.3.1? My goal is to process messages from a queue in certain interval...some listener that wakes up every minute to process messages.
I have the following configuration, but the delay is not honored. When a message is rolled back, it is immediately picked for processing.
<spring:bean id="MQConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<spring:property name="transportType" value="1"/>
<spring:property name="hostName" value="myHost"/>
<spring:property name="port" value="1414"/>
<spring:property name="queueManager" value="myQmgr"/>
</spring:bean>
<jms:connector name="queueConnector" connectionFactory-ref="MQConnectionFactory"
specification="1.1" username="xxx" password="yyy"
disableTemporaryReplyToDestinations="true"
numberOfConcurrentTransactedReceivers="3" maxRedelivery="5">
<service-overrides transactedMessageReceiver="com.mulesoft.mule.transport.jms.TransactedPollingJmsMessageReceiver"/>
</jms:connector>
<jms:endpoint name="someQueue" queue="osmQueue" connector-ref="queueConnector">
<jms:transaction action="ALWAYS_BEGIN"/>
<property key="pollingFrequency" value="60000"/>
</jms:endpoint>
I did a lot of search but am unable to indentify a proper solution. If there is a better option, I'm open. Appreciate any help. 2 days and no response? Did I phrase the question wrong?
Have you tried using Quartz?
This config fires up your JMS inbound every minute
<flow name="ftpFlow2" doc:name="ftpFlow2">
<quartz:inbound-endpoint jobName="job1" repeatInterval="60000" responseTimeout="10000" doc:name="Quartz">
<quartz:endpoint-polling-job>
<quartz:job-endpoint ref="someQueue"/>
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
</flow>