You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by si...@avalon.apache.org on 2004/02/20 16:20:00 UTC

[Apache Avalon Wiki] Updated: AvalonYouMakeTheDecision

   Date: 2004-02-20T07:19:59
   Editor: 160.33.82.119 <>
   Wiki: Apache Avalon Wiki
   Page: AvalonYouMakeTheDecision
   URL: http://wiki.apache.org/avalon/AvalonYouMakeTheDecision

   fixed formatting -farra

Change Log:

------------------------------------------------------------------------------
@@ -1,7 +1,3 @@
-http://avalon.apache.org/images/header.gif
-
-This page is part of the wiki materials for the [wiki:WhatIsAProject top-level] [http://avalon.apache.org Apache Avalon] project.
-
 = You Make The Decision =
 
 ==== Comparing avalon to other framework technologies ====
@@ -34,63 +30,66 @@
 
 With JBoss, you can download a 30MB zipfile containing kitchen sink and blender, which you can unzip and run, providing you with an EJB server, a Servlet Engine, a database, with no further setup neccessary:
 
-{{{ wget http://unc.dl.sourceforge.net/sourceforge/jboss/jboss-3.2.1.zip }}}
-{{{ unzip jboss-3.2.1.zip }}}
-{{{ mv jboss-3.2.1 /usr/local/jboss-3.2.1 }}}
-{{{ ln -s /usr/local/jboss-3.2.1 /usr/local/jboss }}}
-{{{ /usr/local/jboss/bin/run }}}
+{{{
+ wget http://unc.dl.sourceforge.net/sourceforge/jboss/jboss-3.2.1.zip
+ unzip jboss-3.2.1.zip
+ mv jboss-3.2.1 /usr/local/jboss-3.2.1
+ ln -s /usr/local/jboss-3.2.1 /usr/local/jboss 
+ /usr/local/jboss/bin/run 
+}}}
 
 === Avalon ===
 
 Avalon does not provide a similar "kitchen sink"-style distribution. You are usually required to think about the way you want to organise your application and how it fits in with your existing infrastructure. Avalon does provide a micro-kernel which can be run directly from the commandline. The EOB project packages up Avalon-Phoenix, an EJB-style container, the Jetty Servlet engine, and hypersonicSQL. This is the closest avalon gets to providing a ["J2EE"]-style setup:
 
-{{{ # install Avalon-Phoenix }}}
-{{{ wget  }}}
-{{{  http://dist.apache.easynet.nl/avalon/phoenix/phoenix-latest-bin.zip }}}
-{{{ unzip phoenix-latest-bin.zip }}}
-{{{ mv phoenix-4.0.4-bin /usr/local/phoenix-4.0.4 }}}
-{{{ ln -s /usr/local/phoenix-4.0.4 /usr/local/phoenix }}}
-
-{{{ # get and install an EJB-style container with servlet support and }}}
-{{{ # ["HypersonicSQL"] }}}
-{{{ wget  }}}
-{{{  http://unc.dl.sourceforge.net/sourceforge/eob/eob-with-http-and-db.sar }}}
-{{{ mv eob-with-http-and-db.sar /usr/local/phoenix/apps }}}
+{{{ 
+# install Avalon-Phoenix 
+ wget http://dist.apache.easynet.nl/avalon/phoenix/phoenix-latest-bin.zip
+ unzip phoenix-latest-bin.zip 
+ mv phoenix-4.0.4-bin /usr/local/phoenix-4.0.4 
+ ln -s /usr/local/phoenix-4.0.4 /usr/local/phoenix 
+
+ # get and install an EJB-style container with servlet support and 
+ # ["HypersonicSQL"] 
+ wget ttp://unc.dl.sourceforge.net/sourceforge/eob/eob-with-http-and-db.sar 
+ mv eob-with-http-and-db.sar /usr/local/phoenix/apps 
 
-{{{ /usr/local/phoenix/bin/run }}}
+ /usr/local/phoenix/bin/run 
 
 However, you can use many parts of avalon, and components built with the avalon-framework, without ever installing phoenix. In that case, your installation may look more like the following snippet of a Maven project.xml file:
 
-{{{        <dependency> }}}
-{{{            <id>avalon-logkit</id> }}}
-{{{            <groupId>logkit</id> }}}
-{{{            <version>1.2</version> }}}
-{{{        </dependency> }}}
-{{{        <dependency> }}}
-{{{            <id>avalon-framework</id> }}}
-{{{            <groupId>framework</id> }}}
-{{{            <version>4.1.4</version> }}}
-{{{        </dependency> }}}
-{{{        <dependency> }}}
-{{{            <id>excalibur-logger</id> }}}
-{{{            <version>1.0.1</version> }}}
-{{{        </dependency> }}}
-{{{        <dependency> }}}
-{{{            <id>excalibur-pool</id> }}}
-{{{            <version>1.2</version> }}}
-{{{        </dependency> }}}
-{{{        <dependency> }}}
-{{{            <id>excalibur-i18n</id> }}}
-{{{            <version>1.0</version> }}}
-{{{        </dependency> }}}
-{{{        <dependency> }}}
-{{{            <id>excalibur-logger</id> }}}
-{{{            <version>1.0.1</version> }}}
-{{{        </dependency> }}}
-{{{        <dependency> }}}
-{{{            <id>excalibur-component</id> }}}
-{{{            <version>complete-1.1</version> }}}
-{{{        </dependency> }}}
+{{{      
+         <dependency> 
+            <id>avalon-logkit</id> 
+            <groupId>logkit</id> 
+            <version>1.2</version> 
+        </dependency> 
+        <dependency> 
+            <id>avalon-framework</id> 
+            <groupId>framework</id> 
+            <version>4.1.4</version> 
+        </dependency> 
+        <dependency> 
+            <id>excalibur-logger</id> 
+            <version>1.0.1</version> 
+        </dependency> 
+        <dependency> 
+            <id>excalibur-pool</id> 
+            <version>1.2</version> 
+        </dependency> 
+        <dependency> 
+            <id>excalibur-i18n</id> 
+            <version>1.0</version> 
+        </dependency> 
+        <dependency> 
+            <id>excalibur-logger</id> 
+            <version>1.0.1</version> 
+        </dependency> 
+        <dependency> 
+            <id>excalibur-component</id> 
+            <version>complete-1.1</version> 
+        </dependency> 
+}}}
 
 coupled with a custom "project:deploy" goal which results in the building and installation of your application in whatever way makes sense.
 
@@ -138,47 +137,50 @@
 
 Servlets provide a very nice way to provide web functionality to an application. A realistic example of an application encoded as a set of servlets is[wiki:AxisProjectPages Apache Axis]. The main entrypoint into the application is the [http://cvs.apache.org/viewcvs.cgi/*checkout*/xml-axis/java/src/org/apache/axis/transport/http/AxisServlet.java?rev=HEAD&content-type=text/plain AxisServlet] class. This servlet follows a setup roughly like:
 
-{{{ public class MyServlet extends ["HttpPServlet"] }}}
-{{{ { }}}
-{{{    public void init() }}}
-{{{    { }}}
-{{{        ServletContext context = getServletConfig().getServletContext(); }}}
-{{{        // configure servlet behaviour based on context }}}
-{{{    } }}}
-{{{     }}}
-{{{    public void destroy() }}}
-{{{    { }}}
-{{{        if( engine != null ) }}}
-{{{            /* TODO: destroy the engine and remove from ctx */ ; }}}
-{{{    } }}}
-{{{     }}}
-{{{    protected void service( HttpServletRequest req, }}}
-{{{          HttpServletResponse resp ) }}}
-{{{          throws ServletException, IOException }}}
-{{{    { }}}
-{{{        ServletContext ctx = getServletConfig().getServletContext(); }}}
-{{{        MyAppEngine engine = getEngine( context ); }}}
-{{{        MyAppHandler handler = engine.getHandler( req, res, ctx ); }}}
-{{{        handler.handle( req, res, ctx ); }}}
-{{{    } }}}
-{{{     }}}
-{{{    public static MyAppEngine getEngine( ServletContext ctx ) }}}
-{{{    { }}}
-{{{        Object o = context.getAttribute( MyAppEngine.class.getName() ); }}}
-{{{        if ( o instanceof MyAppEngine ) }}}
-{{{            return (MyAppEngine)o; }}}
-{{{        else }}}
-{{{        { }}}
-{{{            Map config = null; }}}
-{{{            /* TODO: create config based on ctx */ }}}
-{{{            MyAppEngine engine = MyAppEngineFactory.createEngine( }}}
-{{{                config ); }}}
-
-{{{            context.setAttribute( MyAppEngine.class.getName(), }}}
-{{{                engine ); }}}
-{{{        } }}}
-{{{    } }}}
-{{{ } }}}
+{{{
+ public class MyServlet extends ["HttpPServlet"] 
+ { 
+    public void init() 
+    { 
+        ServletContext context = getServletConfig().getServletContext(); 
+        // configure servlet behaviour based on context 
+    } 
+     
+    public void destroy() 
+    { 
+        if( engine != null ) 
+            /* TODO: destroy the engine and remove from ctx */ ; 
+    } 
+     
+    protected void service( HttpServletRequest req, 
+          HttpServletResponse resp ) 
+          throws ServletException, IOException 
+    { 
+        ServletContext ctx = getServletConfig().getServletContext(); 
+        MyAppEngine engine = getEngine( context ); 
+        MyAppHandler handler = engine.getHandler( req, res, ctx ); 
+        handler.handle( req, res, ctx ); 
+    } 
+     
+    public static MyAppEngine getEngine( ServletContext ctx ) 
+    { 
+        Object o = context.getAttribute( MyAppEngine.class.getName() ); 
+        if ( o instanceof MyAppEngine ) 
+            return (MyAppEngine)o; 
+        else 
+        { 
+            Map config = null; 
+            /* TODO: create config based on ctx */ 
+            MyAppEngine engine = MyAppEngineFactory.createEngine( 
+                config ); 
+
+            context.setAttribute( MyAppEngine.class.getName(), 
+                engine ); 
+        } 
+    } 
+ } 
+}}}
+
 
 Surely, this a setup that is difficult to beat, isn't it?
 
@@ -190,146 +192,146 @@
 
 Here's an example of a MyAppEngine implemented using Avalon-Fortress (note this is untested code that probably contains typos and misses some try/catch statements and the like):
 
-{{{ public class MyAppEngine extends DefaultContainer }}}
-{{{ { }}}
-{{{    public MyAppHandler getHandler( HttpServletRequest req, }}}
-{{{          HttpServletResponse resp, ServletContext ctx ) }}}
-{{{    { }}}
-{{{        try }}}
-{{{        { }}}
-{{{            MyAppHandlerManager m = getServiceManager().lookup( }}}
-{{{                    MyAppHandlerManager.ROLE ); }}}
-{{{            return m.getHandler( req, resp, ctx ); }}}
-{{{        } }}}
-{{{        catch( ServiceException se ) }}}
-{{{        { }}}
-{{{            return getErrorHandler(); }}}
-{{{        } }}}
-{{{    } }}}
-{{{     }}}
-{{{    public MyAppHandler getErrorHandler() }}}
-{{{    { }}}
-{{{        return null; /* TODO: implement fail-safe mechanism in case }}}
-{{{                        of a fortress configuration problem */ }}}
-{{{    } }}}
-{{{ } }}}
-{{{ public class DefaultMyAppHandlerManager extends AbstractLogEnabled }}}
-{{{        implements MyAppHandlerManager, Configurable, Initializable }}}
+{{{
+ public class MyAppEngine extends DefaultContainer 
+ { 
+    public MyAppHandler getHandler( HttpServletRequest req, 
+          HttpServletResponse resp, ServletContext ctx ) 
+    { 
+        try 
+        { 
+            MyAppHandlerManager m = getServiceManager().lookup( 
+                    MyAppHandlerManager.ROLE ); 
+            return m.getHandler( req, resp, ctx ); 
+        } 
+        catch( ServiceException se ) 
+        { 
+            return getErrorHandler(); 
+        } 
+    } 
+     
+    public MyAppHandler getErrorHandler() 
+    { 
+        return null; /* TODO: implement fail-safe mechanism in case 
+                        of a fortress configuration problem */ 
+    } 
+ } 
+ public class DefaultMyAppHandlerManager extends AbstractLogEnabled 
+        implements MyAppHandlerManager, Configurable, Initializable 
 {
-{{{    protected Configuration m_configuration; }}}
-{{{    protected HashMap m_handlers = new HashMap(); }}}
-{{{     }}}
-{{{    /** }}}
-{{{     * Expect configuration of the form: }}}
-{{{     * <handler-manager> }}}
-{{{     *  <handlers> }}}
-{{{     *   <handler regex="/\*checkout\*/.*" }}}
-{{{     *      className="com.my.handlers.CheckoutHandler"> }}}
-{{{     *    <!-- handler-specific configuration goes here --> }}}
-{{{     *   </handler> }}}
-{{{     *   <handler regex="/\*commit\*/.*" }}}
-{{{     *      className="com.my.handlers.CommitHandler"/> }}}
-{{{     *  </handlers> }}}
-{{{     * </handler-manager> }}}
-{{{     */ }}}
-{{{    public void configure( Configuration config ) }}}
-{{{            throws ConfigurationException }}}
-{{{    { }}}
-{{{        m_configuration = config; }}}
-
-{{{        Configuration[] conf = }}}
-{{{                m_configuration.getChild("handlers").getChildren(); }}}
-{{{        Configuration[] elements = config.getChildren(); }}}
-{{{        for ( int i = 0; i < elements.length; i++ ) }}}
-{{{        { }}}
-{{{            Configuration element = elements[i]; }}}
-{{{            String regex = element.getAttribute( "regex" ); }}}
-{{{            String className = element.getAttribute( "class" ); }}}
-{{{            m_handlers.put( regex, }}}
-{{{                new HandlerEntry( regex, className, element ); }}}
-{{{        } }}}
-{{{    } }}}
-{{{     }}}
-{{{    public void initialize() }}}
-{{{            throws InitializationException }}}
-{{{    { }}}
-{{{        Iterator it = m_handlers.values().iterator(); }}}
-{{{        while( it.hasNext() ) }}}
-{{{        { }}}
-{{{            HandlerEntry entry = it.next(); }}}
-{{{            try }}}
-{{{            { }}}
-{{{                entry.m_clazz = Class.forName( entry.m_className ); }}}
-{{{                if( !(MyAppHandler.isAssignableFrom( entry.m_clazz ) ) }}}
-{{{                { }}}
-{{{                    getLogger().error( }}}
-{{{                        "instance of handler with regex " + }}}
-{{{                        regex + " and className " + className + }}}
-{{{                        "does not implement MyAppHandler!", cnfe ); }}}
-{{{                     it.remove(); }}}
-{{{                } }}}
-{{{            } }}}
-{{{            catch( ClassNotFoundException cnfe ) }}}
-{{{            { }}}
-{{{                getLogger().error( }}}
-{{{                   "can't create instance of handler with regex " + }}}
-{{{                   regex + " and className " + className, cnfe ); }}}
-{{{                it.remove(); }}}
-{{{            } }}}
-{{{            catch( InstantiationException ie ) }}}
-{{{            { }}}
-{{{                getLogger().error( }}}
-{{{                   "can't create instance of handler with regex " + }}}
-{{{                   regex + " and className " + className, ie ); }}}
-{{{                it.remove(); }}}
-{{{            } }}}
-{{{        } }}}
-{{{    } }}}
-{{{     }}}
-{{{    public MyAppHandler getHandler( req, resp, ctx ) }}}
-{{{    { }}}
-{{{        return getHandler( req.getContextPath() ); }}}
-{{{    } }}}
-{{{    public MyAppHandler getHandler( String path ) }}}
-{{{    { }}}
-{{{        Iterator it = m_handlers.values().iterator(); }}}
-{{{        while( it.hasNext() ) }}}
-{{{        { }}}
-{{{            HandlerEntry entry = it.next(); }}}
-{{{            if( path.matches( entry.m_regex ) ) }}}
-{{{            { }}}
-{{{                MyAppHandler h = entry.m_clazz.newInstance(); }}}
-
-{{{                ContainerUtil.enableLogging( h, getLogger() ); }}}
-{{{                ContainerUtil.configure( h, entry.m_configuration ); }}}
-{{{                ContainerUtil.initialize( h ); }}}
-
-{{{                return h; }}}
-{{{            } }}}
-{{{        } }}}
-{{{        return null; }}}
-{{{    } }}}
-{{{     }}}
-{{{    class HandlerEntry }}}
-{{{    { }}}
-{{{        String m_regex; }}}
-{{{        String m_className; }}}
-{{{        Class m_clazz; }}}
-{{{        Configuration m_configuration; }}}
-{{{         }}}
-{{{        HandlerEntry( String regex, String className, Configuration configuration ) }}}
-{{{        { }}}
-{{{            m_regex = regex; m_className = className; m_clazz = null; }}}
-{{{            m_configuration = configuration; }}}
-{{{        } }}}
-{{{    } }}}
+    protected Configuration m_configuration; 
+    protected HashMap m_handlers = new HashMap(); 
+     
+    /** 
+     * Expect configuration of the form: 
+     * <handler-manager> 
+     *  <handlers> 
+     *   <handler regex="/\*checkout\*/.*" 
+     *      className="com.my.handlers.CheckoutHandler"> 
+     *    <!-- handler-specific configuration goes here --> 
+     *   </handler> 
+     *   <handler regex="/\*commit\*/.*" 
+     *      className="com.my.handlers.CommitHandler"/> 
+     *  </handlers> 
+     * </handler-manager> 
+     */ 
+    public void configure( Configuration config ) 
+            throws ConfigurationException 
+    { 
+        m_configuration = config; 
+
+        Configuration[] conf = 
+                m_configuration.getChild("handlers").getChildren(); 
+        Configuration[] elements = config.getChildren(); 
+        for ( int i = 0; i < elements.length; i++ ) 
+        { 
+            Configuration element = elements[i]; 
+            String regex = element.getAttribute( "regex" ); 
+            String className = element.getAttribute( "class" ); 
+            m_handlers.put( regex, 
+                new HandlerEntry( regex, className, element ); 
+        } 
+    } 
+     
+    public void initialize() 
+            throws InitializationException 
+    { 
+        Iterator it = m_handlers.values().iterator(); 
+        while( it.hasNext() ) 
+        { 
+            HandlerEntry entry = it.next(); 
+            try 
+            { 
+                entry.m_clazz = Class.forName( entry.m_className ); 
+                if( !(MyAppHandler.isAssignableFrom( entry.m_clazz ) ) 
+                { 
+                    getLogger().error( 
+                        "instance of handler with regex " + 
+                        regex + " and className " + className + 
+                        "does not implement MyAppHandler!", cnfe ); 
+                     it.remove(); 
+                } 
+            } 
+            catch( ClassNotFoundException cnfe ) 
+            { 
+                getLogger().error( 
+                   "can't create instance of handler with regex " + 
+                   regex + " and className " + className, cnfe ); 
+                it.remove(); 
+            } 
+            catch( InstantiationException ie ) 
+            { 
+                getLogger().error( 
+                   "can't create instance of handler with regex " + 
+                   regex + " and className " + className, ie ); 
+                it.remove(); 
+            } 
+        } 
+    } 
+     
+    public MyAppHandler getHandler( req, resp, ctx ) 
+    { 
+        return getHandler( req.getContextPath() ); 
+    } 
+    public MyAppHandler getHandler( String path ) 
+    { 
+        Iterator it = m_handlers.values().iterator(); 
+        while( it.hasNext() ) 
+        { 
+            HandlerEntry entry = it.next(); 
+            if( path.matches( entry.m_regex ) ) 
+            { 
+                MyAppHandler h = entry.m_clazz.newInstance(); 
+
+                ContainerUtil.enableLogging( h, getLogger() ); 
+                ContainerUtil.configure( h, entry.m_configuration ); 
+                ContainerUtil.initialize( h ); 
+
+                return h; 
+            } 
+        } 
+        return null; 
+    } 
+     
+    class HandlerEntry 
+    { 
+        String m_regex; 
+        String m_className; 
+        Class m_clazz; 
+        Configuration m_configuration; 
+         
+        HandlerEntry( String regex, String className, Configuration configuration ) 
+        { 
+            m_regex = regex; m_className = className; m_clazz = null; 
+            m_configuration = configuration; 
+        } 
+    }
+}}}
 
 === Conclusion ===
 
 Rather than replacing the servlet API with something incompatible, meaning all the existing work that has gone into that API and the containers to support it would be void, Avalon provides some great tools, like Avalon-Fortress, which you can seamlessly embed into your servlet application, handling all of your "system-level concerns".
 
-
-
 == I'll have that neither shaken nor stirred please (EJBs vs Avalon-Framework components) ==
 
 === EJB Sucks ===
@@ -350,34 +352,38 @@
 
 With Avalon-AMTAGS, in order to qualify your components as a component you have to do next to nothing:
 
-{{{ /** @avalon.service type="MyService" */ }}}
-{{{ class MyClass implements MyService { /* ... */ } }}}
+{{{ 
+   /** @avalon.service type="MyService" */ 
+   class MyClass implements MyService { /* ... */ } 
+}}}
 
 === Avalon properly seperates concerns ===
 
 When you decide you need to address some system-level concern (like logging), you usually need to add only a single method:
 
-{{{ class MyClass implements MyService, LogEnabled }}}
-{{{ { }}}
-{{{    void enableLogging( Logger logger ) { /* ... */ } }}}
-{{{ } }}}
+{{{ 
+ class MyClass implements MyService, LogEnabled 
+ { 
+    void enableLogging( Logger logger ) { /* ... */ }
+ }
 
 When you need to address a concern which is not system-level, Avalon does usuallly not provide it (by design!), and you write (or reuse) a component which addresses it for you:
 
-{{{ class MyClass implements MyService, Servicable }}}
-{{{ { }}}
-{{{    MyHelperService m_helper = null; }}}
-
-{{{    void service( ServiceManager sm ) throws ServiceException }}}
-{{{    { }}}
-{{{        helper = sm.lookup( MyHelperService.ROLE ); }}}
-{{{    } }}}
-{{{ } }}}
+{{{ 
+    class MyClass implements MyService, Servicable 
+  { 
+   MyHelperService m_helper = null; 
+
+    void service( ServiceManager sm ) throws ServiceException 
+    { 
+        helper = sm.lookup( MyHelperService.ROLE ); 
+    } 
+  }
+}}} 
 
 This is hands-down the closest you can get at the moment to cleancut AspectOrientedProgramming without requiring an extension of the java language.
 
-{{{ TODO: point out some examples of typical bad mixture of concerns in }}}
-{{{ EJB }}}
+{{{ TODO: point out some examples of typical bad mixture of concerns in EJB }}}
 
 == predicatibility beats RAD on big projects (JNDI vs IoC) ==
 
@@ -405,11 +411,13 @@
 
 Once you have your base platform in place like you want it to, you have followed all advice on system decomposition avalon provides, and you have successfully determined what components you need and what they will do, avalon gets out of the way. Implementing your components is a simple matter of defining a work interface you completely design yourself
 
-{{{ interface SomeWorkInterface }}}
-{{{ { }}}
-{{{     public String ROLE = SomeWorkInterface.class.getName(); }}}
-{{{      }}}
-{{{     Result doThis(); }}}
-{{{ } }}}
+{{{ 
+    interface SomeWorkInterface 
+ { 
+     public String ROLE = SomeWorkInterface.class.getName(); 
+      
+     Result doThis(); 
+ } 
+}}}
 
 and providing an implementation that uses the Avalon-Framework lifecycle to get at all the stuff it needs from its environment. When you write the implementation of your work interface, what "stuff" it needs will quickly become apparent and you add lifecycle interfaces to get at that stuff.

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org