Jozef Tomek created CAMEL-7708:
----------------------------------
Summary: Dozer class loading works only in last bundle
Key: CAMEL-7708
URL: https://issues.apache.org/jira/browse/CAMEL-7708
Project: Camel
Issue Type: Bug
Components: camel-dozer
Affects Versions: 2.13.2
Reporter: Jozef Tomek
DozerTypeConverterLoader in it's init() method sets
CamelToDozerClassResolverAdapter, properly resolving resources only within
bundle being currently loaded, to Dozer's BeanContainer.getInstance().
Because of Dozer using singletons, this DozerClassLoader implementation is then
used for mappings done in context of all bundles. This effectively means that
class loading will work only for the bundle (using dozer) that was started the
last.
Code of interest:
{code:title=org.apache.camel.converter.dozer.DozerTypeConverterLoader|borderStyle=solid}
167 CamelToDozerClassResolverAdapter adapter = new
CamelToDozerClassResolverAdapter(camelContext);
168 BeanContainer.getInstance().setClassLoader(adapter);
{code}
*Symptoms*
For me the symptoms were NPE when Dozer's JAXBBeanFactory tried to create
mapping-target class instance by loading ObjectFactory class and calling the
appropriate create method. Installed CamelToDozerClassResolverAdapter was
unable to load ObjectFactory residing in different bundle (started not as the
last one), which immediatelly caused NPE.
However I would say it has to fail even when default bean creation method
instead of JAXBBeanFactory is used.
*Workaround*
Since I had to deliver working module that day, my quick and not very nice
workaround was to extend DozerTypeConverterLoader, override its' init() method
and after calling super.init() replace the loader set on
BeanContainer.getInstance() with my custom DozerClassLoader.
This custom loader knows what bundle it was created for, what loader was set on
BeanContainer.getInstance() before super.init() changed it \[one hopefully
working for all bundles that are already started\], and (new) one that
super.init() changed it to \[one working for this new bundle\].
This custom loader then checks what bundle context is it called from using ugly
{code}
((BundleDelegatingClassLoader)
Thread.currentThread().getContextClassLoader()).getBundle()
{code}
approach. Then it delegates call to proper dozer class loader - either one for
that bundle or fallback.
--
This message was sent by Atlassian JIRA
(v6.2#6252)