NIHVIVO-336 Improve the function of StartupManager and StartupStatus

This commit is contained in:
j2blake 2011-09-23 18:51:05 +00:00
parent 65bba272df
commit 0726b3280e
2 changed files with 110 additions and 16 deletions

View file

@ -18,7 +18,16 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* TODO * Instantiate and run the ServletContextListeners for Vitro, while accumulating
* messages in StartupStatus.
*
* The startup listeners are stored in a file with one full-qualified class name
* per line. Blank lines and comment lines (starting with '#') are ignored.
*
* No exception in the listeners should prevent the successful completion.
* However, an uncaught exception or a fatal error status will cause the
* StartupStatusDisplayFilter to disply the problem instead of showing the home
* page (or any other requested page).
*/ */
public class StartupManager implements ServletContextListener { public class StartupManager implements ServletContextListener {
private static final Log log = LogFactory.getLog(StartupManager.class); private static final Log log = LogFactory.getLog(StartupManager.class);
@ -175,8 +184,11 @@ public class StartupManager implements ServletContextListener {
try { try {
log.debug("Initializing '" + listener.getClass().getName() + "'"); log.debug("Initializing '" + listener.getClass().getName() + "'");
listener.contextInitialized(sce); listener.contextInitialized(sce);
ss.listenerExecuted(listener);
} catch (Exception e) { } catch (Exception e) {
ss.fatal(listener, "Threw unexpected exception", e); ss.fatal(listener, "Threw unexpected exception", e);
log.error("Listener threw fatal exception: '"
+ listener.getClass().getName() + "'", e);
} }
} }

View file

@ -2,6 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.startup; package edu.cornell.mannlib.vitro.webapp.startup;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -10,11 +12,16 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener; import javax.servlet.ServletContextListener;
/** /**
* TODO * Accumulates a list of messages from the StartupManager, and from the context
* listeners that the run during startup.
*/ */
public class StartupStatus { public class StartupStatus {
private static final String ATTRIBUTE_NAME = "STARTUP_STATUS"; private static final String ATTRIBUTE_NAME = "STARTUP_STATUS";
// ----------------------------------------------------------------------
// static methods
// ----------------------------------------------------------------------
public static StartupStatus getBean(ServletContext ctx) { public static StartupStatus getBean(ServletContext ctx) {
StartupStatus ss; StartupStatus ss;
@ -29,6 +36,10 @@ public class StartupStatus {
return ss; return ss;
} }
// ----------------------------------------------------------------------
// methods to set status
// ----------------------------------------------------------------------
private List<StatusItem> itemList = new ArrayList<StatusItem>(); private List<StatusItem> itemList = new ArrayList<StatusItem>();
public void info(ServletContextListener listener, String message) { public void info(ServletContextListener listener, String message) {
@ -58,21 +69,22 @@ public class StartupStatus {
addItem(StatusItem.Level.FATAL, listener, message, cause); addItem(StatusItem.Level.FATAL, listener, message, cause);
} }
/** Say that a previous fatal error prevented this listener from running. */
public void listenerNotExecuted(ServletContextListener listener) { public void listenerNotExecuted(ServletContextListener listener) {
addItem(StatusItem.Level.NOT_EXECUTED, listener, "Not executed", null); addItem(StatusItem.Level.NOT_EXECUTED,
listener,
"Not executed - startup was aborted by a previous fatal error.",
null);
} }
public boolean isStartupAborted() { /** Create a simple item for this listener if no other exists. */
public void listenerExecuted(ServletContextListener listener) {
for (StatusItem item : itemList) { for (StatusItem item : itemList) {
if (item.level == StatusItem.Level.FATAL) { if (item.getSourceName().equals(listener.getClass().getName())) {
return true; return;
} }
} }
return false; addItem(StatusItem.Level.INFO, listener, "Ran successfully.", null);
}
public List<StatusItem> getStatusItems() {
return Collections.unmodifiableList(itemList);
} }
private void addItem(StatusItem.Level level, ServletContextListener source, private void addItem(StatusItem.Level level, ServletContextListener source,
@ -80,22 +92,92 @@ public class StartupStatus {
itemList.add(new StatusItem(level, source, message, cause)); itemList.add(new StatusItem(level, source, message, cause));
} }
// ----------------------------------------------------------------------
// methods to query status
// ----------------------------------------------------------------------
public boolean allClear() {
return getErrorItems().isEmpty() && getWarningItems().isEmpty();
}
public boolean isStartupAborted() {
return !getErrorItems().isEmpty();
}
public List<StatusItem> getStatusItems() {
return Collections.unmodifiableList(itemList);
}
public List<StatusItem> getErrorItems() {
List<StatusItem> list = new ArrayList<StartupStatus.StatusItem>();
for (StatusItem item : itemList) {
if (item.level == StatusItem.Level.FATAL) {
list.add(item);
}
}
return list;
}
public List<StatusItem> getWarningItems() {
List<StatusItem> list = new ArrayList<StartupStatus.StatusItem>();
for (StatusItem item : itemList) {
if (item.level == StatusItem.Level.WARNING) {
list.add(item);
}
}
return list;
}
// ----------------------------------------------------------------------
// helper classes
// ----------------------------------------------------------------------
public static class StatusItem { public static class StatusItem {
public enum Level { public enum Level {
INFO, WARNING, FATAL, NOT_EXECUTED INFO, WARNING, FATAL, NOT_EXECUTED
} }
final Level level; private final Level level;
final String sourceName; private final String sourceName;
final String message; private final String shortSourceName;
final Throwable cause; private final String message;
private final String cause;
public StatusItem(Level level, ServletContextListener source, public StatusItem(Level level, ServletContextListener source,
String message, Throwable cause) { String message, Throwable cause) {
this.level = level; this.level = level;
this.sourceName = source.getClass().getName(); this.sourceName = source.getClass().getName();
this.shortSourceName = source.getClass().getSimpleName();
this.message = message; this.message = message;
this.cause = cause;
if (cause == null) {
this.cause = "";
} else {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
cause.printStackTrace(pw);
this.cause = sw.toString();
}
}
public Level getLevel() {
return level;
}
public String getSourceName() {
return sourceName;
}
public String getShortSourceName() {
return shortSourceName;
}
public String getMessage() {
return message;
}
public String getCause() {
return cause;
} }
} }