abhay198717
abhay198717

Reputation: 33

How to map REST web service using ServletContainerInitializer?

I want to map REST API using ServletContainerInitializer and my code is

@Override
public void onStartup(Set<Class<?>> classes, ServletContext container)
        throws ServletException {
    // TODO Auto-generated method stub
    Map<String, String> map=new HashMap<String, String>();
    map.put("com.sun.jersey.config.property.packages", "org.pack");

    ServletRegistration.Dynamic dispatcher = container.addServlet(
            "restful", new ServletContainer());
    dispatcher.setInitParameters(map);
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/rest/*");

}

The application runs without any error but the webservice is not created. Please suggest where I m wrong and how to use ServletContainerInitializer in any web application.

Thanks in advance

Upvotes: 3

Views: 1253

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209052

From what I understand about the ServletContainerInitializer is that it's based on the service provider pattern. I went through a tutorial about it a while ago and can't find it now. But you can see some of the requirements in the ServiceLoader javadocs. It states:

A service provider is identified by placing a provider-configuration file in the resource directory META-INF/services. The file's name is the fully-qualified binary name of the service's type. The file contains a list of fully-qualified binary names of concrete provider classes, one per line.

Steps I took to get your example to work:

Create a Maven jar project with these dependencies

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-servlet</artifactId>
    <version>1.18.1</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-core</artifactId>
    <version>1.18.1</version>
</dependency>

Create a META-INF/services dir. You can put directly in the src or with Maven I like to put it src/main/resources. They will both end up in the same place.

Create a file named javax.servlet.ServletContainerInitializer and put the fully qualified name of your ServletContainerInitializer implementation in there. Put the file in the META-INF/services. Here's mine

 META-INF/services/
              javax.servlet.ServletContainerInitializer

     // content
     jersey.servlet.initializer.MyJerseyContainerInitializer

enter image description here

Here is the initializer class

package jersey.servlet.initializer;

import com.sun.jersey.spi.container.servlet.ServletContainer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class MyJerseyContainerInitializer implements ServletContainerInitializer{

    @Override
    public void onStartup(Set<Class<?>> set, ServletContext sc) 
                                                    throws ServletException {
        System.out.println("===============================================");
        System.out.println("                 onStartup()                   ");
        System.out.println("===============================================");
        Map<String, String> map = new HashMap<>();
        map.put("com.sun.jersey.config.property.packages", 
                   "jersey.servlet.initializer.rest");

        ServletRegistration.Dynamic dispatcher = sc.addServlet(
                "restful", new ServletContainer());
        dispatcher.setInitParameters(map);
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/rest/*");
    }
}

And a simple rest resource class

package jersey.servlet.initializer.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path("/resource")
public class Resource {

    @GET
    public Response getResponse() {
        return Response.ok("ServletContainerInitializer test OK!").build();
    }
}

Then I built the jar and installed it to the local repo. Then created another Maven web project, adding the above jar to the project. That's it. Ran it on Tomcat 8 and also 7, and BAM

enter image description here


That aside

The jersey-serlvet.jar (which is required to use the ServletContainer class you are using) already comes with the com.sun.jersey.server.impl.container.servlet.JerseyServletContainerInitializer. Why do we need to create our own?


EDIT

Its work on maven but i want to do it without maven. Would i have to add project jar into the lib folder for without maven.

Yes, you could build a fat jar for the initializer .jar (including the Jersey jars). Then you would need to place the web project WEB-INF/lib. All Maven really does it help with the dependencies and build the .war file. It will also put the initializer jar into the WEB-INF/lib of the webapp. So just follow suit, not using Maven. If you don't want to build a fat jar just make sure all the dependencies are included in the lib

Upvotes: 2

Related Questions