Mark Lutton
Mark Lutton

Reputation: 7027

RESTEasy JAX-RS dynamic dispatching other than subresources

RESTEasy (JAX-RS) allows dynamic dispatching via sub-resources. For instance:

POST /customers/create
{"name":"Smith","country":"jp"}

We can have a root resource to handle the path "/customers" with a method annotated with no HTTP method but with @Path("/create"). This method returns a resource that JAX-RS looks at to continue handling the request. However, this resource must handle the "/customers/create" path.

I have an existing situation where different kinds of entities can be created:

POST /customers/create
{"name":"Smith"}

POST /locations/create
{"name":"Chicago"}

I would like to add the ability to create any kind of entity based on an additional property in the body of the request:

POST /entities/create
{"type":"customer","name":"Smith"}

In essence I want to forward the request to the code that handles "POST /customers/create". I can write sub-resource locator that gets called for "POST /entities/create" and returns the Customer resource, but JAX-RS fails to dispatch the request because the Customer resource doesn't handle the path "/entities/create". Is there a way I can change the URL to /customers/create when forwarding the request?

At this point I can't change the API to make "customers" a true subresource of "entities".

Upvotes: 5

Views: 1691

Answers (2)

Xavier Coulon
Xavier Coulon

Reputation: 1600

If you're using RestEasy 3 which implements JAX-RS 2.0, then you can try to use a ContainerRequestFilter annotated with @Provider @PreMatching.

Within this Filter, you can call the ContainerRequestContext#setRequestUri(URI) method to change the request URI based on the content of the request, and thus, forward from to /entities/create to /customers/create or /locations/create. The @PreMatching annotation means that the Filter will be called before the target resource method is matched, so this is where you should be able to perform the redirect.

(You may even replace the content of the request, eg: {"type":"customer","name":"Smith"} -> {"name":"Smith"} using the ContainerRequestContext#getInputStream() and ContainerRequestContext#setInputStream(InputStream) methods)

HTH Xavier

Upvotes: 6

V G
V G

Reputation: 19002

I doubt there is a standard JAX-RS way to change the URL before returning a subresource. But I have a possible solution to your problem.

Define that Generic Rest Resource like this: POST /entities/{entityType}. Depending on the path parameter entityType you can decide directly what subresouce you can instantiate (e.g using a static Map<String, Class<?>> to hold the entity paths)

Upvotes: 0

Related Questions