|
|||||
|
|||||
JBoss Microcontainer Compared
Jboss Microcontainer is a fairly new light weight IoC container. It has some unique and interesting feature that is not found in Spring/PicoContainer/Nuts. JBoss Microcontainer emphasizes the concept as a state machine. It manages fine grained state transition for managed beans. Around the state machine model, JBoss MC supports hot-redeployment, hot-reconfiguration of any individual bean/service. Unlike the hot-swapping support in other containers (Pico, Yan, SeaSar), this hot-redeployment capability is more powerful in that it doesn't require use of interface and dynamic proxy. It works for any pojo. Other uses of the state machine include that one could explicitly ask for an "instantiated" dependent bean without waiting for it to be fully configured. The states defined by JBoss are: Not Installed, Described, Instantiated, Configured, Create, Start, Installed and Error. JBoss MC is closely integrated with AOP. Many advanced features, such as moduling, are expected to be implemented with AOP. Nonetheless, JBoss Microcontainer is not a general purpose IoC container. It does have some ability to configure and wire up objects. But many useful features that can be found in Spring/Pico/Nuts are missing in JBoss. For instance:
Similar to PicoContainer/Yan, JBoss Microcontainer provides a set of API that can be used directly to manage beans without having to use xml. The API of JBoss Microcontainer, however, looks more like Spring rather than PicoContainer/Yan because it models a set of MetaData classes that passively describe the bean attributes. (BeanMetaData, PropertyMetaData, ParameterMetaData, etc.) In contrast, PicoContainer/Yan's API both abstract a concept that can actively go out and create the component instance — Component for Yan and ComponentAdapter for Pico. The Spring/JBoss approach may provide more direct control over the beans, but lack the flexibilities provided by PicoContainer/Yan's approach. Time for some examples, let's list some syntax of JBoss and Nuts first. Simple BeanJava: new com.acme.Example();
JBoss: <bean name="Name1" class="com.acme.Example"/> Nuts: <bean id="Name1" class="com.acme.Example"/> ConstructorJava: new com.acme.Example(new String("example string"), 4); JBoss: <bean name="Name1" class="com.acme.Example"> <constructor> <parameter>example string</parameter> <parameter>4</parameter> </constructor> </bean> Nuts: <ctor id="Name1" class="com.acme.Example" args="example string, 4"/> In order to disambiguate between overloaded constructors, explicit type specification can be used. JBoss: <bean name="Name1" class=com.acme.Example"> <constructor> <parameter>example string</parameter> <parameter class="long">4</parameter> </constructor> </bean> Nuts: <ctor id="Name1" class="com.acme.Example" params="java.lang.String, long" args="example string, 4"/> FactoriesJava: Example Name1 = ExampleFactory.createExample(); JBoss: <bean name="Name1" class=com.acme.Example"> <constructor factoryClass="com.acme.ExampleFactory" factoryMethod="createExample"/> </bean> Nuts: <method class="com.acme.ExampleFactory" name="createExample" args=""/> Java: ExampleFactory Factory1 = new com.acme.ExampleFactory();
Example Name1 = Factory1.createExample();
JBoss: <bean name="Factory1" class=com.acme.ExampleFactory"/> <bean name="Name1" class=com.acme.Example"> <constructor factoryMethod="createExample"> <factory bean="Factory1"/> </constructor> </bean> Nuts: <method id="Name1" name="createExample" args=""> <bean class=com.acme.ExampleFactory"/> </bean> Java: ExampleFactory Factory1 = new com.acme.ExampleFactory(); Example Name1 = Factory1.createExample(new String("example string")); JBoss: <bean name="Factory1" class=com.acme.ExampleFactory"/> <bean name="Name1" class=com.acme.Example"> <constructor factoryMethod="createExample"> <factory bean="Factory1"/> <parameter>example string</parameter> </constructor> </bean> Nuts: <method id="Name1" name="createExample" args="example string"> <bean class=com.acme.ExampleFactory"/> </bean> PropertiesJava: Example example = new com.acme.Example(); example.setTitle(new String("example string")); JBoss: <bean name="Name1" class="com.acme.Example"> <property name="title">example string</property> </bean> Nuts: <bean id="Name1" class="com.acme.Example" props="{title=example string}"/> String Valuesnull is denoted as <null> in JBoss. While in Nuts, it is denoted as "$null". JBoss: <bean name="Name1" class="com.acme.Example"> <property name="title"><null/></property> </bean> Nuts: <bean name="Name1" class="com.acme.Example" props="{title=$null}"/> Explicit type can also be specified for literals. In JBoss: <bean name="Name1" class="com.acme.Example"> <property name="number" class="java.lang.Long">4</property> </bean> Nuts: <bean name="Name1" class="com.acme.Example"> <prop key="number"><value val="4" type="java.lang.Long"/></prop> </bean> Dependency On Other BeansJava: Long four = new Long(4); Example example = new com.acme.Example(); example.setNumber(four); JBoss: <bean name="Four" class="java.lang.Long"> <constructor><parameter>4</parameter></constructor> </bean> <bean name="Name1" class=com.acme.Example"> <property name="number"><inject bean="Four"/></property> </bean> Nuts: <bean id="Four" class="java.lang.Long" args="4"/> <bean id="Name1" class="com.acme.Example" props="{number=$Four}"/> Circular DependencyJava: Example Name1 = new Example(); Example Name2 = new Example(); Name1.setOther(Name2); // We said we don't wait for a fully configured Name2 Name2.setOther(Name1); // Complete the confguration of Name2 JBoss: <bean name="Name1" class=com.acme.Example"> <property name="number"><inject bean="Name2" state="Instantiated"/></property> </bean> <bean name="Name2" class=com.acme.Example"> <property name="number"><inject bean="Name1"/></property> </bean> Nuts: <bean id="Name1" class="com.acme.Example" props="{number=$Name2}"/> <bean id="Name2" class="com.acme.Example" props="{number=$Name1}"/> The JBoss version requires explicit setting of state="Instantiated" to tell the framework that we don't wait for a fully configurated "Name2". Nuts does this automatically because in most cases the order of configuration doesn't matter. And in case you do want to make sure that "Name2" gets injected with a fully configured "Name1", the configuration can be written as: <sequence id="Name2"> <bean var="Name1" class="com.acme.Example"/> <bean var="Name2" class="com.acme.Example"/> <setter component="$Name1" name="number" val="$Name2"/> <bean component="$Name2" props="{number=$Name1}"/> </sequence> which basically follows the same steps as the Java code. Indirect DependencyJava: URL url = new URL("http://acme.com/index.html"); Example example = new com.acme.Example(); example.setHost(url.getHost()); JBoss: <bean name="URL" class="java.net.URL"> <constructor><parameter>http://acme.com/index.html</parameter></constructor> </bean> <bean name="Name1" class=com.acme.Example"> <property name="host"><inject bean="URL" property="host"/></property> </bean> Nuts: <ctor id="URL" class="java.net.URL" args="http://acme.com/index.html"/> <bean id="Name1" class="com.acme.Example"> <prop key="host"> <getter component="$URL" name="host"/> </prop> </bean> CollectionJBoss's collection syntax is quite similar to that of Nuts. Though JBoss has no support for Concise Collection Literal. Java: Example example = new com.acme.Example(); List list = new LinkedList(); list.add(new String("A string")); list.add(new URL("http://acme.com/index.html")); list.add(someBean); List subList = new ArrayList(); subList.add(new String("Another string")); list.add(subList); element.setList(list); JBoss: <bean name="Name1" class="com.acme.Example"> <property name="list"> <list class="java.util.LinkedList" elementClass="java.lang.String"> <!-- uses elementClass --> <value>A string</value> <!-- a URL --> <value class="java.lang.URL">http://acme.com/index.html</value> <!-- inject some other bean --> <value><inject bean="SomeBean"/></value> <!-- a list inside a list --> <value> <list elementClass="java.lang.String"> <value>Another string</value> </list> </value> </list> </property> </bean> Nuts: <bean id="Name1" class="com.acme.Example"> <prop key="list"> <list of="java.lang.String" type="java.util.LinkedList"> <value val="A string"/> <!-- a URL --> <value type="java.lang.URL">http://acme.com/index.html</value> <!-- inject some other bean --> <value val="$SomeBean"/> <!-- a list inside a list --> <list of="java.lang.String"> <value val="Another string"/> </list> </list> </property> </bean> There's also another kind of collection, java.util.Map. Java: Example example = new com.acme.Example(); Map map = new Hashtable(); map.put(new String("one"), new String("1")); map.put(new Integer(4), new String("4")); map.put(new String("ten"), new Long(10)); map.put(new String("bean"), someBean); element.setMap(map); JBoss: <bean name="Name1" class=com.acme.Example"> <property name="map"> <map class="java.util.Hashtable" keyClass="java.lang.String" valueClass="java.lang.String"> <!-- uses keyClass and valueClass --> <entry><key>one</key><value>1</value></entry> <!-- uses valueClass --> <entry><key class="java.lang.Integer">4</key><value>Four</value></entry> <!-- uses keyClass --> <entry><key>ten</key><value class="java.lang.Long">10</value></entry> <entry><key>bean</key><value><inject bean="SomeBean"/></value></entry> </map> </property> </bean> Nuts: <bean id="Name1" class="com.acme.Example"> <prop key="map"> <map of="java.lang.String" type="java.util.Hashtable" key-type="java.lang.String"> <!-- uses keyClass and valueClass --> <entry key="1" val="1"/> <!-- uses valueClass --> <entry key="4" key-type="int" val="Four"/> <!-- uses keyClass --> <entry key="ten"><value val="10" type="long"/></entry> <entry key="bean" val="$SomeBean"/> </map> </property> </bean> Overall, the Nuts' syntax is more concise. LifecycleJBoss lifecycle support looks richer than Spring. Because it supports parametered lifecycle. For a simple Lifecycle with dependencies between components: <bean name="Name1" .../> <bean name="Name2" ...> <depends>Name1</depends> </bean> Nuts: <sequence id="Name2"> <bean id="Name1" initializer="create" starter="start" stopper="stop" disposer="destroy" .../> <bean id="Name2" initializer="create" starter="start" stopper="stop" disposer="destroy" .../> </sequence> To support parametered lifecycle, JBoss uses nested lifecycle tags: <bean name="Name1" class="com.acme.Example"> <create method="initialize"> <parameter><inject bean="SomeBean"/></parameter> </create> </bean> which is similar to Nuts: <sequence id="Name1"> <bean var="Name1" class="com.acme.Example"/> <lifecycle name="initializer"> <method component="$Name1" name="initialize" args="$SomeBean"/> </lifecycle> <return val="$Name1"/> </sequence> SummaryWith relatively limited functionalities and flexibilities as a dependency injection framework, JBoss doesn't compete with general purpose DI frameworks such as Spring. Yet, JBoss MC is more targeted to be a part of JBoss application server with a unique model of state machine and the ability of hot-redeployment, hot-reconfiguration, which I did not find a match in any of the other major open source IOC containers. |
|||||
|
Copyright 2003-2006 - The Codehaus. All rights reserved unless otherwise noted.
Powered by Atlassian Confluence
|
|||||