尝试跟踪部署到 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
:
- 创建并注释服务及其实现。
public interface MyService {//...}
@OsgiServiceProvider(classes=MyService .class)
@Singleton
public class MyServiceImpl implements MyService {//...}
- 使用带有
blueprint-maven-plugin
和 maven-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
- 将包含该捆绑包的功能复制到 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 );
我大致这样向 apache karaf 添加了一个 OSGI 服务 MyService
:
- 创建并注释服务及其实现。
public interface MyService {//...}
@OsgiServiceProvider(classes=MyService .class)
@Singleton
public class MyServiceImpl implements MyService {//...}
- 使用带有
blueprint-maven-plugin
和maven-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
- 将包含该捆绑包的功能复制到 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 );