Dozer:Osgi环境中的ClassNotFoundException

时间:2014-05-07 15:30:17

标签: osgi dozer

我在Osgi environement(Apache karaf)中使用Dozer。版本用户5.4.0。 Pom依赖关系如下所示。

    <dependency>
        <groupId>net.sf.dozer</groupId>
        <artifactId>dozer-osgi</artifactId>
        <version>5.4.0</version>
    </dependency>

我们通过xml文件使用自定义映射。当dozer映射器引用映射的映射xml时,它不会获得该文件中引用的类。我得到以下例外。

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)

知道如何在osgi中使用推土机吗?

3 个答案:

答案 0 :(得分:2)

Dozer使用类加载器来加载至少以下资源:

  • 映射定义XML文件。映射定义文件包含自定义映射规则。
  • 使用Class.forName()基于完全限定类名的类。

Dozer有一个可插入的类加载配置,允许为类和资源设置自定义类加载器:

org.dozer.util.DozerClassLoader classLoader=...;
BeanContainer.getInstance().setClassLoader(classLoader);  

然而,Dozer的设计并未考虑OSGi。自定义类加载器设置在Dozer单例上。这与延迟加载映射定义文件相结合可能会产生意外结果。

由于类加载器是在单例上设置的,因此它会影响通过Dozer导入资源的所有包。但是,如果以下条件有效,则可以实施可接受的解决方法:

  • 捆绑包按顺序启动。
  • 在捆绑包启动阶段完全设置推土机。

第一个条件将阻止覆盖BeanContainer的类加载器属性,直到捆绑包开始。

第二个条件将允许Dozer在BeanContainer单例被另一个包重置之前加载任何自定义映射文件及其中引用的所有类。

唯一缺少的部分是自定义Dozer类加载器,以及捆绑包中的Dozer初始化。

委托给bundle的类加载器的Dozer类加载器如下所示:

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;
}
}

然后在捆绑启动期间 - 例如在蓝图中急切地创建了bean构造函数或init-method - 设置自定义类加载器,映射文件并强制解析映射文件:

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;
}

上述方法并非最佳。在实践中,它似乎有效,并且它是一个可行的解决方法,直到取消单身人士和在Dozer中,类加载对OSGi更加友好。

这个答案改编自我的博客:http://modio.io/dozer-pojo-mapper-in-osgi/

答案 1 :(得分:0)

看起来您需要将acording包导入“dsp.core”包。 只要这不导入该包,推土机就无法访问它。

答案 2 :(得分:0)

你能确定Apache Karaf中的推土机捆绑是否有效?您可以通过webconsole或命令进行检查。

我在OSGI(Apache Karaf)中使用下面的工件并为我工作

    <dependency>
        <groupId>net.sf.dozer</groupId>
        <artifactId>dozer</artifactId>
        <version>5.4.0</version>
    </dependency>