javaservletsjax-rsjersey-2.0resty-gwt

Jersey Setting up 2 servlets


I'm trying to setup my project with Jersey to basically have 2 servlets: a private one for access by the client application, and a public facing one that acts as an API. The api calls are a subset of the private ones. (In case this is relevant my client side is GWT with RestyGWT). My resources are all stored in either:

com.path.to.server.resources.internal
com.path.to.server.resources.api

Where the private servlet should encompass both of those packages, and the api should only use the api package.

I would like my internal calls to look like this:

https:// localhost:8445/resources/authentication/login

and my api calls to look like this:

https:// localhost:8445/api/users/getuser

My web.xml looks like this:

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

    <!-- Servlets -->
    <servlet>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.path.to.server.resources.exceptionmappers;com.path.to.server.resources.api;com.path.to.server.resources.internal</param-value>
        </init-param>
    </servlet>

    <servlet>
        <servlet-name>com.path.to.server.ApiApplication</servlet-name>
    </servlet>

    <servlet-mapping>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>com.path.to.server.ApiApplication</servlet-name>
        <url-pattern>/api</url-pattern>
    </servlet-mapping>

</web-app>

I have the ApiApplication setup like this:

public class ApiApplication extends ResourceConfig
{
    public ApiApplication()
    {
        System.out.println("SETTING UP API");
        packages("com.path.to.server.resources.exceptionmappers;com.path.to.server.resources.api");
    }
}

Now that I have all that setup, I'm trying to hit my service. I'm using a DirectRestService that looks like this:

@Path("resources/authentication")
public interface AuthenticationService extends BaseService
{
    @POST
    @Path("/login/{loginType}")
    @Produces(MediaType.APPLICATION_JSON)
    Session login(@HeaderParam("Authorization") String authorization, @PathParam("loginType") UserTypes loginType);

    @POST
    @Path("/findActiveSession")
    @Produces(MediaType.APPLICATION_JSON)
    Session findActiveSession();
}

The server resource that implements that looks like this:

@Path("authentication")
public class AuthenticationResource extends BaseResource implements AuthenticationService
{
    public Session login(String authorization, UserTypes loginType)
    {
        // Code to do stuff
    }

    public Session findActiveSession()
    {
        // Code to do stuff
    }
}

When I visit https:// localhost:8445, the findActiveSession() method is called from my client, but I get a 404. The service URL as shown in Chrome's network monitor looks like this:

https:// localhost:8445/resources/authentication/findActiveSession

It's all very confusing as to which things need what paths. Things I'm not sure about:

Is the AuthenticationResource Path correct? Does it even need the Path annotation?

Is it correct for the private servlet to use the javax.ws.rs.core.Application?

Am I correctly setting up the custom servlet with the Application subclass (ApiApplication)?


Solution

  • I've finally come up with a solution that is working. I don't know if it's entirely correct, but it gives me the results I want:

    My web.xml

    <web-app id="WebApp_ID" version="3.0" [...]>
        <!-- Servlet for direct client/server calls -->
        <servlet>
            <servlet-name>InternalApplication</servlet-name>
            <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>jersey.config.server.provider.packages</param-name>
                <param-value>
                    path.to.server.resources.exceptionmappers,path.to.server.resources.api,path.to.server.resources.internal
                </param-value>
            </init-param>
        </servlet>
    
        <!-- Servlet for API calls -->
        <servlet>
            <servlet-name>ApiApplication</servlet-name>
            <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>jersey.config.server.provider.packages</param-name>
                <param-value>
                    path.to.server.resources.exceptionmappers,path.to.server.resources.api
                </param-value>
            </init-param>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>InternalApplication</servlet-name>
            <url-pattern>/resources/*</url-pattern>
        </servlet-mapping>
    
        <servlet-mapping>
            <servlet-name>ApiApplication</servlet-name>
            <url-pattern>/api/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

    I didn't end up needing the Application subclasses.