-
1. Re: Scoped Kernels
adrian.brock Feb 12, 2007 9:12 AM (in response to adrian.brock)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. :-) -
2. Re: Scoped Kernels
adrian.brock Feb 12, 2007 9:17 AM (in response to adrian.brock)
2) We register an "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.
The reason why the alias would be simpler to implement
is because managing the scoped bean from the global scope introduces
all sorts of problems with ordering that are likely to lead to deadlocks.
e.g. Having to take locks in the scoped kernel from the global scope
to look at the state, etc. -
3. Re: Scoped Kernels
alesj Feb 19, 2007 4:34 AM (in response to adrian.brock)Should I simply (re)move all the dependent information (allContexts, contextsByState, errorContexts, installing) from the parent controller, and stick it into the scoped one in PreInstallAction (and a simple reverse on the uninstall). Or is there something I should be careful about?
-
4. Re: Scoped Kernels
alesj Feb 19, 2007 5:56 AM (in response to adrian.brock)On the uninstall:
public void undeploy(DeploymentUnit unit, BeanMetaData deployment) { controller.uninstall(deployment.getName()); }
How to get to the Scoped controller that holds the actual ControllerContext?
Look in the current controller if the context is there and uninstall it, else go to child controllers and call the uninstall on them - the one that returns non-null is the one that unistalled the context? -
5. Re: Scoped Kernels
alesj Feb 19, 2007 11:13 AM (in response to adrian.brock)Ok, forget about the previous two posts.
I have a prototype impl ready and working (it is doing what expected and it doesn't break any of the existing tests). Just need to write some real tests for this new feature :-).
I'll do this tomorrow, and if the tests pass, I'll commit the code (since it doesn't effect the previous non-scoped stuff) and then we can discuss this further.
Scott, or should I totally wait for Friday to pass by, and then commit? -
6. Re: Scoped Kernels
starksm64 Feb 19, 2007 11:43 AM (in response to adrian.brock)"alesj" wrote:
Scott, or should I totally wait for Friday to pass by, and then commit?
I'll update the current 2.0 branch from trunk today so you can commit when its ready. -
7. Re: Scoped Kernels
alesj Feb 21, 2007 5:16 AM (in response to adrian.brock)I'm quite done with scoping, but I have encountered a few problems:
1) When a bean that represents the classloader for other beans is deployed in some scope, other dependent beans (from same scope) are unable to find him - since they are not described yet == no scope knowlegde.
2) If I deploy bean with the same name and the same class in 2 different scopes, KernelControllerContext scope lacks some differentiation between different context instances - fullScope with INSTANCE and CLASS is the same for both context instances. I currently added context's hash under WORK level, to be able to test this.
3) While testing, how to get the actual bean / context from bootstrapping kernel / controller, since the real bean / context is present in some scoped child controller. -
8. Re: Scoped Kernels
alesj Feb 21, 2007 6:06 AM (in response to adrian.brock)"alesj" wrote:
3) While testing, how to get the actual bean / context from bootstrapping kernel / controller, since the real bean / context is present in some scoped child controller.
I've added this:private class TestController extends AbstractController { private AbstractController delegate; public TestController(AbstractController controller) throws Exception { this.delegate = controller; } public ControllerContext getContext(Object name, ControllerState state) { return findContext(delegate, name, state); } private ControllerContext findContext(AbstractController controller, Object name, ControllerState state) { ControllerContext context = controller.getContext(name, state); if (context != null) { return context; } else { for (AbstractController childController : controller.getControllers()) { ControllerContext ctx = findContext(childController, name, state); if (ctx != null) return ctx; } } return null; } }
I have some public methods in AbstractController that it would be better if they were not public. I'll fix them later - when we decide what to put in SPI. -
9. Re: Scoped Kernels
starksm64 Feb 21, 2007 1:21 PM (in response to adrian.brock)I think we need some notion of scoped names that allows this to be done easily. This seems to be needed in order to resolve item 2) as well. A proper alias would then be a simple name in a scope that links to the scoped name to which the alias resolves.
Regarding 1), I'm not clear on what the relationship is between the kernels, names spaces, and type systems are. I'm assuming that whether or not the type systems are isolated/shared is strictly a function of the bean configuration in the kernels. Based on the initialization algorithm Adrian described, it should be possible to pickup the beans in a given state across the graph of kernel instances. Are you traversing all contexts across all kernels for a given state? -
10. Re: Scoped Kernels
alesj Feb 22, 2007 8:02 AM (in response to adrian.brock)"scott.stark@jboss.org" wrote:
Are you traversing all contexts across all kernels for a given state?
I'm doing a simple current --> parent chain context lookup.
The problem is when a CL bean is defined in some scope, it is part of the ScopedController after PreInstall state. But the CL bean dependant beans are still in the 'Not installed' state, since they need CL for MetaData, so they are still having a bootstrap Controller assigned to them - which doesn't know about context's in his child Controllers == ScopedControllers. -
11. Re: Scoped Kernels
adrian.brock Feb 23, 2007 11:20 AM (in response to adrian.brock)"alesj" wrote:
I'm quite done with scoping, but I have encountered a few problems:
1) When a bean that represents the classloader for other beans is deployed in some scope, other dependent beans (from same scope) are unable to find him - since they are not described yet == no scope knowlegde.
You can't use a classloader in a scope if the scope requires
that classloader to exist before it is constructed.
It's like trying to have a deployment depend upon a classloader
in that deployment. In that case, you fix it by doing:<classloader><null/></classloader>
So it doesn't depend upon itself.
2) If I deploy bean with the same name and the same class in 2 different scopes, KernelControllerContext scope lacks some differentiation between different context instances - fullScope with INSTANCE and CLASS is the same for both context instances. I currently added context's hash under WORK level, to be able to test this.
I don't understand this. 2 contexts in different scopes should not have
the same ScopeKey.
3) While testing, how to get the actual bean / context from bootstrapping kernel / controller, since the real bean / context is present in some scoped child controller.
There are a number of apis that need updating to understand Scope.
i.e. passing in the ScopeKey as an additional parameter.
The old api should invoke the new api with the default scope.
Retrieving the context is one of them.
There are other apis that need to be able to retrieve all contexts in all scopes
and include the scope in the identity.
The checking of incomplete contexts in the kernel deployer
or the repository service is one of the latter. -
12. Re: Scoped Kernels
alesj Feb 23, 2007 12:24 PM (in response to adrian.brock)"adrian@jboss.org" wrote:
I don't understand this. 2 contexts in different scopes should not have
the same ScopeKey.
The problem that I encountered was when I had two beans with the same class and same name deployed into 2 different scopes, I always got annotations meta data for the first one deployed --> obvious, since keys matched --> no scope differentiation."adrian@jboss.org" wrote:
There are a number of apis that need updating to understand Scope.
i.e. passing in the ScopeKey as an additional parameter.
The old api should invoke the new api with the default scope.
Retrieving the context is one of them.
There are other apis that need to be able to retrieve all contexts in all scopes
and include the scope in the identity.
The checking of incomplete contexts in the kernel deployer
or the repository service is one of the latter.
If you could just 'mark' all the necessary API methods that need updateing, I'll go and 'fix' them. -
13. Re: Scoped Kernels
adrian.brock Feb 23, 2007 12:34 PM (in response to adrian.brock)"alesj" wrote:
"adrian@jboss.org" wrote:
There are a number of apis that need updating to understand Scope.
i.e. passing in the ScopeKey as an additional parameter.
The old api should invoke the new api with the default scope.
Retrieving the context is one of them.
There are other apis that need to be able to retrieve all contexts in all scopes
and include the scope in the identity.
The checking of incomplete contexts in the kernel deployer
or the repository service is one of the latter.
If you could just 'mark' all the necessary API methods that need updateing, I'll go and 'fix' them.
Anything that takes a "name" and returns a ControllerContext
is in the first category.
e.g.ControllerContext getInstalledContext(Object name);
Anyhing that returns a collection of controller contexts is in the second categorySet<ControllerContext> getNotInstalled();
I don't think there is anything that returns a list of names
but there are places like the incomplete deployment code
that needs to understand that the full unique name is no longer just
getName() but also needs to use ConstrollerContext.getScopeKey() -
14. Re: Scoped Kernels
alesj Feb 23, 2007 12:49 PM (in response to adrian.brock)"adrian@jboss.org" wrote:
but also needs to use ConstrollerContext.getScopeKey()
From previous problem (duplicate 'context') temp fix, I currently have Context's hashCode under WORK level to diff the contexts. What's the appropriate fix?
What about this new scope key - gained from class/bean (deployment) annotations? Should it be considered once it is resolved - with some update to current context scope - or is this how I used it ok --> install ScopeKey.