hlship 2003/09/10 09:54:52
Modified: hivemind/xdocs navigation.xml case1.xml
Log:
Protect the (not so) innocent.
Revision Changes Path
1.18 +2 -2 jakarta-commons-sandbox/hivemind/xdocs/navigation.xml
Index: navigation.xml
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/xdocs/navigation.xml,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- navigation.xml 9 Sep 2003 22:09:21 -0000 1.17
+++ navigation.xml 10 Sep 2003 16:54:52 -0000 1.18
@@ -24,7 +24,7 @@
<item name="Inversion of Control" href="/ioc.html"/>
<item name="Multi-Threading" href="/multithreading.html"/>
<item name="Overriding Services" href="/override.html"/>
- <item name="Case Study #1: Vista Startup/Shutdown"
+ <item name="Case Study #1: Application Startup/Shutdown"
href="case1.html"/>
</menu>
<menu name="Resources">
1.3 +91 -68 jakarta-commons-sandbox/hivemind/xdocs/case1.xml
Index: case1.xml
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/xdocs/case1.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- case1.xml 9 Sep 2003 14:51:58 -0000 1.2
+++ case1.xml 10 Sep 2003 16:54:52 -0000 1.3
@@ -6,26 +6,33 @@
]>
<document>
<properties>
- <title>Case Study #1: Vista Startup</title>
+ <title>Case Study #1: Application Startup / Shutdown</title>
<author email="[EMAIL PROTECTED]">Howard M. Lewis Ship</author>
</properties>
<body>
<section name="Introduction">
+<blockquote>
+This case study is based on work done for my current employer, who has not (yet)
+given approval to mention the project by name. The package names and module
+ids have been changed, and some minor changes and simplifications have been made.
+The actual name of the product has been disguised as <em>Oubliette</em>.
+</blockquote>
+
+
<p>
-<a href="http://www.webct.com/products/viewpage?name=products_vista">Vista</a> is
the
-enterprise academic software offering from WebCT. Vista is a fairly large product,
consisting
+The Oubliette product is a fairly large J2EE web application deployed into BEA
WebLogic. Oubliette consists
of well over six thousand classes, divided into a large number of tools and
services.
-Vista has been a production project for several years, long before HiveMind was
available.
-HiveMind's introduction into Vista (on something of a trial basis) was to cleanup
the startup
+Oubliette has been a production project for several years, long before HiveMind was
available.
+HiveMind's introduction into Oubliette (on something of a trial basis) was to
cleanup the startup
and shutdown process for the application.
</p>
<p>
-Vista runs inside BEA WebLogic as an enterprise application; however, it is still
logically a
+Oubliette runs inside BEA WebLogic as an enterprise application; however, it is
still logically a
number of subsystems, many of which require some form of startup or shutdown logic.
For example,
-the Vista Help service caches help data stored in the database; the Vista Mail tool
sets up
+the Oubliette Help service caches help data stored in the database; the Oubliette
Mail tool sets up
periodic database cleanup jobs. All told, there are over 40 startup tasks, and a
handful of shutdown
tasks.
</p>
@@ -35,11 +42,16 @@
A small WebLogic startup class would invoke the EJB, and the EJB would invoke
static methods
on many other classes (some of which would lookup other EJBs and invoke methods on
them).
This approach had grown quite unwieldy, especially in light of efforts
-to improve and modularize the Vista build process. HiveMind was brought in to
rationalize
-this aspect of Vista, with the goal being to make the fewest possible changes
+to improve and modularize the Oubliette build process. HiveMind was brought
in to rationalize
+this aspect of Oubliette, with the goal being to make the fewest possible changes
to existing code.
</p>
+<p>
+An important aspect of startup and shutdown is the order of operations; there are
dependencies between
+different tasks that must be honored in terms of which task is executed first.
+</p>
+
</section>
<section name="Overview">
@@ -52,7 +64,7 @@
<p>
The overall approach is to provide HiveMind module deployment descriptors for the
various
-tools and services of Vista; each module contributes tasks to a Startup or
Shutdown extension point.
+tools and services of Oubliette; each module contributes tasks to a Startup or
Shutdown extension point.
</p>
<p>
@@ -63,17 +75,17 @@
</section>
-<section name="Module vista.framework.initshut">
+<section name="Module oubliette.framework.startup">
<p>
-The <code>vista.framework.initshut</code> ("initialization and shutdown") module
+The <code>oubliette.framework.startup</code> ("initialization and shutdown") module
contains the services and extension points for startup and shutdown. It also
contains
Java classes corresponding to task contributions.
</p>
<source><![CDATA[<?xml version="1.0"?>
-<module id="vista.framework.initshut" version="1.0.0">
- <description>Module for startup and shutdown code within Vista.</description>
+<module id="oubliette.framework.startup" version="1.0.0">
+ <description>Module for startup and shutdown code within
Oubliette.</description>
<extension-point id="Startup">
<description>Defines startup tasks.</description>
@@ -98,7 +110,7 @@
</attribute>
<rules>
<create-object
-
class="com.webct.platform.framework.initshut.service.Task"
+
class="com.oubliette.framework.startup.service.Task"
/>
<read-attribute attribute="order"
property="order"
translator="int"/>
@@ -121,7 +133,7 @@
</attribute>
<rules>
<create-object
-
class="com.webct.platform.framework.initshut.service.StaticTask"
+
class="com.oubliette.framework.startup.service.StaticTask"
/>
<read-attribute attribute="class"
property="className"/>
<read-attribute attribute="method"
property="methodName"
@@ -140,13 +152,13 @@
<extension point-id="Startup">
<task title="Python" order="50"
-
class="com.webct.platform.framework.initshut.ejb.PythonStartup"/>
+ class="com.oubliette.framework.startup.common.PythonStartup"/>
</extension>
<extension point-id="Shutdown">
<task title="Update Status" order="100">
<invoke-static
-
class="com.webct.platform.framework.initshut.ejb.VistaStatus"
+
class="com.oubliette.framework.startup.common.OublietteStatus"
method="shutdown"/>
</task>
</extension>
@@ -154,7 +166,7 @@
<service id="Startup" interface="java.lang.Runnable">
<invoke-factory service-id="hivemind.BuilderFactory">
<construct
-
class="com.webct.platform.framework.initshut.service.TaskExecutor"
+
class="com.oubliette.framework.startup.service.TaskExecutor"
log-property="log"
messages-property="messages">
<set-extension-point property="tasks"
point-id="Startup"/>
@@ -167,7 +179,7 @@
<service id="Shutdown" interface="java.lang.Runnable">
<invoke-factory service-id="hivemind.BuilderFactory">
<construct
-
class="com.webct.platform.framework.initshut.service.TaskExecutor"
+
class="com.oubliette.framework.startup.service.TaskExecutor"
log-property="log"
messages-property="messages">
<set-extension-point property="tasks"
point-id="Shutdown"/>
@@ -182,9 +194,6 @@
<p>
Notes:
<ul>
-<li>HiveMind does not require that the module id match a package name; in this case,
-the module id ("vista.framework.initshut") is shorter and simpler than the
-principal package ("com.webct.platform.framework.initshut"). </li>
<li>
We use the <code>ref-id</code> attribute of &schema; to avoid unwanted
duplication.
</li>
@@ -192,7 +201,7 @@
Extension points, extensions and services can be specified in any order.
</li>
<li>
-We use the simplest possible interface for the services:
<code>java.lang.Runnable</code>.
+We use the simplest possible interface for the Startup and Shutdown services:
<code>java.lang.Runnable</code>.
</li>
</ul>
</p>
@@ -217,7 +226,7 @@
The task to execute is specified in one of three ways:
<ul>
<li>As a Java class implementing the
- <code>com.webct.platform.framework.initshut.service.Executable</code>
interface (using the <code>class</code> attribute)</li>
+ <code>com.oubliette.framework.startup.service.Executable</code> interface
(using the <code>class</code> attribute)</li>
<li>As a HiveMind service, implementing the service (using the
<code>service-id</code> attribute)</li>
<li>As a public static method of a class (using the enclosed
<code><invoke-static></code> element)</li>
</ul>
@@ -226,7 +235,7 @@
<p>
The <code>Executable</code> interface is similar to the
<code>java.lang.Runnable</code> interface:
<source>
-package com.webct.platform.framework.initshut.service;
+package com.oubliette.framework.startup.service;
/**
* Variation of <code>java.lang.Runnable</code> that allows for
@@ -244,7 +253,7 @@
</p>
<p>
-Shortly, we'll see how the servlet invokes the Startup service.
+Shortly, we'll see how the application's master servlet invokes the Startup
service.
</p>
<p>
@@ -260,15 +269,15 @@
</p>
<source>
-package com.webct.platform.framework.initshut.service;
+package com.oubliette.framework.startup.service;
import org.apache.commons.hivemind.Orderable;
/**
- * Configuration element for the <code>vista.framework.initshut.Startup</code> or
- * <code>vista.framework.initshut.Shutdown</code>
+ * Configuration element for the <code>oubliette.framework.startup.Startup</code> or
+ * <code>oubliette.framework.startup.Shutdown</code>
* extension points. Each element has a title,
- * an [EMAIL PROTECTED] com.webct.platform.framework.initshut.service.Executable}
+ * an [EMAIL PROTECTED] com.oubliette.framework.startup.service.Executable}
* object, and an order
* (used to sort the Startup items into an order of execution).
*/
@@ -333,7 +342,7 @@
</p>
<source><![CDATA[
-package com.webct.platform.framework.initshut.service;
+package com.oubliette.framework.startup.service;
import java.util.List;
@@ -342,7 +351,7 @@
import org.apache.commons.logging.Log;
/**
- * Implementation for the <code>vista.framework.initshut.Startup</code>
+ * Implementation for the <code>oubliette.framework.startup.Startup</code>
* and <code>Shutdown</code> services.
* Reads the corresponding configuration, sorts the elements,
* and executes each.
@@ -446,6 +455,20 @@
}
]]>
</source>
+
+<p>
+HiveMind has a static convienience method, <code>sortOrderables()</code>, used to
sort a list of Orderable
+objects into order, which is used here. Remember that the contributions to the
Startup (and Shutdown)
+extension points are made from multiple modules and there's no way to predict in
what order those contributions
+will show up in the <code>tasks</code> property, which is why explicit sorting is
necessary.
+</p>
+
+<p>
+At one time, there was a discussion about using a thread pool to allow execution of
some of the tasks in parallel.
+That's
+a premature optimization: even with over forty startup tasks, startup still only
takes about forty seconds.
+</p>
+
</subsection>
<subsection name="StaticTask class">
@@ -456,7 +479,7 @@
</p>
<source>
-package com.webct.platform.framework.initshut.service;
+package com.oubliette.framework.startup.service;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -467,7 +490,7 @@
/**
* Implementation of
- * [EMAIL PROTECTED] com.webct.platform.framework.initshut.service.Executable}
+ * [EMAIL PROTECTED] com.oubliette.framework.startup.service.Executable}
* that Invokes a static method on a public class.
*/
public class StaticTask extends BaseLocatable implements Executable
@@ -552,17 +575,17 @@
<p>
Other modules, in their HiveMind module deployment descriptors, make contributions
-into the Startup and Shutdown extension points of the
<code>vista.framework.initshut</code>
+into the Startup and Shutdown extension points of the
<code>oubliette.framework.startup</code>
module. For example:
<source><![CDATA[
<?xml version="1.0"?>
-<module id="vista.coreservice.mail" version="1.0.0">
+<module id="oubliette.coreservice.mail" version="1.0.0">
- <extension point-id="vista.framework.initshut.Startup">
+ <extension point-id="oubliette.framework.startup.Startup">
<task title="Mail" order="2600"
-
class="com.webct.platform.coreservice.mail.startup.MailStartup"/>
+ class="com.oubliette.coreservice.mail.startup.MailStartup"/>
</extension>
@@ -575,13 +598,13 @@
Other modules take advantage of the <invoke-static> element:
<source><![CDATA[<?xml version="1.0"?>
-<module id="vista.coreservice.garbagecollection" version="1.0.0">
+<module id="oubliette.coreservice.garbagecollection" version="1.0.0">
- <extension point-id="vista.framework.initshut.Startup">
+ <extension point-id="oubliette.framework.startup.Startup">
<task title="Scheduling Garbage Collection" order="3900">
<invoke-static
-
class="com.webct.platform.coreservice.garbagecollection.startup.GarbageCollectionStartup"
+
class="com.oubliette.coreservice.garbagecollection.startup.GarbageCollectionStartup"
/>
</task>
@@ -595,7 +618,7 @@
<section name="Servlet Initialization">
<p>
-The servlet for the web application is responsible for constructing the registry
+The master servlet for the web application is responsible for constructing the
registry
and storing it (using <code>HiveMind.setDefault()</code>) so that
other code may access it.
</p>
@@ -625,16 +648,16 @@
HiveMind.setDefault(registry);
Runnable startup =
- (Runnable)registry.getService("vista.framework.initshut.Startup",
Runnable.class);
+
(Runnable)registry.getService("oubliette.framework.startup.Startup", Runnable.class);
- LOG.info("*** Executing vista.framework.initshut.Startup service ***");
+ LOG.info("*** Executing oubliette.framework.startup.Startup service
***");
startup.run();
}
catch (Exception ex)
{
LOG.error(
- "Unable to execute vista.framework.initshut.Startup service: " +
ex.getMessage());
+ "Unable to execute oubliette.framework.startup.Startup service: "
+ ex.getMessage());
}
}
]]></source>
@@ -654,20 +677,21 @@
We take advantage of a WebLogic extension to know when the application server is
being shut down.
<source>
-package com.webct.platform.framework.initshut;
+package com.oubliette.framework.startup;
+
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
-import com.webct.platform.framework.initshut.ejb.initshut;
-import com.webct.platform.framework.initshut.ejb.initshutHome;
+import com.oubliette.framework.startup.ejb.Shutdown;
+import com.oubliette.framework.startup.ejb.ShutdownHome;
/**
* Shutdown class called by the WebLogic container.
*/
public class Shutdown
{
- private final static String INIT_EJB_JNDI_NAME =
- "com.webct.platform.framework.initshut.ejb.initshutHome";
+ private final static String EJB_JNDI_NAME =
+ "com.oubliette.framework.startup.ejb.initshutHome";
/** Prevent instantiation */
private Shutdown()
@@ -675,19 +699,18 @@
}
/**
- * Gets the initshut EJB and invokes <code>shutdown()</code>.
+ * Gets the Shutdown EJB and invokes <code>shutdown()</code>.
*/
public static void main(String args[]) throws Exception
{
- // Call the initshut EJB
InitialContext context = new InitialContext();
- initshutHome home =
- (initshutHome)PortableRemoteObject.narrow(
- context.lookup(INIT_EJB_JNDI_NAME),
- initshutHome.class);
+ ShutdownHome home =
+ (ShutdownHome)PortableRemoteObject.narrow(
+ context.lookup(EJB_JNDI_NAME),
+ ShutdownHome.class);
- initshut bean = (initshut)home.create();
+ Shutdown bean = (Shutdown)home.create();
bean.shutdown();
}
@@ -699,7 +722,7 @@
<p>
The implementation of the initshut EJB is similarily straight-forward:
<source><![CDATA[
-package com.webct.platform.framework.initshut.ejb;
+package com.oubliette.framework.startup.ejb;
import java.rmi.RemoteException;
@@ -710,26 +733,26 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import com.webct.platform.framework.ejb.BaseSessionBean;
+import com.oubliette.framework.ejb.BaseSessionBean;
/**
* Handles shutdown logic.
*
*/
-public class initshutEJB extends BaseSessionBean implements Iinitshut
+public class ShutdownEJB extends BaseSessionBean
{
- private static final Log LOG = LogFactory.getLog(initshutEJB.class);
+ private static final Log LOG = LogFactory.getLog(ShutdownEJB.class);
public void ejbCreate() throws RemoteException, CreateException
{
}
/**
- * Called by J2EE Container shutdown calss for Vista shutdown processing.
+ * Called by J2EE Container shutdown calss for Oubliette shutdown processing.
*
* <p>
- * Gets the <code>vista.framework.initshut.Shutdown</code> service and executes
it.
+ * Gets the <code>oubliette.framework.startup.Shutdown</code> service and
executes it.
*
*/
@@ -745,11 +768,11 @@
}
Runnable r =
- (Runnable)registry.getService("vista.framework.initshut.Shutdown",
Runnable.class);
+ (Runnable)registry.getService("oubliette.framework.startup.Shutdown",
Runnable.class);
r.run();
- LOG.info("**** Vista shutdown complete ****");
+ LOG.info("**** Oubliette shutdown complete ****");
}
}]]>
</source>
@@ -762,7 +785,7 @@
<p>
This case study has shown how easy it is to leverage HiveMind for a complex task. A
monolithic EJB was broken down into
tiny, agile contributions to an extension point. The startup and shutdown logic is
kept close to the contributing
-modules', in those modules' HiveMind deployment descriptor. Contributions are in
expressive, easily readable XML.
+modules, in those modules' HiveMind deployment descriptors. Contributions are in
expressive, easily readable XML.
</p>
<p>A single class is used to implement multiple, similar services, just by
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]