001    package hirondelle.web4j;
002    
003    import javax.servlet.ServletConfig;
004    
005    import hirondelle.web4j.model.AppException;
006    import hirondelle.web4j.database.ConnectionSource;
007    
008    /**
009     Perform startup tasks.
010    
011     <P>See {@link hirondelle.web4j.BuildImpl} for important information on how this item is configured. 
012     {@link hirondelle.web4j.BuildImpl#forStartupTasks()} 
013     returns the configured implementation of this interface.
014    
015     <P>Allows the application programmer to perform any needed initialization tasks. 
016     
017     <P>These tasks are performed only once, upon startup (caveat below). 
018     For example, the application may need to place items into application scope. Here's an example 
019     <a href="http://www.javapractices.com/apps/fish/javadoc/src-html/hirondelle/web4j/config/Startup.html">implementation</a> 
020     taken from an example application.
021     
022     <P>
023     See {@link hirondelle.web4j.database.ConnectionSource#init(java.util.Map)}, for startup 
024     tasks related to database connections. 
025     
026     <P>Startup tasks often depend on a database. If all of your databases are running when your app 
027     starts up, then all startup tasks will be completed during start-up. 
028     
029     <P>However, sometimes a database may be down when your application starts up.
030     In that case, web4j will keep track of which databases are down. Later, when a request comes into its Controller,
031     it will re-test each offending database, to see if it's now running; when the database is seen to be running, then 
032     web4j will then pass the name of the database to {@link #startApplication(ServletConfig, String)}.
033     (This processing takes place after startup, and thus, in a multi-threaded environment. The framework performs 
034     the necessary external synchronization of this class.) 
035    */
036    public interface StartupTasks {
037      
038      /**
039       Perform any startup tasks needed by the application.
040       <P>Possible tasks include:
041       <ul>
042       <li>disseminate values configured in <tt>web.xml</tt>
043       <li>place items into application scope, such as code tables read from the database
044       <li>set the default {@link java.util.TimeZone}
045       </ul>
046       
047       <P>This method is called by WEB4J near the end of startup processing.  
048       It's first called with an empty String for the database name; this is intended for any 
049       tasks that may be unrelated to any database at all.
050       It's then called again, once for each database defined by {@link ConnectionSource#getDatabaseNames()} (in 
051       the iteration order of the <tt>Set</tt> returned by that method).  
052       
053       <P>Example of a typical implementation:
054    <pre>
055    public void startApplication(ServletConfig aConfig, String aDbName) throws DAOException {
056      if (!Util.textHasContent(aDbName)){
057        //tasks not related to any db
058      }
059      else if (ConnectionSrc.DEFAULT.equals(aDbName)){
060        //tasks related to this db
061      }
062      else if (ConnectionSrc.TRANSLATION.equals(aDbName)){
063        //tasks related to this db
064      }
065    }</pre>
066    
067     <P>This method is called N+1 times by the framework, where N is the number of databases. 
068     The framework has confirmed that the database is running before it calls this method.
069       
070       @param aConfig is not a Map, as in other interfaces, since startup tasks 
071       often need more than just settings in <tt>web.xml</tt> - for example, placing code tables in app scope will 
072       need access to the <tt>ServletContext</tt>.
073       @param aDatabaseName refers to one of the names defined by {@link ConnectionSource#getDatabaseNames()}, 
074       or an empty string. Implementations of this method should reference those names directly, instead of 
075       hard-coding strings.
076      */
077      void startApplication(ServletConfig aConfig, String aDatabaseName) throws AppException;
078      
079    }