001
002 /*
003 * Copyright (C) 2011 Archie L. Cobbs. All rights reserved.
004 *
005 * $Id: ContextMainClass.java 19 2011-02-16 14:42:52Z archie.cobbs $
006 */
007
008 package org.dellroad.stuff.main;
009
010 import org.springframework.context.support.ClassPathXmlApplicationContext;
011
012 /**
013 * Support superclass for {@link MainClass} implementations that wish to execute
014 * with an associated Spring application context.
015 */
016 public abstract class ContextMainClass extends MainClass {
017
018 protected ClassPathXmlApplicationContext context;
019
020 private void openContext() {
021 String path = getContextLocation();
022 this.log.info("opening application context " + path);
023 this.context = new ClassPathXmlApplicationContext(path, getClass());
024 }
025
026 private void closeContext() {
027 this.log.info("closing application context");
028 this.context.close();
029 this.context = null;
030 }
031
032 /**
033 * Get the classpath location of this instance's associated XML application context.
034 * The returned string will resolved on the classpath relative to this instance's class.
035 *
036 * <p>
037 * The implementation in {@link ContextMainClass} returns {@code getClass().getSimpleName() + ".xml"},
038 * which will locate an XML file in the same package and with the same name.
039 */
040 protected String getContextLocation() {
041 return getClass().getSimpleName() + ".xml";
042 }
043
044 /**
045 * Autowire this instance using its associated application context.
046 * This may be invoked by {@link #runInContext} to autowire this bean using its associated context.
047 *
048 * <p>
049 * For this to work, the application context must have autowiring enabled, e.g., via
050 * {@code <context:annotation-config/>}.
051 */
052 protected void autowire() {
053 this.log.info("autowiring instance of " + this.getClass() + " using " + this.context.getAutowireCapableBeanFactory());
054 this.context.getAutowireCapableBeanFactory().autowireBean(this);
055 }
056
057 @Override
058 public final int run(final String[] args) throws Exception {
059
060 // Open context
061 openContext();
062
063 // Invoke subclass
064 try {
065 return this.runInContext(args);
066 } catch (Exception e) {
067 this.log.error("caught exception during execution", e);
068 throw e;
069 } finally {
070 closeContext();
071 }
072 }
073
074 /**
075 * Execute the main method. The application context will be open when this method is invoked.
076 */
077 protected abstract int runInContext(String[] args) throws Exception;
078 }
079