org.mule.routing.AsynchronousUntilSuccessfulProcessingStrategy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mule-core Show documentation
Show all versions of mule-core Show documentation
Mule server and core classes
/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.routing;
import static org.mule.routing.UntilSuccessful.DEFAULT_PROCESS_ATTEMPT_COUNT_PROPERTY_VALUE;
import static org.mule.routing.UntilSuccessful.PROCESS_ATTEMPT_COUNT_PROPERTY_NAME;
import org.mule.DefaultMuleEvent;
import org.mule.DefaultMuleMessage;
import org.mule.VoidMuleEvent;
import org.mule.api.MessagingException;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.MuleMessage;
import org.mule.api.exception.MessagingExceptionHandler;
import org.mule.api.exception.MessagingExceptionHandlerAware;
import org.mule.api.lifecycle.Initialisable;
import org.mule.api.lifecycle.InitialisationException;
import org.mule.api.lifecycle.Startable;
import org.mule.api.lifecycle.Stoppable;
import org.mule.api.store.ObjectStoreException;
import org.mule.config.ExceptionHelper;
import org.mule.config.i18n.CoreMessages;
import org.mule.config.i18n.MessageFactory;
import org.mule.message.DefaultExceptionPayload;
import org.mule.retry.RetryPolicyExhaustedException;
import org.mule.util.concurrent.ThreadNameHelper;
import org.mule.util.queue.objectstore.QueueKey;
import org.mule.util.store.QueuePersistenceObjectStore;
import java.io.Serializable;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Until successful asynchronous processing strategy.
*
* It will return successfully to the flow executing the router once it was able to
* store the message in the object store.
*
* After that it will asynchronously try to process the message through the internal route.
* If route was not successfully executed after the configured retry count then the message
* will be routed to the defined dead letter queue route or in case there is no dead letter
* queue route then it will be handled by the flow exception strategy.
*/
public class AsynchronousUntilSuccessfulProcessingStrategy extends AbstractUntilSuccessfulProcessingStrategy implements Initialisable, Startable, Stoppable, MessagingExceptionHandlerAware
{
private static final String UNTIL_SUCCESSFUL_MSG_PREFIX = "until-successful retries exhausted. Last exception message was: %s";
private static final Random random = new Random();
protected transient Log logger = LogFactory.getLog(getClass());
private MessagingExceptionHandler messagingExceptionHandler;
private ExecutorService pool;
private ScheduledExecutorService scheduledRetriesPool;
@Override
public void initialise() throws InitialisationException
{
if (getUntilSuccessfulConfiguration().getObjectStore() == null)
{
throw new InitialisationException(
MessageFactory.createStaticMessage("A ListableObjectStore must be configured on UntilSuccessful."),
this);
}
}
@Override
public void start()
{
final String threadPrefix = String.format("%s%s.%s", ThreadNameHelper.getPrefix(getUntilSuccessfulConfiguration().getMuleContext()),
getUntilSuccessfulConfiguration().getFlowConstruct().getName(), "until-successful");
pool = getUntilSuccessfulConfiguration().getThreadingProfile().createPool(threadPrefix);
scheduledRetriesPool = getUntilSuccessfulConfiguration().createScheduledRetriesPool(threadPrefix);
scheduleAllPendingEventsForProcessing();
}
@Override
public void stop()
{
scheduledRetriesPool.shutdown();
scheduledRetriesPool = null;
pool.shutdown();
pool = null;
}
@Override
protected MuleEvent doRoute(MuleEvent event) throws MessagingException
{
try
{
final Serializable eventStoreKey = storeEvent(event);
scheduleForProcessing(eventStoreKey, true);
if (getUntilSuccessfulConfiguration().getAckExpression() == null)
{
return VoidMuleEvent.getInstance();
}
return processResponseThroughAckResponseExpression(event);
}
catch (final Exception e)
{
throw new MessagingException(
MessageFactory.createStaticMessage("Failed to schedule the event for processing"), event, e,
getUntilSuccessfulConfiguration().getRouter());
}
}
private void scheduleAllPendingEventsForProcessing()
{
try
{
for (final Serializable eventStoreKey : getUntilSuccessfulConfiguration().getObjectStore().allKeys())
{
try
{
scheduleForProcessing(eventStoreKey, true);
}
catch (final Exception e)
{
logger.error(MessageFactory.createStaticMessage("Failed to schedule for processing event stored with key: " + eventStoreKey), e);
}
}
}
catch (Exception e)
{
logger.warn("Failure during scheduling of until successful previous jobs " + e.getMessage());
if (logger.isDebugEnabled())
{
logger.debug(e);
}
}
}
private void scheduleForProcessing(final Serializable eventStoreKey, boolean firstTime)
{
if (firstTime)
{
submitForProcessing(eventStoreKey);
}
else
{
this.scheduledRetriesPool.schedule(new Callable