org.openspaces.pu.container.integrated.IntegratedProcessingUnitContainer.java Source code

Java tutorial

Introduction

Here is the source code for org.openspaces.pu.container.integrated.IntegratedProcessingUnitContainer.java

Source

/*
 * Copyright (c) 2008-2016, GigaSpaces Technologies, Inc. All Rights Reserved.
 *
 * 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.
 */

package org.openspaces.pu.container.integrated;

import com.gigaspaces.admin.cli.RuntimeInfo;
import com.gigaspaces.logger.GSLogConfigLoader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openspaces.pu.container.CannotCloseContainerException;
import org.openspaces.pu.container.ProcessingUnitContainer;
import org.openspaces.pu.container.spi.ApplicationContextProcessingUnitContainer;
import org.openspaces.pu.container.support.BeanLevelPropertiesParser;
import org.openspaces.pu.container.support.ClusterInfoParser;
import org.openspaces.pu.container.support.CommandLineParser;
import org.openspaces.pu.container.support.ConfigLocationParser;
import org.openspaces.pu.container.support.SpaceNameParser;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;

import java.util.Arrays;

/**
 * The integrated processing unit container wraps Spring {@link org.springframework.context.ApplicationContext
 * ApplicationContext}. It is created using {@link org.openspaces.pu.container.integrated.IntegratedProcessingUnitContainerProvider
 * IntegratedProcessingUnitContainerProvider}. <p/> <p>An integrated processing unit container can
 * be used to run a processing unit within an existing environment. An example of what this existing
 * environment will provide is the classpath that the processing unit will run with. Examples for
 * using the integrated processing unit container can be integration tests or running the processing
 * unit from within an IDE. <p/> <p>The integrated processing unit container also provides a a main
 * method ({@link #main(String[])} which uses the {@link org.openspaces.pu.container.integrated.IntegratedProcessingUnitContainerProvider}
 * and the provided parameters create itself. Please see the javadoc for the main method for a full
 * list of the possible parameters values.
 *
 * @author kimchy
 */
public class IntegratedProcessingUnitContainer extends ApplicationContextProcessingUnitContainer {

    private static final Log logger = LogFactory.getLog(IntegratedProcessingUnitContainer.class);

    private final ApplicationContext applicationContext;

    /**
     * Constructs a new integrated processing unit container based on the provided Spring {@link
     * org.springframework.context.ApplicationContext}.
     */
    public IntegratedProcessingUnitContainer(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    /**
     * Returns the spring application context this processing unit container wraps.
     */
    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * Closes the processing unit container by destroying the Spring application context.
     */
    @Override
    public void close() throws CannotCloseContainerException {
        if (applicationContext instanceof DisposableBean) {
            try {
                ((DisposableBean) applicationContext).destroy();
            } catch (Exception e) {
                throw new CannotCloseContainerException(
                        "Failed to close container with application context [" + applicationContext + "]", e);
            }
        }
        super.close();
    }

    /**
     * Allows to run the integrated processing unit container. Uses the {@link
     * org.openspaces.pu.container.integrated.IntegratedProcessingUnitContainerProvider} and the
     * parameters provided in order to configure it. <p/> <p/> The following parameters are allowed:
     * <ul> <li><b>-config [configLocation]</b>: Allows to add a Spring application context config
     * location. See {@link org.openspaces.pu.container.integrated.IntegratedProcessingUnitContainerProvider#addConfigLocation(String)}.
     * This is an optional parameter and it can be provided multiple times.</li> <li><b>-properties
     * [beanName] [properties]</b>: Allows to inject {@link org.openspaces.core.properties.BeanLevelProperties},
     * see {@link org.openspaces.pu.container.integrated.IntegratedProcessingUnitContainerProvider#setBeanLevelProperties(org.openspaces.core.properties.BeanLevelProperties)}.
     * [beanName] is optional, if not used, the properties will set the {@link
     * org.openspaces.core.properties.BeanLevelProperties#setContextProperties(java.util.Properties)}.
     * If used, will inject properties only to the bean registered under the provided beanName
     * within the Spring context (see {@link org.openspaces.core.properties.BeanLevelProperties#setBeanProperties(String,
     * java.util.Properties)}). The [properties] can either start with <code>embed://</code> which
     * mean they will be provided within the command line (for example:
     * <code>embed://propName1=propVal1;propName2=propVal2</code>) or they can follow Spring {@link
     * org.springframework.core.io.Resource} lookup based on URL syntax or Spring extended
     * <code>classpath</code> prefix (see {@link org.springframework.core.io.DefaultResourceLoader}).</li>
     * <li><b>-cluster [cluster parameters]</b>: Allows to configure {@link
     * org.openspaces.core.cluster.ClusterInfo}, see {@link org.openspaces.pu.container.integrated.IntegratedProcessingUnitContainerProvider#setClusterInfo(org.openspaces.core.cluster.ClusterInfo)}.</li>
     * The following parameters are allowed: <code>total_members=1,1</code> (1,1 is an example
     * value), <code>id=1</code> (1 is an example value), <code>backup_id=1</code> (1 is an example
     * value) and <code>schema=primary_backup</code> (primary_backup is an example value). No
     * parameter is required. For more information regarding the Space meaning of this parameters
     * please consult GigaSpaces reference documentation within the Space URL section. </ul>
     */
    public static void main(String[] args) throws Exception {
        GSLogConfigLoader.getLoader();

        //when calling with space-instance script, and no arguments were passed, we concatenate --help
        //IntegratedProcessingUnitContainer can also run without arguments and load pu.xml
        showUsageOptionsOnHelpCommand(args);

        logger.info("Starting with args: " + Arrays.toString(args) + "\n"
                + RuntimeInfo.getEnvironmentInfoIfFirstTime());
        try {
            final ProcessingUnitContainer container = createContainer(args);
            logger.info("Started successfully");

            // Use the MAIN thread as the non daemon thread to keep it alive
            final Thread mainThread = Thread.currentThread();
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    try {
                        logger.info("Shutdown hook triggered");
                        container.close();
                        logger.info("Shutdown complete");
                    } finally {
                        mainThread.interrupt();
                    }
                }
            });
            while (!mainThread.isInterrupted()) {
                try {
                    Thread.sleep(Long.MAX_VALUE);
                } catch (InterruptedException e) {
                    // do nothing, simply exit
                }
            }
        } catch (Exception e) {
            printUsage();
            e.printStackTrace(System.err);
            System.exit(1);
        }
    }

    private static void showUsageOptionsOnHelpCommand(String[] args) {
        for (String arg : args) {
            if (arg.equals("--help")) {
                printUsage();
                System.exit(0);
            }
        }
    }

    public static ProcessingUnitContainer createContainer(String[] args) throws Exception {
        CommandLineParser.Parameter[] params = CommandLineParser.parse(args);

        IntegratedProcessingUnitContainerProvider provider = new IntegratedProcessingUnitContainerProvider();
        provider.setBeanLevelProperties(BeanLevelPropertiesParser.parse(params));
        provider.setClusterInfo(ClusterInfoParser.parse(params));
        ConfigLocationParser.parse(provider, params);
        provider.setSpaceName(SpaceNameParser.parse(params));

        String userName = null;
        String password = null;
        for (CommandLineParser.Parameter param : params) {
            if (param.getName().equals("user")) {
                userName = param.getArguments()[0];
            } else if (param.getName().equals("password")) {
                password = param.getArguments()[0];
            } else if (param.getName().equals("secured")) {
                provider.setSecured(Boolean.parseBoolean(param.getArguments()[0]));
            }
        }
        if (userName != null && password != null) {
            provider.setUserDetails(userName, password);
        }

        return provider.createContainer();
    }

    public static void printUsage() {
        System.out.println(
                "usage options: [-name ...] [-cluster ...] [-properties ...] [-user xxx -password yyy] [-secured true/false]");
        System.out.println();
        System.out.println("    --help                                   : Shows this usage options menu");
        System.out.println();
        System.out.println(
                "    <no parameters>                          : by default uses classpath*:/META-INF/spring/pu.xml");
        System.out.println(
                "    -name [data grid name]                   : Specify the data grid name (required if pu.xml not found)");
        System.out.println("    -cluster [cluster properties]            : Allows to specify cluster parameters");
        System.out.println(
                "             schema=partitioned              : The cluster schema to use (default is partitioned)");
        System.out.println(
                "             total_members=1,1               : The number of instances and number of backups to use");
        System.out
                .println("             id=1                            : The instance id of this processing unit");
        System.out.println("             backup_id=1                     : The backup id of this processing unit");
        System.out.println("    -properties [properties-loc]             : Location of context level properties");
        System.out.println(
                "    -properties [bean-name] [properties-loc] : Location of properties used applied only for a specified bean");
        System.out.println(
                "    -user x -password y                      : Configures a secured processing unit propagated with the supplied user and password");
        System.out.println(
                "    -secured true                            : Configures a secured processing unit (implicit when using -user/-password)");
        System.out.println();
        System.out.println();
        System.out.println("Some Examples:");
        System.out.println();
        System.out.println("1. -name myDataGrid");
        System.out
                .println("    > Starts a processing unit with a non-clustered data grid instance named myDataGrid");
        System.out.println();
        System.out.println("2. -cluster schema=partitioned total_members=2,1");
        System.out.println(
                "    > Starts a processing unit with a partitioned cluster schema of two members (with one backup each) all in one process");
        System.out.println(
                "    > add -name myDataGrid to provide the cluster with a name, and each instance will follow the naming convention: ");
        System.out.println("       first  partition: dataGrid.1 , backup of first  partition: dataGrid.1_1");
        System.out.println("       second partition: dataGrid.2 , backup of second partition: dataGrid.2_1");
        System.out.println();
        System.out.println("3. -cluster schema=partitioned total_members=2,1 id=1");
        System.out.println(
                "    - Starts only the first instance (id=1) of a processing unit belonging to a 2,1 partitioned cluster (two members with one backup each)");
        System.out.println();
        System.out.println("4. -cluster schema=partitioned total_members=2,1 id=1 backup_id=1");
        System.out.println(
                "    - Starts only the backup of the first instance (id=1) of a processing unit belonging to a 2,1 partitioned cluster (two members with one backup each)");
        System.out.println();
        System.out.println("5. -cluster schema=partitioned total_members=2,0");
        System.out.println(
                "    > Starts a processing unit with a partitioned cluster schema of two members (without any backups) all in one process");
        System.out.println();
        System.out.println("6. -cluster schema=partitioned total_members=2,0 id=1");
        System.out.println(
                "    > Starts only the first instance (id=1) of a processing unit belonging to a 2,0 partitioned cluster (two members without any backups)");
        System.out.println();
        System.out.println(
                "7. -properties file://config/context.properties -properties space1 file://config/space1.properties");
        System.out.println(
                "    > Starts a processing unit using context level properties (context.properties) and bean level properties (space1.properties) applied to bean named space1");
        System.out.println();
        System.out.println(
                "8. -properties embed://prop1=value1 -properties space1 embed://prop2=value2;prop3=value3");
        System.out.println(
                "    > Starts a processing unit using context level properties with a single property called prop1 with value1 and bean level properties with two properties");
        System.out.println();
        System.out.println("9. -secured true");
        System.out.println("    > Starts a processing unit with a secured data grid");
        System.out.println();
    }
}