« - »

Stand-alone Spring application runner

6 May 2009

Today I had to do something a little different, which was to create a number of stand-alone applications that ran outside of a web container to manipulate various files and tables in a batch mode. I wanted to leverage some existing components, which were all built to have their dependencies resolved by Spring, so I wanted to build things in such a way that Spring would still be in the picture.

My first attempts were just stand-alone applications that had a static void main method that grabbed the Spring context and then used it to get a configured instance of themselves. After that, I toyed with an abstract class that contained some of that code, but eventually I ended up using an independent application “runner” that contained all of the standard start-up and shut-down stuff that I wanted, but wasn’t really related to the application that I wanted to run. To make that work, I first created an interface, the SpringBatchJob, to represent the applications that I wanted to run:

package org.restafarian.core.batch;

/**
 *
 * <p>Spring batch job interface.</p>
 *
 */
public interface SpringBatchJob {

  /**
   * <p>This is the main "run" method called by the job runner.</p>
   */
  public void run() throws Exception;
}

Then I created the SpringBatchJobRunner to grab the name/location of the applicationContext.xml file from a run-time argument, create the context, use the context to get the Spring-cconfigured application, and then launch the application:

package org.restafarian.core.batch;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 *
 * <p>Spring batch job runner.</p>
 *
 */
public class SpringBatchJobRunner {
  private static final Log log = LogFactory.getLog(SpringBatchJobRunner.class);

  /**
   * <p>The Spring batch job runner main method.</p>
   *
   * @param args the run-time arguments
   */
  public static void main(String[] args) {
    // initiate batch job run
    log.info("SpringBatchJobRunner starting.");
    log.info(" ");

    // validate bootstrap parameters
    if (args.length != 1) {
      log.error("Invalid number of run-time arguments - job terminated.");
      System.exit(1);
    }  

    // load Spring context
    String springContextFile = args[0];
    log.info("Using Spring context file " + springContextFile);
    ApplicationContext context = new ClassPathXmlApplicationContext(springContextFile);
    if (context == null) {
      log.error("No Spring context available - job terminated.");
      System.exit(1);
    }  

    // load application to run
    SpringBatchJob springBatchJob = (SpringBatchJob) context.getBean("application");
    if (springBatchJob == null) {
      log.error("No application configured to run - job terminated.");
      System.exit(1);
    }  

    // run application
    log.info("Launching application " + springBatchJob.getClass().getName());
    log.info(" ");
    try {
      springBatchJob.run();
    } catch (Exception e) {
      log.error("Application " + springBatchJob.getClass().getName() + " terminated with
           an exception: " + e, e);
      System.exit(1);
    }

    // normal batch job completion
    log.info(" ");
    log.info("SpringBatchJobRunner complete.");
  }
}

It’s pretty simple code, so it doesn’t require a lot of explanation, but it ended up being quite a handy little utility for running all of the different batch jobs that I had to put together. I may end up enhancing it after using it for a while, but for now at least, it does everything that I need it to do.


http://blog.restafarian.org/2009/05/stand-alone-spring-application-runner/

Leave a reply

You must be logged in to post a comment.