Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to forward a REST request to another resource?

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

/categories
/categories/{catId}

that's implemented like this:

@Path("/categories")
@Produces("application/json")
public class CategoryResourcesApi {

    @GET
    public Response getCategories() {
        // ...
    }

    @GET @Path("/{catId}")
    public Response getCategory(@PathParam("catId") String catId) {
        // ...
    }

    // ...

}

and another one that serves:

/products
/products/{prodId}

and has a similar implementation:

@Path("/products")
@Produces("application/json")
public class ProductResourcesApi {

    @GET
    public Response getProducts() {
        // ...
    }

    // ...

}

Apart from these straightforward paths, I also need to serve these:

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

which would be products related to a specific category.

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

I'm using @Context and other annotations in my resource implementations, so a direct new ProductResourcesAPI().getProducts() wouldn't work, I guess.

Is there any way to forward from one resource path to another within the JAX-RS (or Jersey) framework? What other options do I have? I'd like to keep all this easily maintainable if possible, that's why I chose one resource for each root path with subresources within.

like image 244
watery Avatar asked Oct 30 '15 10:10

watery


People also ask

How do I forward a Spring MVC request?

A request can be basically processed in three ways: a) resolved by Spring in a controller action, b) forwarded to a different controller action, c) redirected to client to fetch another URL. Forward: performed internally by Spring. the browser is completely unaware of forward, so its original URL remains intact.

Who is responsible for forwarding a request in Spring MVC?

redirect will respond with a 302 and the new URL in the Location header; the browser/client will then make another request to the new URL. forward happens entirely on a server side. The Servlet container forwards the same request to the target URL; the URL won't change in the browser.

What is request and response in rest?

It is a set of rules that developers follow when they create their API. One of these rules states that you should be able to get a piece of data (called a resource) when you link to a specific URL. Each URL is called a request while the data sent back to you is called a response.


1 Answers

For this you can use Sub-resource locators, which is basically a method in the resource class that returns another resource class. The thing about the examples in the link is that they instantiate the resource class themselves, 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)
    }
}

which works, but I am not sure if it preserves injections, for instance if you wanted to inject @Context UriInfo into a field in ItemContentResource. It should work though if you injected into the method param instead.

To get around this, there is the ResourceContext, which when used, should preserve all the 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) {
    }
}

The getProducts would map to the URI /categories/{catId}/products/{prodId}. You just need to check if the catId is null (only if you need it to do any lookup) I guess to determine if the request is a request to the root products resource or to the parent categories resource. Small price to pay for code reuse I guess.

And just looking at your comment, I believe in the past Swagger didn't support sub-resource locators, but I believe now they do. You may want to search around for any discussions if you have problems with it. Here's a discussion, and another one, and another one

like image 105
Paul Samsotha Avatar answered Sep 18 '22 12:09

Paul Samsotha