You will be redirected to our new website in 5 seconds...
If you are not automatically taken to our new web site,
please click on the hyperlink :
http://jodd.org
Jodd
build: 309
updated: Jun 17 2008
 

SourceForge.net Logo

freebsd  Support this project

home Home | download | home Contact | SourceForge | File Releases releases | News news |  
Petite
*A small rock holds back a great wave. (Homer)
Table of Contents

JDateTime betaPetite is an IOC container. Yes, yet another one;) Then again, it is quite simple to use, requires no configuration, it is so small so anyone can understand how it works from the code, doesn't depends on third-parties and... Well, it will always stay this way. Enough said:)

Highlights
  • Small, fast, elegant
  • Various scopes
  • Zer0 configuration using annotations

Basics and manual registration

Lets take two POJO beans:

public class Foo {
	Boo boo;
	public void foo() {
		if (boo != null) boo.boo();
		System.out.println("foo");
	}
}
public class Boo {
	public void boo() {
		System.out.println("boo");
	}
}

Petite container builds bean name from class name. When not specified explicitaly, bean names are created by uncapitalizing the class name. As for any other container, beans must be registered before usage. Petite registration is done in Java - no proprietary or weird XML configuration is required.

In this basic example, Foo and Boo can be registered manually:

PetiteContainer petite = new PetiteContainer();
petite.register(Foo.class);		// equivalent to: petite.register("foo", Foo.class);
petite.register(Boo.class);

Now both beans are registered in the container. They can be fetched by their bean name:

Foo foo = (Foo) petite.getBean("foo");
foo.foo();

Although registered, beans are still not wired. Let's see how to instruct Petite to wire beans.

Wiring beans

By default, Petite injects beans in all annotated fields, where field name is used as a bean reference. So, to wire these two beans together, it is enough to annotate the attribute of Foo:

public class Foo {
	@PetiteInject
	Boo boo;
	...
}

That is all, beans will be wired when they come out of container. Note that accessors methods (setXxx() & getXxx() are not required, although will be used if exists).

Auto-registration

Since Petite registration is done in Java, it is easy to extend it to some custom way for registering beans (i.e. reading configuration from XML file). Still, manual registration is usually error prone and hard to maintain. Petite provides another way to register beans: auto-registration. Petite auto-registration tool will scan classes on the classpath (including classes insed jar files) and register all beans that are annotated as Petite bean. Since class scanning of full path (and all jars) may be a long operation, it is possible and easy to fine-tune this process by specifying the scanning path and included/excluded jars and packages (see: FindClass) in order to reduce the amount of scanned classes. During scanning, Petite examine classes in a smart way, so only annotated Petite beans will be actually dynamically loaded and then registered in the container.

As said, before running the auto-registration tool, beans must be annotated as Petite beans:

@PetiteBean
public class Foo {

...

@PetiteBean
public class Boo {

Auto-registration is now simple:

PetiteContainer petite = new PetiteContainer();
AutomagicPetiteConfig petiteCfg = new AutomagicPetiteConfig();
petiteCfg.configure(petite);

Please note that usage of @PetiteBean annotation does not imply usage of @PetiteInject annotation and vice-versa.

Wiring constructors

Similarly as for the bean properties, Petite provides beans wiring using constructors. In above example, we can modify the Foo class:

public class Foo {
	final Boo boo;
	public Foo(@PetiteInject Boo boo) {
		this.boo = boo;
	}
	...
}

Wiring beans using constructors has some limitations. There must be one or none suitable constructors, otherwise, exception is thrown. Suitable constructor is one that has all parameters annotated. Partially annotated constructors are detected and exception is thrown.

Interfaces

Until now we have been working only with concrete bean implementations. Let's look at the situation when some beans have more than one bean implementation. Petite also accepts bean's interfaces, when pointer to concrete implementation is defined by template in an annotation value, set on package (or interface itself). Common usage is to set package annotation @PetiteImpl with value that specifies the naming convention for concrete implementation. This is best seen on the example.

Let's have the bean interface and its implementation:

package jodd.petite.test;

public interface Ioo {
	void hello();
	Foo getFoo();
}
package jodd.petite.test.impl;

public class DefaultIoo implements Ioo {

	@PetiteInject
	Foo foo;

	public void hello() {
		System.out.println("DefaultIoo.hello");
	}

	public Foo getFoo() {
		return foo;
	}
}

Although it is possible to annotate the interface, this is not consider as a practical approach, since for single implementation change all interfaces have to be manually changed. Therefore, we will use package annotation, defined in package-info.java:

@PetiteImpl("impl.Default*")
package jodd.petite.test;

import jodd.petite.meta.PetiteImpl;

When an interface is registered in the Petite container, it will first examine the interface for @PetiteImpl and then, if not found, its package. Annotation's value represents class name template that starts from interface's package. Star character ('*') represents actual interface name. So, in above example, when Ioo interface is registered, Petite will look for jodd.petite.test.impl.DefaultIoo class.

All wirings are defined in the concrete implementation, not the interface. When using auto-configuration, only interfaces have to be annotated with @PetiteBean.

Auto-wire

Although not preferable, Petite supports auto-wiring of the beans. When turned on for a container, all bean's properties will be considered for wiring. This behavior is equivalent to one when all fields are actually annotated with @PetiteInject. Note that Petite still uses this annotation in auto-wire mode.

Single bean may be registered for auto-wiring mode independently from container. Auto-wiring can be turned on/off anytime. Using auto-wiring feature may have some impact on application's performance.

Scopes

Petite beans are scoped. The following scopes are implemented:

  • Prototype: creates new bean instance on each retrieval.
  • Singleton: only one bean instance per container.
  • Session: one bean instance per HTTP session.

Users may create custom scopes easily.

Create proxies transparently

It is easy to generate bean proxies transparently. Petite has single point of bean registration. Therefore, user may override this method and create proxy over bean type before it is registered in the container. An easy way to create proxy is using Proxetta:

public class MyPetiteContainer extends PetiteContainer {

	protected final Proxetta proxetta;

	public MyPetiteContainer(Proxetta proxetta) {
		this.proxetta = proxetta;
	}

	@Override
	protected void registerBean(String name, Class type, Class scopeType, Autowire autowire) {
		type = proxetta.defineProxy(type);
		super.registerBean(name, type, scopeType, autowire);
	}
}
Misc

Petite detects and disallows circular dependencies.