2015-11-25 42 views
0

我们一直在使用OSGI和Jboss 7.0.1,并且有多个支持我们应用程序的bundle。我们正在尝试调整Major.Minor.Micro的版本控制策略以适应接口+服务实现+基于消费者的模式,但似乎我们的策略可能并不正确。什么是BKM部署OSGI捆绑包有新的变化?

当我们碰到api和服务的次要版本时,消费者无法使用新服务而无需进行软件包刷新。

下面是用例。

com.helloworld.api从束的Helloworld API(接口束)

public interface IHelloService { 
    public void sayHello(String abc); 
} 

的Helloworld API Menifest文件

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" 

出口与1.0.0版本从开始实施HelloServiceImpl来自包Helloworldservice

public class HelloServiceImpl implements IHelloService { 

@Override 
    public void sayHello(String abc) { 
     System.out.println(" \n\n ~~~~~~~~~ "+abc+" ~~~~~~~~~ " + " \n\n"); 
    } 
} 

Menifest文件的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: 

从束消费者服务(使用服务跟踪器或谷歌吉斯方法)由消费者消耗。它一直呼吁sayHello循环。对于消费者服务

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" 

HelloWorldServiceProxy.getInstance().getHelloWorldService().sayHello("abc " + "Index" + i); 

Menifest文件之后,我们做出修改API,并添加新的方法。这导致将次要版本升级到1.1.0。为了支持这一点,我们实施了新的服务方法,但期望消费者不受影响。

com.helloworld.api从束的Helloworld API导出的与版本1.1.0

public interface IHelloService { 
    public void sayHello(String abc); 
    public void sayHello(String abc, String def, int a); 
} 

Menifest文件为的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" 

通过HelloServiceImpl实施来自包Helloworldservice

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"); 
    } 
} 

Menifest文件

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阿比HelloWorld服务捆绑,消费者包是无法开始使用与包1.1.0导出的新服务。我们不得不刷新消费者包以使其工作。

我们在这里做错了什么?

到目前为止,我们一直在部署没有任何版本的新捆绑包(默认为0.0.0)。使用相同软件包修订部署新软件包对于微小更改工作良好,但在我们从Jboss执行全局软件包刷新之前,任何方法签名更改或新方法使用都会导致NoSuchMethod异常。这就是我们决定使用Jboss版本策略的原因。

+0

BKM是什么意思? –

+0

最好的已知方法:) – Manan

回答

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服务。

摘要:

  • 刷新安装/更新后的强制性。
  • 二手bnd
+0

嗨Kriens,非常感谢您的回复。我想把重点放在单一修改上。因此为了避免复杂性使用这样的版本。我以前没有尝试过providerType和consumerType接口,我会试试看。此外,我们还在小版本崩溃之后对API和API.Service进行了封装刷新,但消费者在刷新之前也没有拿起新服务。你是否也建议对消费者进行包装刷新,即使它没有改变?它不会造成消费者的中断吗? – Manan

+0

因此,基本上,当api导出和服务导入都从1.0.0迁移到1.1.0时,为什么我们不得不在使用1.0.0的消费者上进行包更新?新版本与消费者兼容,不应该能够使用它,而不必在消费者(因为我们在新部署的api和服务上执行包刷新)进行包刷新? – Manan

+0

理论上你可以最小化刷新的效果。实际上,您可以通过在刷新调用中指定它们来选择性地刷新所需的捆绑包(该框架自动添加所有依赖项)。但是,我从来不能理解为什么要交换一小段时间来重新启动对于相当大的复杂性。由于总是有需要重新启动的情况,因此您不能依赖此行为。所以我会尽量减少复杂性并使用一条路径,而不是在代码中创建许多可能的星座。 –

相关问题