How to programmatically determine JAX-RS resource paths?

Suppose I have a set of JAX-RS locators and sublocators, for example:

@Path("/users") public class UserListResource { @Path("/{id}") public UserResource getCustomer(@PathParam("id") int id) { // Find and return user object } } public class UserResource { @GET public String get() {...} } 

For example, a UserResource object with identifier 5 will have the path "/users/5" . On my system, I have several different resources.

Now the question is: how can the server determine the path to a given resource? Can I do this programmatically through some JAX-RS API or do I need to implement code that uses reflection? (I know how to do the latter, but would prefer a different approach.)

  • At that moment when I need to know the path, I do not have a request object at all. For example, I have a timer that does some background processing and then changes some objects in the domain model and then informs all clients about the changed entities (including their paths).
  • I know that as part of the request, I can add a UriInfo object that provides this, but I need to know the path in advance (to inform clients about changes that have not necessarily occurred using JAX-RS).
  • I don’t want to repeat the path information elsewhere, and I also don’t want to have a set of path fragment constants for each resource type (in this case "/users" and "/{id}" ).
+4
source share
4 answers

When I read your question, you need to create a URI, knowing only the resource class and id parameter.

This can be done using the UriBuilder class, as in:

 UriBuilder builder=UriBuilder.fromResource(UserListResource.class); URI uri=builder.path(UserListResource.class,"getCustomer").build(5); 

It uses reflection under the hood, so the refactor is not so simple, but that's all that is available at the moment.

+2
source

In general, keep in mind that something sounds rather strange with the architecture of your application. It's hard to put your finger on, but the pattern of questions you ask raises a series of red flags about how you are going to do it. Keep in mind that if you want to create a RESTful API for your application that you might need to stop, take a few steps back and rethink what you are trying to do.

To your obvious questions ...

Now the question is: how can the server determine the path to a given resource? Can I do this programmatically through some JAX-RS API or do I need to implement code that uses reflection? (I know how to do the latter, but would prefer a different approach.)

The server knows the path that is always provided by the user and is used to navigate the collection of resource classes that make up your application. If you need an instance of UriInfo for a specific call, you must enter it as part of that specific call:

 @GET public String get(@Context UriInfo info) {...} 

Any information required from an external context (for example, what is a resource identifier) ​​is best conveyed during construction. You can re-view it from the URL (which can be obtained from UriInfo ), but this is probably the wrong approach.

Otherwise, if you are doing something much more complex, then you need to be more specific in your question.

  • At that moment when I need to know the path, I do not have a request object at all. For example, I have a timer that does some background processing and then changes some objects in the domain model and then informs all clients about the changed entities (including their paths).
  • I know that as part of the request, I can add a UriInfo object that provides this, but I need to know the path in advance (to inform clients about changes that have not necessarily occurred through JAX-RS).

How are you going to inform customers? Usually there is no mechanism for sending messages from the server to clients, and clients are usually protected from the firewall, so they cannot host the service directly.

Theoretically, you can link (explicitly, by URL) each resource with its own RSS feed, which the client could listen to if they selected. You cannot make customers listen, but you can give them the opportunity to do so. If you go along this route, you don’t need to know UriInfo “ahead of time”, because the location information will be present at key points (i.e., when creating the resource), and then you simply refer to the fact that you have control.

But this is only one way to do this, and it adds a lot of complexity; you would only do this if it was important to your application. It is often easier to just do a customer survey from time to time. (Note that some types of modifications are inherently very destructive, especially by changing the identifier or deleting a resource. Do not expect something to smoothly deal with them.)

  • I do not want to repeat the path information elsewhere, and I also do not want to have a set of path fragment constants for each resource type (in this case, “ /users ” and “ /{id} ”).

Tough. Repeated information in several places, if you are conducting it sequentially from the source of one , is common practice. There is nothing wrong.

+1
source

As I understand your question, you want to know the path as the request arrives, but before it gets to your resource; are you open to using servlet filters?

Special JAX-RS filters are supported only in version 2.0

0
source

For the record: after I posted the question, I thought a little about our architecture and came to the conclusion that submitting URLS is not as useful as I thought. In any case, the application must know some information about the structure of the application:

  • Continuing the above example: even if the client did not know the URL pattern for individual users, he should assume that there is a list of users and know his URL; it also has hard-coded knowledge about which dialog to display for user editing, etc.

So, in general, trying to tell the client (yourself) the URL that he needs is not worth the effort. Instead, we decided to go with a custom API definition file that includes data about the contents of the resources and their URL scheme. This file is used to create the following:

  • resource server classes with valid JAX-RS annotations
  • other URL code schema specification document for other developers
  • for our own client (including the URL, for example, the user with identifier 5 has a URL ...), so we don’t need to worry about inconsistencies between our client and server.

This approach has the following advantages:

  • The need for the server to determine the URLs from the annotations disappears, as the client can do this on his own as soon as he receives a notification that includes the identifier of the object.
  • We do not need to worry about inconsistencies between our client and server, since all information is derived from one source.
  • We have one source for the API definition in the version control section, which you can use to check backward compatibility with older versions.

Note: I probably would not argue that the resulting API remains "true" to the RESTful web services idea, but it works for us, and the elements that it takes from the "real" REST architectural style should make the API more understandable and understandable than a traditional contract is the first web service.

0
source

All Articles