How to redirect a REST request to another resource?

In my current architecture, I have a JAX-RS resource that is behind:

/categories /categories/{catId} 

which is implemented as follows:

 @Path("/categories") @Produces("application/json") public class CategoryResourcesApi { @GET public Response getCategories() { // ... } @GET @Path("/{catId}") public Response getCategory(@PathParam("catId") String catId) { // ... } // ... } 

and another that serves:

 /products /products/{prodId} 

and has a similar implementation:

 @Path("/products") @Produces("application/json") public class ProductResourcesApi { @GET public Response getProducts() { // ... } // ... } 

Besides these simple paths, I also need to serve them:

 /categories/{catId}/products /categories/{catId}/products/{prodId} 

which will be products belonging to a certain category.

The most natural thing to do is to make ProductResourcesApi serve them, but by the way, I understand the structure of JAX-RS annotations, it can only be served by CategoryResourcesApi (or, ultimately, a third class, I think).

I use @Context and other annotations in my resource implementations, so the direct new ProductResourcesAPI().getProducts() does not work, I think.

Is there a way to forward one resource path to another within the framework of JAX-RS (or Jersey)? What other options do I have? I would like to keep all this easy, if possible convenient, so I selected one resource for each root path with sub-resources inside.

+5
source share
1 answer

To do this, you can use Subresource Locators , which is basically a resource class method that returns another resource class. The point in the examples in the link is that they instantiate the resource class, for example

 @Path("/item") public class ItemResource { @Path("content") public ItemContentResource getItemContentResource() { return new ItemContentResource(); } } public class ItemContentResource { @PUT @Path("{version}") public void put(@PathParam("version") int version) } } 

but I'm not sure if it saves the injections, for example if you want to insert @Context UriInfo into a field in ItemContentResource . It should work, although if you enter param into the parameter.

To get around this, there is a ResourceContext that, when used, must retain all injections. For example, in your current case, you can do

 @Path("/categories") @Produces("application/json") public static class CategoryResourcesApi { @Context private ResourceContext resourceContext; @Path("/{catId}/products") public ProductResourcesApi getProducts() { return resourceContext.getResource(ProductResourcesApi.class); } } @Path("/products") @Produces("application/json") public static class ProductResourcesApi { @Context private UriInfo info; @GET @Path("/{id}") public Response getProducts( @PathParam("id") String prodId, @PathParam("catId") String catId) { } } 

getProducts will be displayed in URI /categories/{catId}/products/{prodId} . You just need to check if catId null (only if you need to do this for any search), I am assuming to determine if the request is a request for a root product resource or a parent category resource. I guess a small price to reuse the code.

And just looking at your comment, I believe that Swagger did not support resource locators in the past, but I believe that they do it now. You can look for any discussions if you have problems with it. Here is a discussion , another , and one more

+7
source

Source: https://habr.com/ru/post/1234860/


All Articles