ClassLoader injection Scope issue
alesj Oct 27, 2008 9:06 AMHacking around my demos, I came across this CL usage.
<deployment xmlns="urn:jboss:bean-deployer:2.0"> <classloader><inject bean="custom-classloader:0.0.0"/></classloader> <classloader name="custom-classloader" xmlns="urn:jboss:classloader:1.0" export-all="NON_EMPTY" import-all="true"/> <bean name="CB1" class="org.jboss.demos.ioc.classloader.CustomBean"/> </deployment>
This looks legit as we have similar config in JBoss5/conf.
But it fails for me with this exception:
Caused by: java.lang.IllegalStateException: No context for AbstractDependencyValueMetaData@4d2af2{value=custom-classloader:0.0.0}
at org.jboss.beans.metadata.plugins.AbstractDependencyValueMetaData.getValue(AbstractDependencyValueMetaData.java:205)
at org.jboss.kernel.plugins.config.Configurator.getClassLoader(Configurator.java:665)
at org.jboss.kernel.plugins.config.Configurator.getClassLoader(Configurator.java:646)
at org.jboss.kernel.plugins.dependency.KernelScopeInfo.getScope(KernelScopeInfo.java:97)Why this works in JBoss5 and not here? ;-)
The reason is that this was never tested outside jbossas/conf directory.
Meaning none of those config files are picked up by BeanMetaDataDeployer.
It's the BMDD that causes this to fail while merging scopes.
ScopeInfo scopeInfo = context.getScopeInfo();
if (scopeInfo != null)
{
mergeScopes(scopeInfo.getScope(), unit.getScope());
mergeScopes(scopeInfo.getMutableScope(), unit.getMutableScope());
ScopeInfo::getScope
// THIS IS A HACK - the scope originally gets initialise with a class name, we fix it to have the class
ScopeKey key = super.getScope();
Scope scope = key.getScope(CommonLevels.CLASS);
if (scope == null)
return key;
Object qualifier = scope.getQualifier();
if (qualifier instanceof Class)
return key;
String className = (String) qualifier;
ClassLoader cl;
try
{
cl = Configurator.getClassLoader(beanMetaData);
}
catch (Throwable t)
{
throw new RuntimeException("Error getting classloader for " + key, t);
}
Where Configurator::getClassLoader invokes AbstractDependencyValueMetaData::getValue,
but ADVMD instance has not yet been visited, hence its underlying context is null:
public Object getValue(TypeInfo info, ClassLoader cl) throws Throwable
{
ControllerState state = dependentState;
if (state == null)
state = ControllerState.INSTALLED;
if (context == null)
throw new IllegalStateException("No context for " + this);
Controller controller = context.getController();
Using MC bean metadata outside MC's Controller looks dangerous. :-)