2015-11-25 74 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

理論上你可以最小化刷新的效果。實際上,您可以通過在刷新調用中指定它們來選擇性地刷新所需的捆綁包(該框架自動添加所有依賴項)。但是,我從來不能理解爲什麼要交換一小段時間來重新啓動對於相當大的複雜性。由於總是有需要重新啓動的情況,因此您不能依賴此行爲。所以我會盡量減少複雜性並使用一條路徑,而不是在代碼中創建許多可能的星座。 –

相關問題