eclipse-ee4j / krazo

Apache License 2.0
50 stars 19 forks source link

Support sub-resource locators #338

Open erdlet opened 2 years ago

erdlet commented 2 years ago

In https://github.com/eclipse-ee4j/mvc-api/issues/17 was a discussion about supporting sub-resource locators. We should investigate and add this feature, as it helps to implement nested resources in a clear structure.

chkal commented 2 years ago

TBH: I never used sub-resource locators in any JAX-RS app so far. I wonder how widely used this feature actually is.

erdlet commented 2 years ago

I learned to like them within the past months :D In case you have nested resources like /books/{id}/authors it helps a lot to structure the code like the resource.

I think the effort to support them isn't too high, so we could give it a try?

chkal commented 2 years ago

Sure, if the effort isn't that high, it is definitely worth doing it.

BTW: How does CDI injection work for sub-resources?

erdlet commented 2 years ago

I pass the CDI beans from the main controller down to the sub-resource locator. But tbh, I'll need to have a deeper look into the spec for details.

chkal commented 2 years ago

I guess that CDI handling for sub-resources is one of the things that needs to be clarified as soon as Jakarta REST fully migrates to CDI...

erdlet commented 1 year ago

BTW: How does CDI injection work for sub-resources?

I tried this a few weeks ago in a plain Jakarta REST resource and you did something similar to this:

@RequestScoped
@Path("/foobar")
public class MyResource {

  @Inject
  private MySubResource subresource;

 @Path("/subresource")
  public MySubResource subresource() {
    return subresource;
  }
}

I got all my injections resolved properly and had no problem.

chkal commented 1 year ago

Thanks for sharing this example. Injecting the sub-resource and returning it from the resource method should work fine. I fully agree to this.

I just wonder if this pattern works for real-world use cases. Because typically you will have to pass some kind of context to the sub resource instance. Like the ID of the parent entity or something like this. Just like in the example from the JAX-RS spec:

https://jakarta.ee/specifications/restful-ws/3.1/jakarta-restful-ws-spec-3.1.html#sub_resources

In this example, an ID is passed to the constructor of the sub-resource, which kind of makes sense. However, this would require to manually create an instance of the sub-resource, and therefore you won't get injection support for that object out of the box.

Not sure if I'm missing something here. I'm just trying to understand how this could work in practice.

erdlet commented 1 year ago

I just wonder if this pattern works for real-world use cases. Because typically you will have to pass some kind of context to the sub resource instance. Like the ID of the parent entity or something like this.

TBH I solved this by adding some 'wither' setting the context information and returning the injected instance again. Works like a charm but truly isn't an absolutely clean solution. But on the other side, this is still more readable / maintainable than gigantic controllers with deep resource paths.

The example above would look like this:

@RequestScoped
@Path("/foobar")
public class MyResource {

  @Inject
  private MySubResource subresource;

 @Path("/{id}/subresource")
  public MySubResource subresource(@PathParam("id") final Long id) {
    return subresource.withFoobarId(id);
  }
}
chkal commented 1 year ago

Interesting pattern. I agree that this is most likely the best solution out there.

It would be interesting to learn which aspects of the spec are currently not compatible with sub-resources.