表面上,以上的应用似乎设计简单合理。为什么 会出现这样的问题呢? 原因很简单:此servlet非彼 servlet。
当blueprint容器建立起模型时,上例提到的 servlet bean已实例化并注入了所需的osgi服务。 但是,当用户发起http请求时,一个新的servlet 实例在HttpService那里被创建,这个servlet实例 不是blueprint容器创建的那个,而且因为这个 servlet不是由blueprint容器托管的,所以不会被 注入所需的那个osgi服务,自然那个服务引用就 一直为null了。
问题原因找到了,那么怎么样在这个非blueprint 托管的servlet实例里引用osgi服务呢?
blueprint在发布一个osgi服务时,还会将它同时 注册到jndi上,所以,你可以用这个服务的jndi名 来查找到这个服务并引用它。
Blueprint的OSGI服务JNDI名是这样定义的:
<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 ;http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd" default-timeout="0"> < reference id="CoderService" interface="com.ponder.ICodeService"/> </blueprint>
那么,blueprint就会注册一个jndi名为 blueprint.comp/CoderService的jndi entry。
在serlvet里就可以这样引用这个服务:
import javax.naming.InitialContext; import javax.naming.NamingException; ... ... try { InitialContext ic = new InitialContext(); com.ponder.ICodeService ref= (com.ponder.ICodeService) ic.lookup("blueprint:comp/CoderService"); if(null!=ref){ ... ... } } catch (NamingException e) { ... ... }
由于OSGI的服务是动态的,可能以上代码在运行 时,CoderService服务未必存在,所以,以上代 码需判断服务引用ref是否为null。
以上解决方案可以解决我们的问题,但并不完 美,是否还是可以象最初想的那样,直接通过 blueprint注入osgi服务,而不需要借助JNDI呢? 容我想想看先... ...。