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)

Reply via email to