it.geosolutions.geoserver.jms.client.JMSContainer.java Source code

Java tutorial

Introduction

Here is the source code for it.geosolutions.geoserver.jms.client.JMSContainer.java

Source

/* Copyright (c) 2011 GeoSolutions - http://www.geo-solutions.it/.  All rights reserved.
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package it.geosolutions.geoserver.jms.client;

import it.geosolutions.geoserver.jms.JMSFactory;
import it.geosolutions.geoserver.jms.configuration.ConnectionConfiguration;
import it.geosolutions.geoserver.jms.configuration.TopicConfiguration;
import it.geosolutions.geoserver.jms.configuration.ConnectionConfiguration.ConnectionConfigurationStatus;
import it.geosolutions.geoserver.jms.configuration.JMSConfiguration;

import java.io.IOException;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;

import org.geotools.util.logging.Logging;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.JmsException;
import org.springframework.jms.listener.DefaultMessageListenerContainer;

/**
 * 
 * Connection handler
 * 
 * @author Carlo Cancellieri - GeoSolutions SAS
 * 
 */
final public class JMSContainer extends DefaultMessageListenerContainer implements DisposableBean {

    private final static Logger LOGGER = Logging.getLogger(JMSContainer.class);

    @Autowired
    public JMSFactory jmsFactory;

    @Autowired
    public List<JMSContainerHandlerExceptionListener> jmsContainerHandleExceptionListener;

    private JMSConfiguration config;

    private boolean verified = false;

    // times to test (connection)
    private static int max;

    // millisecs to wait between tests (connection)
    private static long maxWait;

    public JMSContainer(JMSConfiguration config, JMSQueueListener listener) {
        super();

        // configuration
        this.config = config;

        // the listener used to handle incoming events
        setMessageListener(listener);

    }

    @PostConstruct
    private void init() {
        // change the default autostartup status to false
        setAutoStartup(false);

        // force no concurrent consumers
        setConcurrentConsumers(1);

        // set to topic
        setPubSubDomain(true);

        // set subscription durability
        setSubscriptionDurable(
                Boolean.parseBoolean(config.getConfiguration(TopicConfiguration.DURABLE_KEY).toString()));

        // set subscription ID
        setDurableSubscriptionName(config.getConfiguration(JMSConfiguration.INSTANCE_NAME_KEY).toString());

        // times to test (connection)
        max = Integer.parseInt(config.getConfiguration(ConnectionConfiguration.CONNECTION_RETRY_KEY).toString());

        // millisecs to wait between tests (connection)
        maxWait = Long
                .parseLong(config.getConfiguration(ConnectionConfiguration.CONNECTION_MAXWAIT_KEY).toString());

        // check configuration for connection and try to start if needed
        final String startString = config.getConfiguration(ConnectionConfiguration.CONNECTION_KEY);
        if (startString != null && startString.equals(ConnectionConfigurationStatus.enabled.toString())) {
            if (!connect()) {
                if (LOGGER.isLoggable(Level.SEVERE)) {
                    LOGGER.severe("Unable to connect to the broker, force connection status to disabled");
                }

                // change configuration status
                config.putConfiguration(ConnectionConfiguration.CONNECTION_KEY,
                        ConnectionConfigurationStatus.disabled.toString());

                // store changes to the configuration
                try {
                    config.storeConfig();
                } catch (IOException e) {
                    LOGGER.log(Level.SEVERE, e.getMessage(), e);
                }
            }
        } else {
            // configure (needed by initializeBean)
            configure();
        }
    }

    private static void verify(final Object type, final String message) {
        if (type == null)
            throw new IllegalArgumentException(message != null ? message : "Verify fails the argument check");
    }

    /**
     * try to disconnect
     * 
     * @return true if success
     */
    public boolean disconnect() {
        if (isRunning()) {
            LOGGER.info("Disconnecting...");
            stop();
            for (int rep = 1; rep <= max; ++rep) {
                LOGGER.info("Unregistering...");
                if (!isRunning()) {
                    LOGGER.info("Succesfully un-registered from the destination topic");
                    LOGGER.warning(
                            "You will (probably) loose next incoming events from other instances!!! (depending on how you have configured the broker)");
                    return true;
                }
                LOGGER.info("Waiting for connection shutdown...(" + rep + "/" + max + ")");
                try {
                    Thread.sleep(maxWait);
                } catch (InterruptedException e) {
                    LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
                }
            }
        } else {
            LOGGER.severe("Connection is already stopped");
        }

        return false;
    }

    private void configure() {
        final Properties conf = config.getConfigurations();

        // set destination
        setDestination(jmsFactory.getClientDestination(conf));

        // use a CachingConnectionFactory
        setConnectionFactory(jmsFactory.getConnectionFactory(conf));
    }

    /**
     * try to connect
     * 
     * @return true in success case, false otherwise
     */
    public boolean connect() {
        if (!isRunning()) {
            LOGGER.info("Connecting...");
            start();
            if (isRunning()) {
                for (int repReg = 1; repReg <= max; ++repReg) {
                    LOGGER.info("Registration...");
                    if (isRegisteredWithDestination()) {
                        LOGGER.info("Now GeoServer is registered with the destination");
                        return true;
                    } else if (repReg == max) {
                        LOGGER.log(Level.SEVERE, "Registration aborted due to a connection problem");
                        stop();
                        LOGGER.info("Disconnected");
                    } else {
                        LOGGER.info("Impossible to register GeoServer with destination, waiting...");
                    }
                    LOGGER.info("Waiting for registration...(" + repReg + "/" + max + ")");
                    try {
                        Thread.sleep(maxWait);
                    } catch (InterruptedException e) {
                        LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
                    }
                }
            } else {
                LOGGER.severe("Impossible to start a connection to destination.");
                stop();
                LOGGER.info("Disconnected");
                return false;
            }
        } else {
            LOGGER.severe("Connection is already running");
        }
        return false;
    }

    @Override
    public void start() throws JmsException {
        if (!verified) {
            verify(jmsFactory, "failed to get a JMSFactory");
            verified = true;
        }
        if (!isRunning()) {

            // configure the container
            configure();

            // start it
            super.start();

            // initialize the container
            initialize();

        }
    }

    @Override
    public void destroy() {
        super.stop();
        super.destroy();
    }

    @Override
    protected void handleListenerSetupFailure(Throwable ex, boolean alreadyRecovered) {
        super.handleListenerSetupFailure(ex, alreadyRecovered);

        if (jmsContainerHandleExceptionListener != null) {
            for (JMSContainerHandlerExceptionListener handler : jmsContainerHandleExceptionListener) {
                handler.handleListenerSetupFailure(ex, alreadyRecovered);
            }
        }
    }
}