I think this is a more generic java question, but I'll explain what I'm trying to do and hopefully someone can point me the right way;
I'm trying to create a generic abstract class that all my resources can extend from.
The abstract class has basic CRUD implementations for the standard stuff
@Produces("application/vnd.api+json")
@Consumes("application/vnd.api+json")
public abstract class AbstractResource {
static final Logger LOGGER = LoggerFactory.getLogger(AbstractResource.class);
AbstractRepository repository;
AbstractResource(AbstractRepository repository) {
this.repository = repository;
}
@GET
public Response getAll(@Auth User user, @QueryParam("query") String query) {
String result = query != null ? repository.getByQuery(query) : repository.getAll();
return Response.status(Response.Status.OK).entity(result).build();
}
@GET
@Path("/{id}")
public Response getById(@Auth User user, @PathParam("id") String id) {
String result = repository.getById(id);
return Response.status(Response.Status.OK).entity(result).build();
}
@POST
public Response save(@Auth User user, String payload) {
String result = repository.save(payload);
return Response.status(Response.Status.OK).entity(result).build();
}
@PATCH
@Path("/{id}")
public Response update(@Auth User user, @PathParam("id") String id, String payload) {
String result = repository.update(payload);
return Response.status(Response.Status.OK).entity(result).build();
}
@DELETE
@Path("/{id}")
public Response delete(@Auth User user, @PathParam("id") String id) {
repository.delete(id);
return Response.status(Response.Status.NO_CONTENT).build();
}
}
I can use this without a problem simply doing
@Path("/movies")
public class MovieResource extends AbstractResource {
public MovieResource(MovieRepository repository) {
super(repository);
}
}
and I can now access all the methods and override as required.
Where I run into problems is when I need to overload a method. Take the first getAll
method from the abstract class as example, I want to change the parameters in only the Movie.class
@Path("/movies")
public class MovieResource extends AbstractResource {
public MovieResource(MovieRepository repository) {
super(repository);
}
@GET
public Response getAll(@Auth User user, @QueryParam("query") String query, @QueryParam("limit") String limit, @QueryParam("page") String page) {
String result = repository.getPaginated(limit, page);
return Response.status(Response.Status.OK).entity(result).build();
}
}
So the getAll
method has a different set of parameters in just the Movie.class
. This causes Jersey to blow up with
[[FATAL] A resource model has ambiguous (sub-)resource method for HTTP method GET and input mime-types as defined by"@Consumes" and "@Produces" annotations at Java methods public javax.ws.rs.core.Response space.cuttlefish.domain.resources.MovieResource.getAll(space.cuttlefish.domain.model.User,java.lang.String,java.lang.String,java.lang.String) and public javax.ws.rs.core.Response space.cuttlefish.domain.resources.AbstractResource.getAll(space.cuttlefish.domain.model.User,java.lang.String) at matching regular expression /movies. These two methods produces and consumes exactly the same mime-types and therefore their invocation as a resource methods will always fail.; source='org.glassfish.jersey.server.model.RuntimeResource@6a1ef65c']
Because the original getAll
method of the abstract already has the @GET
annotation.
So, how do I go about solving this?
Do I remove all the annotations from the abstract class, and then have to override and re-add the annotations in each resource? That just seems messy and prone to error... There must be a better solution here?
Is there something blindingly obvious I've just overlooked?
Would love some help!
Aucun commentaire:
Enregistrer un commentaire