使用新更改部署OSGI捆绑包的BKM是什么?

时间:2015-11-25 18:48:21

标签: java jboss osgi versioning

我们一直在使用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.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服务包时,使用者服务包无法开始使用随包1.1.0导出的新服务。我们不得不刷新消费者包以使其有效。

我们在这里做错了吗?

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

1 个答案:

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

摘要:

  • 安装/更新后必须刷新。
  • 二手bnd