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 }