8

I'm trying to get hold of some injected context (for example Session or HttpServletRequest) in a Servlet I've written, running on Grizzly, but nothing I do seems to work. The whole process seems to stall rather prematurely with the following error:

SEVERE: Missing dependency for field: javax.servlet.http.HttpServletRequest com.test.server.LolCat.hsr

The server is dead simple, it consists of two files, the static entry point (Main.java):

package com.test.server;

import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;

import org.glassfish.grizzly.http.server.HttpServer;
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import com.sun.jersey.api.core.ClassNamesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;

public class Main {

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost/").port(8080).build();
    }

    public static final URI BASE_URI = getBaseURI();

    public static void main(String[] args) throws IOException {
        ResourceConfig rc = new ClassNamesResourceConfig(LolCat.class);
        HttpServer httpServer = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
        System.in.read();
        httpServer.stop();
    }
}

and the serlvet (LolCat.java):

package com.test.server;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;

@Path(value = "/lol")
public class LolCat {

    @Context HttpServletRequest hsr;

    @GET
    @Path(value="/cat")
    public String list() {
        return "meow";
    }

}

Specifically, it's the @Context-line in the above source file that is the source and solution to all my problems. I need it, and according to everything I've read about Jersey and Servlets it should work, but alas it does not. I've also tried using GrizzlyWebContainerFactory instead of the GrizzlyServerFactory, but to no avail.

For reference, the project is compiled with the following dependencies:

  • org.glassfish.grizzly:grizzly-framework:jar:2.2.21
  • org.glassfish.grizzly:grizzly-http:jar:2.2.21
  • org.glassfish.grizzly:grizzly-http-servlet:jar:2.2.21
  • org.glassfish.grizzly:grizzly-http-server:jar:2.2.21
  • com.sun.jersey:jersey-server:jar:1.17
  • com.sun.jersey:jersey-servlet:jar:1.17
  • com.sun.jersey:jersey-core:jar:1.17
  • javax.servlet:javax.servlet-api:jar:2.5.0
  • com.sun.jersey:jersey-grizzly2:jar:1.17
  • com.sun.jersey:jersey-grizzly2-servlet:jar:1.17
  • asm:asm:jar:3.3.1
Mic
  • 6,741
  • 3
  • 24
  • 25

4 Answers4

4

This Main class works fine for me:

package com.test.server;

import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;

import com.sun.jersey.api.core.ClassNamesResourceConfig;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.http.server.Response;
import org.glassfish.grizzly.servlet.ServletRegistration;
import org.glassfish.grizzly.servlet.WebappContext;

public class Main {
    private static final String JERSEY_SERVLET_CONTEXT_PATH = "";

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost").port(8080).path("/").build();
    }

    public static final URI BASE_URI = getBaseURI();

    public static void main(String[] args) throws IOException {
        // Create HttpServer and register dummy "not found" HttpHandler
        HttpServer httpServer = GrizzlyServerFactory.createHttpServer(BASE_URI, new HttpHandler() {

            @Override
            public void service(Request rqst, Response rspns) throws Exception {
                rspns.setStatus(404, "Not found");
                rspns.getWriter().write("404: not found");
            }
        });

        // Initialize and register Jersey Servlet
        WebappContext context = new WebappContext("WebappContext", JERSEY_SERVLET_CONTEXT_PATH);
        ServletRegistration registration = context.addServlet("ServletContainer", ServletContainer.class);
        registration.setInitParameter(ServletContainer.RESOURCE_CONFIG_CLASS, 
                ClassNamesResourceConfig.class.getName());
        registration.setInitParameter(ClassNamesResourceConfig.PROPERTY_CLASSNAMES, LolCat.class.getName());
        registration.addMapping("/*");
        context.deploy(httpServer);

        System.in.read();
        httpServer.stop();
    }
}

Try http://localhost:8080/lol/cat in your browser. You can change JERSEY_SERVLET_CONTEXT_PATH to update Servlet's context-path.

alexey
  • 1,959
  • 10
  • 9
  • It worked, with the type safety of plaintext :). Is it possible to register a class without using the String/String setInitParameter? – Mic Apr 04 '13 at 11:06
  • I think Jersey's GrizzlyWebContainerFactory might be extended/improved so you wouldn't need to deal with init parameters, but anyway it's going to be a wrapper over the same WebappContext registration code. – alexey Apr 04 '13 at 17:29
  • Help!.. My code gets as far as `WebappContext context = new WebappContext(...` then it suddenly crashes with `Exception in thread "main" java.lang.NoSuchMethodError: org.glassfish.grizzly.utils.DataStructures.getConcurrentMap(IFI)Ljava/util/concurrent/ConcurrentMap;`. Tried with Java 7 and 8, using jersey-container-grizzly-http:2.5 and jersey-container-grizzly2-servlet:2.5 – Michael M Dec 08 '15 at 00:45
  • 1
    Fixed my issue. For anyone that run into this, I changed my dependency in my .pom file from `org.glassfish.jersey.containersjersey-container-grizzly2-servlet` .. to .. `org.glassfish.grizzly grizzly-http-servlet` ... this had me pulling my hair out!! – Michael M Dec 08 '15 at 01:35
4

As per developers explanations - Grizzly is not fully compliant to JAX-RS 2.0 so there will be no official contexts injections/wrapping. See Jersey Bug-1960 Applicable for Jersey + Grizzly version 2.7+

Luckily there is a way to inject Grizzly request/response objects. Kind of tricky but works Code sample provided in one of Jersey's unit tests. See Jersey container test

So code fragment will be:

import javax.inject.Inject;
import javax.inject.Provider;

public someclass {
    @Inject
    private Provider<Request> grizzlyRequestProvider;

    public void method() {
         if (grizzlyRequestProvider != null) {
            Request httpRequest = grizzlyRequestProvider.get();

            // Extract what you need
         }
    }
}

Works fine both for filters and service methods

Alfishe
  • 3,430
  • 1
  • 25
  • 19
2

You can also manually register a ResourceContext

  HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(getBaseURI());

  WebappContext context = new WebappContext("WebappContext", "/api");
  ServletRegistration registration = context.addServlet("ServletContainer",
    new ServletContainer(config));
  registration.addMapping("/*");
  context.deploy(httpServer);

Where config is your resource context.

0

Try something like this :-

public class Main {

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost/").port(8080).build();
    }

    public static void main(String[] args) throws IOException {
        ResourceConfig rc = new ResourceConfig().packages("com.example");//path to you class files
        HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
        System.in.read();
        httpServer.stop();
    }
}
Sumit Kumar Saha
  • 799
  • 1
  • 12
  • 25