RE: RE: Event Processing at servlet startup..
Kirk Daries <[email protected]>
| Newsgroups | gmane.comp.java.enhydra.barracuda.general |
|---|---|
| Message-ID | <D09B591872D1D611AF2B0010B5A1AAD07BE4F7@WCSMAIL> |
Hi Christian, ObjectRepositoryAssembler sounds very cool. The configuration side of things sounds very similar to the 'Kilim' project which is hosted at ObjectWeb. http://kilim.objectweb.org/ The only diff being, the respository side of things. I'll def consider playing with this approach. Until then.. I think i'll hack it abit. We're going live next week after all! ;) Regards KD -----Original Message----- From: Christian Cryder [mailto:[email protected]] Sent: 17 June 2003 08:29 To: [email protected] Subject: RE: [Barracuda] RE: Event Processing at servlet startup.. Hi Kirk, > First off. I'm not familiar with the ObjectRepositoryAssembler class. > I know it's similar to the ApplicationAssembler The ObjectRepositoryAssembler basically allows you to do 2 things: a) scripting (ie. invoking methods on objects or classes) b) putting things into the Global ObjectRepository (like DataSources) which your code can then access Here's an example from our app... First, we set various constants, like this: <!-- Set the Path information --> <object class="com.atmr.atmreports.AppKeys"> <prop name="WEBINF_PATH">E:\WebApps\atmreports\cvsroot\ATMReports\TestApp\WEB-INF< /prop> <prop name="WEB_URL">http://localhost:8080/TestApp</prop> <prop name="EMAIL_USERS">false</prop> <prop name="EMAIL_ADMIN">[email protected]</prop> <prop name="IS_DEMO_VERSION">false</prop> </object> The values being changed here are all public static constants in the AppKeys class. This is how we do ALL webapp configuration. Next, let's look at an example of how we set up data sources... <!-- ATMReports Data Source --> <object name="$ds" class="com.jnetdirect.jsql.JSQLPoolingDataSource"> <method name="setURL">jdbc:JSQLConnect://localhost/database=TestApp/user=foo</method > <method name="setMinPoolSize">2</method> <method name="setMaxPoolSize">10</method> <method name="setMaxIdleTime">60</method> <method name="setManagementCycleTime">2</method> </object> <register key="DB_ATMR" val="$ds"/> This actually creates an instance of the JSQLPoolingDataSource class and names it "$ds". Then it invokes various methods to configure it. Then it places it in the Global Object Repository under the name "DB_ATMR". All of our code can then access the data source using a couple of convenience methods like this: /** * Quick and handy method to get a reference to the ATMReports data source */ public static DataSource getDataSource() { return getDataSource(AppKeys.DB_ATMR); } /** * Get a reference to a data source from the object-repository */ public static DataSource getDataSource(String dsn) { ObjectRepository or = ObjectRepository.getGlobalRepository(); if (or==null) throw new RuntimeException("Fatal Error: global ObjectRepository missing"); if (dsn==null) dsn = AppKeys.DB_ATMR; DataSource ds = (DataSource) or.getState(dsn); if (ds==null) throw new RuntimeException("No DataSource named "+dsn+" found in the object repository"); return ds; } So what this means is that actuall application code that needs a data source simple does this: DataSource ds = AppUtil.getDataSource(); Pretty convenient. Now once our data sources are configured, we then want to set up code tables. These are static objects that hold the contents of various db tables, which we cache and share across the app. In order to do this, we'll need to reference the data source (no prob, since its been placed in the global object repository). So our line in object-repository.xml looks something like this: <object name="$cts" class="com.atmr.atmreports.CodeTables" /> <register key="CODE_TABLES" val="$cts"/> What happens is that when CodeTables is instanciated, the constructor calls an init() method that does this: protected void init() { logger.info("Setting up CodeTables..."); //start by getting a reference to the data source DataSource ds = getDataSource(); Class cls[] = getCodeTableClasses(); for (int i=0; i<cls.length; i++) { Class cl = cls[i]; try { logger.info("attempting to setup code table for class "+cl); CodeTableProvider ctp = (CodeTableProvider) cl.newInstance(); boolean success = ctp.setupCodeTable(ds, this); logger.info("...success: "+success); } catch (Exception e) { logger.error("...error trying to instantiate code table: "+cl.getName(), e); } } } We also could have had made it so the constructor didn't do anything, and instead called the init() method manually ourselves: <object name="$cts" class="com.atmr.atmreports.CodeTables" > <method name="init" /> </object> <register key="CODE_TABLES" val="$cts"/> Hopefully, the point of all of this is clear - the ObjectRepositoryAssembler provides a very simple yet powerful mechanism to instantiate objects, manipulate them programatically, and then even place them into the global object repository if so desired. We do ALL of our webapp configuration using this mechanism, which means that everything else in the app (including web.xml, event-gateways.xml, event-hierarchy.xml, etc) is identical across all platforms. The only configuration information is stored in object-repository.xml. We DON'T store object-repository.xml under cvs. Instead, we have an install that will copy a sample.object-repository.xml file (which IS stored under cvs) into place if the default one doesn't exist. In addition, for deploying webapps, we also store machine specific configurations under cvs in a special directory (WEB-INF/conf). For instance, we have files like: CRYDER-TestApp.object-repository.xml CRYDER-TestApp2.object-repository.xml WILSON-TestApp.object-repository.xml WILSON-TestApp2.object-repository.xml The deployment process selects the appropriate file (based on <machine name>-<webapp name>) and copies it into place. We currently only do this for production webapps, but it could be applied to dev installs as well. A final point about the object repository approach. When running in a webapp, shared resources (like datasources, etc) are placed in the global repository and your code accesses them by retrieving them from there. The question arises, what about code that is also meant to be run as a standalone app (ie. from a main() method)? It turns out this is very easy too...all that is necessary is to configure log4j and then assemble the object repository, just like this: public static void main(String args[]) { try { //manually configure the log4j stuff DOMConfigurator.configure("../log4j.xml"); //setup the object repository AppUtil.setupObjectRepository(); //execute cvtBusiness new Foo().doSomething(); } catch (Exception e) { System.out.println("Unexpected Exception: "+e); e.printStackTrace(); } } //end main() So its possible to run the same piece of code both from within the servlet context but also directly as a standalone app. Pretty slick for testing and debugging and unit tests. The point of all of this is that the whole object-repository.xml approach gives us a way to configure webapps that a) is very easy to use b) is very powerful c) provides a single point of configuration (rather than having things scattered about in different places) d) is container neutral (changing from Tomcat to some other appserver does NOT require any configuration changes) e) supports multiple configurations on a per-machine/webapp name basis, and easily integrates into cvs and deployment mechanisms as well f) makes it easy for code to be run BOTH in a servlet environment AND directly as an application Given my limited understanding of your system, I'd strongly recommend considering the object repository approach - I don't think I'd mess with trying to fire events after the ApplicationGateway is up and running; I'd just use the object repository stuff to do all the configuration by setting configuration constants and invoking methods in configuration objects as needed. Please feel free to holler if you have questions... Christian ---------------------------------------------- Christian Cryder Internet Architect, ATMReports.com Project Chair, BarracudaMVC - http://barracudamvc.org ---------------------------------------------- "Coffee? I could quit anytime, just not today" > -----Original Message----- > From: [email protected] > [mailto:[email protected]]On Behalf Of Kirk Daries > Sent: Tuesday, June 17, 2003 12:51 AM > To: [email protected] > Subject: RE: [Barracuda] RE: Event Processing at servlet startup.. > > > Hi Christian, > > Thanx for the response. First off. I'm not familiar with the > ObjectRepositoryAssembler class. > I know it's similar to the ApplicationAssembler.. in that it uses > a xml file > to load stuff. > Other than that... I'm not too sure how it's being used. > Something to do with keeping state right? > > Let me give you a little background on our environment here at the moment. > In 1 week's time we're going live with our first Barracuda application. > It's taken +- a year to get this baby going and is quite a huge system. > Property managment. Resource management. Finance. Budgeting, etc etc. > Everything running over a VPN/WAN across the western cape(South Africa). > > Because of the size of the project... we've had to customize our > development > environment to get the most out of Barracuda. Currently.. there are 5 > developers > working on the project(includ me). Each has been delegated a subset of the > system... > which we consider to be an application in it's own right. > So that's 1 system and 9 little applications. > > Since each developer is responsible for 1 or more applications, we rely on > the functionality I added > to ApplicationAssembler which allow's multiple processing of the assembler > xml files. > This way... developers can work in the proverbial little black > room and not > have to worry about/have to wait > for other developers. Once we deploy to test/production. The latest source > is obtained from cvs and deployed > to the correct context dir. Upon servlet startup, the application > assembler > processes everyone's assembler > files. > > Now.. to get to your question. > We have only one servlet for the entire system. It's generic and know's > nothing about the system. > > All it's know's is to load any config files it finds and does the setting > up. > Database pooling, and what ever it finds. > Now. > What I'd like to do... is to be able to set static variables based on > database information. > > E.g. > <ACTUAL CODE SNIPPET HERE> > public static int STATUS_NOT_OPEN; > public static int STATUS_BUDGETING_ONLY; > public static int STATUS_BUDGETING_AND_PAYMENTS; > public static int STATUS_POSTING_ONLY; > public static int STATUS_FROZEN; > public static int STATUS_CLOSED; > > public static int ACTION_INITIAL; > public static int ACTION_ADJUSTMENT; > public static int ACTION_TRANSFER; > > > Remember.... > These variables are set based on a few database tables and their > key values. > Each Application requires this sort of setup. > > However, since our servlet know's nothing about any of the > applications.... > Up till now... I've had to hack it abit. > When the very first user log's in. I check to see if the static variables > are setup. > If not.. I load them. Each application has a Login_listener which > is mapped > to the login event. > > It's not Ideal as far as I'm concerned. > That's why I'd like to have some sort of startup event fired > which notifies > all applications that > they can now start processing their own initialization. > I hope that makes sense. > > >Now Barracuda is capabale of handling this (ie. dispatching to > >events that don't generate a response), but you wouldn't exactly > be able to > >reuse the event handlers either. In other words, you're not going to want > to > >try using these handlers to do setup stuff AND actually generate > >responses...it'd just be one or the other. > That's fine. It's just for initialization. > > Thanx Christian, > KD > > -----Original Message----- > From: Christian Cryder [mailto:[email protected]] > Sent: 16 June 2003 05:37 > To: BarracudaMVC > Subject: [Barracuda] RE: Event Processing at servlet startup.. > > > Hi Kirk, > > Ok, so I'm just now getting around to responding to this...sorry its taken > me so long! > > > Is there a mechanism to fire 'events' during my initializeLocal method > > withing my ApplicationGateway... > > Right now, there's not, but we could probably create something if need be. > First, however, I want to better understand exactly what you're trying to > accomplish. > > > Here's what I'd like to do. > > > > E.g. > > > > public void initializeLocal() { > > super.initializeLocal(); > > > > //Startup configuration... > > . > > . > > . > > //Done Setting up the Servlet > > > > //Now I'd like to notify all interested event listeners > > //that the servlet has done starting up. > > > > //If so.. then go and do their own mini initializations.. > > // database stuff and what not.. > > > > //Pseudo Code Follows here... > > Have 2 Events and Listeners...specified in my ApplicationAssembler XML > > > > ServeletStartupComplete.Event and After_StartupComplete.Event which > > extends ServeletStartupComplete.Event > > > > Get the EventQueue... > > Add After_StartupComplete.Event to the queue > > Let Barracuda process the queue and all interested listeners > > //End Pseudo Code > > > > The idea is that I'd like all interested listeners to listen for > > ServeletStartupComplete.Event. > > > > This way.. when I add the After_StartupComplete.Event..the queue should > > process all the waiting listeners.. > > So here's a couple of questions. First of all, most events are designed to > generate a response back to the client...you wouldn't be doing that here > (presumably). Now Barracuda is capabale of handling this (ie. > dispatching to > events that don't generate a response), but you wouldn't exactly > be able to > reuse the event handlers either. In other words, you're not going > to want to > try using these handlers to do setup stuff AND actually generate > responses...it'd just be one or the other. > > Now, the next question that I have relates to the wisdom of actually doing > this type of thing in event handlers. Typically, event handlers are short > lived, that is, instances are created when they are needed and then > discarded for gc once they're done...you don't typically have > event handlers > living beyond the scope of a single req-resp cycle. > > So the question arises, why would you actually need to notify > them that the > servlet is up and running? I guess this relates to the thing I'm > still most > unclear on here...what types of specific things do you actually > want to see > configured here? > > My gut feeling is that it'd be much easier to be using the > ObjectRepositoryAssembler for this task, but I don't want to jump to > conclusions either. So if you could provide some more specific > details here, > I will try to follow up with a more complete response (and I promise to > address it today rather than wait another couple of weeks ;-) > > Christian > ---------------------------------------------- > Christian Cryder > Internet Architect, ATMReports.com > Project Chair, BarracudaMVC - http://barracudamvc.org > ---------------------------------------------- > "Coffee? I could quit anytime, just not today" > > > -----Original Message----- > From: Kirk Daries [mailto:[email protected]] > Sent: Tuesday, June 10, 2003 2:29 AM > To: Christian Cryder > Subject: Event Processing at servlet startup.. > > > Hi Christian... > > Sorry to bother you.. > I know your're extremly busy with your studies and work.. > > A while back you said you had an idea how I could solve this problem... > Could you point me in the right direction?? > > Thanx > KD > > >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> > > Hi Guys, > > Quick question. > Is there a mechanism to fire 'events' during my initializeLocal method > withing my ApplicationGateway... > > I'm not sure if there is a mechanism already.. or a better way... > > Here's what I'd like to do. > > E.g. > > public void initializeLocal() { > super.initializeLocal(); > > //Startup configuration... > . > . > . > //Done Setting up the Servlet > > //Now I'd like to notify all interested event listeners > //that the servlet has done starting up. > > //If so.. then go and do their own mini initializations.. > // database stuff and what not.. > > //Pseudo Code Follows here... > Have 2 Events and Listeners...specified in my ApplicationAssembler XML > > ServeletStartupComplete.Event and After_StartupComplete.Event which > extends ServeletStartupComplete.Event > > Get the EventQueue... > Add After_StartupComplete.Event to the queue > Let Barracuda process the queue and all interested listeners > //End Pseudo Code > > The idea is that I'd like all interested listeners to listen for > ServeletStartupComplete.Event. > > This way.. when I add the After_StartupComplete.Event..the queue should > process all the waiting listeners.. > > Regards > KD > > _______________________________________________ > Barracuda mailing list > [email protected] > http://barracudamvc.org/lists/listinfo/barracuda > _______________________________________________ > Barracuda mailing list > [email protected] > http://barracudamvc.org/lists/listinfo/barracuda _______________________________________________ Barracuda mailing list [email protected] http://barracudamvc.org/lists/listinfo/barracuda