Ori Popowski
Ori Popowski

Reputation: 10662

Can Jersey build a resource class through specific constructor based on the request URI?

I have a class

@Path("/foo")
public class Foo {

    public Foo() {
    }

    public Foo(int n) {
    }

    @GET
    @Produces(MediaType.TEXT_HTML)
    @Path("/isAlive")
    public String isAlive() {
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/getConfigFromDB")
    public Response getConfigFromDB(Request) {
    }

Suppose that this is the first call to this web app and the the class has to be constructed for the first time. Can I configure Jersey to choose the second constructor if the path is "http://localhost/foo/isAlive" and the first constructor if the request path is "http://localhost/foo/getConfigFromDB"?

Upvotes: 1

Views: 3498

Answers (2)

lefloh
lefloh

Reputation: 10961

You can manage Resource instantiation yourself overriding Application#getSingletons:

@ApplicationPath("/r")
public class RestApplication extends Application {

    @Override
    public Set<Object> getSingletons() {
        Foo foo = new Foo();
        Bar bar = new Bar(42);
        return new HashSet<Object>(Arrays.asList(foo, bar));
    }

}

But therefore you'll need two classes, each one with the full path:

@Path("/foo/isAlive")
public class Foo {

    public Foo() {}

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public Response isAlive() {
        return Response.ok("foo is alive").build();
    }

}

@Path("/foo/getConfigFromDB")
public class Foo2 {

    private int n;

    public Foo2(int n) {
        this.n = n;
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public Response isAlive() {
        return Response.ok("bar initialized with " + n).build();
    }

}

You could also use a Subresource:

@Path("/foo")
public class Foo {

    public Foo() {}

    @GET
    @Path("/isAlive")
    @Produces(MediaType.TEXT_PLAIN)
    public Response isAlive() {
        return Response.ok("foo is alive").build();
    }

    @Path("/getConfigFromDB")
    @Produces(MediaType.TEXT_PLAIN)
    public Bar getConfigFromDB() {
        return new Bar(4711);
    }

}

public class Bar {

    private int n;

    public Bar(int n) {
        this.n = n;
    }

    @GET
    public Response get() {
        return Response.ok("Bar initialized with " + n).build();
    }

}

But if your problem is about getting authentification-information in the second method as you wrote in a comment I would not use the constructor anyway. See this answer for some other examples.

Upvotes: 2

Xavier Coulon
Xavier Coulon

Reputation: 1600

AFAIK, the Resource instanciation is a responsability of the JAX-RS implementation, and a resource class must have an empty constructor or a constructor with parameters annotated with @Context, @Header, @PathParam, @CookieParam, @MatrixParam, @QueryParam or @PathParam. Also, a new instance of your Resource class will be created for each incoming request.

If your application is deployed on a JavaEE container or includes Spring, you can use the @inject annotation to get access to other services of your application, if that can help you.

Upvotes: 1

Related Questions