简体   繁体   English

如何在OSGI框架中的Runtime动态加载Java类?

[英]How to dynamically load Java classes at Runtime in OSGI framework?

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. 我们正在项目中执行POC,我们在其中发送基于SOAP的请求,并相应地从Web服务获取SOAP响应。 We aim to leverage webservices template (client side API) provided by spring framework in our application. 我们的目标是在我们的应用程序中利用spring框架提供的webservices模板(客户端API)。 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. 根据我们的架构,我们创建一个OSGI兼容的包(对于我们使用webservices模板API与Web服务交互的代码),然后将其部署到Apache Felix容器中。 We have also installed all the dependent OSGI compliant bundles in the Felix container so that all the dependencies are resolved. 我们还在Felix容器中安装了所有依赖于OSGI的捆绑包,以便解决所有依赖关系。

As per the webservices template, the default Web Service Message sender is HttpUrlConnectionMessageSender which is dynamically loaded at run time by the class loader. 根据webservices模板,默认Web服务消息发送方是HttpUrlConnectionMessageSender,它由类加载器在运行时动态加载。 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. 根据我的理解,我们得到以下异常,因为Felix容器无法从依赖的OSGI包加载类(Web服务包包含HttpUrlConnectionMessageSender)。请参阅下面的异常日志。

* 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)

Caused by: java.lang.ClassNotFoundException: org.springframework.ws.transport.http.HttpUrlConnectionMessageSender 引起: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)

As per my understanding,Felix container is unable to dynamically load the class using ClassUtils.forName() which exists in another bundle. 根据我的理解,Felix容器无法使用存在于另一个包中的ClassUtils.forName()动态加载类。 I see this as a collaboration issue where the current bundle has a different class loader as opposed to class loader of dependent bundle. 我认为这是一个协作问题,当前的bundle有一个不同的类加载器,而不是依赖bundle的类加载器。

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. 请分享您的想法/指示以解决上述问题。快速回复将受到高度赞赏,并可能有助于我们使我们的POC成功。

Thanks in advance, Mridul Chopra 先谢谢,Mridul Chopra

Classloading in the form of Class.forName() is not a problem in any OSGi container. Class.forName()形式的类加载在任何OSGi容器中都不是问题。 You problem here is that the MANIFEST.MF file does not contain the right import declarations. 这里的问题是MANIFEST.MF文件不包含正确的导入声明。 One bundle should export the org.springframework.ws.transport package, while your bundle should import the same package. 一个bundle应该导出org.springframework.ws.transport包,而你的bundle应该导入相同的包。

If you are using Maven to build your bundle, you can use the Felix Bundle Plugin to generate the right manifest information. 如果您使用Maven构建捆绑包,则可以使用Felix Bundle Plugin生成正确的清单信息。

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

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>bundle</packaging>

But, the examples above is when you are using Maven as a build tool. 但是,上面的示例是当您使用Maven作为构建工具时。 If you are using Gradle, you can use the Gradle OSGi plugin to build manifest. 如果您使用的是Gradle,则可以使用Gradle OSGi插件来构建清单。 Or, if using Ant you can use SpringSource Bundlor project (btw, which also has a Maven plugin). 或者,如果使用Ant,您可以使用SpringSource Bundlor项目 (btw,它也有一个Maven插件)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM