我大致以这种方式向apache karaf添加OSGI服务MyService
:
public interface MyService {//...}
@OsgiServiceProvider(classes=MyService .class)
@Singleton
public class MyServiceImpl implements MyService {//...}
blueprint-maven-plugin
和maven-bundle-plugin
来处理anotations。 OSGi-service的声明及其实现结果在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
现在我想出于兼容性原因将该服务绑定到JNDI名称。我尝试通过在init()
中实施MyServiceImpl
并使用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");
为了调查我首先检查了捆绑包是否已启动并且该服务已添加到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]
然后我使用debug参数重新启动了karaf并将断点设置为init()
和addedService()
。观察显示:init()
被调用,因此ServiceTracker
应该正确地添加到包中。但addingService()
并未被调用。
我错过了什么?
答案 0 :(得分:0)
在blueprint.xml中,您使用其界面&#34; com.foo.bar.MyService&#34;发布服务。因此,您需要在服务跟踪器查找中使用相同的名称。
顺便说一下。你为什么要使用ServiceTracker?如果您从impl的@PostConstruct发布服务,那么只需使用:
发布implContext c = new InitialContext();
bind(c, "java:global/com.foo.bar.bundle/MyServiceImpl!com.foo.bar.MyService", this );