Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameters to resource using embedded Jetty

I have a resource I want to expose that has a constructor with parameters for injection. However I'm not using any injection framework, and I've got Jetty embedded.

Right now Jetty scans for Resources with this:

ServletContextHandler servletContextHandler = new ServletContextHandler(server, "/server");
ServletHolder jerseyServletHolder = new ServletHolder(ServletContainer.class);
jerseyServletHolder.setInitParameter("com.sun.jersey.config.property.packages", "my.package.to.scan");
servletContextHandler.addServlet(jerseyServletHolder, "/*");

But it prevents me from injecting anything in the constructor, so I have to use a default constructor.

I'd like to specify my own instance to pass to my resource constructor. Is there a way to instantiate the resource manually and add it to the servlet container?

Is it possible to do something like this :

MyRestResource resource = new MyRestResource(param1, param2);
servletContextHandler.addServlet(resource);

or something like that?

like image 326
Pacane Avatar asked Dec 21 '22 07:12

Pacane


2 Answers

You can inject dependencies into Jersey resources by registering a (Jersey) ServletContainer with a customized ResourceConfig. Please have a look at the code below as an example of creating a TimeResource class with a clock injected into it via a constructor.

public void start() {
    server = new Server(6666);
    ServletContextHandler handler = new ServletContextHandler();
    handler.setContextPath("");
    // adds Jersey Servlet with a customized ResourceConfig
    handler.addServlet(new ServletHolder(new ServletContainer(resourceConfig())), "/*");
    server.setHandler(handler);
    try {
        server.start();
    } catch (Exception e) {
        throw new RuntimeException("Could not start the server", e);
    }
}

private ResourceConfig resourceConfig() {
    // manually injecting dependencies (clock) to Jersey resource classes
    return new ResourceConfig().register(new TimeResource(clock));
}

A full example with source code is available under:

http://unclejamal.github.io/2013/09/18/manual-dependency-injection-with-jersey-and-embedded-jetty.html

like image 175
Pawel Duda Avatar answered Dec 31 '22 15:12

Pawel Duda


If MyRestResource is a Servlet, then you can use the existing servlet holder constructor.

ServletContextHandler servletContextHandler = new ServletContextHandler(server, "/server");
ServletHolder jerseyServletHolder = new ServletHolder(ServletContainer.class);
jerseyServletHolder.setInitParameter("com.sun.jersey.config.property.packages", "my.package.to.scan");
servletContextHandler.addServlet(jerseyServletHolder, "/*");
MyRestResource resource = new MyRestResource(param1, param2);
// wrap resource in a ServletHolder
ServletHolder resourceHolder = new ServletHolder(resource);
// assign resource to a Servlet pathSpec
servletContextHandler.addServlet(resourceHolder, "/rest");

If you have a servlet, and want to access something setup at startup time, use the ContextHandler.setAttribute(String, Object) and ServletContext.getAttribute(String) techniques.

In your server startup

ServletContextHandler servletContextHandler = new ServletContextHandler(server, "/server");
ServletHolder jerseyServletHolder = new ServletHolder(ServletContainer.class);
jerseyServletHolder.setInitParameter("com.sun.jersey.config.property.packages", "my.package.to.scan");
servletContextHandler.addServlet(jerseyServletHolder, "/*");
MyRestResource resource = new MyRestResource(param1, param2);
// Set resource as a context attribute
servletContextHandler.setAttribute("rest-1", resource);

Then access is later from the servlet api

ServletContext ctx = servletRequest.getServletContext();
MyRestResource resource = (MyRestResource) ctx.getAttribute("rest-1");
like image 44
Joakim Erdfelt Avatar answered Dec 31 '22 14:12

Joakim Erdfelt