在引用的服务停止后终止 OSGI 蓝图bundle



我有这样的问题。我有两个OSGI蓝图包。其中一个就像一个服务,另一个正在使用它。我正在卡拉夫上运行它们。所以,我想实现功能,所以当我停止服务时,我的另一个捆绑包也应该停止。我的xml的

    <?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" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd ">
    <reference id="weatherService" availability="mandatory" interface="com.myslyv4uk.weather.api.WeatherService" />  
    <bean id="showWeatherImpl" class="com.myslyv4uk.client.impl.ShowWeatherServiceImpl"
        init-method="start" destroy-method="stop" >
        <argument ref="weatherService" />
    </bean>
</blueprint>
<?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 ">
    <bean id="weatherServiceImpl" class="com.myslyv4uk.weather.impl.WeatherServiceImpl"
        init-method="start" destroy-method="stop" />
    <service ref="weatherServiceImpl">
        <interfaces>
            <value>com.myslyv4uk.weather.api.WeatherService</value>
        </interfaces>
    </service>  
</blueprint>

跳过了 Java 代码。我只想说ShowWeatherService使用WeatherService打印随机数。它们都有启动/停止方法。我需要以这种方式实现配置或功能,因此从 karaf 卸载 WeatherService 捆绑包后,ShowWeatherService 也停止了。问题是我无法从天气服务到显示天气服务进行引用,因为它将是循环引用,此捆绑包不会启动。我该怎么办?如何从其他捆绑包终止捆绑包?

当该服务出现故障时,我不会停止需要服务的捆绑包。这不是OSGi中处理的方式。

相反,你的showWeatherImpl捆绑包可以使用http白板模式将自己作为servlet提供。这意味着它提供了一个实现 servlet 的服务。如果强制服务引用出现故障,蓝图将自动注销捆绑包的所有服务。

当然,如果您例如在showWeatherImpl中使用bean中的java代码将自己注册为servlet,则这无济于事。在这种情况下,您可以使用服务引用回调,当服务来来去去时会通知您。

当然,就像Grzegorz提到的那样,声明式服务在默认情况下比蓝图更加动态,并且可以更好地处理这种情况。

警告

在此回答中,我将解释如何在所需服务消失时停止蓝图包。此代码按预期工作,但由于各种原因,这是一个坏主意


您可以在绑定/取消绑定服务时注册侦听器,并在删除服务时执行操作。这是一个关于如何做到这一点的示例。

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd ">
    <bean id="referenceListener" class="your.ReferenceListener">
        <property name="bundleContext" ref="blueprintBundleContext"/>
    </bean>
    <reference id="weatherService"
               availability="mandatory"
               interface="com.myslyv4uk.weather.api.WeatherService">
        <reference-listener ref="referenceListener"
                            unbind-method="unbind" />
    </reference>
    <bean id="showWeatherImpl" class="com.myslyv4uk.client.impl.ShowWeatherServiceImpl"
        init-method="start" destroy-method="stop" >
        <argument ref="weatherService" />
    </bean>
</blueprint>

引用侦听器 Bean 在删除服务时被调用。通过注入捆绑包上下文,您可以停止捆绑包本身:

public class ReferenceListener {
private Logger log; // set this up
private BundleContext bundleContext;
public void setBundleContext(BundleContext bundleContext) {
    this.bundleContext = bundleContext;
}
// Called when the service is injected
public void bind(ServiceReference<?> sr) {
    log.info("Bind of ServiceReference {} to bundle {}",
            sr, bundleContext.getBundle());
}
// Called when the service is removed
public void unbind(ServiceReference<?> sr) {
    log.info("Unbind of ServiceReference {} from bundle {}",
            sr, bundleContext.getBundle());
    try {
        if (bundleContext.getBundle().getState() == Bundle.ACTIVE) {
            log.warn("Bundle {} will be stopped after unbind of mandatory ServiceReference {}",
                    bundleContext.getBundle(), sr);
            bundleContext.getBundle().stop();
        }
    } catch (BundleException e) {
        log.error("Cannot stop bundle {} after unbind of ServiceReference {}",
                bundleContext.getBundle().getBundleId(),
                sr,
                e);
    }
}
}

此解决方案有效,但有一些缺点,例如,如果重新启动容器,则会删除服务,从而将捆绑包设置为"已停止"状态。

最新更新