OSGi Внедрение декларативных услуг

Я пытаюсь сделать простой сервис OSGi, используя декларативные сервисы на локальном сервере Glassfish. Предоставляющий плагин всегда активен.

У меня возникли проблемы с внедрением в мой сервлет, который потребляет мой сервис, при вызове сервлета ссылка становится пустой, потому что это не тот объект, который был введен со ссылкой на сервис.

Я проверил это, поместив точку останова в мой установщик ссылок, и увидел, что мой сервис внедряется, но когда я нажимаю на кнопку, которая вызывает мой сервлет в моем приложении, ссылка на сервис становится пустой, потому что это не тот же объект (т.е. получает введено в servlet_Instance #1, но вызывает метод servlet_Instance #2. Я должен упустить небольшую деталь, потому что я могу найти и использовать свой сервис при выполнении

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

Плагин, используемый для генерации моих файлов XML: 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>

Мой сервлет

@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>

Также я попытался, но не повезло, потому что мой сервлет, похоже, не найден (Ошибка 404 - Запрошенный ресурс () недоступен.), Чтобы сделать так, как написал там Питер Криенс: Как использовать OSGi-сервис из OSGi HTTP Service

Поэтому я изменил свой сервлет так:

@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

<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-all комплекты, и сервис там работает и работает, он говорит, что мой потребительский комплект использует его.

1 ответ

Решение

У вас есть две стороны, создающие экземпляры вашего сервлета. Один - это DS, а другой - веб-контейнер. Вы не можете иметь 2 мастера. Веб-контейнер в основном должен быть ответственным, так как он будет отправлять запросы только к экземпляру вашего сервлета, который он создает.

Если бы была реализация, которая поддерживала как веб-контейнер, так и DS, то вы были бы настроены. Но я никогда не слышал о такой вещи.

Я не знаю, поддерживает ли Glassfish спецификацию OSGi для веб-приложений (гл. 128). Если это так, то вы можете взаимодействовать с уровнем обслуживания OSGi, как описано в 128.6.

Другие вопросы по тегам