我们一直在使用OSGI和Jboss 7.0.1,并且有多个软件包支持我们的应用程序。我们正在尝试调整Major.Minor.Micro的版本控制策略,以实现接口+服务实现+基于消费者的模型,但似乎我们的策略可能不正确。
当我们提升api和服务的次要版本时,消费者无法使用新服务而无需进行包刷新。
以下是用例。
包 com.helloworld.api 从bundle 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:
消费者从捆绑消费者服务(使用服务跟踪器或Google Guice方法)消费。它继续在循环中调用sayHello。
HelloWorldServiceProxy.getInstance().getHelloWorldService().sayHello("abc " + "Index" + i);
消费者服务的清单文件
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.0public 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服务包时,使用者服务包无法开始使用随包1.1.0导出的新服务。我们不得不刷新消费者包以使其有效。
我们在这里做错了吗?
到目前为止,我们一直在部署没有任何版本的新捆绑包(默认为0.0.0)。部署具有相同软件包修订版的新软件包适用于微更改,但在我们从Jboss执行全局软件包刷新之前,任何方法签名更改或新方法使用都会导致NoSuchMethod异常。这就是我们决定使用Jboss版本策略的原因。
答案 0 :(得分:0)
安装/更新新捆绑包后,您应该始终刷新。没有例外。刷新未与更新/安装集成的唯一原因是您现在可以在刷新之前安装/更新多个软件包。
我对你的例子也有点疑惑。你谈到语义版本控制,但你的导入是从[1.3.0,∞),所以没有语义版本? (它还有助于删除大多数标题之类的不必要信息。)
那么最佳做法是什么?
首先,服务由包定义。对于此服务,您可以使用两种类型的接口:使用者实现的接口和提供者的接口。对于主要的释放凹凸,仅在非向后兼容时更改用户界面。提供者界面在次要释放凹凸上被破坏。 (major.minor.micro)OSGi支持接口的@ConsumerType(默认)和@ProviderType注释。
如果您使用bnd,则会自动获得导入范围。即如果你的IHello
(最好不要附加服务)从1.0开始:
IHello.java:
package com.example.hello;
public interface IHello {
void sayHell();
}
@Version("1.0.0")
package-info.java:
import org.osgi.annotation.versioning.Version;
由于默认情况下这是@ConsumerType,我们将获得以下导入:
Import-Package: com.example.hello;version='[1.0,2)'
但是,IHello界面可能代表提供者。所以我们应该用@ProviderType注释它:
IHello.java:
package com.example.hello;
import org.osgi.annotation.versioning.ProviderType;
@ProviderType
public interface IHello {
void sayHell();
}
如果您现在编写实现IHello服务的提供程序,则bnd将检测com.example.hello包的版本。由于它看到你实现它,它将写出以下导入:
Import-Package: com.example.hello;version='[1.0,1.1)'
如果我们编写了IHello服务的客户端,我们的导入将是[1.0,2]。
如果我们现在向IHello添加一个方法,我们应该将版本提升到1.1,因为IHello是一个@ProviderType。 (如果它是@ConsumerType,我们将被迫将其提升为2.0)
package-info.java:
@Version("1.1.0")
package-info.java:
import org.osgi.annotation.versioning.Version;
IHello.java:
package com.example.hello;
import org.osgi.annotation.versioning.ProviderType;
@ProviderType
public interface IHello {
void sayHell();
void sayHello(String s);
}
我们现在有效地打破了IHello服务的提供者,这正是我们想要的!这将阻止调用由针对1.0编译的实现支持的1.1服务。
摘要: