avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Robert McIntosh <rob...@bull-enterprises.com>
Subject Re: [RT] The Next Big Component Architecture
Date Wed, 02 Jul 2003 15:39:44 GMT
Speaking as a user of avalon/fortress, I agree completely on the 
usability and complexity aspects of your statements. I still have a hard 
time getting across to coworkers just exactly avalon is. For the longest 
time my boss thought it was an xml config tool. After about the 8th time 
of saying "the config is just one small portion of it", he finally got 
it. It seems to me at this point in Avalon's life that it can be used by 
really smart people, or those who want to invest a lot of time in 
learning how to use it, to help out other people. In other words, guru 1 
can setup phoenix/merlin/whatever with some services and allow non-guru 
2-10 to use them easily. Make sense?

The hardest thing as a user to get or understand is the roles config. 
Last time I looked (a few months or so), there was almost no docs on how 
to set this stuff up. I first went by examples, but they were outdated 
and nothing worked. I eventually got it, but it wasn't trivial. Your 
mention of the declarative side of things is really interesting to me, 
cause that is what our product is geared towards. We use avalon/fortress 
to help facilitate the services side of things, but what we do is allow 
the developer the option of decalaring, through the config of our 
components, most if not all aspects of an applications domain model and 
processes.

Robert

Leo Simons wrote:

> Hi gang,
>
> some ramblings of a madman before I head off to bed.
>
> cheers,
>
> - LSD
>
> Looking back a little
> ---------------------
> A few years ago [0], the web application world was a mess. We had 
> servlets [1], which involved embedding html inside java code, and we 
> had jsps, which involved custom markup that was just as ugly. The 
> business component world was just as messy, with EJB 1.0 out [2] but 
> very little actual support and buggy, pricy servers. We also had 
> applets which allowed us to circumvent all that ugly stuff by 
> circumventing the entire http/html layer and writing ugly binary 
> socket-based protocols. The latter got unpractical as netscape lost 
> the browser war and Swing arrived on the scene too late.
>
> Still, there was a good JDK [3], including one for linux, and the JFC 
> were shaping up pretty nicely. We jumped to java en masse. Booming 
> business.
>
> "This is a mess. Lets fix it."
> ------------------------------
> So we had JServ 1.0, JBoss 1.0, something called "tomcat" no-one 
> actually used, lots of crappy code, and not much potential for reuse. 
> Several lessons were learned in developing all of that stuff, and 
> several projects formed all around the open source world that fixed 
> various pieces of the puzzles and scratched various itches.
>
> Lessons learned
> ---------------
> Let's look at some of the things we've figured out along the way....
>
> Java works: Well duh! It was clear to many that there was a good base
>     platform here that got most details reasonably right (even if
>     Stack inherited cruft from Vector).
>
> XML works, too: A, the beauty of a simple markup language both
>     machine-readable and human-readable!
>
> language mixing sucks: embedding markup language or scripting language
>     inside inside programming language quickly becomes unreadable.
>     Parsers or templating technologies make life easier.
>
> decouple: I won't seriously consider programming big applications in a
>     language that doesn't have the keyword 'interface' these days
>
> big design is bad: one acronym - EJB. Ugh.
>
> open source wins: in 2003, almost every important component for building
>     server side software is open source. Except for a JDK, for some
>     reason.
>
> unit tests: More Important Than Interfaces. The various parts of XP
>     methodology are slowly saturating the java world.
>
> ...and one could go on and on. The landscape is still improving.
>
> Sharing Is Hard
> ---------------
> look at the number of "web application frameworks" out there. Dozens 
> of them. Look at the lack of common ground they have. Missed 
> potential. It takes an extreme amount of energy to figure out a way to 
> encapsulate some basic functionality so that it can successfully be 
> shared even across a limited problem domain.
>
> One of the things avalon is supposed to enable is reuse within a 
> problem domain, or even across problem domains. However, we have not 
> succeeded in making this so easy and obvious that the average java 
> bloke can figure out in an afternoon how to do it. Sharing remains hard.
>
> In practice, the only clean form of sharing occurs on a large scale is 
> when someone succeeds in totally isolating a cross-cutting concern 
> into an appropriately partitioned vessel. Like log4j.jar or JAXP, or 
> GUI javabeans. These are the exception rather than the rule, 
> especially as partitioning grows.
>
> There are exceptions, where inferior or all-encompassing tech still 
> manages to become a standard, usually grown out of a standards body 
> (DOM) or corporate backing (EJB), but those usually get competition 
> from people who've scratched their itch and improved on the concept 
> (JDOM, EOB).
>
> So, some statements summed up
> -----------------------------
> The java platform works, but frameworks like avalon remain complex, 
> too complex for the average joe user (or the average professional with 
> only a day or two to spend [5]) to actually gain critical mass without 
> corporate backing. Therefore, basic software architecture is still 
> being re-invented on a daily basis and sharing remains very hard.
>
> The winning concepts
> --------------------
> * IoC
> * COP
> * Api/Impl seperation
> * KISS
> * XP, test first
> * asynced events, pipelining
> * aspects
> * attributes
> * scriptability
> * pluggability
> * strong typing
>
> Avalon has IoC, COP, Api/Impl seperation. Attributes are coming. 
> Various stuff is easily added. The main thing it misses is KISS. The 
> other main thing is pluggability. Avalon is _not_ pluggable. 
> Components written using avalon are pluggable inside other components 
> written using avalon. Applying avalon to an existing system often 
> requires a big overhaul and lots of refactoring. Applying avalon to an 
> existing programmer takes a week at least.
>
> Avalon4 Just Doesn't Cut It
> ---------------------------
> I've been slowly forming this opinion over several months of looking 
> at many many avalon-related technologies. Take a look at phoenix, ecm, 
> fortress, microcontainer, tweety, merlin, plexus, eob, guiapp, cocoon. 
> Each and every one of these requires too much work for every component 
> you write because there are *so many strict contracts*. Contracts are 
> good, but they need to be intuitive, too.
>
> The challenge
> -------------
> Lose the baggage. Make it simpler. Make it smaller. Encapsulate the 
> dynamism in a single place. KISS. Yes, Paul & friends figured it out 
> already [6].
>
> The Next Big Component Architecture will be about Small Architecture.
>
> What it might look like
> -----------------------
> Here's a not-attribute-aware, jython-scripted, api/impl seperated, 
> IoC/COP, aspect-oriented, strongly typed bean. It is also a regular 
> javabean that can run in any simple java2 environment.
>
> --- Parser.java ---
>
> /** a basic work interface */
> public interface Parser
> {
>     Node parse( Source source );
> }
>
> --- SomeParser.java ---
>
> /**
>  * a basic bean with some system-level needs (logging), some
>  * configuration requirements and a dependency on another
>  * component.
>  */
> public class SomeParser implements Parser
> {
>     private Log m_log = null;
>     private boolean m_validate = false;
>     private XmlReader m_XmlReader = null;
>
>     //////////////////////////////
>     /// work interface: Parser ///
>     //////////////////////////////
>
>     public void parse( Source source )
>     {
>         m_log.debug( "source url: " + source.getURL() );
>        
>         /* ... */
>
>         if( m_validate )
>             validate( source );
>         /* ... */
>     }
>
>     //////////////////////
>     /// required stuff ///
>     //////////////////////
>
>     public void setLog( Log log )
>     {
>         m_log = log;
>     }
>     public void setValidate( boolean validate )
>     {
>         m_validate = validate;
>     }
>     public void setXmlReader( XmlReader reader )
>     {
>         m_XmlReader = reader;
>     }
>
>     ///////////////////////
>     /// utility methods ///
>     ///////////////////////
>
>     protected validate( Source source ) { /* ... */ }
> }
>
> --- MyAppDefaultInit.py ---
>
> # a common jython script that adds basic custom configuration
> # support, AOP interceptors and an event interceptor
>
> instance.log = container.getLog( config.attrs.name )
> instance.log.logLevel = config.elems.log-level
>
> # time method calls
> if( config.elems.instrument )
>   interceptors.add( method="*", on="preCall",
>     action="context.parse.startTime=System.currentTimeMillis()" )
>   interceptors.add( method="*", on="postCall",
>     action={
>       context.parse.endTime=System.currentTimeMillis()
>       timeTaken = context.parse.startTime - context.parse.endTime
>       properties.log.debug( "time taken for " \
>           + currentMethod + "call: " timeTaken )
>     } )
>
> # enable hot reconfiguration
> interceptors.add( event="reconfigure"
>     action={
>       instance.log = container.getLog( event.config.attrs.name )
>       instance.log.logLevel = event.config.elems.log-level
>     } )
>
> --- SomeParserInit.py ---
>
> # a class-specific jython script that extends the behaviour from
> # the above script
>
> container.call( "MyAppDefaultInit.py" )
>
> instance.xmlReader = container.getComponent( "xml-reader" )
>
> # update validate property before parsing to allow for
> # runtime reconfiguration
> interceptors.add( method="parse", on="preCall",
>     "instance.validate=config.elems.validate" )
>
> # enable hot reconfiguration
> interceptors.add( event="reconfigure"
>     action={
>       instance.validate = event.config.elems.validate
>     } )
>
> --- WEB-INF/components.config.xml ---
>
> # a sample xml configuration file, might be passed in using
> # configure( Configuration conf ) or configure( Node node )
> # or by using a jython script
> <components>
>     <defaults>
>         <config>
>             <instrument>false</instrument>
>             <log-level>DEBUG</log-level>
>         </config>
>     </defaults>
>     <component name="xml-reader"
>         class="org.sf.xml-utils.XmlReader"
>         lifestyle="threadsafe"/>
>
>     <component name="parser"
>         class="SomeParser"
>         lifestyle="pooled">
>
>         <config>
>             <validate>true</validate>
>             <instrument>true</instrument>
>         </config>
>     </component>
> </components>
>
> --- MyBean.java ---
>
> /**
>  * doesn't care about configurations, scripts, or whatever,
>  * but understands what setXXX() implies.
>  */
> public class MyBean
> {
>     private Parser m_parser;
>
>     public MyBean()
>     {
>         m_parser = new SomeParser();
>         m_parser.setLog( new SimpleLog( "parser" ) );
>         m_parser.setValidate( true );
>         m_parser.setXmlReader( new XmlReader() );
>     }
>     public void doStuff()
>     {
>         m_parser.parse( /* ... */ );
>     }
> }
>
> --- MyComponent.java ---
>
> /**
>  * client component; similarly might have an init
>  * script and/or configuration
>  */
> public class MyComponent implements Something
> {
>     private Parser m_parser;
>
>     public void setParser( Parser parser )
>     {
>         m_parser = parser;
>     }
> }
>
> --- WEB-INF/plugins.conf.xml ---
>
> <plugins>
>     <plugin id="improved-pool" version="1.1-dev">
>         <config>
>             <initialSize>5</initialSize>
>         </config>
>     </plugin>
>     <plugin id="jelly-scripting-support" version="1.0"/>
>     </plugin>
> </plugins>
>
> --- $PLUGINS/improved-pool-1.1-dev.jar/plugin.py ---
>
> instance = new ImprovedPoolManager()
> instance.initialSize = config.elems.initialSize
> container.pool = instance
>
> --- $PLUGINS/jelly-scripting-support/plugin.py ---
>
> instance = new JellyScriptManager()
> container.addScriptingSupport( instance, "*.jelly" )
>
> Just Do It already!
> -------------------
> I've been playing with some of this stuff. I'm wondering whether I 
> should bring it over here or make it public elsewhere, or not at all. 
> Comments?
>
> References
> ----------
> [0] - http://web.archive.org/web/19980110194101/http://java.apache.org/
> [1] - 
> http://web.archive.org/web/20000303060921/java.sun.com/products/servlet/index.html 
>
> [2] - 
> http://web.archive.org/web/19980215013218/java.sun.com/pr/1997/dec/pr971210-01.html 
>
> [3] - 
> http://web.archive.org/web/19980214234112/java.sun.com/products/jdk/1.1/index.html 
>
> [4] - http://web.archive.org/web/19980110194101/http://java.apache.org/
> [5] - http://jeremy.zawodny.com/blog/archives/cat_java.html
> [6] - http://www.picocontainer.org/
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
> For additional commands, e-mail: dev-help@avalon.apache.org
>


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


Mime
View raw message