Question

I am trying to do a simple OSGi service using Declarative Services on a local Glassfish server. The plugin which provides is always active.

I got trouble with the injection into my servlet that consumes my service, the reference is null when the servlet gets called because it isn't the same object that the one which got injected with the service reference.

I tested it by putting a breakpoint into my reference setter, and I saw my service getting injected, but when I click on the button that calls my servlet into my application the service reference is null because it isn't the same object (i.e. gets injected in servlet_Instance #1 but invoke the method on servlet_Instance #2. I must be missing a little detail, because I can find and use my service when doing

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

The plugin used to generate my XMLs files : 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>

This is my service class

@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);
}

}

the generated XML is

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

My servlet is

@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û");
}
}

the Generated 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>

Also I tried, but no luck because my servlet doesn't seem to be found (Error 404 - The requested resource () is not available.), to do as Peter Kriens wrote there : How to consume OSGi service from OSGi HTTP Service

So I modified my servlet like so :

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

The generated XML is

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

I access the servlet from my JSP

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

To test the above I have in my deployed bundles org.apache.felix.http.api-2.2.1, org.apache.felix.http.whiteboard-2.2.1 just as in the post. Didn't find if there is a switch to put on.

Also I checked with org.apache.felix.webconsole-4.2.0-all the bundles, and the service is there up and running, it says that my consumer bundle is using it.

Was it helpful?

Solution

You have two parties creating instances of your servlet. Once is DS and the other is the web container. You cannot have 2 masters. The web container basically has to be in charge since it will only send requests to the instance of your servlet that it creates.

If there was an implementation that supported both web container and DS, then you would be set. But I have never heard of such a thing.

I don't know if Glassfish supports the OSGi Web Application Specification (Ch 128). If it does, then you can interact with the OSGi service layer as described in 128.6.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top