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

com.ebay.jetstream.application.JetstreamApplication Maven / Gradle / Ivy

/*******************************************************************************
 *  Copyright © 2012-2015 eBay Software Foundation
 *  This program is dual licensed under the MIT and Apache 2.0 licenses.
 *  Please see LICENSE for more information.
 *******************************************************************************/
package com.ebay.jetstream.application;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jmx.export.annotation.ManagedResource;

import com.ebay.jetstream.config.Configuration;
import com.ebay.jetstream.config.RootConfiguration;
import com.ebay.jetstream.event.support.ShutDownOrchestrator;
import com.ebay.jetstream.management.Management;
import com.ebay.jetstream.util.CommonUtils;
import com.ebay.jetstream.xmlser.Hidden;

/**
 * @author shmurthy
 * 
 *         A container class for hosting Jetstream Event based applications. This class will provide a main method and
 *         shutdown hook. It will start core services like messaging, monitoring and control, logging etc. It will load
 *         the entry bean specified in configuration. The rest of the wiring will be driven by this entry bean. This
 *         class can serve as a main for applications or as a collocated container. If this container's main is used,
 *         then the following command line arguments must be specified Viz, appname, configfile name and config version.
 *         If it is collocated with another container, these 3 parameters can be programatically set.
 * 
 */

@ManagedResource(objectName = "Application")
public class JetstreamApplication {

  private static class ShutdownHook extends Thread {
    @Override
    public void run() {
      try {
        getInstance().shutdown();
      }
      catch (Throwable t) {
        throw CommonUtils.runtimeException(t);
      }
      System.out.println("Gracefully shutdown"); //KEEPME
    }
  }

  private static Class s_applicationClass = JetstreamApplication.class;
  private static JetstreamApplication s_application;
  private static final Logger LOGGER = LoggerFactory.getLogger("com.ebay.jetstream.application");
  private ThreadPoolExecutor m_worker;
  private BlockingQueue m_workQueue;

  protected static Class getApplicationClass() {
    return s_applicationClass;
  }

  public static Configuration getConfiguration() {
    return RootConfiguration.getConfiguration();
  }

  @Hidden
  public static JetstreamApplication getInstance() {
    if (s_application == null) {
      synchronized (s_applicationClass) {
        if (s_application == null) {
          try {
            s_applicationClass.newInstance();
          }
          catch (Exception e) {
            throw CommonUtils.runtimeException(e);
          }
        }
      }
    }
    return s_application;
  }

  /**
   * Every Jetstream application shares a common main(). It creates the instance of the application, configures command
   * line options, parses the command line based on the options, starts the application based on the resulting
   * configuration, and then runs the application.
   * 
   * @param args
   *          command line arguments
   */
  public static void main(String[] args) throws Exception {
    System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.Jdk14Logger");
    JetstreamApplication ta = null;
    try {
      ta = getInstance();
      // Allow JetstreamApplication option handling methods to be protected
      final JetstreamApplication optionHandler = ta;
      new CliOptions(new CliOptionHandler() {
        public Options addOptions(Options options) {
          return optionHandler.addOptions(options);
        }

        public void parseOptions(CommandLine line) {
          optionHandler.parseOptions(line);
        }
      }, args);
      
      if (System.getenv("COS") == null)
    	  System.setProperty("COS", "Dev");
      
      ta.init();
    }
    catch (Exception e) {
      LOGGER.error( "Failed to start Application" + e.getLocalizedMessage());		
      System.err.println("Failed to start application: " + e);
      e.printStackTrace(System.err);
      System.exit(1);
    }
    ta.run(); // this is the container's event loop
  }

  protected static void setApplicationClass(Class applicationClass) {
    s_applicationClass = applicationClass;
  }

  private final Object m_monitor = new Object();
  private final AtomicBoolean m_shutdown = new AtomicBoolean(false);

  private final JetstreamApplicationInformation m_applicationInformation = new JetstreamApplicationInformation(this);

  protected JetstreamApplication() {
    if (s_application != null)
      throw new IllegalStateException(s_application.getClass().getName() + " is already running");
    s_application = this;
    RootConfiguration.applicationClass(m_applicationInformation, getClass());
    Runtime.getRuntime().addShutdownHook(new ShutdownHook());
   
  }

  /**
   * Adds options specific to this application. It may be overridden for custom application specific option
   * configuration.
   * 
   * @param options
   *          the Options to configure with new custom application command line options.
   * 
   * @return the configured options.
   */
  protected Options addOptions(Options options) {
    options.addOption("b", "beans", true, "Beans to start during initialization");
    options.addOption("c", "config", true, "Configuration URL or file path");
    options.addOption("cv", "configversion", true, "Version of configuration");
    options.addOption("n", "name", true, "Name of application");
    options.addOption("p", "port", true, "Monitoring port");
    options.addOption("z", "zone", true, "URL or path of dns zone content");
    options.addOption("nd", "nodns", false, "Not a network application");
    options.addOption("wqz", "workqueuesz", true, "work queue size");
    options.addOption("wt", "workerthreads", true, "worker threads");
    return options;
  }

  public JetstreamApplicationInformation getApplicationInformation() {
    return m_applicationInformation;
  }
  
  /**
 * @param work
 * @return true if success else false
 */
  public boolean submitWork(WorkRequest work) {
	  if (m_workQueue != null)
		  return m_workQueue.offer(work);

	  return false;
  }

  /**
   * Override this method to do initialization in a custom JetstreamApplication.
   * 
   * @throws Exception
   */
  protected void init() throws Exception {
    JetstreamApplicationInformation ai = getApplicationInformation();
    ai.selfLocate();
    
    m_workQueue = new LinkedBlockingQueue(ai.getWorkQeueSz());
    m_worker = new ThreadPoolExecutor(ai.getWorkerThreads(), 3, 30, TimeUnit.SECONDS, m_workQueue, new ThreadPoolExecutor.CallerRunsPolicy());
    m_worker.prestartCoreThread();
    
    Management.addBean(ai.getApplicationName(), this);
    logInfo("Starting services for " + ai);
    String[] configs = ai.getConfigRoots();
    RootConfiguration rc = configs == null ? new RootConfiguration(ai) : new RootConfiguration(ai, configs);
    rc.start();
    String[] sa = ai.getBeans();
    if (sa != null)
      for (String bean : sa)
        rc.getBean(bean);
  }

  protected void logInfo(String message) {
	  LOGGER.info( message);
  }

  protected void logSevereError(String message) {
	  LOGGER.error( message);
  }

  /**
   * Parse the options given on the command line. This method may be overridden for application specific command line
   * option handling.
   * 
   * @param commandLine
   *          the parsed command line.
   */
  protected void parseOptions(CommandLine commandLine) {
    JetstreamApplicationInformation ai = getApplicationInformation();
    if (commandLine.hasOption('b')) {
      ai.setBeans(commandLine.getOptionValues('b'));
    }
    if (commandLine.hasOption('c')) {
      ai.setConfigRoots(commandLine.getOptionValues('c'));
    }
    if (commandLine.hasOption("cv")) {
      ai.setConfigVersion(commandLine.getOptionValue("cv"));
    }
    if (commandLine.hasOption('n')) {
      ai.setApplicationName(commandLine.getOptionValue('n'));
    }
    if (commandLine.hasOption('p')) {
      ai.setManagementPort(Integer.valueOf(commandLine.getOptionValue('p')));
      System.setProperty("jetty_port",commandLine.getOptionValue('p'));
    } else{
    	 System.setProperty("jetty_port" ,  String.valueOf(9999));
    }
    if (commandLine.hasOption('z')) {
      ai.setZone(commandLine.getOptionValue('z'));
    }
    if (commandLine.hasOption("nd")) {
      ai.useDNS(false);
    }
    
    if (commandLine.hasOption("wqz")) {
    	ai.setWorkQueueSz(Integer.valueOf(commandLine.getOptionValue("wqz")));
    }
    
    if (commandLine.hasOption("wt")) {
    	ai.setWorkerThreads(Integer.valueOf(commandLine.getOptionValue("wt")));
    }

  }

  /**
   * Override this method to do work in the Jetstream application.
   */
  protected void run() throws Exception {
    // Do nothing by default
  }

  public void shutdown() throws InterruptedException, Exception {
    try {
      if (ShutDownOrchestrator.getInstance() != null) {
        ShutDownOrchestrator.getInstance().shutDown();
      }
      logInfo("Shutting down " + getApplicationInformation().getApplicationName());
    }
    finally {
      Configuration c = getConfiguration();
      if (c != null)
        c.close();
      synchronized (m_monitor) {
        m_shutdown.set(true);
        m_monitor.notifyAll();
        if (m_worker!=null)
        	m_worker.shutdown();
      }
    }
  }

  /**
   * shutdown shuts down all core services. It must be called for graceful exit, and is called automatically if
   * System.exit() is called.
   */
  // 8853 fix - do not show this link no matter what @ManagedOperation

  protected void waitForShutdown() {
    while (!m_shutdown.get()) {
      System.out.println("waiting for shutdown"); //KEEPME
      synchronized (m_monitor) {
        try {
          m_monitor.wait(10000);
        }
        catch (InterruptedException e) {
          // Ignore
        }
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy