如何在OSGI框架中的运行时动态加载Java类? [英] How to dynamically load Java classes at Runtime in OSGI framework?

查看:132
本文介绍了如何在OSGI框架中的运行时动态加载Java类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在项目中执行POC,在该项目中,我们发送基于SOAP的请求,并相应地从Web服务获取SOAP响应.我们的目标是在应用程序中利用spring框架提供的webservices模板(客户端API).根据我们的体系结构,我们创建一个与OSGI兼容的捆绑包(用于使用webservices模板API与该Web服务进行交互的代码),然后将该捆绑包部署到Apache Felix容器中.我们还在Felix容器中安装了所有依赖于OSGI的捆绑软件,以便解决所有依赖关系.

We are performing a POC in our project, where in we send SOAP based request and correspondingly get a SOAP response from a web service. We aim to leverage webservices template (client side API) provided by spring framework in our application. As per our architecture, we create an OSGI compliant bundle (for our code that uses webservices template API to interact with the web service) which is then deployed into the Apache Felix container. We have also installed all the dependent OSGI compliant bundles in the Felix container so that all the dependencies are resolved.

根据webservices模板,默认的Web Service消息发送者是HttpUrlConnectionMessageSender,它在运行时由类加载器动态加载.据我了解,由于Felix容器无法从相关的OSGI捆绑软件(Web服务捆绑软件包含HttpUrlConnectionMessageSender)中加载类,因此我们收到以下异常.

As per the webservices template, the default Web Service Message sender is HttpUrlConnectionMessageSender which is dynamically loaded at run time by the class loader. As per my understanding, we are getting the below exception because the Felix container is not able to load the class from the dependent OSGI bundle (web services bundle contains the HttpUrlConnectionMessageSender).Please refer to the exception logs below.

* org.springframework.beans.factory.BeanInitializationException: Could not find default strategy class for interface [org.springframework.ws.transport.WebServiceMessageSender]; nested exception is java.lang.ClassNotFoundException:org.springframework.ws.transport.http.HttpUrlConnectionMessageSender at  org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:126)

    at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:90)

    at org.springframework.ws.client.core.WebServiceTemplate.initMessageSenders(WebServiceTemplate.java:320)

    at org.springframework.ws.client.core.WebServiceTemplate.initDefaultStrategies(WebServiceTemplate.java:306)

    at org.springframework.ws.client.core.WebServiceTemplate.<init>(WebServiceTemplate.java:143)

    at test.soapservice.service.SOAPServiceImpl.<init>(SOAPServiceImpl.java:40)

    at test.soapservice.service.SOAPServiceActivator.start(SOAPServiceActivator.java:17)

    at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)

    at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)

    at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)

    at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)

    at org.apache.felix.gogo.command.Basic.start(Basic.java:729)

原因:java.lang.ClassNotFoundException:org.springframework.ws.transport.http.HttpUrlConnectionMessageSender

Caused by: java.lang.ClassNotFoundException: org.springframework.ws.transport.http.HttpUrlConnectionMessageSender

    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)

    at java.security.AccessController.doPrivileged(Native Method)

    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)

    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)

    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)

    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)

    at org.springframework.util.ClassUtils.forName(ClassUtils.java:211)

    at org.springframework.util.ClassUtils.forName(ClassUtils.java:164)

    at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:114)

据我了解,Felix容器无法使用另一个捆绑包中存在的ClassUtils.forName()动态加载类.我认为这是一个协作问题,其中当前捆绑软件具有与依赖捆绑软件的类加载器不同的类加载器.

As per my understanding,Felix container is unable to dynamically load the class using ClassUtils.forName() which exists in another bundle. I see this as a collaboration issue where the current bundle has a different class loader as opposed to class loader of dependent bundle.

该社区的某人是否遇到了相同的异常?如果是,那么您采取了哪些步骤来解决运行时类依赖关系?请分享您的想法/观点以解决上述问题.我们将高度赞赏您的快速回复,这可能有助于我们使POC取得成功.

Did someone from this community have encountered the same exception? If yes, then what were steps taken by you to resolve the run time class dependency? Please share your thoughts/pointers to resolve the above issue.A quick response would be highly appreciated and may help us to make our POC successful.

预先感谢, Mridul Chopra

Thanks in advance, Mridul Chopra

推荐答案

Class.forName()形式进行类加载在任何OSGi容器中都不是问题.您的问题是MANIFEST.MF文件不包含正确的导入声明.一个捆绑软件应导出org.springframework.ws.transport软件包,而您的捆绑软件应导入相同的软件包.

Classloading in the form of Class.forName() is not a problem in any OSGi container. You problem here is that the MANIFEST.MF file does not contain the right import declarations. One bundle should export the org.springframework.ws.transport package, while your bundle should import the same package.

如果您使用Maven构建捆绑包,则可以使用 Felix捆绑插件以生成正确的清单信息.

If you are using Maven to build your bundle, you can use the Felix Bundle Plugin to generate the right manifest information.

<plugins>
  <plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
      <instructions>
        <Private-Package>my.private.package.*</Private-Package>
      </instructions>
    </configuration>
  </plugin>
</plugins>

这应该检查您的代码并添加导入,以获取不在私有"包范围内的任何内容.要完成这项工作,您应该做的另一件事是将packaging类型设置为bundle.

This should inspect your code and add imports for anything that is not inside your "private" package scope. One other thing you should do to make this work is to set the packaging type to bundle.

<packaging>bundle</packaging>

但是,上面的示例是将Maven用作构建工具时的情况.如果您使用的是Gradle,则可以使用 Gradle OSGi插件来构建清单.或者,如果使用Ant,则可以使用 SpringSource Bundlor项目(顺便说一句,它也有一个Maven插件).

But, the examples above is when you are using Maven as a build tool. If you are using Gradle, you can use the Gradle OSGi plugin to build manifest. Or, if using Ant you can use SpringSource Bundlor project (btw, which also has a Maven plugin).

这篇关于如何在OSGI框架中的运行时动态加载Java类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆