[Design the new POJO MicroContainer] - Re: Scoped Kernels
by adrian@jboss.org
Now let's look at a concrete example I was thinking about over the weekend.
We want to define a "subsystem". This is a scoped kernel such that
nobody else can play with our beans. i.e. it is a private implementation deployment.
A simple case would be the old JBossJTA subsystem.
| <deployment>
| <scope level="subsystem" qualifier="JBoss JTA"/>
|
| <bean name="XIDFactory">
| ...
| </bean>
|
| <bean name="TransactionManager">
| <property name="xidFactory><inject bean="XIDFactory"/></property>
| ...
| </bean>
| </deployment>
|
So far so good. Nobody else can see our XIDFactory, it is private to our scope.
BUT others want to use the TransactionManager.
In practice of course, they should be using the TransactionManagerLocator
class, since we want to integrate in other places where we don't
construct the TM. So this example is a bit academic.
This could be formalised as having a root deployment:
| <deployment>
| <bean name="TransactionManager"
| <constructor factoryClass="TransactionManagerLocator" factoryMethod="getInstance"/>
| </bean>
| </deployment>
|
This is good because it will work in all environments the transaction manager locator
class supports, it allows IOC injection again, and the locator class
knows how to find the TransactionManager defined in the "JBoss JTA" scope
using a private factory method when run inside JBoss.
It does however have one drawback.
The dependencies are not really being checked/satisifed.
Since we are using a private factory method in the TransactionManagerLocator
somebody could forget to deploy the "JBoss JTA" scope deployment and it
will still work. It will just use a default configuration for the TransactionManager.
Maybe this is what we want? But probably only in this use cases.
Although, in a lot of other use cases, the binding is not really coming
from direct POJO injection, but from jndi bindings, etc.
e.g. DataSources.
If we tweak the example a bit and assume we do want people to be
able to directly inject the TransactionManager (and there is nothing
like the TransactionManagerLocator) then we need a mechanism to
promote the TransactionManager into the default scope.
One mechanism would be to do an "export". i.e. I define the bean
in a scoped kernel, but I also want it available in the global scope.
| <bean name="TransactionManager" export="true">
|
There would be two ways to implement this.
1) The context really exists in the global scope, but for the sake of
dependencies it uses the "JBoss JTA" scope.
2) We register and "alias" in the global scope.
I think (2) will be a lot simpler to implement.
Essentially, the alias would just act as a "proxy/delegate" to the real
context in the scoped kernel. The root kernel would recognise the
context as a proxy and not try to manage it.
And Scott has been asking for a generic alias mechanism anyway. :-)
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4015033#4015033
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4015033
19 years, 1 month
[Design the new POJO MicroContainer] - Scoped Kernels
by adrian@jboss.org
Based on the discussion here:
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4015013#4015013
I want to fork off part of the discussion which is how to implement the scoped kernel.
Let's start with how the current singleton kernel controller works.
The alogorithm goes something like (uninstall is mainly the reverse):
| atEveryInstall()
| {
| do
| {
| // Go through the states in order from lowest (NotInstalled) to highest (Installed)
| for (State state : statesInOrder)
| {
| // Get the contexts that are ready for the next state
| // i.e. dependencies are satisifed
| for (Context c : readyToPromoteToNextState(s))
| {
| // Double check because of "manual" and recursive calls
| if (notAlreadyPromoted(c))
| promoteToNextState(c);
| }
| }
| }
| // We loop because promotions in later states can satisfy dependencies
| // in earlier states.
| until (nothing changes state);
| }
|
With scoped kernels the parent kernel needs to know about its children.
A context in the scoped kernel can depend upon the parent kernel
but not vice-versa.
So as well as going through the contexts in this kernel
there needs to be an additional:
| for (Controller child : childControllers)
| {
| child.atEveryInstall(c);
| }
|
i.e. Once we have no more changes in the parent controller
(i.e. the do until loop exits) we invoke the children.
This alogorithm will avoid any problems with recursion or deadlocks
since everything is done in one order parent -> child.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4015020#4015020
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4015020
19 years, 1 month
[Design the new POJO MicroContainer] - Re: Scoped beans deployment
by adrian@jboss.org
"adrian(a)jboss.org" wrote :
| I think that what we should really do is have a notion of ScopeKey in the
| BeanMetaData[Factory] and the ControllerContext.
|
Essentially what I'm saying is what is done now in the DescribeAction
(mostly delegating to the MetaDataRepository to determine default rules)
should be done at (pre-)installation time.
We would essentially implement the default rules in the AbstractBeanMetaData
(so they can be overridden).
The difficulty comes in the notion of the scoped kernel.
Before we can do the install, we need to create the scoped kernel
and for that we need metadata scope to exist so we remember the scope.
(There's also potentially a race condition here with two threads trying
to create the same scope - but that's another story).
I think the solution is for the BeanMetaData to fully describe itself
and then have the install/uninstall into the root kernel do the work
from the description (again mostly delegating the KernelMetaDataRepository).
The difference being that the install/uninstall just "does it" based
on what the BeanMetaData tells it, it doesn't make any policy decisions.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4015013#4015013
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4015013
19 years, 1 month
[Design the new POJO MicroContainer] - Re: Scoped beans deployment
by adrian@jboss.org
"alesj" wrote : "adrian(a)jboss.org" wrote :
| | Stages (1) and (2) are optional if they already exist
| |
| | 1) Create a MutableMetaData for this scope
| | 2) Create a kernel (or maybe just a kernel controller) for this scope and add it to
| | the MutableMetaData, the kernel's parent would come from any kernel in the
| | parent's scope or the default kernel if there is no such thing
| | 3) Deploy the bean(s) into that scoped kernel
| |
|
| Where to plug-in these stages?
| Since I need to know bean annotations before I deploy bean into the controller (BeanMetaDataDeployer, AbstractKernelDeployer), but currently they are realized in DescribeAction.
| Or should I do my own scope-annotation lookup just before I do the deployment into controller?
I think that what we should really do is have a notion of ScopeKey in the
BeanMetaData[Factory] and the ControllerContext.
I've avoided adding it so far until we've sorted out the usecases for the
metadata, but it is definitely something that should be there.
If it is not specified, you would just use the deault rules from the
annotations or failing that ScopeKey.DEFAULT_SCOPE
I think we really need to discuss the use cases for how the metadata works.
I don't have a problem with you prototyping something so we have
something to "play with'. But the only way we are really going to workout
what the api should look like is by going through examples on
how we expect this feature to be used.
I'll start a seperate thread on one example I was thinking about over the weekend.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4015003#4015003
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4015003
19 years, 1 month