尝试跟踪部署到 apache karaf 的捆绑包中的服务。 ServiceTracker#addingService 没有被调用

Trying to track a service in a bundle deployed to apache karaf. ServiceTracker#addingService doesn't get called

我大致这样向 apache karaf 添加了一个 OSGI 服务 MyService

  1. 创建并注释服务及其实现。
public interface MyService {//...}

@OsgiServiceProvider(classes=MyService .class)
@Singleton
public class MyServiceImpl implements MyService {//...}
  1. 使用带有 blueprint-maven-pluginmaven-bundle-plugin 的 maven 构建来处理注释。 OSGi 服务的声明及其实现结果为 bundle.jar!/OSGI-INF/blueprint/autowire.xml:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
<bean id="myServiceImpl" class="com.foo.bar.MyServiceImpl"
  ext:field-injection="true" init-method="init">
    <property name="contextFactory" ref="initialContextFactory-"/>
</bean>
<service ref="myServiceImpl" interface="com.foo.bar.MyService"/>
</blueprint>

包知道 XML 因为它在 MANIFEST.MF:

Bundle-Blueprint: OSGI-INF/blueprint/autowire.xml
  1. 将包含该捆绑包的功能复制到 karaf-home/deploy

出于兼容性原因,现在我想将该服务绑定到 JNDI 名称。我尝试通过在 MyServiceImpl 中实现 init() 并使用 ServiceTracker:

来实现这一点
@PostConstruct
public void init() {
    BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
    ServiceTracker tracker = new ServiceTracker(context, this.getClass(), null) {
        @Override
        public Object addingService(ServiceReference reference) {
            Object serviceObj = super.addingService(reference);
            try {
                Context c = new InitialContext();
                bind(c, "java:global/com.foo.bar.bundle/MyServiceImpl!com.foo.bar.MyService", serviceObj );
            }
            catch (NamingException e) { e.printStackTrace(); }
            return serviceObj;
       }
    };
    tracker.open();
}

private void bind(Context ctx, String name, Object value) { //... }

不幸的是,如果我进行查找,我会得到 javax.naming.NotContextException

new InitialContext().lookup("java:global/com.foo.bar.bundle/MyServiceImpl!com.foo.bar.MyService");

为了调查,我首先检查了 bundle 是否已启动以及是否在 karaf 控制台中添加了服务:

karaf@root()> bundle:list | grep bundle
155 | Active   |  80 | 0.0.1.SNAPSHOT     | bundle
karaf@root()> bundle:services 155

bundle (155) provides:
----------------------
[com.foo.bar.MyService]

然后我用调试参数重新启动了karaf,并在init()addedService()中设置了一个断点。观察显示:init() 被调用,所以 ServiceTracker 应该正确地添加到包中。但是 addingService() 没有被调用。

我错过了什么?

在 blueprint.xml 中,您使用其接口 "com.foo.bar.MyService" 发布服务。因此,您需要在服务跟踪器查找中使用相同的名称。

顺便说一句。为什么要使用 ServiceTracker?如果您从 impl 的 @PostConstruct 发布服务,则只需使用以下方式发布 impl:

Context c = new InitialContext();
bind(c, "java:global/com.foo.bar.bundle/MyServiceImpl!com.foo.bar.MyService", this );