Search code examples
javajerseyjax-rs

JAX-RS / jersey: client proxy: how to inject path parameter from context instead of method argument?


I am use the proxy pattern to call web services using JAX-RS and Jersey. I would like to conceptually do something like... add @Context annotation to the interface like:

@Path("foo/{instance}")
public interface Foo 
{
    @Context private UriInfo uriInfo;

    @POST
    @Path("doit")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Thing1 doit(Thing2 arg);
}

But of course one cannot do that, it is an interface not a class. But an interface is what is needed for using the proxy pattern. I create a client using the proxy pattern:

ClientBuilder builder = ClientBuilder.newBuilder().register(JacksonJsonProvider.class);
MyRequestFilter filter = new MyRequestFilter();
builder = builder.register(filter);
WebTarget target = builder.build().target(url);
Foo serviceClient = WebResourceFactory.newResource(Foo.class, target);

However, calling serviceClient.doit(...) results in IllegalStateException: The template variable 'instance' has no value. I tried using a ClientRequestFilter to inject the instance variable, but my filter method is not even called before this exception is thrown. Is there any way to inject a path parameter from the client without adding it as a @PathParam argument to every method? The reason is, I already have an interface defined which I want my proxy client to implement, and adding a parameter changes the signatures.


Solution

  • Ultimately, there seems no way to do this directly. I've not found any way to inject the "instance" from a context in a Jersey client proxy. Even when Foo is class, and a ClientRequestFilter is installed, the filter is not called before the error is issued. As a workable solution, I basically took what @andrewjames suggested and created an interface with the extra instance argument. This satisfied the requirement to be able to create a proxy with a WebTarget. Then I created a class that implements the base interface (the one without the instance parameter in the methods), wraps the proxy instance, and delegates all method calls to the proxy. This isn't pretty, but since all of this is coming from a code-generation tool, neither is it especially tedious or error-prone.