classes/hirondelle/web4j/StartupTasks.java
changeset 0 3060119b1292
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/classes/hirondelle/web4j/StartupTasks.java	Wed Dec 04 17:00:31 2013 +0100
@@ -0,0 +1,79 @@
+package hirondelle.web4j;
+
+import javax.servlet.ServletConfig;
+
+import hirondelle.web4j.model.AppException;
+import hirondelle.web4j.database.ConnectionSource;
+
+/**
+ Perform startup tasks.
+
+ <P>See {@link hirondelle.web4j.BuildImpl} for important information on how this item is configured. 
+ {@link hirondelle.web4j.BuildImpl#forStartupTasks()} 
+ returns the configured implementation of this interface.
+
+ <P>Allows the application programmer to perform any needed initialization tasks. 
+ 
+ <P>These tasks are performed only once, upon startup (caveat below). 
+ For example, the application may need to place items into application scope. Here's an example 
+ <a href="http://www.javapractices.com/apps/fish/javadoc/src-html/hirondelle/web4j/config/Startup.html">implementation</a> 
+ taken from an example application.
+ 
+ <P>
+ See {@link hirondelle.web4j.database.ConnectionSource#init(java.util.Map)}, for startup 
+ tasks related to database connections. 
+ 
+ <P>Startup tasks often depend on a database. If all of your databases are running when your app 
+ starts up, then all startup tasks will be completed during start-up. 
+ 
+ <P>However, sometimes a database may be down when your application starts up.
+ In that case, web4j will keep track of which databases are down. Later, when a request comes into its Controller,
+ it will re-test each offending database, to see if it's now running; when the database is seen to be running, then 
+ web4j will then pass the name of the database to {@link #startApplication(ServletConfig, String)}.
+ (This processing takes place after startup, and thus, in a multi-threaded environment. The framework performs 
+ the necessary external synchronization of this class.) 
+*/
+public interface StartupTasks {
+  
+  /**
+   Perform any startup tasks needed by the application.
+   <P>Possible tasks include:
+   <ul>
+   <li>disseminate values configured in <tt>web.xml</tt>
+   <li>place items into application scope, such as code tables read from the database
+   <li>set the default {@link java.util.TimeZone}
+   </ul>
+   
+   <P>This method is called by WEB4J near the end of startup processing.  
+   It's first called with an empty String for the database name; this is intended for any 
+   tasks that may be unrelated to any database at all.
+   It's then called again, once for each database defined by {@link ConnectionSource#getDatabaseNames()} (in 
+   the iteration order of the <tt>Set</tt> returned by that method).  
+   
+   <P>Example of a typical implementation:
+<pre>
+public void startApplication(ServletConfig aConfig, String aDbName) throws DAOException {
+  if (!Util.textHasContent(aDbName)){
+    //tasks not related to any db
+  }
+  else if (ConnectionSrc.DEFAULT.equals(aDbName)){
+    //tasks related to this db
+  }
+  else if (ConnectionSrc.TRANSLATION.equals(aDbName)){
+    //tasks related to this db
+  }
+}</pre>
+
+ <P>This method is called N+1 times by the framework, where N is the number of databases. 
+ The framework has confirmed that the database is running before it calls this method.
+   
+   @param aConfig is not a Map, as in other interfaces, since startup tasks 
+   often need more than just settings in <tt>web.xml</tt> - for example, placing code tables in app scope will 
+   need access to the <tt>ServletContext</tt>.
+   @param aDatabaseName refers to one of the names defined by {@link ConnectionSource#getDatabaseNames()}, 
+   or an empty string. Implementations of this method should reference those names directly, instead of 
+   hard-coding strings.
+  */
+  void startApplication(ServletConfig aConfig, String aDatabaseName) throws AppException;
+  
+}