Advanced use of the Jersey resource model: variable annotation for entity - jersey-2.0

I need to use the programmatic API to build a Jersey resource method and define its handling method/class/inflector. At the end, the resource should look like something like this:
#Path("helloworld")
public class HelloWorldResource {
#POST
#Consumes("text/plain")
public String getHello(
#CustomEntityAnnotation("World") CustomEntityClass name) {
return "Hello " + name.toString() + "!";
}
}
But I need to build many such resources with different values for paths and more importantly: different values for the #CustomEntityAnnotation annotation.
Let me add that this annotation must later be accessed by a ContainerResponseFilter, and by a MessageBodyWriter<CustomEntityClass>.
Unfortunately, I can't find in the docs where I shall add this annotation to the resource Method model builder, and what should be the signature of the method handler.
Any help would be very much appreciated.
Kind regards,
Maxime

Related

Where to put #OpenAPIDefinition?

The documentation for defining general API information using the quarkus-smallrye-openapi extension is extremely sparse, and does not explain how to use all the annotations for setting up the openApi generation.
For some background, I am using a clean and largely empty project (quarkus version1.0.1.FINAL) generated from code.quarkus.io, with a single class defined as followed (With the attempted #OpenAPIDefinition annotation):
#OpenAPIDefinition(
info = #Info(
title = "Custom API title",
version = "3.14"
)
)
#Path("/hello")
public class ExampleResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}
I have eventually found that general api information (contact info, version, etc) through much digging is defined using the #OpenAPIDefinition annotation, but when used on my existing endpoint definition, no changes are made to the generated openapi specification. What am I doing wrong?
Try putting the annotation on the JAX-RS Application class. I realize you don't need one of those in a Quarkus application, but I think it doesn't hurt either. For reference in the specification TCK:
https://github.com/eclipse/microprofile-open-api/blob/master/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/JAXRSApp.java

How to map different actions to Web API methods that would have same signature

I am trying to create a REST service using Web Api best practices and I came to a situation I don't know how to handle.
Imagine I have groups and inside of each group I have users.
This is how my GroupController looks like:
[RoutePrefix("api/v1/groups")]
public class GroupsController : ApiController
{
[HttpGet]
[Route("{id:int}")]
public IHttpActionResult Get(int id)
{
return Ok();
}
// I also want to add endpoint which fetches all the users inside of group and I'd like to do it like this:
[HttpGet]
[Route("{id:int}/users")]
public IHttpActionResult Get(int id)
{
return Ok();
}
}
As you can see, my second method won't compile since we can not have two methods with the same signature in the same class.
My route template looks like the standart one:
config.Routes.MapHttpRoute(
name: "DefaultRouting",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
I know that I can add a route which maps also action method name but I was wondering if there's a better way for achieving my goal. I'd like to stick to the best principles for writing RESTful services. As I know, one of the suggestions is to avoid custom action names since this is more common for WCF services.
Don't mix MapHttpRoute() style routing configuration and attribute-based routing. It's simpler to use one or the other (I prefer attribute-based as it's explicit and allows for clearer class method names).
You also seem to not be calling the method necessary to enable attribute-based routing on your config - config.MapHttpAttributeRoutes().
Finally, I'd rename your methods as follows to ensure there is no clash in the method signatures: GetGroups(int id)and GetUsersForGroup(int id)

Jersey annotation #Path with empty value on class level do not work

I declared a rest service by adding #Path("/") on class level and then on method level I declared another #Path("cars"). It doesn't seem to find the service method unless the #Path() on the class level is not empty.
Any ideas why this can't happen?
if the code is like the following
#Path("/cars")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public interface CarService {
#POST
void create(Car car);
}
it works.
If it is like the below
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public interface CarService {
#POST
#Path("/cars")
void create(CarDto car);
}
it doesn't.
Few things you should aware while writing resource code,
1.You must use the appropriate method like get,post or put based on operation otherwise it throw 405 error.
2.You must specify a unique path to all otherwise it would conflicts. Having a method name as path name is better idea.
3.You should declare the produce and consume type appropriately.
Good luck, code well.

How to write jersey to match "/hello" and "/hello?name=Mike" with different method?

The client may request two urls with the same path but different query strings:
1. /hello
2. /hello?name=Mike
How to use jersey to define two different methods for each of them?
Here is an example:
#Path("/hello")
public class HelloResource {
#Produces("text/plain")
public String justHello() {}
// how to call this method only the query string has "name"
#Produces("text/plain")
public String helloWithName() {}
}
You can't do this, Jersey only matches the path. See http://jersey.java.net/nonav/documentation/latest/jax-rs.html for full details.
You can build your own switch based on the query parameter being present. In general, name=mike is not very RESTy anyways. Jersey does support:
/hello/{name}
And that's the way it's meant to be used.
Actually you can. You just need to have a single method mapped to /hello/ that checks for the query parameter. If it exists, delegate to another method as a sub-resource.
http://jersey.java.net/nonav/documentation/latest/jax-rs.html#d4e374

Best practice in dependency injection

This is a question about how best to do DI, so it's not tied to any particular DI/IoC framework because, well, framework should be chosen based on pattern and practice rather than the other way around, no?
I'm doing a project where repository has to be injected into services, a service may require multiple repositories and I'm curious about the pros and cons between following approaches:
Inject repositories in service constructor
public class SomeService : ISomeService
{
private IRepository1 repository1;
private IRepository2 repository2;
public SomeService(IRepository1 repository1, IRepository2 repository2)
{
this.repository1 = repository1;
this.repository2 = repository2;
}
public void DoThis()
{
//Do something with repository1
}
public void DoThat()
{
//Do something with both repository1 and repository2
}
}
Inject a custom context class that include everything any service may need but lazy instantiated (the IServiceContext will be a protected field in BaseService)
public class SomeService : BaseService, ISomeService
{
public SomeService(IServiceContext serviceContext)
{
this.serviceContext= serviceContext;
}
public void DoThis()
{
//Do something with serviceContext.repository1
}
public void DoThat()
{
//Do something with both serviceContext.repository1 and serviceContext.repository2
}
}
Inject into methods that need them only
public class SomeService : ISomeService
{
public void DoThis(IRepository1 repository1)
{
//Do something with repository1
}
public void DoThat(IRepository1 repository1, IRepository2 repository2)
{
//Do something with both repository1 and repository2
}
}
Some pointers would be appreciated, moreover what're the aspects that I should consider in evaluating alternative like these?
The preferred way of injecting dependencies is Constructor Injection.
Method Injection is less ideal, because this will quickly result in having to pass around many dependencies from service to service and it will cause implementation details (the dependencies) to leak through the API (your method).
Both options 1 and 2 do Constructor Injection, which is good. If you find yourself having to inject too many dependencies in a constructor, there is something wrong. Either you are violating the Single Responsibility Principle, or you are missing some sort of aggregate service, and this is what you are doing in option 2.
In your case however, your IServiceContext aggregate service is grouping multiple repositories together. Many repositories behind one class smells like a unit of work to me. Just add a Commit method to the IServiceContext and you will surely have a unit of work. Think about it: don't you want to inject an IUnitOfWork into your service?
The first option seems to be the most natural from a DI perpective. The service class requires both repositories to perform its function, so making them required in order to construct an instance makes sense semantically (and practically).
The second option sounds a bit like Service Location, which is generally considered an anti-pattern (see http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx). In a nutshell, it creates implicit dependencies, where explicit dependencies are always preferred.
I would do either constructor based injection or property based injection. I would not pass in a context that contains the dependencies unless that context is serving some other purpose.
I prefer constructor based injection for required dependencies, as it makes it super easy for the object creation to blow up if something is missing. I got that from here. If you are going to verify that your dependencies are met, then you have to do it with constructor based injection, since there is no way to tell which setter is the last setter to be fired.