DeploymentClassLoader as a bean
adrian.brock Mar 6, 2008 11:23 AMThe way this was implemented was completely wrong:
<deployment> <classloader><bean ...></classloader> </deployment>
I spent forever trying to figure out how it worked at all,
looking through all the metadata visitor stuff. It turned out it wasn't there
at all!
It was in the xml parsing which means manual deployment doesn't have the feature!!!!
Besides that:
ClassLoaderMetaData had been made into a BeanMetaDataFactory
which is meaningless. How can a classloader be made up of multiple beans
which one do you use as the classloader? :-)
I've implemented this "properly", but it is a bit hacky
(mainly to automagically avoid common mistakes ;-)
When the deployer asks the deployment for the beans it now adds
the classloader. And also makes sure it can't use itself as its own classloader
public List<BeanMetaData> getBeans() { List<BeanMetaData> result = new ArrayList<BeanMetaData>(); // Include the classloader if it is a bean ClassLoaderMetaData classLoaderMetaData = getClassLoader(); if (classLoaderMetaData != null) { ValueMetaData classLoader = classLoaderMetaData.getClassLoader(); if (classLoader instanceof BeanMetaData) { // Hack, if it doesn't have a classloader use the "null" classloader // we don't want it to gain itself as the classloader BeanMetaData classLoaderBean = (BeanMetaData) classLoader; if (classLoaderBean.getClassLoader() == null) classLoaderBean.setClassLoader(new AbstractClassLoaderMetaData(new AbstractValueMetaData())); result.add((BeanMetaData) classLoader); } } List<BeanMetaDataFactory> factories = getBeanFactories(); if (factories != null && factories.isEmpty() == false)
Then in the part where the deployment/bean are checked for classloader
AbstractKernelDeployer::deploybean()
I replace the bean with an injection if it is coming from a deployment classloader
confiigured as a bean.
ClassLoaderMetaData deploymentClassLoader = deployment.getClassLoader(); if (deploymentClassLoader != null) { // If the deployment classloader is a bean, replace it with an injection ValueMetaData classLoader = deploymentClassLoader.getClassLoader(); if (classLoader instanceof BeanMetaData) { classLoader = new AbstractDependencyValueMetaData(((BeanMetaData) classLoader).getName()); beanClassLoader = new AbstractClassLoaderMetaData(classLoader); } else { beanClassLoader = deploymentClassLoader; } bean.setClassLoader(beanClassLoader); }
AbstractClassLoaderMetaData is no longer a BeanMetaDataFactory
(implying multiple beans) and xml parsing no longer contains
logic that should never have been there.