【问题标题】:OSGi Declarative services injectionOSGi 声明式服务注入
【发布时间】:2013-10-09 05:18:26
【问题描述】:

我正在尝试在本地 Glassfish 服务器上使用声明式服务来做一个简单的 OSGi 服务。提供的插件始终处于活动状态。

我在注入使用我的服务的 servlet 时遇到了问题,调用 servlet 时引用为空,因为它与注入服务引用的对象不同。

我通过在我的引用设置器中放置一个断点来测试它,我看到我的服务被注入了,但是当我点击将我的 servlet 调用到我的应用程序中的按钮时,服务引用为空,因为它不是同一个对象(即在 servlet_Instance #1 中注入,但在 servlet_Instance #2 上调用该方法。我一定遗漏了一些细节,因为我可以在这样做时找到并使用我的服务

final BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
     loggingTestServiceInterface = (LoggingTestServiceInterface) bundleContext.getService(bundleContext
     .getServiceReference(LoggingTestServiceInterface.class.getName()));

用于生成我的 XMLs 文件的插件:maven-scr-plugin

<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.14.0</version>
<executions>
    <execution>
        <id>generate-scr-scrdescriptor</id>
        <goals>
            <goal>scr</goal>
        </goals>
    </execution>
</executions>
<configuration>
    <supportedProjectTypes>
        <supportedProjectType>war</supportedProjectType>
        <supportedProjectType>jar</supportedProjectType>
        <supportedProjectType>bundle</supportedProjectType>
    </supportedProjectTypes>
</configuration>
</plugin>

这是我的服务类

@Component(immediate = false, name = "Shikashi", service = {LoggingTestServiceInterface.class}, enabled = true)
public class LoggingTestService implements LoggingTestServiceInterface
{
private final LoggerUtils loggerUtils = new LoggerUtils();

public LoggingTestService()
{
}

@Activate
public void start(final BundleContext bundleContext)
{
    System.out.println("StartTest Service Fune");
}

@Deactivate
public void stop()
{
    System.out.println("Stop Test Service Jitensha");
}

@Modified
public void modify()
{
    System.out.println("Stop Test Service onnanogo");
}

private Logger createLogger(final Class<?> clazz)
{
    return Logger.getLogger(clazz);
}

@Override
public void logDebug(final Class<?> clazz, final String message)
{
    logDebug(clazz, message, null);
}
    @Override
public void logDebug(final Class<?> clazz, final String message, final Throwable throwable)
{
    final Logger logger = createLogger(clazz);
    logger.debug(message, throwable);
}

}

生成的XML是

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
<scr:component enabled="true" immediate="false" name="Shikashi" activate="start" deactivate="stop" modified="modify">
    <implementation class="com.sti.logging.service.LoggingTestService"/>
    <service servicefactory="false">
        <provide interface="com.sti.loggingservices.serviceinterface.LoggingTestServiceInterface"/>
    </service>
</scr:component>

我的 servlet 是

@WebServlet(name = "Wakarimashita", urlPatterns = { "/Wakarimashita"})
@Component
public class Wakarimashita extends HttpServlet
{
private LoggingTestServiceInterface loggingTestServiceInterface;

@Override
protected void doGet(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) throws ServletException, IOException
{
    // Method just to setup the Servlet to understand how it works

    final String language = "language";
    final String path = "/sigbud/language/";

    if (httpServletRequest.getParameter(language) != null)
    {
        if (httpServletRequest.getParameter(language).equalsIgnoreCase("Nihongo"))
        {
            httpServletResponse.sendRedirect(path + "nihongo.jsp");
        }
        else if (httpServletRequest.getParameter(language).equalsIgnoreCase("Eigo"))
        {
            httpServletResponse.sendRedirect(path + "eigo.jsp");
        }
        else if (httpServletRequest.getParameter(language).equalsIgnoreCase("Funansugo"))
        {
            httpServletResponse.sendRedirect(path + "funansugo.jsp");
        }
        else
        {
            httpServletResponse.sendRedirect(path + "unknown.jsp");
        }
    }
    else
    {
        super.doGet(httpServletRequest, httpServletResponse);
    }

    loggingTestServiceInterface.logError(getClass(), "Wakarimasen");
}
    @Reference(service = LoggingTestServiceInterface.class, cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
public void bindLoggingTestServiceInterface(final LoggingTestServiceInterface loggingTestServiceInterface)
{
    this.loggingTestServiceInterface = loggingTestServiceInterface;
}

public void unbindLoggingTestServiceInterface(final LoggingTestServiceInterface loggingTestServiceInterface)
{
    if (this.loggingTestServiceInterface.equals(loggingTestServiceInterface))
    {
        this.loggingTestServiceInterface = null;
    }
}
@Activate
public void start(final BundleContext bundleContext)
{
    System.out.println("StartTest Service Taisho");
}

@Deactivate
public void stop()
{
    System.out.println("Stop Test Service Fukutaisho");
}

@Modified
public void modify()
{
    System.out.println("Stop Test Service san jyû kyû");
}
}

生成的 XML

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
<scr:component name="com.sti.sigbud.servlet.Wakarimashita" activate="start" deactivate="stop" modified="modify">
    <implementation class="com.sti.sigbud.servlet.Wakarimashita"/>
    <reference name="LoggingTestServiceInterface" interface="com.sti.loggingservices.serviceinterface.LoggingTestServiceInterface" cardinality="1..1" policy="dynamic" bind="bindLoggingTestServiceInterface" unbind="unbindLoggingTestServiceInterface"/>
</scr:component>

我也尝试过,但没有运气,因为似乎找不到我的 servlet(错误 404 - 请求的资源 () 不可用。),按照 Peter Kriens 在那里写的:How to consume OSGi service from OSGi HTTP Service

所以我像这样修改了我的 servlet:

@Component(service = Servlet.class, property = {"alias=/Wakarimashita"})
public class Wakarimashita extends HttpServlet

生成的XML是

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
<scr:component name="com.sti.sigbud.servlet.Wakarimashita" activate="start" deactivate="stop" modified="modify">
    <implementation class="com.sti.sigbud.servlet.Wakarimashita"/>
    <service servicefactory="false">
        <provide interface="javax.servlet.Servlet"/>
    </service>
    <property name="alias" value="/Wakarimashita"/>
    <reference name="LoggingTestServiceInterface" interface="com.sti.loggingservices.serviceinterface.LoggingTestServiceInterface" cardinality="1..1" policy="dynamic" bind="bindLoggingTestServiceInterface" unbind="unbindLoggingTestServiceInterface"/>
</scr:component>

我从我的 JSP 访问 servlet

<form action="Wakarimashita" method="GET">
        <input type="text" name="language" size="50"/>
    <input type="submit" value="Submit" />
</form>

为了测试上述内容,我在已部署的捆绑包 org.apache.felix.http.api-2.2.1、org.apache.felix.http.whiteboard-2.2.1 中进行了测试,就像在帖子中一样。没查到有没有开关可以打开。

我还检查了 org.apache.felix.webconsole-4.2.0-所有捆绑包,服务已经启动并运行,它说我的消费者捆绑包正在使用它。

【问题讨论】:

  • Wakarimasen deshita...

标签: servlets dependency-injection osgi declarative-services maven-scr-plugin


【解决方案1】:

您有两方创建 servlet 的实例。一个是 DS,另一个是 Web 容器。你不能有 2 个主人。 Web 容器基本上必须负责,因为它只会向它创建的 servlet 实例发送请求。

如果有一个同时支持 Web 容器和 DS 的实现,那么您将被设置。但我从来没有听说过这样的事情。

我不知道 Glassfish 是否支持 OSGi Web 应用程序规范(第 128 章)。如果是这样,那么您可以按照 128.6 中的描述与 OSGi 服务层进行交互。

【讨论】:

  • 您好,我发现我面临着 2 个容器来管理我的代码。由于我似乎使用 Glassfish OSGi Web Container,我可以通过 getServletContext().getAttributes("osgi-bundle") 访问我的包上下文,就像在规范中一样,并从那里获取我的服务,想知道某处是否有配置在 Glassfish 或插件/工具或任何其他方式来创建我的 servlet 让我使用注入
  • 不,是非此即彼。
  • 好的,我将按照规范访问服务,因此从 servlet 上下文中使用 getServletContext().getAttributes("osgi-bundle") 获取我的服务和服务参考
  • 在这种情况下,由于您无法使用 DS,请考虑使用ServiceTracker 来妥善管理您对服务的使用。
猜你喜欢
  • 2021-01-05
  • 1970-01-01
  • 2012-04-27
  • 2018-05-20
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多