{"id":1372,"date":"2012-05-27T15:51:58","date_gmt":"2012-05-27T20:51:58","guid":{"rendered":"http:\/\/unitstep.net\/?p=1372"},"modified":"2012-05-27T15:51:58","modified_gmt":"2012-05-27T20:51:58","slug":"jax-rsjersey-needs-an-required-annotation-for-parameters","status":"publish","type":"post","link":"https:\/\/unitstep.net\/blog\/2012\/05\/27\/jax-rsjersey-needs-an-required-annotation-for-parameters\/","title":{"rendered":"JAX-RS\/Jersey needs an @Required annotation for parameters"},"content":{"rendered":"
I’ve been using Jersey as a JAX-RS implementation for a little while now, and one thing that it could benefit from is the addition of an This isn’t so much of an issue for The behaviour of such a required annotation might be as follows:<\/p>\n Right now, there’s not really an elegant way to make something like a Parameter classes<\/a> can be useful for transforming the single input of a parameter into a single output, and also for verifying that the input parameter value is valid. This can be useful for ensuring that an input parameter can be converted into a specific object, or that it matches a specific format. <\/p>\n As an example, consider the Note: The following examples use the However, if the parameter is not present at all – for example, if this was obtained via the We need something that gets rid of the necessary null-checking in each resource method.<\/p>\n Coda Hale provides another brilliant example how to use Injection Providers<\/a> in Jersey. Basically, with Injection Providers, you can do everything that you could do with Parameter classes, and more.<\/p>\n While Parameter classes are useful only for single-input to single-output mapping, Injection Providers can map multiple inputs to single or multiple outputs. This could allow you to take multiple values in the HTTP<\/acronym> request and use them populate a single Bean, or use them to form some more complex single value. It also allows you to do validation, as throwing a So, we can achieve a similar effect using an Injection Provider. A first attempt at resolving the issue yields the CsvListProvider class:<\/p>\n However, while this works as expected, it has the unfortunate side effect that the source of the parameter (an HTTP<\/acronym> header of “X-TEST”) has to be specified in the Provider class rather than on the annotation. This isn’t ideal since we have to create a new Injection Provider class for each HTTP<\/acronym> header we want to make required.<\/p>\n I have been trying to figure out a solution to this. One possible way might be to change the AbstractInjectableProvider to the following declaration:<\/p>\n We could then define a custom annotation type to take the place of It seems like we need a proper solution to this via a change in Jersey. Evidently, others have come to the same conclusion<\/a>, as there are at least two<\/a> issues<\/a> open for Jersey related to this.<\/p>","protected":false},"excerpt":{"rendered":" I’ve been using Jersey as a JAX-RS implementation for a little while now, and one thing that it could benefit from is the addition of an @Required annotation for resource method parameters. Right now, when parameters are not provided by the client\/request, they are simply set to null, creating the need for duplicated null-checking in […]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[208,197,396,395,137,156],"tags":[394],"_links":{"self":[{"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/posts\/1372"}],"collection":[{"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/comments?post=1372"}],"version-history":[{"count":21,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/posts\/1372\/revisions"}],"predecessor-version":[{"id":1400,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/posts\/1372\/revisions\/1400"}],"wp:attachment":[{"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/media?parent=1372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/categories?post=1372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/tags?post=1372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}@Required<\/code> annotation for resource method parameters. Right now, when parameters are not provided by the client\/request, they are simply set to
null<\/code>, creating the need for duplicated null-checking in resource methods. An
@Required<\/code> annotation would solve this issue and reduce code duplication.<\/p>\n
@PathParam<\/code> parameters, (since you won’t even get to the proper resource method without a matching URI) but it does affect
@HeaderParam<\/code> and
@QueryParam<\/code> (among others) since they aren’t needed for Jersey to determine which resource method to invoke. By that definition, they are implicitly optional. There should be a way to make them required.<\/p>\n
\n
Response<\/code> with
Status.BAD_REQUEST<\/code> (HTTP<\/acronym> 400) would be returned to the client.<\/li>\n
@HeaderParam<\/code> required. Here are some solutions I’ve tried.
\n<\/p>\nAttempt #1: Parameter classes<\/h3>\n
CsvListParam<\/code> class. This class takes a comma-separated list as a parameter, and returns a
List<String><\/code> comprising each entry in the list. It does an additional check to ensure that the input is not blank, according to StringUtils.isBlank()<\/a>. If it is blank, a 400 Bad Request response is returned to the client via the
WebApplicationException<\/code> thrown. <\/p>\n
AbstractParam<\/code> class from Coda Hale’s article<\/a>.<\/p>\n
public class CsvListParam extends AbstractParam<List<String>> {\r\n\r\n public CsvListParam(String param) throws WebApplicationException {\r\n super(param);\r\n }\r\n\r\n @Override\r\n protected List<String> parse(final String suppliedStringValue) throws Throwable {\r\n if (StringUtils.isBlank(suppliedStringValue)) {\r\n throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).build());\r\n }\r\n return Arrays.asList(StringUtils.split(suppliedStringValue, \",\"));\r\n }\r\n}\r\n\r\n@GET\r\n@Path(\"test\")\r\npublic Response test(@HeaderParam(\"X-TEST\") final CsvListParam param) {\r\n final String output;\r\n if (null != param) {\r\n output = param.getValue().toString();\r\n } else {\r\n output = \"param was null\";\r\n }\r\n return Response.ok(output).build();\r\n}<\/code><\/pre>\n
@HeaderParam<\/code> annotation and the header was not present – then the code in the parameter class will not even be invoked by Jersey<\/strong>. Instead, the value will simply be
null<\/code>. If we require this parameter, it results in nasty if-else null-checking code in each of our resource methods that requires the parameter.<\/p>\n
Attempt #2: Injection Providers<\/h3>\n
WebApplicationException<\/code> from an Injection Provider will cause the contained
Response<\/code> or status to be properly returned to the client.<\/p>\n
@Provider\r\npublic class CsvListProvider extends AbstractInjectableProvider<CsvListParam> {\r\n public CsvListProvider() {\r\n super(CsvListParam.class);\r\n }\r\n\r\n @Override\r\n public CsvListParam getValue(final HttpContext httpContext) {\r\n final String suppliedStringValue = httpContext.getRequest().getHeaderValue(\"X-TEST\");\r\n return new CsvListParam(suppliedStringValue);\r\n }\r\n}\r\n\r\n@GET\r\n@Path(\"test\")\r\npublic Response test(@Context final CsvListParam param) {\r\n final String output = param.getValue().toString();\r\n return Response.ok(output).build();\r\n}<\/code><\/pre>\n
Further attempts<\/h3>\n
public abstract class AbstractInjectableProvider<E, A extends Annotation> extends AbstractHttpContextInjectable<E> implements InjectableProvider<A, Type><\/code><\/pre>\n
A<\/code> instead of always using
@Context<\/code>. However, this doesn’t work, as we have no way of then obtaining any of the annotation’s values in the concrete Provider class. A solution like this would require changes in the core of Jersey to make it work, thus reducing the solution essentially the same as having an
@Required<\/code> annotation as proposed above.<\/p>\n
Conclusion<\/h3>\n