All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mule.providers.SimpleRetryConnectionStrategy Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.
 */
/**
 * Copyright 2012 Bull S.A.S.
 *
 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 * you may not use  this file  except in  compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Jasmine: patch for not outputting stack traces when reconnecting to a JMS resource.
// See: http://jira.jasmine.objectweb.org/browse/MONITORING-165

package org.mule.providers;

import org.mule.config.ExceptionHelper;
import org.mule.config.i18n.CoreMessages;
import org.mule.umo.provider.UMOConnectable;
import org.mule.util.ObjectUtils;

import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;

/**
 * A simple connection retry strategy where the a connection will be attempted X
 * number of retryCount every Y milliseconds. The retryCount and frequency
 * properties can be set to customise the behaviour.
 */

public class SimpleRetryConnectionStrategy extends AbstractConnectionStrategy
{
    public static final int DEFAULT_FREQUENCY = 2000;
    public static final int DEFAULT_RETRY_COUNT = 2;
    public static final int RETRY_COUNT_FOREVER = -1;

    protected static class RetryCounter extends ThreadLocal
    {
        public int countRetry()
        {
            return ((AtomicInteger) get()).incrementAndGet();
        }
        
        public void reset()
        {
            ((AtomicInteger) get()).set(0);
        }

        public AtomicInteger current()
        {
            return (AtomicInteger) get();
        }

        // @Override
        protected Object initialValue()
        {
            return new AtomicInteger(0);
        }
    }

    protected static final RetryCounter retryCounter = new RetryCounter();

    protected static final ThreadLocal called = new ThreadLocal();

    private volatile int retryCount = DEFAULT_RETRY_COUNT;
    private volatile long frequency = DEFAULT_FREQUENCY;

    protected void doConnect(UMOConnectable connectable) throws FatalConnectException
    {
        while (true)
        {
            final Boolean recursiveCallDetected = (Boolean) ObjectUtils.defaultIfNull(called.get(), Boolean.FALSE);
            if (!recursiveCallDetected.booleanValue())
            {
                retryCounter.countRetry();
            }
            called.set(Boolean.TRUE);

            try
            {
                connectable.connect();
                if (logger.isDebugEnabled())
                {
                    logger.debug("Successfully connected to " + getDescription(connectable));
                }
                break;
            }
            catch (InterruptedException ie)
            {
                // If we were interrupted it's probably because the server is
                // shutting down
                throw new FatalConnectException(
                    // TODO it's not only endpoint that is reconnected, connectors too
                    CoreMessages.reconnectStrategyFailed(this.getClass(), 
                        this.getDescription(connectable)), ie, connectable);
            }
            catch (Exception e)
            {
                if (e instanceof FatalConnectException)
                {
                    // rethrow
                    throw (FatalConnectException) e;
                }
                if (retryCount != RETRY_COUNT_FOREVER && retryCounter.current().get() >= retryCount)
                {
                    throw new FatalConnectException(
                        // TODO it's not only endpoint that is reconnected, connectors too
                        CoreMessages.reconnectStrategyFailed(this.getClass(),
                            this.getDescription(connectable)), e, connectable);
                }

                if (logger.isInfoEnabled())
                {
                    StringBuffer msg = new StringBuffer(512);
                    msg.append("Failed to connect/reconnect: ");
                    msg.append(getDescription(connectable));
                    msg.append("Waiting for ");
                    msg.append(frequency);
                    msg.append("ms before reconnecting. Failed attempt ");
                    msg.append(retryCounter.current().get());
                    msg.append(" of ");
                    msg.append((retryCount != RETRY_COUNT_FOREVER ? String.valueOf(retryCount) : "unlimited"));
                    logger.info(msg.toString());
                }

                try
                {
                    Thread.sleep(frequency);
                }
                catch (InterruptedException e1)
                {
                    throw new FatalConnectException(
                        // TODO it's not only endpoint that is reconnected, connectors too
                        CoreMessages.reconnectStrategyFailed(this.getClass(), 
                            this.getDescription(connectable)), e, connectable);
                }
            }
            finally
            {
                called.set(Boolean.FALSE);
            }
        }
    }

    /**
     * Resets any state stored in the retry strategy
     */
    public synchronized void resetState()
    {
        retryCounter.reset();
    }

    public int getRetryCount()
    {
        return retryCount;
    }

    /**
     * How many times to retry. Set to -1 to retry forever.
     * @param retryCount number of retries
     */
    public void setRetryCount(int retryCount)
    {
        this.retryCount = retryCount;
    }

    public long getFrequency()
    {
        return frequency;
    }

    public void setFrequency(long frequency)
    {
        this.frequency = frequency;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy