问题现象
目前在OSGi环境中记录log日志有很多选择,用的最多的应该是slf4j,针对slf4j的增强也很多,像eclipse/equinox环境中采用logback,karaf中采用pax-logging。
因为没有注意到pax-logging-api的bundle里导出了org.slf4j(包括多个版本),我在karaf(karaf运行时采用pax-logging-api)中碰到org.slf4j.impl的package use conflict异常,如下:
Unable to execute command on bundle 100: The bundle "slf4j.api_1.7.5 [100]" could not be resolved. Reason: Package uses conflict: Import-Package: org.slf4j.impl; version="1.7.0"
此时我的bundle列表如下:
21 | Active | 8 | 1.7.1 | OPS4J Pax Logging - API 100 | Installed | 30 | 1.7.5 | slf4j-api 101 | Installed | 30 | 1.7.5 | jul-to-slf4j 102 | Active | 30 | 1.0.13 | Logback Classic Module 103 | Active | 30 | 1.0.13 | Logback Core Module
问题产生原因
在我的系统里,karaf因为集成了eclipse virgo项目,所以log服务bundle包括pax-logging、logpack和slf4j都出现了,正是因为这样,才产生了package冲突问题。
关于包冲突的根源解释请参考OSGi规范和这篇Diagnosing OSGi uses conflicts文章。
简单理解如下:
系统中存在多个bundle(b1、b2)导出相同的package包A,同时bundle(b3)要导入相同名称的包A,OSGi框架在解析时,第一解析到的导出包A的bundle(b1)如果其导入也已经满足,即处于Resolved状态,则后续的bundle(b3)导入包A时,优先导入b1导出的包A。此时,如果bundle(b3)导出包B,而包B需要use包A,则其他bundle(b5)需要导入b2的包A,同时也导入包B时,将产生包冲突。
在karaf下解决问题的办法
知道了问题产生的原因,现在整理解决思路:第一步,找到导出org.slf4j.impl的bundle,找到导入org.slf4j.impl的bundle;第二步,确定各个相关bundle导入导出的版本;第三步,解决具体问题。
首先,看第一步,在karaf的命令行输入:
package:exports
输出如下:
…… org.slf4j.bridge | 1.7.5 | 101 | jul.to.slf4j org.slf4j.helpers | 1.4.3 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j.helpers | 1.5.11 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j.helpers | 1.6.6 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j.helpers | 1.7.1 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j.helpers | 1.7.5 | 100 | slf4j.api org.slf4j.impl | 1.7.5 | 102 | ch.qos.logback.classic org.slf4j.spi | 1.4.3 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j.spi | 1.5.11 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j.spi | 1.6.6 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j.spi | 1.7.1 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j.spi | 1.7.5 | 100 | slf4j.api org.slf4j | 1.4.3 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j | 1.5.11 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j | 1.6.6 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j | 1.7.1 | 21 | org.ops4j.pax.logging.pax-logging-api org.slf4j | 1.7.5 | 100 | slf4j.api ……
从导出列表中可以看到,导出org.slf4j.impl的bundle只有ch.qos.logback.classic,而导出org.slf4j的有两个bundle,分别是pax-logging-api和slf4j.api。
现在看导入,在karaf命令行输入:
package:imports
输出如下:
(&(osgi.wiring.package=org.slf4j)(&(version>=1.5.0)(!(version>=2.0.0)))) | | 37 | org.apache.aries.blueprint.cm | true (&(osgi.wiring.package=org.slf4j)(&(version>=1.6.0)(!(version>=2.0.0)))) | | 23 | org.apache.mina.core | true (&(osgi.wiring.package=org.slf4j)(&(version>=1.7.0)(!(version>=2.0.0)))) | | 123 | org.eclipse.virgo.kernel.model | true (&(osgi.wiring.package=org.slf4j)(version>=1.5.0)) | | 53 | org.ops4j.pax.url.commons | true (&(osgi.wiring.package=org.slf4j)(version>=1.7.0)) | | 102 | ch.qos.logback.classic | true (&(osgi.wiring.package=org.slf4j)(version>=1.7.5)) | | 101 | jul.to.slf4j | true (&(osgi.wiring.package=org.slf4j)) | optional | 127 | org.apache.felix.http.jetty | true (&(osgi.wiring.package=org.slf4j.bridge)(&(version>=1.7.0)(!(version>=2.0.0)))) | | 105 | org.eclipse.virgo.medic.core | true (&(osgi.wiring.package=org.slf4j.helpers)(&(version>=1.7.0)(!(version>=2.0.0)))) | | 105 | org.eclipse.virgo.medic.core | true (&(osgi.wiring.package=org.slf4j.helpers)(version>=1.7.0)) | | 102 | ch.qos.logback.classic | true (&(osgi.wiring.package=org.slf4j.impl)(version>=1.7.0)) | | 102 | ch.qos.logback.classic | true (&(osgi.wiring.package=org.slf4j.spi)(version>=1.7.0)) | | 102 | ch.qos.logback.classic | true (&(osgi.wiring.package=org.slf4j.spi)(version>=1.7.5)) | | 101 | jul.to.slf4j | true
从导入看,logback.classic在导出org.slf4j.impl的同时需要导入org.slf4j。因slf4j.api处于Installed状态无法看到其导入。
查看slf4j.api的bundle头信息,在karaf命令行输入:
Bundle:headers 100
输出如下:
Bundle-Name = slf4j-api Bundle-Description = The slf4j API Bundle-SymbolicName = slf4j.api Bundle-Version = 1.7.5 Bundle-ManifestVersion = 2 Import-Package = org.slf4j.impl; version=1.6.0 Export-Package = org.slf4j; version=1.7.5, org.slf4j.spi; version=1.7.5, org.slf4j.helpers; version=1.7.5
查看logback.classic的bundle头信息,输出如下:
org.slf4j.impl; uses:="org.slf4j.spi, ch.qos.logback.core.status, ch.qos.logback.classic.util, org.slf4j.helpers, ch.qos.logback.classic, ch.qos.logback.core, ch.qos.logback.classic.selector, ch.qos.logback.core.joran.spi, org.slf4j, ch.qos.logback.core.util"; version=1.7.5
通过上述诊断,结合包冲突的原理,可以看出,
1)pax-logging-api在karaf中优先级别高于slf4j.api,此时OSGi框架已经识别到org.slf4j包;
2)在解析slf4j.api时,因slf4j.api需要导入org.slf4j.impl,而其之前没有bundle导出slf4j.impl,所以其解析状态不能变为Resolved;
3)当解析到logback.classic时,此bundle导出了slf4j.impl,但其同时use包org.slf4j,因此logback.classic优先导入pax-logging-api导出的org.slf4j包。
4)此时在其解析slf4j.api时,slf4j.api本身导出的org.slf4j与其导入org.slf4j.impl所在的logback.classic所导入的pax logging中的org.slf4j冲突。
相关推荐
apache karaf 中文文档,非常适合入门的手册,思路清晰,
该文档描述演示了karaf中cxf的引入及其错误解决方法。
karaf运行环境 karaf内置命令 karaf骨架使用 bundle、feature开发及部署流程 maven私服搭建
个人对学习karaf还是有一定帮助的,好东西大家一起分享。
karaf框架,开发OSGI必备利器
[Packt Publishing] Apache Karaf 学习教程 (英文版) [Packt Publishing] Learning Apache Karaf (E-Book) ☆ 图书概要:☆ Develop and deploy applications using the OSGi-based runtime container, Apache ...
Learning Apache Karaf 配套源码 Learning Apache Karaf 配套源码
karaf 手册和入门资料
java 模块化,关于karaf的资源 内容: apache-karaf-4.2.0.tar.gz karaf-DEV_GUIDE.zip karaf-master.zip Karaf-Microservices-master.zip karaf-springboot-master.zip os-osgiblueprint-sample.zip
Develop and deploy applications using the OSGi-based runtime container, Apache Karaf Overview Understand Apache Karaf’s commands and control capabilities Gain familiarity with its provisioning ...
learning Apache Karaf.pdf 相应的源码
Karaf是Apache旗下的一个开源项目.Karaf同时也是一个基于OSGi的运行环境,Karaf提供了一个轻量级的OSGi容器,可以用于部署各种组件,应用程序.Karaf提供了很多特性用于帮助开发者和用户更加灵活的部署应用,例如:热部署,...
decanter示例,根据karaf网站文档构建项目,文档中存在一系列的问题,在本项目中已经进行过修正。
介绍osgi 轻量级容器,KARAF 。使用
Learning Karaf Cellar
自己写的一段重启karaf的自动化脚本,希望对大家有帮助。
karaf-recipes Karaf 3.0.3 的 Karaf 项目的基本配方。 包括 OSGI 服务、REST 服务、ui、kar 应用程序和分发的示例我该如何设置? 从根目录运行“mvn clean install” 将 tar.gz 文件从“distro/target”文件夹复制...
一个基于OSGi的运行环境,Karaf提供了一个轻量级的OSGi容器,可以用于部署各种组件
标签:activemq-karaf-5.9.0-javadoc.jar,activemq,karaf,5.9.0,javadoc,jar包下载,依赖包
distribution-karaf-0.3.0-Lithium.zip