我们一直在使用OSGI和Jboss 7.0.1,并且有多个bundle支持我们的应用程序 . 我们正在尝试调整Major.Minor.Micro的版本控制策略,以用于基于接口服务实现消费者的模型,但似乎我们的策略可能不正确 .
当我们提升api和服务的次要版本时,消费者无法使用新服务而无需进行包刷新 .
下面是用例 .
包 com.helloworld.api 从包 Helloworld API (接口包)以1.0.0版导出
public interface IHelloService {
public void sayHello(String abc);
}
Helloworld API 的清单文件
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Helloworld API
Bundle-SymbolicName: exp1.com.helloworld.api
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.helloworld.internal.Activator
Bundle-Vendor: ABC
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.osgi.framework;version="1.3.0",
org.osgi.util.tracker;version="1.4.0"
Bundle-ClassPath: .
Export-Package: com.helloworld.api;version="1.0.0"
由 Helloworldservice 实现 HelloServiceImpl
public class HelloServiceImpl implements IHelloService {
@Override
public void sayHello(String abc) {
System.out.println(" \n\n ~~~~~~~~~ "+abc+" ~~~~~~~~~ " + " \n\n");
}
}
Helloworldservice 的清单文件
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Helloworldservice
Bundle-SymbolicName: exp1.com.helloworld.service
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.helloworldservice.internal.Activator
Bundle-Vendor: ABC
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.helloworld.api;version="1.0.0",
org.osgi.framework;version="1.3.0"
Bundle-ClassPath:
消费者使用捆绑包 Consumer Service 消费(使用服务跟踪器或Google Guice方法) . 它继续在循环中调用sayHello .
HelloWorldServiceProxy.getInstance().getHelloWorldService().sayHello("abc " + "Index" + i);
Consumer Service 的清单文件
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Consumer Service
Bundle-SymbolicName: exp1.com.consumer
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.consumer.internal.Activator
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.helloworld.api;version="1.0.0",
org.osgi.framework;version="1.3.0",
org.osgi.util.tracker;version="1.4.0"
之后我们对api进行修改并添加新方法 . 这导致将次要版本提升到1.1.0 . 为了支持这一点,我们在服务中实现了新方法,但期望消费者不受影响 .
package com.helloworld.api 从bundle Helloworld API 导出版本1.1.0
public interface IHelloService {
public void sayHello(String abc);
public void sayHello(String abc, String def, int a);
}
Helloworld API 的清单文件
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Helloworld API
Bundle-SymbolicName: exp1.com.helloworld.api
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.helloworld.internal.Activator
Bundle-Vendor: ABC
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.osgi.framework;version="1.3.0",
org.osgi.util.tracker;version="1.4.0"
Bundle-ClassPath: .
Export-Package: helloworld.api;version="1.1.0"
由捆绑 Helloworldservice 实现 HelloServiceImpl
public class HelloServiceImpl implements IHelloService {
@Override
public void sayHello(String abc) {
System.out.println(" \n\n ~~~~~~~~~ "+abc+" ~~~~~~~~~ " + " \n\n");
}
@Override
public void sayHelloNew(String abc, String def, int a) {
System.out.println(" \n\n ~~~~~~~~~ "+abc+" NEW METHOD ### WITH CHANGE ### ~~~~~~~~~ " + abc +" " + def +" \n\n");
}
}
显示文件
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Helloworldservice
Bundle-SymbolicName: exp1.com.helloworld.service
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.helloworldservice.internal.Activator
Bundle-Vendor: ABC
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.helloworld.api;version="1.1.0",
org.osgi.framework;version="1.3.0"
Bundle-ClassPath:
但是,现在当我们部署HelloWorld Api和HelloWorld Service捆绑包时,使用者捆绑包无法开始使用随包1.1.0导出的新服务 . 我们不得不刷新消费者捆绑包以使其工作 .
我们在这里做错了吗?
到目前为止,我们一直在部署没有任何版本的新捆绑包(默认为0.0.0) . 部署具有相同软件包修订版的新软件包适用于微更改,但在我们从Jboss执行全局软件包刷新之前,任何方法签名更改或新方法使用都会导致NoSuchMethod异常 . 这就是我们决定使用Jboss版本策略的原因 .
1 回答
安装/更新新捆绑包后,您应该始终刷新 . 没有例外 . 刷新未与更新/安装集成的唯一原因是您现在可以在刷新之前安装/更新多个软件包 .
我对你的例子也有点疑惑 . 你谈到语义版本控制,但你的导入是从[1.3.0,∞),所以没有语义版本? (它还有助于删除大多数 Headers 之类的不必要信息 . )
那么最佳做法是什么?
首先,服务由包定义 . 对于此服务,您可以使用两种类型的接口:由使用者实现的接口和由提供者实现的接口 . 对于主要的释放凹凸,仅在非向后兼容时更改用户界面 . 提供者界面在次要释放凹凸上被破坏 . (major.minor.micro)OSGi支持接口的@ConsumerType(默认)和@ProviderType注释 .
如果您使用bnd,则会自动获得导入范围 . 即如果你的
IHello
(最好不要附加服务)从1.0开始:由于默认情况下这是@ConsumerType,我们将获得以下导入:
但是,IHello接口可能代表提供者 . 所以我们应该用@ProviderType注释它:
如果您现在编写实现IHello服务的提供程序,则bnd将检测com.example.hello包的版本 . 由于它看到你实现它,它将写出以下导入:
如果我们编写了IHello服务的客户端,我们的导入将是[1.0,2] .
如果我们现在向IHello添加一个方法,我们应该将版本提升到1.1,因为IHello是一个@ProviderType . (如果它是@ConsumerType,我们将被迫将其提升到2.0)
我们现在有效地打破了IHello服务的提供者,这正是我们想要的!这将阻止调用由针对1.0编译的实现支持的1.1服务 .
摘要:
安装/更新后必须进行
refresh .
二手bnd