From composer-commits-return-64-apmail-incubator-composer-commits-archive=incubator.apache.org@incubator.apache.org Mon Feb 04 06:34:04 2008 Return-Path: Delivered-To: apmail-incubator-composer-commits-archive@locus.apache.org Received: (qmail 99102 invoked from network); 4 Feb 2008 06:34:04 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 4 Feb 2008 06:34:04 -0000 Received: (qmail 4517 invoked by uid 500); 4 Feb 2008 06:33:54 -0000 Delivered-To: apmail-incubator-composer-commits-archive@incubator.apache.org Received: (qmail 4484 invoked by uid 500); 4 Feb 2008 06:33:53 -0000 Mailing-List: contact composer-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: composer-dev@incubator.apache.org Delivered-To: mailing list composer-commits@incubator.apache.org Received: (qmail 4455 invoked by uid 99); 4 Feb 2008 06:33:53 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 03 Feb 2008 22:33:53 -0800 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 04 Feb 2008 06:33:29 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 0A8F71A9842; Sun, 3 Feb 2008 22:33:35 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r618174 [2/5] - in /incubator/composer/trunk: ./ composer-site/ composer-site/src/ composer-site/src/assembly/ composer-site/src/config/ composer-site/src/resources/ composer-site/src/resources/images/ composer-site/src/resources/style/ com... Date: Mon, 04 Feb 2008 06:33:26 -0000 To: composer-commits@incubator.apache.org From: hammant@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080204063336.0A8F71A9842@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: incubator/composer/trunk/composer-site/src/site/content/builder.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/builder.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/builder.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/builder.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,70 @@ + + + + +Building Containers + + +

Rather than new up a Apache Composer instance with the right ComponentFactory, LifecycleStategy and ComponentMonitor, your can use ContainerBuilder for conveniece. Refer to Martin's 'Fluent +Interface' article, for some of the motivation behing this class.

+

Some simple examples :

+
+pico = new ContainerBuilder().build();
+pico.addComponent(Apple.class);
+
+
pico = new ContainerBuilder().withCaching().build();
+pico.addComponent(Apple.class);
+
+pico = new ContainerBuilder().withCaching().build();
+pico.addComponent(Apple.class);
+
+
pico = new ContainerBuilder().withHiddenImplementations().build();
+pico.addComponent(Apple.class);
+ +

More varations for behaviors :

+
+pico = new ContainerBuilder().withLifecycle().withConsoleMonitor().build();
+pico.addComponent(Apple.class);
+
+
pico = new ContainerBuilder().withMonitor(ConsoleComponentMonitor.class).build();
+pico.addComponent(Apple.class);
+
+import static org.picocontainer.injectors.Injectors.SDI;
+import static org.picocontainer.behaviors.Behaviors.caching;
+import static org.picocontainer.behaviors.Behaviors.implementationHiding;
+import static org.picocontainer.behaviors.Behaviors.synchronizing;
+...  
+pico = new ContainerBuilder(SDI()).withBehaviors(caching(), implementationHiding(), synchronizing()).build();
+pico.addComponent(Apple.class);
+
+

Setting a parent container :

+
child = new ContainerBuilder(parentContainer).build();
+child.addComponent(Apple.class);
+ +

Specifying an injection type:

+
+pico = new ContainerBuilder().withAnnotationInjection().build();
+pico.addComponent(Apple.class);
+
+

Specifying an injection type a different way:

+
+import static org.picocontainer.injectors.Injectors.SDI;
+...
+pico = new ContainerBuilder(SDI()).build();
+pico.addComponent(Apple.class);
+

A custom container component used by a custom ComponentBehavior (though could be used by ComponentMonitor or LifecycleStrategy as easily):

+ +
+
+pico = new ContainerBuilder()
+    .withCustomContainerComponent(new MyQuantumPhysicsConnector())
+    .withComponentFactory(MyQuantumPhysicsConnectionNeedingComponentBehavior.class).build();
+pico.addComponent(Apple.class);
+

A custom container implementation (DefaultApache Composer is the default):

+
+
MyCustomApache Composer pico = (MyCustomApache Composer) new ContainerBuilder().implementedBy(MyCustomApache Composer.class).build();
+pico.addComponent(Apple.class);
+
+ + Added: incubator/composer/trunk/composer-site/src/site/content/class-naming.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/class-naming.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/class-naming.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/class-naming.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,23 @@ + + + + +Class Naming + + +

Apache Composer's class naming changed substantially between 1.0 and 2.0. There are two major influences for this:

+
    +
  1. Dan North's "Behavior Driven Design" agenda and his interest in Neuro Linguistic Programming (NLP)
  2. +
  3. Steve Yegge's technical fable : Execution in the Kingdom of Nouns
  4. +
+

The take away from both is that we don't have to have long classnames like CachingComponentAdapterFactory and ImplementationHidingComponentAdapterFactory, we can in fact have shorter names, that read better in their intended use:

+
  new DefaultApache Composer(new Caching());
+

Similarly, method names can play a part in simplicity and meaning for real situations where they are used.

+
  new DefaultApache Composer(new Caching().wrap(new ImplementationHiding()));
+
+

Caching, the class, implements an abstraction called BehaviorFactory as do many others. All BehaviorFactory implementations make implementations of Behavior like 'Cached'. Similarly 'ConstructionInjection' (and similar) make implementations of Injector like 'ConstructorInjector' (and similar). Both BehaviorFactory and InjectionFactory are extensions of ComponentFactory.

+

+

 

+

 

+ + Added: incubator/composer/trunk/composer-site/src/site/content/comparisons.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/comparisons.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/comparisons.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/comparisons.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,175 @@ + + + + + +Container Comparisons + + +
+
+

Overview

+

This document aims to compare Apache Composer to other IoC containers, both lightweight and not.

+

There are a number of published API specifications since Java was initially released that proport to be container/component designs. We discuss then here, suggesting there are goals that some have met, and some not. This may help you make better design choices for your own components.

+
+
+

IoC Containers

+
+

Spring Framework

+

The Spring Framework is a J2EE framework. As such, Dependency Injection and Lifecycle is only one of its concerns. Apache Composer, on the other hand, is concerned only with Dependency Injection, configuration and Lifecycle.

+
+
+

Apache Avalon and its containers

+

(Avalon ceased development in 2005)

+

Apache hosted a project that had been running for many years called Avalon. It had many components that fit that its design and many containers is writtern in Java. Avalon components were characterised by implementation of many optional interfaces. Avalon components were distributed with meta-information in XML in the jar file. More XML is required to assemble components together for the same of a application. Avalon Phoenix, Excalibur Component Manager (ECM), Avalon Fortress and Avalon Merlin were the pertinent containers.

+

The Avalon Framework required implementing components to implement a number of interfaces. By the end of the the project, this had proven historically to be a bit of a turn-off for component writers. Those interfaces were :-

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Avalon Interface Apache Composer equivalent
LogEnabled Logging agnostic
Contextualizable n/a
Serviceable (was Composable) arguments are injected
Configurable arguments are injected
Parameterizable n/a
Initializable Constructor is the equivalent lifecycle concept
Startable Startable
Suspendable n/a
Recontextualizable n/a
Recomposable n/a
Reconfigurable n/a
Reparameterizable n/a
Disposable Disposable
+

Avalon is a Contextualized Lookup IoC design.

+
+

Example

+ +
+
+
import org.apache.avalon.framework.ServiceManager;
+import org.apache.avalon.framework.Serviceable;
+import org.apache.avalon.framework.ServiceException;
+
+public class Shop implements Serviceable, Initializable {
+    StockManager stockManager;
+    String shopZipCode;
+    public void service(ServiceManager sm) throws ServiceException {
+        stockManager = (StockManager) sm.lookup("StockManager");
+    }
+    public void initialize() {
+        // all service()ing has been done.
+    }
+}
+
+
+

A component has to have service (component) declarations in an external file. The Loom container (forked from + Phoenix) has .xinfo files for each component to meet such needs. All Avalon container have some mechanism for storing + configuration and assembly externally to the class. Cross referenced against the xinfo files, Loom's assembly.xml + defines the implementations to be used for component types. Thus all Avalon components must be + interface/implementation separated. Another Avalon using server technology is Keel.

+

It has to be said that all post-Avalon projects are not as active as they could be.

+
+

Using Contextualized Dependency Lookup Components + Without a Container.

+ +

The downside of the this design is that components can only be used without the container with great + difficulty. If at all. Thus a proper container is needed at all times, and you have to choose one for + different purposes. If you do manage to instantiate components without a container, you might miss one of the + essential service dependencies. The component-using class will continue to compile, but at run time it will + be apparent that there are missing dependencies. Because of the these complexities, unit testing with frameworks like JUnit is very difficult for of Avalon components.

+
+
+
+
+
+

Sun specified nearly-IoC Containers & Component designs

+

Sun have specified several container/component designs over the years.

+
+

Enterprise Java Beans

+

Clearly Entity and Session beans run inside a container. The API is well defined, and to varying degrees of success one can deploy EJB appllications to WebLogic, WebSphere, Orion and JBoss etc. For assembly and configuration, there is high use of element-normal XML . There are some mandated parent objects and interfaces for various to extend and/or implement. Resolution is done by the components themselves via JNDI more often than not.

+

Apache Composer Components are simpler in they they do not force an extensive XML markup, nor require the implementing of certaing interfaces or extening base classes. Quite importantly the relationship between factory (home), implementation (bean) and interface (remote) parts is much more real in Apache Composer-style components. EJB 2.0 components are nearly impossible to unit-test without much effort.

+

With the advent of EJB 3.0 (which the our team directly influenced), things became easier for EJB developers. Annotations were used to mark fields, and methods for injection. Strangely constructors were not eligible for injection. It was reported back to the our team that it was felt that the J2EE container makers would not find it easy making multi-argument constructor injection a reality.

+
+
+

Servlets

+

Not so obvious - Servlets are contained by a servlet container. They are generally bundled with (or replaced by) value added propositions like JSP, but it is still a container/component design. High use of XML for assembly and configuration. Servlets have no concept of parent container or the conatainer above that (sometimes EJB) and its provision of components, which is very unfortunate. Servlets have a number of interfaces to honor, none of which is too malignent. Servlets typically deal with external (or parent) components via RMI or JNDI. In more recent releases of EJB, local interfaces rather than RMI may be the mechanism for connection the parent components. WebLogic have always provided an optimizing mechanism for this interoperation

+

As with EJB, Apache Composer Components are far simpler. This is probably because they offer no web experience, without an extension. Servlets again are not that unit-testable.

+
+
+

Applets

+

Applets, though presently not so often used, are a good example of Container/Component separations. There is very little XML in use by Applets. Configuration is typically delivered in applet tags in HTML. Applets are granted some access to the parent container, the brower, and its DOM model for pages and other applets. There very little standardisation for Browser as a container.

+

As with EJB, Apache Composer Components are far simpler. Applets are unit-testable but with a little effort. Complex DOM interoperation is impossible under unit testing.

+
+
+

Mainable (Not actually a container)

+
+
+
public static void main(String[] args) {}
+
+
+ + +

Familiar? Hopefully not Static plays no part in a good IoC container/component design. This includes static launching of Java Webstart (JNLP) applications. If you have to keep mainable functionaility separate your components away from the main() class so they may be instntiated separately. In .NET you'll have to make sure that the application assembly is a small bootstrap to a component one.

+
+
+

JNDI (Java API)

+

A huge map of clunkily access components via a very non-IoC mechanism. It has to be strapped with much XML to prevent inappropriate access. This is not IoC because the component reaches out for external component dependancies whenever it feels like. This last fact clouds Serlvets and EJB use.

+
+
+

AWT, Swing, SWT (Java graphic toolkits)

+

Nice container/component designs. In the case of Swing, perhaps a little difficult for coders to easily assemble applications.

+
+
+

Eclipse (Java graphical application platform)

+

The Eclipse platform is very compelling. It supports the notion of a pluggable application concept. Each component statically accesses other components via a factory (which at least Paul does not like), though it is clear that some complex classloader magic is going on. The underpinning set of graphical components, SWT , are a simple and elegant design.

+
+
+
+ + + Added: incubator/composer/trunk/composer-site/src/site/content/component-configuration.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/component-configuration.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/component-configuration.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/component-configuration.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,100 @@ + + + +Component Configuration + + +
+

Choices

+

In true IoC style, configuration for a component is pushed into it.

+

With Apache Composer, there are a few ways to do this:

+
    +
  • Design a class to hold the configuration and have getters on it to allow depending components to access configuration.
  • +
  • Manually set the configuration for components as you add them to a container
  • +
  • Leverage the fact that Apache Composer can pick up on named components
  • +
+

Configuration Object

+
+
public interface BigFatComponentConfig {
+  String getSpellingWebServiceURL();
+  String getTimeout();
+}
+public class BigFatComponent {
+  URL spellWebService;
+  String timeout;
+  public BigFatComponent(BigFatComponentConfig config) {
+    this.spellWebService = new URL(config.getSpellingWebServiceURL());
+    this.timeout = config.getTimeout();
+  }  
+  // other methods
+}
+...
+pico.addComponent(BigFatComponent.class)
+pico.addComponent(new BigFatComponentConfigBean("http://foo.com/foo.wsdl", 120))
+
+

Setting config as part of addComponent(..)

+
+
public class BigFatComponent {
+  URL spellWebService;
+  int timeout;
+  public BigFatComponent(String spellingWebServiceURL, int timeout) {
+    this.spellWebService = new URL(spellingWebServiceURL);
+    this.timeout = timeout;
+  }  
+  // other methods
+}
+
+
+...
+pico.addComponent(BigFatComponent.class, new ConstantParameter("http://foo.com/foo.wsdl"), new ConstantParameter(120));
+
+

Configuration using parameter names

+

Consider this component ...

+
+
public class BigFatComponent {
+  URL spellWebService;
+  int timeout;
+  public BigFatComponent(String spellingWebServiceURL, int timeout) throws MalformedURLExeption {
+    this.spellWebService = new URL(spellingWebServiceURL);
+    this.timeout = timeout;
+  }  
+  public String toString() {
+    return "URL=" + spellWebService + ", timeout=" + timeout;  
+  }
+
+  // other methods
+}
+
+
+
+

And this composition ...

+
+
+pico.addConfig("spellingWebServiceURL", "http://foo.com/spelling.wsdl"); // matches constructor parameter name
+pico.addConfig("somethingOtherURL", "http://bar.com/other.wsdl");
+pico.addConfig("timeout", 120); // matches constructor parameter name
+pico.addConfig("timeout2", 456);
+pico.as(Characteristics.USE_NAMES).addComponent(BigFatComponent.class);
+
+BigFatComponent bfc = pico.getComponent(BigFatComponent.class);
+System.out.println("bfc: " + bfc.toString());
+// Prints .. "bfg: URL=http://foo.com/spelling.wsdl, timeout=120"
+
+

This feature of Apache Composer relies on the a non-JDK mechanism of accessing parameter names for methods and constructors. In this case named parameters spellingWebServiceURL and timeout.

+

There are two ways for this to work:

+
    +
  • relying on the fact that your component classes have debug info compiled into them.
  • +
  • post-processing component classes with Paranamer before placing them in their jar
  • +
+

If the parameter name information cannot be accessed at runtime by Apache Composer, then Apache Composer will be unable to differentiate between potential injectable classes of the same type and throws an exception that suggests that there is an ambiguity.

+

This is not a global variable facility. Its scoped with the container in question and its child containers.

+
+

Taking configuration from the elsewhere

+

Configuration can also be bound to components with :

+
+

CommandLineArgumentsApache Composer

+

PropertiesApache Composer

+

SystemPropertiesApache Composer

+
+ + Added: incubator/composer/trunk/composer-site/src/site/content/constructor-injection.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/constructor-injection.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/constructor-injection.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/constructor-injection.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,70 @@ + + + + Constructor Injection + + + +

Overview

+ +

Constructor Injection is a Dependency Injection variant + where an object gets all its dependencies via the constructor. +

+ +

The most important benefits of Constructor Injection are:

+
    +
  • It makes a strong dependency contract
  • +
  • It makes testing easy, since dependencies can be passed in as Mock Objects
  • +
  • It's very succinct in terms of lines of code
  • +
  • Classes that rely on Constructor Injection are generally Good + Citizens +
  • +
  • A dependency may be made immutable by making the dependency reference final
  • +
+

Martin Fowler explains Constructor + Injection + in more detail.
+
+ Apache Composer also supports Setter Injection.

+ +

Origin

+ +

Rachel Davies, while reviewing Joe's forthcoming book, +left a Fermat-like margin note when looking at a coe sample that used +Setter Injection: "Why not use constructors ?". Brilliant and simple. + Using constructors per se, is an ordinary OO feature, but having +a container that works out what to inject where amongst a list of +constructor arguments is something that is useful too. +

+ +

Example

+ +
+
public class Shop {
private final StockManager stockManager;
private final String shopZipCode;
public Shop(StockManager stockManager, String shopZipCode) {
this.stockManager = stockManager;
this.shopZipCode = shopZipCode;
}
}
+
+

Note, for this there is no need to declare needs in any other way. No interfaces, no doclet tags, no external + XML. Just your simple component(s) and Apache Composer. No need for post assembly/config initialization either. If + it is constructed (not withstanding some asserts on nulls) it has its needs satisfied. Components need not be + interface/implementation separated. This is the coder's choice.

+ +

Using Constructor + Injector Components + Without a Container. +

+ +

The component can be used directly, without any container. The missing dependency scenario is not an issue + since it is impossible to instantiate an object without all dependencies being satisfied.

+ +
+
+
Shop shop = new Shop(myStockManager);
+
+
+

Container support +

+ +

Apache Composer was the first lightweight container to support and popularize this for of dependency injection. + Spring Framework has been retrofitted with constructor injection capability, but its primary focus is still + setter injection. Even the once heavyweight technologies like Avalon and OSGi moved towards constructor + injection.

+ \ No newline at end of file Added: incubator/composer/trunk/composer-site/src/site/content/disambiguation.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/disambiguation.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/disambiguation.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/disambiguation.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,61 @@ + + +Disambiguation + + + + + +

Overview

+You may have a component that has a dependency on something that the +container could ordinarily satisfy more than one.  By default, +when Apache Composer is presented with such a situation, it will throw an +exception suggesting the depency resolution is ambiguous. +

Disambiguation using parameter names

+With Apache Composer 2.0 we are able to leverage the parameter names of +constructors and methods in order to remove the ambiguity on +dependancies.
+
+
public class Store {
public Store(StockManager workingDayStockManager, StockManager afterHoursStockManager) {
// etc
}
}
+
+If Store is added to the container appropriately, then its parameter +names 'workingHoursStockManager' +and 'afterHoursStockManager +' can be used in conjunction with similarly named components inject the +right dependency in the right way:
+
+
pico.as(Characteristics.USE_NAMES).addComponent(Store.class); 
+
+ +Access to parameter names was dropped from JDK 6.0 and it is uncertain +whether it will be added as a feature in another release, so +Apache Composer relies on another open source library called Paranamer, +without requiring a dependency on its Jar.  In other words, +Apache Composer has the same classes from Paranamer in its jar.
+
+See CommandLineArgumentsApache Composer, +PropertiesApache Composer +and SystemPropertiesApache Composer +for implementations of Apache Composer that set up components for +subsequent parameter name binding.
+
+Page component-configuration +also shows parameter names being used for binding as does injection.
+
+Usage of parameter names is available for all types of +Dependency-Injection where parameter names are present.
+ +

Disambiguation using Binding Annotations +

+

This worls the same as Guice.  Namely you make an +annotation that extends our 'Bind' annotation and mark it in your constructor or method's signature like so.

+
+
+
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Bind
public static @interface WorkingDayStockManager {}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Bind
public static @interface AfterHoursStockManager {}

public class Store {
public Store(@WorkingDayStockManager StockManager workingDayStockManager,
@AfterHoursStockManager StockManager afterHoursStockManager) {
// etc
}
}
+
+
+Making Apache Composer leverage binding annotations if present is +automatic.

Biniding +annotations specified for constructor parameters (as shown above), +method injection parameters as well as field injection.
+ \ No newline at end of file Added: incubator/composer/trunk/composer-site/src/site/content/downloads.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/downloads.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/downloads.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/downloads.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,15 @@ + + +Downloads + + +

Released Jars (1.3 and 2.0)

+

Core : http://repository.codehaus.org/org/picocontainer/picocontainer/

+

Gems : http://repository.codehaus.org/org/picocontainer/picocontainer-gems/

+

Snapshot Jars (2.1)

+

Core : http://snapshots.repository.codehaus.org/org/picocontainer/picocontainer/

+

Gems : http://snapshots.repository.codehaus.org/org/picocontainer/picocontainer-gems/

+
+

Currently, the Core jar is ~190K, and the Gems jar is ~89K.

+ + \ No newline at end of file Added: incubator/composer/trunk/composer-site/src/site/content/faq.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/faq.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/faq.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/faq.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,234 @@ + + + +FAQ + + +

+ + + + +
Why Apache Composer 2.0?
+

+
+

First EJB 3.0 then Google Guice seemed to copy the ideas from Apache Composer, adding some more value. EJB 3.0 ommitted the essential Constructor Injection, and Guice went far to far down a annotations road. Soon after Guice, even the Spring Framework team decided to do things the direct way with 'JavaConfig'.

+

So Apache Composer 1.x was refactored (not rewritten) into Apache Composer 2.0. All the unit tests were kept, and excerise took hundreds of commits, but the team is pleased with the result.

+
+

+ + + + +
Can my component use multiple constructors?
+

+
+

Yes.

+

You can code multiple constructors for a component:

+
+
+
class MyComp {
+
+  private ThreadPool theThreadPool;
+  
+  public MyComp(ThreadPool threadpool) {
+    theThreadPool = threadpool;
+  }
+
+  public MyComp() {
+    theThreadPool = new DefaultThreadPool();
+  }
+
+  // other methods.
+
+
+}
+
+
+
+

+ + + + +
How does Apache Composer decide what constructor to use?
+

+
+

Apache Composer will instantiate a given component using the "greediest" satisfiable constructor. By greedy, we mean the constructor that takes the most parameters. By satisfiable, we mean constructors where all arguments can be satisfied by other registered components.

+

If you register a component with no satisfiable constructors, or two or more ambiguous "largest" constructors, a RuntimeException will be thrown when you ask for the component instance.

+

We recommend for most components, you use only one constructor, although this is by no means a requirement.

+
+

+ + + + +
How does Apache Composer compare to EJB containers?
+

+
+

Oh blimey, it is rather different. EJB has loads of things you must extend, implement, provide and throw. It is also not an IoC design. It is close in that components are managed by a container, but the cumbersome and static nature of the JNDI lookups ensure that it is not actually IoC. Apache Composer is not a superset of EJB though, as it provides no remoting capability (but NanoContainer will). At least the Apache Composer compatible components hosted in this project do not.

+
+

+ + + + +
How does Apache Composer decide what constructor to use?
+

+
+

Apache Composer will instantiate a given component using the "greediest" satisfiable constructor. By greedy, we mean the constructor that takes the most parameters. By satisfiable, we mean constructors where all arguments can be satisfied by other registered components.

+

If you register a component with no satisfiable constructors, or two or more ambiguous "largest" constructors, a RuntimeException will be thrown when you ask for the component instance.

+

We recommend, for the sake of predictablility, that Apache Composer compatible components use only one constructor, although this is by no means a requirement.

+
+

+ + + + +
How to use primitive types in constructors?
+

+
+

Apache Composer will look for the greediest constructor of your component. But if your component's constructor depends on primitive types you may set the values explicitly.

+
+
+
public interface ThreadPool {
+	void setSize(int);
+}
+
+public class MyComp {
+	private ThreadPool threadPool;
+	public MyComp(ThreadPool pool, int size) {
+		threadPool = pool;
+		threadPool.setSize(size);
+	}
+}
+
+
+

In this case you can set the parameters at registration time:

+
+
+
DefaultApache Composer pico = new DefaultApache Composer();
+pico.addComponent(ThreadPool.class, DefaultThreadPool.class);
+pico.addComponent(MyComp.class, MyComp.class, new Parameters[] {
+	new ComponentParameter(),
+	new ConstantParameter(new Integer(5));
+})
+MyComp myComp = (MyComp)pico.getInstance(MyComp.class);
+
+
+

Use ConstantParameter to set constant values and the ComponentParameter to let Apache Composer resolve the dependency.

+
+

+ + + + +
When should I use Apache Composer?
+

+
+


+ We recommend using Apache Composer when your application consists of many different classes (components) that are related to each other. Instantiating and lacing/connecting a lot of objects can be difficult task.

+
+

+ + + + +
Why Another IoC Framework?
+

+
+

After a long period of watching Inversion of Control frameworks, +and for some of us avoiding them because of their cumbersome nature, we +got together to write what we believe is the simplest possible IoC +design. One, perhaps, that considers the so-designed component as more +important that the container.

+

When we set out to do this in 2003, there was nothing equivalent +to Apache Composer (xContainer originally). XWork, that underpinned +WebWork2 was a general/embeddable Setter Dependency Injection framework, +but not well known. The Spring Framework started in the same timescale, +and we were talking to its authors before Martin Fowlers Dependency +Injection article. Later we discovered that HiveMind (now at Apache) +also was in the same space.

+
+

+ + + + +
Why Constructor Injection?
+

+
+

Constructor Injection is hard to swallow for people who have been living with Interface Lookup or Setter Injection for long. We think it's like TDD. Once you get the grasp of it, you don't go back. Here are some benefits with this type of IoC:

+
    +
  • Constructor Injection makes a stronger dependency contract
  • +
  • It's more succinct in terms of lines of code
  • +
  • It's more succinct in terms dependency-statement-mechanism i.e. no XML, attributes, enabler interfaces etc
  • +
  • A component is characterized by InterfaceImplSeparation with the interface being the service offered to other comps, and the impl declaring whatever goddarned need it likes and that need being wholly up to the implementor of the component and nothing to do with the service contract.
  • +
  • No indeterminate state. Not all the post instantiation setters may be called. Consider the non-container case for comp usage, if v1.2 of that comp introduces a new dependancy, with Constructor Injection the compiler will tell me.
  • +
+
+

+ + + + +
Will we support Guice's @Inject annotation transparently?
+

+
+

We could compile Apache Composer against Guice.jar and leverage the @Inject method with a new InjectionFactory (and probably will). The problem is that there is no easy way to use an annotation without having its class in the classpath. There's no easy 'transparent' solution for this.

+

Things fail silently if the jar is missing, unless the annotation is used - then it fails noisily. Meaning, the mere declaration of an annotation on a component is not enough to cause a ClassNotFoundException on load, if its not used:

+
@Retention(RetentionPolicy.RUNTIME)
+@Target(value={ElementType.METHOD})
+public static @interface Bar {
+}
+
+
+import com.google.inject.Inject;
+public class Foo {
+
+    @Inject
+    @Bar
+    public void setFoo(String str) {
+        System.out.println("0>" + str);
+    }
+
+    public static void main(String[] args) throws NoSuchMethodException {
+
+        Foo foo = new Foo();
+        foo.setFoo("hello");
+
+        Method m = Foo.class.getMethod("setFoo", String.class);
+
+        Annotation[] anns =  m.getDeclaredAnnotations();
+        System.out.println("1> " + anns.length);
+        for (int i = 0; i < anns.length; i++) {
+            Annotation ann = anns[i];
+            System.out.println("2> " + ann.toString());
+        }
+
+        Annotation ann =  m.getAnnotation(Inject.class);
+        System.out.println("3> " + ann);
+    }
+}
+
+

Leaving Guice out of the classpath, and trying to launch Foo...

+
+
commandline: java -cp classes Foo
+0>hellos
+1> 1
+2> @Foo$Bar()
+Exception in thread "main" java.lang.NoClassDefFoundError: org/picocontainer/annotations/Inject
+        at Foo.main(Foo.java:32)
+
+

The class loads, but the @Inject annotation is not present in the set of declared annotations, but another in the classpath is. Lastly when accessed explicitly, there is an exception thrown. Contrast to, the same run with Guice in the classpath:

+
0>hello
+1> 2
+2> @org.picocontainer.annotations.Inject()
+2> @Foo$Bar()
+3> @org.picocontainer.annotations.Inject()
+
+ +
+ + + Added: incubator/composer/trunk/composer-site/src/site/content/fluent-style.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/fluent-style.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/fluent-style.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/fluent-style.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,42 @@ + + + + +Fluent Stype + + +

Apache Composer allows for a very fluent style of use. Refer to Martin's 'Fluent +Interface' article.

+

A simple example :

+
+
+pico = new DefaultApache Composer();
+pico.addComponent(Apple.class).addComponent(Orange.class).addComponent(Pear.class)
+    .addComponent(Banana.class)
+    .addComponent(Grape.class, Grenache.class);
+
+

One with per component properties:

+
+pico = new DefaultApache Composer();
+pico.addComponent(Apple.class)
+    .as(CACHE).addComponent(Orange.class)
+    .as(CACHE, HIDE_IMPLEMENTATION).addComponent(Pear.class)
+    .as(SYNCHRONIZE, CACHE).addComponent(Banana.class)
+    .addComponent(Grape.class, Grenache.class);
+
+

One with properties that are persistently set, half way through.

+
+
pico = new DefaultApache Composer();
+pico.addComponent("Coxs", CoxsApple.class)
+    .addComponent("Golden", GoldenDeliciousApple.class)
+    .addComponent(new ValenciaOrange())
+    .change(SYNCHRONIZE, CACHE, HIDE_IMPLEMENTATION)
+    .addComponent(Pear.class)
+    .addComponent(Banana.class)
+    .addComponent(Grape.class, Grenache.class);
+
+ +

 

+ + Added: incubator/composer/trunk/composer-site/src/site/content/goals.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/goals.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/goals.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/goals.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,26 @@ + + + + +Our Goals + + +

Apache Composer's core was designed with some goals in mind:

+
    +
  • No mandatory dependencies.
  • +
  • No logging built in (we have a Monitor interface and implementations for Commons-Logging and Log4J etc)
  • +
  • No meta-data requirement.
  • +
  • Small jar size.
  • +
  • Embeddable by design (no main method entry point)
  • +
+

If someone has a need for Apache Composer that we did not originally envision, or a feature that could be imlemented, we will try to accomodate it. The principle of Lowest Common Denominator (LCD) allows us for Apache Composer itself, to keep things small, while allowing extensions to deliver the larger visions. Thus, meta-data, dependancies, mainable are all OK for related extensions of Apache Composer.

+

 

+

 

+

 

+

 

+

 

+ + + + + Added: incubator/composer/trunk/composer-site/src/site/content/help/ambiguous-injectable-help.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/help/ambiguous-injectable-help.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/help/ambiguous-injectable-help.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/help/ambiguous-injectable-help.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,48 @@ + + + + + Ambiguous Injectable + +

Apache Composer tries to determine what to inject into the constructor of each component as it instantiates (or setters/fields for other injection types). Sometimes there can be two or more classes that could equally satisfy a constructor:

+
+
pico.add(new Apple("Braeburn"));
+pico.add(new Apple("Granny Smith"));
+pico.add(Pie.class); // needs Apple
+Pie pie = pico.getComponent(Pie.class); // throws AmbiguousComponentResolutionException citing there are two Apples.
+
+
+ +

The best advice is don't setup Apache Composer in a way that would allow ambiguities (just put in one Apple in the case above).

+

An alternative strategy would be to use custom parameters (TODO)

+

One more strategy would be to use names parameters

+
+
class Pie {
+  Pie(Apple grannySmith) {
+    // etc 
+
+  }
+
+}
+
+...
+
+
+pico.add("braeburn", new Apple("Braeburn"));
+pico.add("grannySmith", new Apple("Granny Smith"));
+pico.add(Pie.class); // needs Apple, specifically a Granny Smith.
+Pie pie = pico.getComponent(Pie.class); // OK this time.
+
+
+

To use names Parameters, you are going to need Paranamer 1.0 (or above) in the classpath, as well as ASM 3.0 (or above). If you are expecting Apache Composer to work based on parameter names, but its not doing so, it is most likely that you do not have paranamer-1.0.jar in the classpath. See http://repository.codehaus.org/com/thoughtworks/paranamer/paranamer/ for versions of paranamer. Also http://maven.objectweb.org/maven2/asm/asm/ for the ASM jar.

+

You also have to make a decision as to when parameter name data is made. There are two choices for this:

+
    +
  1. At runtime
  2. +
  3. At build time
  4. +
+

When at runtime, Apache Composer will need to be accompanied by ASM and Paranamer in the classpath. You will also need to compile your Java classes with debug information.

+

When at build time, you will need to use and Ant or Maven fragment to post-process the compiled classes for your app to add the paramaeter name data. At runtime, neither Paranamer nor ASM will be needed. See http://paranamer.codehaus.org/ - specifically the quick start section pertinent to Ant and Maven.

+

 

+

 

+ + Added: incubator/composer/trunk/composer-site/src/site/content/help/unprocessed-properties-help.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/help/unprocessed-properties-help.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/help/unprocessed-properties-help.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/help/unprocessed-properties-help.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,26 @@ + + + + + Unprocessed Properties + +

Properties are a powerful mechanism to add hints at registration time as to what the behavior of a component should be. It only works though when the right component factories are set for the container. Ones that recognise the property and can process it. For example, DefaultConstructor's default constructor sets up an adaptive ComponentFactory that can handle HIDE_IMPL:

+ +
+
pico = new DefaultApache Composer();
+pico.as(HIDE_IMPL).addComponent(Apple.class);
+
+But with a custom ComponentFactory, it may not: +
+
pico = new DefaultApache Composer(new MyComponentFactory);
+pico.as(HIDE_IMPL).addComponent(Apple.class); // fails with CompositionException
+
+The trick is (in this case) to make sure that the right chain of component factories are setup: +
+
pico = new DefaultApache Composer(new MyComponentFactory().wrap(new AdaptiveBehaviorFactory()));
+pico.as(HIDE_IMPL).addComponent(Apple.class); // fails with CompositionException
+
+ +

A component may have many properties as it is added to the container. As each is processed, it is removed from the set. If there are any left after the component has been added the behavior or action that the property suggests has not been setup. Thus a CompositionException being thrown warning of unprocessed properties only happens one or more properties are left - whether they are Apache Composer's own properties or custom ones

+ + Added: incubator/composer/trunk/composer-site/src/site/content/index.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/index.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/index.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/index.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,52 @@ + + + + +Overview + + + + +

What is Apache Composer?

+ +

Apache Composer is a highly embeddable full service Inversion of Control (IoC) container +for components honour the Dependency Injection pattern.

+

You could use it as a lightweight alternative to Sun's J2EE patterns for web applications or general solutions.

+

What is Dependency Injection? Martin Fowler has a good article from 2003, but here is another view: It is a good design pattern that, for large enterprise applications, facilitates:

+
    +
  • easy best practice unit testing vs little and difficult unit testing.
  • +
  • component reuse vs rewriting through ignorance or need
  • +
  • centralized configuration vs components reading their own config (scattered)
  • +
  • clean & declarative architecture vs nest of singletons that nobody can make sense of
  • +
  • maintainability vs developers having difficulties fixing bugs
  • +
  • adaptability vs developers not knowing where to start to add features
  • +
+

Dependency Injection is + quite often, but not exclusively, used by Agile practicioners. It + counters the situation where the enterprise application:

+
    +
  • has grown to be thousands of classes, with dozens if not + hundreds of Singletons
  • +
  • draws similarities to Spaghetti, Hairballs or Balls of Mud
  • +
  • has made development staff looking after it miserable
  • +
  • suffers repeated allegations of being unable to be developed without complete rewrite
  • +
+

Despite it being very compact in size (the core is ~128K and it +has no mandatory dependencies outside the JDK), Apache Composer supports different dependency injection types (Constructor, Setter, Annotated Field and Method) and offers multiple lifecycle and monitoring strategies.

+

Apache Composer has originally been implemented in Java but is also +available for other platforms and languages. These are detailed here.

+
+

Getting Started

+

Take a look at the introduction.

+
+
+

Related projects

+

NanoContainer builds on top of Apache Composer the support for +several scripting meta-languages (XML, Groovy, Bsh, Jython and Rhyno), +AOP, Web frameworks (Struts and WebWork), Persistence (Hibernate) SOAP, +JMX, and much more.

+
+ + + + Added: incubator/composer/trunk/composer-site/src/site/content/injection.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/injection.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/injection.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/injection.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,132 @@ + + +Dependency Injection + + + +

See Martin Fowlers's Inversion of Control Containers and the Dependency Injection article from 2003 for a thorough description. Surely everyone has read this by now?

+

Injection Types

+

Constructor Dependency Injection (CDI)

+

This is where a component has a constructor, with arguments that are its dependencies:

+
+
public class Apple {
private final Orange orange;
private final Pear pear;
private final Banana banana;

public Apple(Orange orange, Pear pear, Banana banana) {
this.orange = orange;
this.pear = pear;
this.banana = banana;
}

// methods
}
+

+The Apache Composer team recomends CDI over other types. There is no need +to mark up the constructor with an annotation. Having more than one +constructor is OK too, as Apache Composer will try to use the one with +the most arguments and fall back to ones with fewer if it cannot +satisfy the longer ones.

+

The component factory for this is ConstructorInjection. It only handles constructor injection types of components. Factory AdaptiveInjection +defaults to constructor injection, after checking first to see it the +component in question is a Annotated Method or Field type (see below).

+

Setter Dependency Injection (SDI)

+

This is where a component has an empty constructor with dependencies provided by setters after instantiation:

+
+
public class Apple {
private Orange orange;
private Pear pear;
private Banana banana;

public setOrange(Orange orange) {
this.orange = orange;
}
public setPear(Pear pear) {
this.pear = pear;
}
public setBanana(Banana banana) {
this.banana = banana;
}
// other methods
}
+
+

Setter methods (those prefixed with 'set') may not be your +preferred choice. You can force a different prefix to be choosable in +Apache Composer, such as 'init' or 'inject'.

+

The component factory for this is SetterInjection. It only handles setter injection types of components.

+

Factory AdaptiveInjection can also handle setter injection types, though it requires that the component was registered with the property 'SDI' in order to activate the Setter Injection functionality. AdaptiveInjection will also fall through to constructor injection if there is no SDI property.

+

If you want to use an prefix other than 'set', then specify your preferred prexix in the non-default constructor for SetterInjection.

+

Annotated Field Dependency Injection

+

This is where a component has an empty constructor with dependencies +indicated by a field annotation and provided automatically by the +container after instantiation.

+
+
public class Apple {
@Inject
private Orange orange;
@Inject
private Pear pear;
@Inject
private Banana banana;

// methods
}
+
+

+Yes thats's right, there's no constructor needed. It means that for a +Unit Test, you cannot simply 'new' the class, which is a downside.

+

The component factory for this is a class AnnotatedFieldInjection. It only handles field-annotation injection types of components.

+

Additionally component factory AdaptiveInjection +can also handle field annotation types, if the @Inject annotation from +Apache Composer's codebase is used as the marker for injection. AdaptiveInjection will also fall through to constructor injection if there is no recognised @Inject annotation.

+

If you want to use an @Inject annotation from another codebase, then +specify the preferred annotation class in the constructor for AnnotatedFieldInjection.

+

Annotated Method Dependency Injection

+

This is where a component has an empty constructor and gets its +dependencies injected into annotated methods after instantiation:

+
+
public class Apple {
private Orange orange;
private Pear pear;
private Banana banana;

@Inject
public injectOrange(Orange orange) {
this.orange = orange;
}
@Inject
public setPear(Pear pear) {
this.pear = pear;
}
@Inject
public provideBanana(Banana banana) {
this.banana = banana;
}
// other methods
}
+
+

The method (whatever its name) needs an @Inject annotation. That's from our codebase (org.picocontainer.Inject).

+

The component factory for this is AnnotatedMethodInjection. It only handles method-annotation injection types of components.

+

Additionally component factory AdaptiveInjection +can also handle method-annotation injection types, if the @Inject +annotation from Apache Composer's codebase is used as the marker for +injection. AdaptiveInjection will also fall through to constructor +injection if there is no recognised annotation.

+

If you want to use an @Inject annotation from another codebase, then +specify the preferred annotation class in the constructor for AnnotatedMethodInjection.

+

Method Dependency Injection

+

This is where a component has an empty constructor and gets all its +dependencies injected into single method after instantiation:

+
+
public class Apple {
private Orange orange;
private Pear pear;
private Banana banana;
public inject(Orange orange, Pear pear, Banana banana) {
this.orange = orange;
this.pear = pear;
this.banana = banana;
}
// other methods
}
+
+

The method name needs be 'inject' unless overridden in the InjectionFactory.

+

The component factory for this is MethodInjection. It only handles method-injection types of components.

+

Additionally component factory AdaptiveInjection can also handle method-injection types, but only if the METHOD_INJECTION characteristic is specified.

+ +

Using Apache Composer with Injection Types

+

Explicit Constructor Injection:

+
+
pico = new DefaultApache Composer(new ConstructorInjection());
pico.addComponent(Apple.class);
+
+

Constructor Injection, is a default too (via AdaptiveInjection):

+
+
pico = new DefaultApache Composer();
pico.addComponent(Apple.class);
+
+

Explicit Setter Injection:

+
+
pico = new DefaultApache Composer(new SetterInjection());
pico.addComponent(Apple.class);
+
+

Explicit Annotated Field injection:

+
+
pico = new DefaultApache Composer(new AnnotatedFieldInjection();
pico.addComponent(Apple.class);
+
+

Explicit Annotated Field injection, with alternate Annotation:

+
+
pico = new DefaultApache Composer(new AnnotatedFieldInjection(MyInjectAnnotaton.class);
pico.addComponent(Apple.class);
+
+

Explicit Annotated Method injection:

+
+
pico = new DefaultApache Composer(new AnnotatedMethodInjection();
pico.addComponent(Apple.class);
+
+

Explicit Annotated Method injection, with alternate Annotation:

+
+
pico = new DefaultApache Composer(new AnnotatedMethodInjection(MyInjectAnnotaton.class);
pico.addComponent(Apple.class);
+
+

Explicit Method injection, implicit injection method prefix ('inject'):

+
+
pico = new DefaultApache Composer(new MethodInjection();
pico.addComponent(Apple.class);
+
+

Explicit Method injection, explicit injection method prefix:

+
+
pico = new DefaultApache Composer(new MethodInjection("setDependencies");
pico.addComponent(Apple.class);
+
+

Method injection, via a characteristic:

+
+
pico = new DefaultApache Composer();
pico.as(Characteristics.METHOD_INJECTION).addComponent(Apple.class);
+
+

Leveraging Parameter Names

+

This is where the type alone is not enough to indicate which +dependency should be put one or more constructor args. The following +component has a need for two of the same type, with some subtly +different characteristics.

+
+
public class AppleProcessor {
private Apple dessertApple;
private Apple cookingApple;

public inject(Apple dessertApple, Apple cookingApple) {
this.dessertApple = dessertApple;
this.cookingApple = cookingApple;

}
// other methods
}

pico.addComponent("dessertApple", GoldenDeliciousApple.class);

pico.addComponent("cookingApple", BramleyApple.class);
pico.as(Characteristics.USE_NAMES).addComponent(AppleProcessor.class);
+
+

In this case the constructor to AppleProcessor has carefully named +parameters - 'dessertApple' and 'cookingApple'. This is picked up on +for the two named components GoldenDeliciousApple and BramleyApple also +set up in the container.

+

There are two ways for this to work:

+
    +
  • relying on the fact that your component classes have debug info compiled into them.
  • +
  • post-processing component classes with Paranamer before placing them in their jar
  • +
+ \ No newline at end of file Added: incubator/composer/trunk/composer-site/src/site/content/interception.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/interception.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/interception.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/interception.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,123 @@ + + + + + Interception + + + + +

This is a rudimentary Aspect Orientated Programing (AOP) capability. With respect to the methods of a component, both + before and after invocation, control can be handed to an interceptor. You can intercept a method call:

+
    +
  • before it is invoked (and optionally veto its invocation, with an alternate return value).
  • +
  • after it is invoked (and optionally override the return value).
  • +
+

There are some limitations:

+
    +
  • it will only work for interface/impl separated components
  • +
  • it needs a class that implements the interface in question +
      +
    • all of the methods need null implementations, even if not intended to be intercepted
    • +
    +
  • +
  • will (likely) break if there's deep recursion into Intercepted instances
  • +
  • you can't intercept an implementation's static methods
  • +
  • it is not possible to modify a method's arguments
  • +
  • the constructor's invocation for the component is not interceptable
  • +
  • the component's fields are not interceptable
  • +
  • only one component invoking the methods on another component will be intercepted. +
      +
    • components and related classes calling their own methods will not be intercepted
    • +
    +
  • +
+
+
public static class BiteReporter implements Apple {
+    private Intercepted.Controller controller;
+
+    public BiteReporter(Intercepted.Controller controller) {
+        this.controller = controller;
+
+    } 
+    public boolean takeBite(int grams) {
+        System.out.println("Bite of " + grams + " grams of apple '" + controller.instance().getName() + "'");
+        return false; // ignored, but necessary.
+    }
+}
+...
+pico = new DefaultApache Composer(new Intercepting());
+pico.addComponent(Apple.class, BraeburnApple.class);
+Intercpeted intercepted = pico.getComponentAdapter(Apple.class).findAdapterOfType(Intercpeted.class);
+intercepted.pre(Apple.class, new BiteReporter(intercepted.getController()));
+// see also Intercpeted.post(...) method.
+Apple a1 = pico.getComponent(Apple.class);
+a1.takeBite(100); 
+// prints Bite of 100 grams of apple 'Braeburn' 
+// ... irrespective of what else Braeburn.takeBite(int) does.
+  
+
+
+
pico = new DefaultApache Composer();
+pico.as(INTERCEPT).addComponent(Apple.class, BraeburnApple.class);
+// etc
+
+
+
pico = new ContainerBuilder.withInterception().build();
+pico.addComponent(Apple.class, BraeburnApple.class);
+// etc
+
+
+
pico = new ContainerBuilder.withBehaviors(interception()).build();
+pico.addComponent(Apple.class, BraeburnApple.class);
+// etc
+
+

Fine grained participation in interception
Assuming you're passing in the Interceptor to the classes you're using for interception of a component, you can + participate in the fate of the method call. For a 'pre' invocation, you can veto the calling of the 'real' + method.

+ +
+
    public boolean takeBite(int grams) {
+        if (grams > 50) {
+             controller.veto();
+
+        }
+        return false; // will be passed back to the caller.
+    }
+
+
+

For a 'post' invocation, you can override the return value of the 'real' method.

+ +
+
    public boolean takeBite(int grams) {        
+
+        if (grams > 50) {
+             controller.override();
+             (Apple) realApple = (Apple) controller.instance();
+             realApple.takeBite(-1 * grams); // undo !
+        }
+        return false; // will be passed back to the caller.
+    }
+
+
+

Also for a 'post' invocation, you can access the return value of the 'real' method.

+ +
+
    public boolean takeBite(int grams) {        
+
+        boolean rv = (boolean) controller.getOriginalRetVal();
+        if (rv == false) {
+             // do something !
+        }
+        return true; // ignored as no 'override'
+    }
+
+
+ + + + Added: incubator/composer/trunk/composer-site/src/site/content/introduction.html URL: http://svn.apache.org/viewvc/incubator/composer/trunk/composer-site/src/site/content/introduction.html?rev=618174&view=auto ============================================================================== --- incubator/composer/trunk/composer-site/src/site/content/introduction.html (added) +++ incubator/composer/trunk/composer-site/src/site/content/introduction.html Sun Feb 3 22:33:20 2008 @@ -0,0 +1,364 @@ + + + + Introduction + + + +

Authors: Aslak Hellesoy, Jon Tirsen

+ +

Basics

+ +

This is a quick introduction to Apache Composer's most important features. Read through it to get an idea of what + Apache Composer is and isn't.

+ +

Apache Composer's most important feature is its ability to instantiate arbitrary objects. This is done through its API, + which is similar to a hash table. You can put java.lang.Class objects in and get object instances back.

+ +

Example:

+ +
+
+
MutableApache Composer pico = new DefaultApache Composer();
+pico.addComponent(ArrayList.class);
+List list = (List) pico.getComponent(ArrayList.class);
+
+
+ +

(i)MutableApache Composer + API

+ +

This code does the same as this:

+ +
+
+
List list = new ArrayList();
+
+
+ +

With a trivial example such as this there is no point in using Apache Composer. This was just to illustrate the basic + API. Apache Composer becomes useful with larger number of classes and interfaces having complex dependencies between + each other:

+ + + + + + + + + + + +
Complex Dependencies Juicer Example
+

(Green means class, Yellow means interface).
+ Apache Composer identifies dependencies by looking at the + constructors of registered classes (Constructor Injection). + Apache Composer can also be though of as a generic factory that + can be configured dynamically. Apache Composer is able to + instantiate a complex graph of several interdependent objects.

+ +

Write some simple classes + and interfaces with + dependencies

+ +

The "Juicer Example" diagram above could translate to the following code (we added a concrete Peelable):

+ +

+ +
+
+
public interface Peelable {
+    void peel();
+}
+
+
+ +
+
+
public class Apple implements Peelable {
+    public void peel() {
+    }
+}
+
+
+ +
+
+
public class Peeler implements Startable {
+    private final Peelable peelable;
+
+    public Peeler(Peelable peelable) {
+        this.peelable = peelable;
+    }
+
+    public void start() {
+        peelable.peel();
+    }
+
+    public void stop() {
+
+    }
+}
+
+
+ +
+
+
public class Juicer {
+    private final Peelable peelable;
+    private final Peeler peeler;
+
+    public Juicer(Peelable peelable, Peeler peeler) {
+        this.peelable = peelable;
+        this.peeler = peeler;
+    }
+}
+
+
+ +

(Note that this code suffers from the antipattern Propagating Dependency but + let's + not + worry + about + that + for + now + )

+ +

Assemble components

+ +

You tell Apache Composer what classes to manage by registering them like this (the order of registration has no + significance):

+ +
+
+
MutableApache Composer pico = new DefaultApache Composer();
+pico.addComponent(Apple.class);
+pico.addComponent(Juicer.class);
+pico.addComponent(Peeler.class);
+
+
+ +

(i)MutableApache Composer + API

+ +

Instantiate components

+ +

You can tell Apache Composer to give you an instance of a class like this (provided it has been registered + previously):

+ +
+
+
Juicer juicer = (Juicer) pico.getComponent(Juicer.class);
+
+
+ +

This will cause Apache Composer to do something similar to this behind the scenes (except that Apache Composer uses + reflection):

+ +
+
+
Peelable peelable = new Apple();
+Peeler peeler = new Peeler(peelable);
+Juicer juicer = new Juicer(peelable, peeler);
+return juicer;
+
+
+ +

Note how Apache Composer figures out that Apple is a Peelable, so that it can be passed to Peeler + and Juicer's constructors.

+ +

Container hierarchies

+ +

Apache Composer provides a powerful alternative to the Singleton. + With container hierarchies you can create singleton-like objects + where you have fine grained control over the visibility scope of + the instance. (The singleton pattern is static and global - it + won't allow more than one instance, and it is visible from + anywhere. Not nice when you try to build a large enterprise + application from it).

+ +

+ +

A container (and its registered components) can get access to components registered in a parent container, but not + vice-versa. Consider this example, using the classes from above:

+ +


+ THIS WON'T WORK! It is for illustration purposes only!
+

+ +
+
+
// Create x hierarchy of containers
+MutableApache Composer x = new DefaultApache Composer();
+MutableApache Composer y = new DefaultApache Composer( x );
+MutableApache Composer z = new DefaultApache Composer( y );
+
+// Assemble components
+x.addComponent(Apple.class);
+y.addComponent(Juicer.class);
+z.addComponent(Peeler.class);
+
+// Instantiate components
+Peeler peeler = (Peeler) z.getComponent(Peeler.class);
+// WON'T WORK! peeler will be null
+peeler = (Peeler) x.getComponent(Peeler.class);
+// WON'T WORK! This will throw an exception
+Juicer juicer = (Juicer) y.getComponent(Juicer.class);
+
+
+ +

This can be visualised as follows:
+

+ +

Let's analyse what will happen here:

+
    +
  • Line 12 will work fine. z will be able to resolve the dependencies for Peeler (which is Fruit) from the parent + container. +
  • +
  • Line 14 will return null, as x can't see Peeler.
  • +
  • Line 16 will throw an exception, since Juicer's dependency to Peeler can't be satisfied (z can't be seen by + y). +
  • +
+

Since this + obviously won't work, keep in mind that this was just an + exercise to illustrate how container hierarchies work.
+ For a more + concrete example of the usage of container hierarchies, see NanoContainer + NanoWar.

+ +

Lifecycle

+ +

Apache Composer has support for Lifecycle. If your classes implement Startable, you can control the lifecycle of all your objects with a simple method call on the + container. The container will figure out the correct order of invocation of start()/stop() + all the objects managed by the container.

+ +

Calling start() on the container will call start() on all container managed objects in the order of their + instantiation. This means starting with the ones that have no dependencies, and ending with the ones that have + dependencies on others:

+ + + + + + + + + + + +
MutableApache Composer.start() MutableApache Composer.stop()
+

Lifecycle also works for hierarchies of containers. Calling start() on a container with child containers will start + all the containers in a breadth-first order, starting with itself. Likewise, calling stop() will call stop() on all + containers in the hierarchy in a depth-first order. The pictures below show what happens when start() and stop() are + called on a container with children.

+ + + + + + + + + + + +
MutableApache Composer.start() MutableApache Composer.stop()
+

In order for hierarchy-aware lifecycle to work, child containers must be registered as components + in their parent container. Just creating a container with another one as a parent will not + cause the parent container to know about the child container.

+

Example

+ +
+
+
MutableApache Composer parent = new DefaultApache Composer(new Caching());
+MutableApache Composer child = new DefaultApache Composer(parent);
+// We must let the parent container know about the child container.
+parent.addComponent(child);
+// This will start the parent, which will start the child.
+parent.start();
+
+
+ +

warning Lifecycle is really only going to work for Apache Composers that are also caching component instances. Caching was a default in Apache Composer 1.x, but is not for 2.x - be warned!

+

Calling lifecycle methods on a container that has a parent container will not propagate the + lifecycle to the parent container.

+

Read more about lifecycle here.

+
+
+
+ +

Contrasting Usage Styles

+ +

With Apache Composer you add components and get instances out in two styles.

+ +

Classic bean style:

+ +
+
+pico = new DefaultApache Composer();
+pico.addComponent(ComponentOneImpl.class) // by type
+pico.addComponent(ComponentTwoImpl.class) // by type
+pico.addComponent(new ComponentThreeImpl()) // by instance
+pico.addComponent(ComponentFourImpl.class) // by type
+
+ComponentFourImpl four = pico.getComponent(ComponentFourImpl.class);
+
+
+

Or you can use a fluent style if you + want:

+ +
+
+ComponentFour four = new DefaultApache Composer()
+    .addComponent(ComponentOne.class)
+    .addComponent(ComponentTwo.class)
+    .addComponent(new ComponentThree())
+    .addComponent(ComponentFour.class)
+    .getComponent(ComponentFour.class);
+
+ +
+
+
+ + + + + + + + + + +