`

Karaf开发中的Package uses conflict问题解决思路

阅读更多

问题现象

   目前在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前需要安装Java SE开发包1.5x或者以上版本,推荐使用环境变量JAVA_HOME指向Java的安装路径。 - Maven 2.2.1或更高版本也是安装Karaf所必需的。在Windows下,构建Karaf的推荐方式是进入到Karaf源码发布...

    Karaf在Eclispe中的启动环境

    标题中的“Karaf在Eclipse中的启动环境”指的是如何在Eclipse集成开发环境中配置和启动Apache Karaf,一个流行的开源OSGi容器。Apache Karaf是一个轻量级的应用服务器,广泛用于构建、部署和管理Java模块化应用。它...

    karaf使用配置文档

    在本文中,我们将深入探讨Karaf的运行环境、内置命令、骨架使用,以及bundle和feature的开发与部署流程。同时,我们也会提及与Karaf配合使用的Maven私有库Archiva的搭建。 **一、Karaf运行环境** Apache Karaf可以...

    karaf cxf

    本文将详细介绍如何在 Karaf 容器中引入 CXF 以及遇到问题时的解决方案。 #### 二、准备工作 1. **下载 Apache Karaf 4.2.0**: - 访问 Apache 官方网站或使用其他可靠途径下载 Apache Karaf 4.2.0。 - 下载完成...

    apache-karaf-4.0.0

    源代码分析可以帮助开发者深入理解Karaf的工作原理,学习如何配置和扩展容器,以及如何在OSGi环境中开发和管理应用程序。这些源码可能包括核心组件、模块、配置文件和示例应用,它们可以作为学习和调试的基础。 ...

    Learning Apache Karaf 配套源码

    从"2048EN_CodeBundle"这个文件名来看,这可能是一个示例代码库,包含了一些与2048游戏相关的实现,用于演示如何在Apache Karaf环境中开发和部署应用程序。通过这些源码,你可以学习到如何将一个应用程序打包为OSGi...

    osgi集成servlet在karaf容器发布

    同时,Karaf的日志输出可以帮助我们调试和解决问题。 总结来说,将Servlet集成到OSGi的Karaf容器中发布REST接口涉及到创建OSGi Bundle、注册Servlet服务、配置Jetty、部署Bundle、设置URL映射等多个环节。这样的...

    karaf 手册和入门资料

    1. **创建新的捆绑包**:开发人员可以创建自己的 OSGi 捆绑包,并利用 Karaf 的热部署特性将其部署到运行时环境中。 2. **扩展 Karaf Shell**:开发者可以通过创建自定义命令来扩展 Karaf 控制台的功能。 3. **利用...

    learning Apache Karaf 配套源码

    在阅读“learning Apache Karaf.pdf”时,结合源码实践,你将能够掌握如何有效地利用Apache Karaf构建和管理复杂的应用程序生态系统,尤其是在微服务架构和云环境中的应用。通过学习和掌握这些内容,你将提升自己在...

    karaf decanter 示例

    在这个"decanter示例"中,我们将深入探讨Decanter的功能,以及如何根据Karaf网站文档来构建和修正项目中的问题。 Decanter的主要功能包括: 1. **系统监控**:通过收集和分析系统的各种指标(如CPU使用率、内存...

    apache-karaf-2.3.5

    Apache Karaf是一个开源的、基于OSGi(Open Service ...通过其丰富的特性、强大的社区支持以及与各种框架的集成,Apache Karaf在企业级应用开发中扮演了重要角色。无论是小型项目还是大型企业系统,都可以从中受益。

    distribution-karaf-0.3.0-Lithium.zip

    标题中的“distribution-karaf-0.3.0-Lithium.zip”是一个软件分发包,基于Apache Karaf,版本号为0.3.0,代号为Lithium。Apache Karaf是一款流行的开源OSGi容器,常用于构建、部署和管理Java应用程序,尤其在企业级...

    Learning Karaf Cellar

    Karaf因其灵活性和高效性被广泛应用于企业级应用开发中。 #### 三、Karaf Cellar的作用 Karaf Cellar是Karaf的一个子项目,主要关注于实现集群功能。它通过一系列的插件和服务,使得多个Karaf实例能够协同工作,...

    apache karaf 2.3.4(Windows版本)

    Apache Karaf是Apache软件基金会开发的一个轻量级OSGi容器,它主要用于构建、部署和管理Java应用程序。在Windows环境下,Apache Karaf提供了便捷的运行方式,使得开发者可以在该平台上快速地进行开发和测试工作。...

    [Apache Karaf] Apache Karaf 学习教程 (英文版)

    [Packt Publishing] Apache Karaf 学习教程 (英文版) [Packt Publishing] Learning Apache Karaf (E-Book) ☆ 图书概要:☆ Develop and deploy applications using the OSGi-based runtime container, Apache ...

    Apache Karaf User's Guide 2.2.8

    Apache Karaf用户指南2.2.8版是针对...Apache Karaf的这些特性使得它成为开发和部署分布式系统、微服务架构以及企业级应用的理想平台。用户可以通过本手册学习如何有效地利用这些特性,管理和运维自己的Karaf环境。

    karaf启动脚本

    Karaf提供了一个轻量级的环境,特别适用于开发云服务、微服务或IoT(物联网)设备上的应用。Karaf的主要特点包括: - **轻量级**:占用资源少。 - **模块化**:基于OSGi框架构建。 - **可扩展性**:支持动态添加和...

    apache-karaf-3.0.9.tar.gz

    10. **热更新**:得益于OSGi的特性,Karaf支持模块的热更新,无需重启整个系统就能更新或修复问题。 在解压"apache-karaf-3.0.9.tar.gz"后,你通常会得到一个名为"apache-karaf-3.0.9"的目录,其中包括配置文件、库...

Global site tag (gtag.js) - Google Analytics