Troncoso Troncoso - 4 months ago 20
Java Question

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

Answer

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>EcoPortalApplication</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>EcoPortalApplication</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.