Some notes about Jax-RS, HTTP statuses and Tomcat
if (Status.OK == response.getStatusInfo()) { // ... }
Jersey being a Jax-RS implementation, it is not chocking that the Jersey client also rely on Jax-RS. It is the case in this piece of code where Status is an enum defined by Jax-RS. But we had an issue with this code: on some environment it happened that our condition was false whereas the HTTP response status was actually 200 (meaning OK).
Truth is, the actual return type of getStatusInfo() is not Status but its intertace StatusType which is also defined by Jax-RS. StatusType define methods allowing to access to the content of a HTTP response status line: the status code (200, 400…) and the reason phrase which provide a short textual description of the status code (OK, BAD REQUEST…).
> GET /version HTTP/1.1 > Accept: */* < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: text/plain < Date: Wed, 17 May 2017 08:55:40 GMT
So, why using an interface here and not directly the enum ? First of all, because the Jax-RS Status enum is limited to standard response codes. The second reason is related to the reason phrase: all the classical reason phrases we know of (FORBIDDEN, BAD REQUEST…) are actually NOT mandatory to be used. As the RFC 2616 says:
The reason phrases listed here are only recommendations — they MAY be replaced by local equivalents without affecting the protocol
< HTTP/1.1 200 SURE, WHY NOT! < Server: Apache-Coyote/1.1 < Content-Type: text/plain < Date: Wed, 17 May 2017 08:55:40 GMT
final Response.StatusType status = reasonPhrase == null ? Statuses.from(code) : Statuses.from(code, reasonPhrase); public static StatusType from(int code) { StatusType result = Response.Status.fromStatusCode(code); return (result != null) ? result : new StatusImpl(code, ""); } public static StatusType from(int code, String reason) { return new StatusImpl(code, reason); }
if (OK.getStatusCode() == response.getStatusInfo().getStatusCode()) { // ... }
Another solution, less verbose but more risky, is to rely on the equals implementation of the status info that is returned:
if (response.getStatusInfo().equals(OK)) { // ... }
This solution is not safe because you cannot really guarantee that the reason phrase returned by your server will match the one defined in the enum. Also, the order of the expression matters because calling equals on an enum will actually compare references. This means that the following code will not work even if the reason phrase returned by the server is the same than the one contained in the enum:
if (OK.equals(response.getStatusInfo()) { // ... }
There is still a question to answer: why did this code failed on some of our environment ? Well, it happened that our local environment was using tomcat 8.5.x whereas other environments were using tomcat 7.x. And guess what: starting from 8.5, tomcat does not send reason phrases anymore by default.