Our REST API is written in Java with JAX-RS.
We make use of the @QueryParam annotation in front of the parameters which come from the query :
Standard code:
@GET
@Path("my-endpoint")
@Produces(MediaType.APPLICATION_JSON)
public Response getMyEndpoint(
@QueryParam("someId") final Integer someId
) {
...
}
Given the nature of @QueryParam, it is accepted that someId will be null if anything wrong happens (missing, or bad value, etc.)
We would like to slightly muscle up on the early validation, but without breaking things.
For example, one way of breaking things would be to do this :
Bad code:
@GET
@Path("my-endpoint")
@Produces(MediaType.APPLICATION_JSON)
public Response getMyEndpoint(
@NotNull @QueryParam("someId") final Integer someId
) {
...
}
Because @QueryParam would still return null if the value is “bad”, but then the @NotNull would raise an exception at runtime and we would end up with error HTTP 500 instead of HTTP 400.
We have implemented a custom annotation @NeededQueryParams
that checks all required parameters at once, like this :
What we have:
@NeededQueryParams({"someId", "someOtherValue"})
@GET
@Path("my-endpoint")
@Produces(MediaType.APPLICATION_JSON)
public Response getMyEndpoint(
@QueryParam("someId") final Integer someId,
@QueryParam("someOtherId") final Integer someOtherIdId,
) {
...
}
It wasn’t too hard, we just introduced a new interface like this :
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NeededQueryParams {
String[] value(); // represents an array
}
And then we wrote the corresponding NeededQueryParamsFilter
class
I don’t really like it because it is somewhat redundant to @QueryParam, plus I do not like this array structure. I would prefer the requirements to remain on a per-param basis, like this :
What we would like:
@GET
@Path("my-endpoint")
@Produces(MediaType.APPLICATION_JSON)
public Response getMyEndpoint(
@NeededQueryParam("someId") final Integer someId,
@NeededQueryParam("someOtherId") final Integer someOtherIdId,
) {
...
}
Is there a way to “replace” JAX-RS’ @QueryParam
with my own @NeededQueryParam
?
Bonus points: If yes, ideally without breaking JAX-RS? I.e. what would be the simplest way to work from the existing implementation instead of replacing it entirely? (I don’t want to introduce weird bugs if JAX-RS keeps evolving). I’m open to chaining the annotations if needed :
Possible alternative solution:
@QueryParam("someOtherId") @IsNeeded final Integer someOtherIdId