The jicarilla container provides a compact inversion-of-control container
API. It is so compact, in fact, that it can do so without requiring any
interface representation!
Overview
Typical usage involves registering some classes and some component
definitions with a container builder, retrieving a resolver from that builder,
and then retrieving instances of the registered classes from that resolver.
Behind the scenes, the container does its magic:
- it handles the instantiation, initialization and disposal of the
instances;
- it provides the instances with their external dependencies and
their configuration;
- it can transparently support different "lifestyles", like "singleton"
instances, single-use instances, per-thread instances, per-request
instances, pooled instances, and others;
- it can handle the lookup of instances from some kind of server or
directory, using protocols like JNDI, JMX, SOAP, RMI or AltRMI. It
can even use these instances in satisfying the dependencies of other
instances;
- it can handle the exporting of hosted instances to a similar server or
directory, providing transparent interoperability with many diverse
environments;
- it can handle the activation and passivation (persistence) of instances,
using mechanisms such as Hibernate, Prevayler, XStream or JDO;
- do many other things depending on what extensions you plug in (do
instrumentation and profiling, method tracing, custom interception,
load balancing, etc etc.);
Most importantly, though each and every one of these features, and all the
other features not mentioned yet, are fully pluggable. This means that
you can start with a really small and simple container that does none of these
things, and gradually add extensions to make it do exactly what you want. No
more and no less. And because of this highly modular architecture, it is quite
easy to create and add your own extensions.
Of course, many users have no desire to do all this feature selection
themselves and just want a package that does what they need "with a few
clicks". To support this desire, jicarilla-container is packaged up together
with preconfigured settings into several different profiles. Just like java
itself has different distributions (mobile, core, enterprise), we package
up the jicarilla container in several different ways as well:
- micro. Just the basics in a jar. If you want to do everything
yourself.
- gui. The basics, plus all the materials you need for productive
GUI client applications.
- power. The basics, plus lots of extensions that integrate the
jicarilla container seamlessly with other container solutions and with
many remote registries.
- web. The power profile, with additional extensions that integrate
the jicarilla container inside the prevalent web technologies (servlets,
struts, webwork, hibernate, ...)
- enterprise. The web profile with additional extensions that
integrate the jicarilla container inside the prevalent enterprise
technologies (JMX, JNDI, EJB, ..._
- kitchensink. All of the above, plus a huge preloaded library of
components, applications and examples.
Inversion of Control Basics
You may associate Inversion of Control (or IoC for short) with big
and complex server application frameworks like Avalon, or solutions
for developing J2EE-based web applications like Spring Framework.
Fortunately, the basics of IoC are far simpler than any of those:
public Apu apu = new ApuImpl();
public Marge marge = new MargeImpl();
public Homer homer = new HomerImpl( marge );
public Bart bart = new BartImpl( homer, marge );
public Lisa lisa = new LisaImpl( homer, marge );
public Maggie maggie = new MaggieImpl( homer, marge );
public HomerAndApuScript first = new HomerAndApuScript(
(HotdogBuyer)homer, apu );
public AllInTheFamilyScript second = new AllInTheFamilyScript(
homer, marge, bart, lisa, maggie );
public Script dbl = new DoubleEpisodeScript( first, second );
dbl.runEpisode();
The important idea is that we have a container (in this
case just a short code snippet) that is responsible for creating components,
glueing them together, and telling them what to do. Control over the
application flow starts at the top (with the container) and flows down (to
the components).
A lot of people have written a lot more about inversion of control (or
the "hollywood principle" as it has also been called), and you can find links
to various papers on the Jicarilla website.
Getting Started with the Builder and Resolver
The easiest way to get a feel for how to work with the jicarilla
container is to look at an example. Continuing the Simpsons example...
here's a jicarilla-container-based version of the
"manual" Simpson container above:
Resolver resolver =
DefaultBuilder.newInstance()
.addComponent( "homer-and-apu", HomerAndApuScript.class )
.addComponent( "all-in-the-family",
AllInTheFamilyScript.class )
.addComponent( ApuImpl.class )
.addComponent( BartImpl.class )
.addComponent( HomerImpl.class )
.addComponent( LisaImpl.class )
.addComponent( MaggieImpl.class )
.addComponent( MargeImpl.class )
.addComponent(
new CustomComponentFactory // todo: create this class
(
DoubleEpisodeScript.class,
new Object[]
{
"homer-and-apu",
"all-in-the-family"
}
)
)
.create();
Script script = (Script)resolver.get( Script.class );
script.runEpisode();
From this simple example, it may not be immediately apparent what benefit
you get from using jicarilla. After all, the functionality is the same, and
the second one is easier to read and understand. But take another look at the
second example. Note how the episode scripts are added before we add any of
the Simpsons characters themselves. You don't have to worry about correctly
ordering all your object creations. This is but a small taste of the huge
benefits you can get from using the jicarilla-container package.
Core Interfaces
{@link org.jicarilla.container.builder.Builder}
The Builder is half of your main interface to the
jicarilla-container package. It hides much of the complexity and magic that
goes on "behind the screen" in the internals of the container package. You use
it just like we did in the example above, to create and populate a
Container instance with all your components. When you are finished
populating the container, you call
{@link org.jicarilla.container.builder.Builder#create()} to get access to an
instance of a Resolver :
{@link org.jicarilla.container.Resolver}
The Resolver is that other half of your main interface to the
jicarilla-container package. You use it just like we did in the example above,
to retrieve references to components that live inside a Container .
This may lead you to compare the Resolver with a naming or
directory service like
JNDI. While you could
use a resolver much like you use JNDI, this is not usually a good idea. Instead
of all your components looking up things inside the JNDI directory, the
container is responsible for doing that for them. So your components
are never aware of the existence of the Resolver . In fact,
your components are never aware that they are living a Container
at all!
{@link org.jicarilla.container.Container},
{@link org.jicarilla.container.KeyRelayingContainer},
The Container is the "meat" of the jicarilla-container
package. It is the "fundamental abstraction", the spider in the center of the
web. If jicarilla-container where an operating system, the
Ccode>Container is what we would call the kernel. And just like 99% of
the time, you have no particular interest in interacting directly with the
operating system kernel, you usually don't interact directly with the
Container either.
{@link org.jicarilla.container.Adapter},
{@link org.jicarilla.container.KeyAwareAdapter}
These two interfaces are the "smart trick" that makes jicarilla-container
so agile, flexible and extensible. A lot of responsibility is taken away from
the container and lives inside Adapters instead. In operating
system terms, that means we would call the Container a
microkernel. While in the majority of cases, you have little reason to use an
Adapter directly, if you're doing really advanced stuff (like
linking components living within your own variant of CORBA into the
jicarilla-container system), Adapter s are what you would need to
write to make it happen.
{@link org.jicarilla.container.Factory}
You're probably familiar with the concept of Factories . They
are "helper objects", often associated with a particular class, that are
responsible for creating new instances of that class. They're commonly used
when simply putting all the creation and instantiation directly inside the
class constructor results in a really big and ugly constructor. The use of
factories inside the jicarilla-container package is no different. The main
thing that sets the jicarilla Factories apart from other factories
is that they are quite "general". By using some pretty smart reflection and
introspection magic, a handful of factories can be used for the instantiation
of dozens (or thousands in a complex system, or even millions if you want to
get silly) of different classes.
Type-1, Type-2, Type-3, Type-4, Type-e^2 IoC Support
You may have heard the buzz surrounding Inversion of Control, and the new
buzzword introduced recently, "dependency injection". You may also have been
quite ignorant of it all. Either case, jicarilla-container provides built-in,
no-brainer, complete, simple, and integrated support for all the flavors of
IoC that are currently popular. And its real easy to add support for new
flavors as well.
In other words, this means that you'll be able to easily plug in components
written for
With little effort and without having to rewrite (or even recompile) your
components. Neath, huh?
todo: specific documentation on doing this kind of thing.
Non-IoC Component Support
But it doesn't stop there! With (usually) just a teeny weeny little bit
more effort, you can plug in EJBs, servlets, Plain Old Java Objects (POJOs),
JDBC data sources, xml files (!), property files, JNDI-hosted components,
JMX-exported components, OSGi bundles, eclipse plugins, SOAP services,
CORBA objects, RMI-exported services, and 20-year-old punchcards! Okay, I may
be getting just a little carried away here, but you get the general idea,
I hope.
todo: specific documentation on doing this kind of thing, rather than
just bragging about it.
|