This is some discussion from the WebWork2 mailing list that has a bearing on this issue. I don't know if the approach described is ideologically compatible with picocontainer but it does seem to me to be a lightweight approach.
Everyone seems to want to write "pure" business objects that have no
dependencies on their framework. This is a good thing. This often translates
to people wanting to write objects that don't know they will be used in a
framework. This seems impossible if you actually want your objects to work
with the features of the framework.
For instance it is likely that any reference you have to something supplied
by the framework should be marked transient. Your code has to declare that -
it can't be managed by the framework.
To integrate this with a framework you'd need a decorator object that
handles the initialization in a framework dependent way and overrides
(perhaps) readObject to refresh the framework supplied values.
A simple way to do this is with xDoclet (another dependency !)
e.g.
package com.mycompany.business;
/** Implements some business rules
- @ioc.framework.configurationMethod setDataSource(DataSource)
public class BusinessObject implements Serializable
{
private transient DataSource frameworkDataSource;
...
public void nonIOCMethod();
}
Running xDoclet on this source file would produce something like:
package org.frameworkorg.com.mycompany.business;
public class BusinessObjectWrapper extends
com.mycompany.business.BusinessObject
{
BusinessObject obj;
public BusinessObjectFrameworkWrapper
{
obj = new BusinessObject();
// calling the ioc methods here removes the need to extend
readObject()
obj.setDataSource(framework.getDataSource());
}
//
public void nonIOCMethod()
{
obj.nonIOCMethod();
}
}
The framework could check to see if an XXXFrameworkWrapper class is
available and, if it is, it would instantiate, configure and return that.
Using xDoclet to generate the necessary classes means that the class should
be able to be adapated to run under any IoC framework - "only" the code
generation boilerplate would need to be changed.
For scoped objects the framework would generate an XXXFrameworkWrapper and
store that in the requested scope. One of the issues being discussed on this
point is the need to re-set the object into the session in a distributed
situation. This should be trivial to accomplish:
e.g.
public void nonIOCMethod()
{
obj.nonIOCMethod();
if(framework.getSession().containsValue(this))
framework.getSession().put(framework.getSessionKey(this),
this); //watch performance on key lookup.
}
The framework specific decorator doesn't, of course, need to go into another package when it's being generated by xDoclet. When you don't have access to the original source you should be able to generate a suitable decorator by other means. e.g. make a config file that specifies the class and nominates the configuration methods.
These examples are trivial. Any XXXFrameworkWrapper only extends its base class. It may be desirable to apply the same configuration to a subclass of BusinessObject. If this is the case then the code generator could (as one strategy) use java.lang.reflect.Proxy to return an object of the desired type while still overriding the correct methods in a framework specific way.
> Based on what you've described, I don't agree with you.
> Personally, I
> think of frameworks such as xwork/webwork can be thought of a
> sophisticated
> adapter. They adapt my business logic to the web, swing,
> jms, what have
> you. When I'm working on presentation or other layer
> integration issues,
> I'm dealing directly with the framework. However, when I'm
> working on
> business logic, I want the framework to get out of my way.
Sure I totally agree that the environment should be gotten out of the way as
much as possible. But exactly how transparent the environment can be is the
subject of my post.
>
> Can you provide a more detailed example of framework features
> you want to
> get access to directly from your business logic?
>
> M
In the discussion so far there are two examples of things I need to do to in my business code that are mandated by the environment. Neither of these is in any way related to the business rules implemented by my model classes:
1. Somehow mark the methods I want called (configured) when the object is instantiated. Currently this requires creating an artificial constructor.
2. Allow the object to work in a servlet environment that manages reloading by serializaton/deserialization. I suspect clustering solutions may also use serialization for distributing objects.
Even if you offload item 1. to yet another configuration file (files?) you still need to address item 2. in some fashion.
The current xwork direction (picocontainer) breaks Serialization which I think is a bad thing. It requires an artificial constructor (also a bad thing IMO). Objects may have to re-set themselves into a session (another environment aware behaviour) in order to be shared in a cluster.
With this proposal you just create your beans knowing they may be distributed (serialized) and that certain things will be supplied by the invoking environment. The things you want to be supplied by the environment get specified twice (once in the code with the transient keyword and once with an xDoclet tag) but in a very non-verbose way. xDoclet could potentially be set up to produce wrapper classes for just about any IoC framework without changing the tags.
I don't quite understand this RFE. Wouldn't Java's native serialisation mechanism take care of this? -Unless the dependencies are transient?
Could you provide a test case (preferrably in compilable code, but pseudocode will also do) that illustrates the desired behaviour?
The responsabilities of the container versus the component are a bit blurry to me too.