Open jerseyrobot opened 11 years ago
@glassfishrobot Commented Reported by cowwoc
@glassfishrobot Commented cowwoc said: FYI, I tried asking this question on the mailing list and http://stackoverflow.com/q/17284419/14731 but got no answer.
@glassfishrobot Commented cowwoc said: It looks like I want to be able to create UriInfo from an arbitrary URI but the only way to get a UriInfo is using ContainerRequestContext.getUriInfo(). I tried ContainerRequestContext.setRequestUri(uri) but it failed with:
java.lang.IllegalStateException: Method could be called only in pre-matching request filter.
at org.glassfish.jersey.server.ContainerRequest.setRequestUri(ContainerRequest.java:329) ~[jersey-server-2.4.jar:na]
I can't use a request filter because I need to process this information inside resource methods (once I understand what kind of operation was invoked), besides which it sounds like this operation would be overkill for what I'm trying to accomplish.
@glassfishrobot Commented cowwoc said: Here is an example of how I would use this functionality. Imagine an API with Rooms, Participants, and Connections. Participants are users who joined a Room. Users send messages to each other through Connections (two participants per connection).
POST /rooms/31298
{
"from": "/rooms/31298/participants/31",
"to": "/rooms/31298/participants/32"
}
creates a connection between participants 31 and 32. How is the server supposed to honor this request? In Jersey 1.0 I would resolve each URI back to a resource. Each resource contains the following methods:
long getId(); URI getUri();
So, once I've got the resource, I invoke getId() to get the database identifier and create the connection. When someone invokes GET /connections/321213 I convert the database id to a resource and from there invoke getUri(). I take the resulting URI and add it to the response body.
@glassfishrobot Commented @mpotociar said: Reclassified as improvement.
@glassfishrobot Commented @mpotociar said: I'm not sure I fully follow. How do you convert the database Id to a resource?
Would these 2 methods help in your use case? https://jax-rs-spec.java.net/nonav/2.0/apidocs/javax/ws/rs/core/UriBuilder.html#fromResource(java.lang.Class https://jax-rs-spec.java.net/nonav/2.0/apidocs/javax/ws/rs/core/UriInfo.html#resolve(java.net.URI
@glassfishrobot Commented cowwoc said: Hi Marek,
How do you convert the database id to a resource?
In the above example, I'd have something like this:
class RoomResource
{
private final long id;
private final UriBuilder uriBuilder;
public RoomResource(RoomsResource parentResource, UriBuilder uriBuilder, long roomId)
{
this.parentResource = parentResource;
// Each parent passes a child resource its URI
this.uriBuilder = uriBuilder;
this.id = roomId;
}
public long getId()
{
return id;
}
public URI getUri()
{
return uri;
}
@POST
public Response RoomResource.createConnection(TwoParticipants participants)
{
long fromParticipant = uriToId(participants.getFrom());
long toParticipant = uriToId(participants.getTo());
Connection connection = Connection.insert(fromParticipant, toParticipant);
ConnectionResource connectionResource = getConnectionById(connection.getId());
return Response.created(connectionResource.getUri()).build();
}
@Path("{connectionId}/")
public ConnectionResource getConnectionById(long id)
{
return new ConnectionResource(this, uriBuilder.path(id + "/"), id);
}
Notice how I use both a conversion from URI to id and id to URI. As mentioned in https://java.net/projects/jersey/lists/users/archive/2013-11/message/62 I now realize that Jersey has no concept of what I call a HTTP Resource (meaning the concept of a resource independent of the response format). I'm looking for a mapping from URI to a resource, independent of the response format, and Jersey doesn't seem to have such a concept per-se. If it had such a concept, the question of how this feature should intersect with filters probably wouldn't be relevant because they wouldn't affect the URI to Resource mapping. Jersey 1.x ResourceContext.matchResource(URI) seemed to behave this way (although maybe not intentionally).
At this point, it's not clear how I can implement this without repeating the URI to Resource mapping twice (once for Jersey using @Path and sub-resource locators, once for my code that implements URI to Resource mapping).
@glassfishrobot Commented cowwoc said: It doesn't seem to be possible to implement this without your help.
I tried using ResourceModel to implement this outside of Jersey but:
It seems that all roads lead to Rome. Jersey needs to provide a mechanism to construct a UriInfo or ContainerRequest to an arbitrary URI.
If you know of another way, please point me in the right direction. I believe this is the only remaining feature preventing me from migrating to Jersey 2.
@glassfishrobot Commented cowwoc said: Another approach would be to fix #2757.
@glassfishrobot Commented levwais said: Hey Guys, This will be super useful for me. I want to create a new endpoint that will get, as a request, a list of URIs (other API endpoints) and will run them in a batch. The missing piece is to find a matching endpoint by a given URI which is something Jersey 1 had via ResourceContext.matchResource(URI) and now, in Jersey 2.x it is impossible.
Thanks, Lev Waisberg Jive Software
@glassfishrobot Commented cowwoc said: Lev,
Take a look at http://stackoverflow.com/a/23620747/14731
It's ugly code, but it works. We can only hope that this will get folded into Jersey proper (so we can use this functionality in a cleaner fashion).
@glassfishrobot Commented This issue was imported from java.net JIRA JERSEY-2172
In Jersey 1.0 we could look up a resource by URI using ResourceContext.matchResource(URI). There doesn't seem to be an equivalent functionality in Jersey 2.0.
Use-case: The request entity body references the URI of a resource. I need to convert this URI into a resource class, then drill down into its database id in order to honor the request.
Affected Versions
[2.4]