简体   繁体   English

在 Apache Felix 上部署 OSGi

[英]OSGi deployment on Apache Felix

I have created my first OSGi service and was trying to deploy it on Apache Felix.我已经创建了我的第一个 OSGi 服务,并试图将它部署在 Apache Felix 上。 When I looked at the system console afterwards I saw that the service was not active and some problems occured:后来查看系统控制台,发现服务没有激活,出现了一些问题:

org.springframework.ws.client.core,version=[2.1,3) -- Cannot be resolved
org.springframework.ws.soap,version=[2.1,3) -- Cannot be resolved
org.springframework.ws.soap.axiom,version=[2.1,3) -- Cannot be resolved
org.springframework.ws.soap.saaj,version=[2.1,3) -- Cannot be resolved

So I looked which jar contained these packages and this comes from spring-ws-core-2.1.2.RELEASE.jar, which is also an OSGi bundle.所以我查看了哪个 jar 包含这些包,这来自 spring-ws-core-2.1.2.RELEASE.jar,它也是一个 OSGi 包。 I deployed that one as well but then again the following error messages occurred:我也部署了那个,但又出现了以下错误消息:

org.springframework.web.servlet,version=[3.1.0, 4.0.0) -- Cannot be resolved

Again a dependency, this time on spring-webmvc-3.2.17.RELEASE.jar.再次依赖,这次是在 spring-webmvc-3.2.17.RELEASE.jar 上。 The problem however is that this one is not an OSGi bundle, how do I solve this issue then?然而,问题是这不是 OSGi 包,那么我该如何解决这个问题呢? Since it is a third party library there is not much I can think of.由于它是第三方库,因此我能想到的不多。

So how can I use non bundle jars in an OSGi container?那么如何在 OSGi 容器中使用非捆绑 jars 呢? And how can I automatically resolve the dependency tree to not having to resolve everything by hand?以及如何自动解决依赖树而不必手动解决所有问题?

I have created the osgi-run project to address this very issue of solving bundles dependencies using the standard Maven dependency resolution (instead of OBR which is not widely supported, unfortunately), supported by Gradle.我创建了osgi-run项目来解决这个问题,即使用标准的 Maven 依赖项解析(而不是没有广泛支持的 OBR,不幸的是)解决这个问题,由 Gradle 支持。

However, the Spring jars are a terrible nightmare to resolve since the Spring Project abandoned support for OSGi, several years ago.然而,Spring jar 是一个可怕的噩梦,因为几年前 Spring 项目放弃了对 OSGi 的支持。

In theory, with osgi-run, you should be able to create a OSGi environment containing the spring-ws-core bundle by using the following gradle file:理论上,使用 osgi-run,您应该能够使用以下 gradle 文件创建包含 spring-ws-core 包的 OSGi 环境:

plugins {
    id "com.athaydes.osgi-run" version "1.5.1"
}

repositories {
    mavenLocal()
    jcenter()
}

dependencies {
    osgiRuntime 'org.springframework.ws:spring-ws-core:2.1.1.RELEASE'
}

This relies on the information in the poms being consistent.这依赖于 poms 中的信息是一致的。 And if any non-bundle is found, it is automatically converted into a OSGi bundle (see wrapping jars ).如果发现任何非捆绑包,它会自动转换为 OSGi 捆绑包(参见wrapping jars )。

However, this is not working... Gradle can print the dependency hierarchy for the spring-ws-core jar, and here's what I get when I use that:但是,这不起作用...... Gradle 可以打印 spring-ws-core jar 的依赖层次结构,这是我使用它时得到的:

+--- org.springframework.ws:spring-ws-core:2.1.1.RELEASE
|    +--- org.springframework.ws:spring-xml:2.1.1.RELEASE
|    |    +--- org.springframework:spring-context:3.1.2.RELEASE
|    |    |    +--- org.springframework:spring-aop:3.1.2.RELEASE
|    |    |    |    +--- aopalliance:aopalliance:1.0
|    |    |    |    +--- org.springframework:spring-asm:3.1.2.RELEASE
|    |    |    |    +--- org.springframework:spring-beans:3.1.2.RELEASE
|    |    |    |    |    \--- org.springframework:spring-core:3.1.2.RELEASE
|    |    |    |    |         +--- org.springframework:spring-asm:3.1.2.RELEASE
|    |    |    |    |         \--- commons-logging:commons-logging:1.1.1
|    |    |    |    \--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    |    |    +--- org.springframework:spring-beans:3.1.2.RELEASE (*)
|    |    |    +--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    |    |    +--- org.springframework:spring-expression:3.1.2.RELEASE
|    |    |    |    \--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    |    |    \--- org.springframework:spring-asm:3.1.2.RELEASE
|    |    +--- commons-logging:commons-logging:1.1.1
|    |    +--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    |    \--- org.springframework:spring-beans:3.1.2.RELEASE (*)
|    +--- org.springframework:spring-context:3.1.2.RELEASE (*)
|    +--- org.springframework:spring-aop:3.1.2.RELEASE (*)
|    +--- org.springframework:spring-oxm:3.1.2.RELEASE
|    |    +--- commons-lang:commons-lang:2.5
|    |    +--- org.springframework:spring-beans:3.1.2.RELEASE (*)
|    |    +--- org.springframework:spring-context:3.1.2.RELEASE (*)
|    |    \--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    +--- org.springframework:spring-web:3.1.2.RELEASE
|    |    +--- aopalliance:aopalliance:1.0
|    |    +--- org.springframework:spring-beans:3.1.2.RELEASE (*)
|    |    +--- org.springframework:spring-context:3.1.2.RELEASE (*)
|    |    \--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    +--- org.springframework:spring-webmvc:3.1.2.RELEASE
|    |    +--- org.springframework:spring-asm:3.1.2.RELEASE
|    |    +--- org.springframework:spring-beans:3.1.2.RELEASE (*)
|    |    +--- org.springframework:spring-context:3.1.2.RELEASE (*)
|    |    +--- org.springframework:spring-context-support:3.1.2.RELEASE
|    |    |    +--- org.springframework:spring-beans:3.1.2.RELEASE (*)
|    |    |    +--- org.springframework:spring-context:3.1.2.RELEASE (*)
|    |    |    \--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    |    +--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    |    +--- org.springframework:spring-expression:3.1.2.RELEASE (*)
|    |    \--- org.springframework:spring-web:3.1.2.RELEASE (*)
|    +--- wsdl4j:wsdl4j:1.6.1
|    +--- commons-logging:commons-logging:1.1.1
|    +--- org.springframework:spring-core:3.1.2.RELEASE (*)
|    \--- org.springframework:spring-beans:3.1.2.RELEASE (*)

I thought there could be some bug in the dependency resolution because it seems that Spring 2 jars are mixed up with Spring 3 jars, according to the resolved dependencies graph above!我认为依赖解析中可能存在一些错误,因为根据上面解析的依赖关系图,似乎 Spring 2 jar 与 Spring 3 jar 混合在一起! But no... it's exactly right .但是不…… 完全正确

But anyway, I got this working after some investigation...但无论如何,经过一番调查,我得到了这个工作......

Investigating unmet bundle requirements调查未满足的捆绑需求

First of all, I noticed that Spring AOP did not resolve because of its org.aopalliance.aop requirement.首先,我注意到 Spring AOP 没有解决,因为它的org.aopalliance.aop要求。

This should come, obviously, from the aopalliance jar (which is not a bundle, at least not the one in Maven Central/JCenter).显然,这应该来自 aopalliance jar(它不是一个包,至少不是 Maven Central/JCenter 中的那个)。

I added this instruction inside the runOsgi block in the Gradle file, so that I could see how osgi-run wrapped the jar into a bundle:我在 Gradle 文件的runOsgi块中添加了这条指令,以便我可以看到osgi-run如何将 jar 打包成一个包:

wrapInstructions {
    printManifests = true
}

Running gradle clean createOsgi again, the manifest gets printed... it looks like this:再次运行gradle clean createOsgi ,清单被打印出来......它看起来像这样:

--------------------------------- Manifest for aopalliance-1.0.jar ---------------------------------
Manifest-Version: 1.0
Bundle-SymbolicName: aopalliance
Bundle-ManifestVersion: 2
Bnd-LastModified: 1474120107912
Import-Package: org.aopalliance.aop
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.3))"
Tool: Bnd-3.1.0.201512181341
Ant-Version: Apache Ant 1.5.4 
Originally-Created-By: 1.4.2_01-b06 (Sun Microsystems Inc.)
Export-Package: org.aopalliance.aop,org.aopalliance.intercept;uses:="o
 rg.aopalliance.aop"
Bundle-Version: 1.0.0
Bundle-Name: aopalliance
Created-By: 1.8.0_60 (Oracle Corporation)

----------------------------------------------------------------------------------------------------

Notice that there is a correctly generated Bundle-Version , but the packages are not exported with that version... by adding the instruction below, we can force the packages to be exported with a version:请注意,有一个正确生成的Bundle-Version ,但包没有与该版本一起导出......通过添加以下指令,我们可以强制使用版本导出包:

wrapInstructions {
    printManifests = true
    manifest( 'aopalliance.*' ) {
        instruction 'Export-Package', '*;version=1.0'
    }
}

Now, the Export-Package instruction in the manifest is correct:现在,清单中的Export-Package指令是正确的:

Export-Package: org.aopalliance.aop;version="1.0",org.aopalliance.inte
rcept;version="1.0";uses:="org.aopalliance.aop"

And running the OSGi container, we see that the Spring AOP bundle still does not resolve, but now the only problem is because its (&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0))) requirement is not satisfied.然后运行 ​​OSGi 容器,我们看到 Spring AOP bundle 仍然没有解决,但是现在唯一的问题是因为它的(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))要求不满足。

The commons.logging jar has a known issue ( documented in the osgi-run README page)... it declares optional dependencies, making it hard to wrap automatically. commons.logging jar 有一个已知问题( 记录osgi-run README 页面中)...它声明了可选的依赖项,使其难以自动包装。

But additionally, the commons.logging jar has an incorrect Specification-Version in the manifest.但此外, commons.logging jar 在清单中的Specification-Version不正确。 It says 1.0 instead of 1.1.1 , and that's what osgi-run uses for the bundle version, so Bundle-Version gets the incorrect value.它说1.0而不是1.1.1 ,这就是osgi-run用于捆绑版本的内容,因此Bundle-Version获得了不正确的值。

By also forcing osgi-run to export the packages with the correct version, the wrapping works correctly and the Spring AOP starts up correctly:通过还强制osgi-run导出具有正确版本的包,包装工作正常并且 Spring AOP 正确启动:

manifest( /commons-logging.*/ ) {
    instruction 'Import-Package', '!javax.servlet,!org.apache.*,*'
    instruction 'Export-Package', '*;version=1.1.1'
}

Now, moving on to the next issue, we notice that org.springframework.web does not resolve because of its requirement on (&(osgi.wiring.package=javax.servlet)(version>=2.4.0)(!(version>=4.0.0))) .现在,继续下一个问题,我们注意到org.springframework.web没有解决,因为它要求(&(osgi.wiring.package=javax.servlet)(version>=2.4.0)(!(version>=4.0.0)))

This one is easy, add the servlet-api bundle (provided by Felix) to the OSGi runtime and it should work... Just add this dependency in the Gradle file:这个很简单,将 servlet-api 包(由 Felix 提供)添加到 OSGi 运行时,它应该可以工作......只需在 Gradle 文件中添加这个依赖项:

osgiRuntime 'org.apache.felix:org.apache.felix.http.servlet-api:1.1.2'

Now, the OSGi environment starts up without any failures!现在,OSGi 环境启动没有任何故障!

Final solution最终解决方案

Here's the full set of bundles installed:这是安装的全套捆绑包:

   ID|State      |Level|Name
    0|Active     |    0|System Bundle (5.4.0)|5.4.0
    1|Active     |    1|aopalliance (1.0.0)|1.0.0
    2|Active     |    1|Commons Lang (2.5.0)|2.5.0
    3|Active     |    1|Jakarta Commons Logging (1.0.0)|1.0.0
    4|Active     |    1|Apache Felix Gogo Command (0.16.0)|0.16.0
    5|Active     |    1|Apache Felix Gogo Runtime (0.16.2)|0.16.2
    6|Active     |    1|Apache Felix Gogo Shell (0.12.0)|0.12.0
    7|Active     |    1|Apache Felix Servlet API (1.1.2)|1.1.2
    8|Active     |    1|Spring AOP (3.1.2.RELEASE)|3.1.2.RELEASE
    9|Active     |    1|Spring ASM (3.1.2.RELEASE)|3.1.2.RELEASE
   10|Active     |    1|Spring Beans (3.1.2.RELEASE)|3.1.2.RELEASE
   11|Active     |    1|Spring Context (3.1.2.RELEASE)|3.1.2.RELEASE
   12|Active     |    1|Spring Context Support (3.1.2.RELEASE)|3.1.2.RELEASE
   13|Active     |    1|Spring Core (3.1.2.RELEASE)|3.1.2.RELEASE
   14|Active     |    1|Spring Expression Language (3.1.2.RELEASE)|3.1.2.RELEASE
   15|Active     |    1|Spring Object/XML Mapping (3.1.2.RELEASE)|3.1.2.RELEASE
   16|Active     |    1|Spring Web (3.1.2.RELEASE)|3.1.2.RELEASE
   17|Active     |    1|Spring Web Servlet (3.1.2.RELEASE)|3.1.2.RELEASE
   18|Active     |    1|Spring Web Services Core (2.1.1.RELEASE)|2.1.1.RELEASE
   19|Active     |    1|Spring XML (2.1.1.RELEASE)|2.1.1.RELEASE
   20|Active     |    1|tomcat-servlet-api (8.0.0)|8.0.0
   21|Active     |    1|JWSDL (1.2.0)|1.2.0

And in case you want to try osgi-run , this is the Gradle file I used:如果您想尝试osgi-run ,这是我使用的 Gradle 文件:

plugins {
    id "com.athaydes.osgi-run" version "1.5.1"
}

repositories {
    mavenLocal()
    jcenter()
}

dependencies {
    osgiRuntime 'org.springframework.ws:spring-ws-core:2.1.1.RELEASE'
    osgiRuntime 'org.apache.felix:org.apache.felix.http.servlet-api:1.1.2'
}

runOsgi {
    wrapInstructions {
        printManifests = true
        manifest( 'aopalliance.*' ) {
            instruction 'Export-Package', '*;version=1.0'
        }
        manifest( /commons-logging.*/ ) {
            instruction 'Import-Package', '!javax.servlet,!org.apache.*,*'
            instruction 'Export-Package', '*;version=1.1.1'
        }
    }
}

Just save this in a build.gradle file, then run gradle createOsgi to get your starter script at build/osgi/run.sh .只需将其保存在build.gradle文件中,然后运行gradle createOsgi以在build/osgi/run.sh获取您的启动脚本。

I will work on osgi-run to try to make things like these get resolved automatically, hopefully in the next version, the first build file shown above will work without further ado.我将在osgi-run上工作以尝试使这些问题自动解决,希望在下一个版本中,上面显示的第一个构建文件将毫不费力地工作。

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

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