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. :-)