Reputation: 41
I am using Dozer in Osgi environement(Apache karaf). Version user 5.4.0. Pom dependency looks like below.
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer-osgi</artifactId>
<version>5.4.0</version>
</dependency>
We are using custom mapping thru xml file. When dozer mapper refers to the mapping xml for a mapping, it is not getting the class referred in the the file. I get following exception.
2014-05-07 00:12:13,734[qtp1876495841-122]|ERROR|com.ge.alsp.dspkservice.services.impl.UserServiceImpl|354-alsp-service-2.0.0|Failed to get user profile.
org.dozer.MappingException: java.lang.ClassNotFoundException: com.ge.alsp.model.usermanagement.Timezone not found from bundle [dsp.core]
at org.dozer.util.MappingUtils.throwMappingException(MappingUtils.java:82)
at org.dozer.util.DefaultClassLoader.loadClass(DefaultClassLoader.java:38)
at org.dozer.util.MappingUtils.loadClass(MappingUtils.java:224)
at org.dozer.loader.DozerBuilder$MappingBuilder.classA(DozerBuilder.java:129)
at org.dozer.loader.xml.XMLParser.parseMapping(XMLParser.java:188)
at org.dozer.loader.xml.XMLParser.read(XMLParser.java:135)
at org.dozer.loader.xml.XMLParser.read(XMLParser.java:43)
at org.dozer.loader.xml.MappingStreamReader.read(MappingStreamReader.java:51)
at org.dozer.loader.xml.MappingFileReader.read(MappingFileReader.java:58)
at org.dozer.DozerBeanMapper.loadFromFiles(DozerBeanMapper.java:227)
Any idea how to make dozer work in osgi ?
Upvotes: 0
Views: 3405
Reputation: 171
Dozer employs a class loader for loading at least the following resources:
Dozer has a pluggable class loading configuration which allows to set a custom class loader for classes and resources:
org.dozer.util.DozerClassLoader classLoader=...;
BeanContainer.getInstance().setClassLoader(classLoader);
However Dozer was not designed with OSGi in mind. Custom class loaders are set on a Dozer singleton. This combined with the lazy loading of mapping definition files can generate unexpected results.
Since the classloader is set on a singleton, it affects all bundles that import resources through Dozer. However if the following conditions are valid then an acceptable workaround can be implemented:
The first condition will prevent the class loader property of the BeanContainer
to be overridden until a bundle has started.
The second condition will allow Dozer to load any custom mapping files and all classes referenced in them before the BeanContainer
singleton is reset by another bundle.
The only missing pieces are the custom Dozer class loader, and the Dozer initialization in the bundle.
The Dozer class loader that delegates to the bundle’s class loader is shown below:
public class OsgiDozerClassLoader implements DozerClassLoader {
private BundleContext context;
@Override
public Class<?> loadClass(String className) {
try {
return context.getBundle().loadClass(className);
} catch (ClassNotFoundException e) {
return null;
}
}
@Override
public URL loadResource(String uri) {
URL url;
url = context.getBundle().getResource(uri);
if (url == null) {
url = DozerClassLoader.class.getClassLoader().getResource(uri);
}
return url;
}
public void setContext(BundleContext context) {
this.context = context;
}
}
Then during bundle startup – e.g. in a blueprint eagerly created bean constructor or init-method
– setup the custom classloader, the mapping files and force parsing of the mapping files:
public DozerBeanMapper getMapper(List<String> files) {
BeanContainer.getInstance().setClassLoader(classLoader);
DozerBeanMapper mapper = new DozerBeanMapper();
mapper.setMappingFiles(files);
// Force loading of the dozer.xml now instead of loading it
// upon the first mapping call
mapper.getMappingMetadata();
return mapper;
}
The above approach is not optimal. In practice it seems to work and its a viable workaround until singletons are removed & class loading becomes more OSGi-friendly in Dozer.
This answer has been adapted from my blog: http://modio.io/dozer-pojo-mapper-in-osgi/
Upvotes: 2
Reputation: 385
Can you make sure whether dozer bundle is active in Apache Karaf? You can check via webconsole or command.
I am using below artifact in OSGI (Apache Karaf ) and works for me
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.4.0</version>
</dependency>
Upvotes: 0
Reputation: 5285
Looks like you need to import the acording package to the "dsp.core" bundle. As long as this doesn't import that package dozer isn't able to access it.
Upvotes: 0