0

It's really nice to have automatic binding with Jersey-Jackson (well, I believe it's actually MOXy the one who manages the bindings), so object serialization and deserialization is done under the hood.

Examples of both that I use in my RESTful service:

@POST
@Consumes(MediaType.APPLICATION_JSON)
public String createTournament(Tournament tournament) {
    return tournamentDao.create(tournament);
}

@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Tournament getTournament(@PathParam("id") String id) {
    Optional<Tournament> optTournament = tournamentDao.getTournament(id);
    if (optTournament.isPresent())
        return optTournament.get();
    throw new NotFoundException();
}

But what if the serialization or the deserialization fails at some point during the process? For example, unknown fields, wrong types, illegal JSON format, etc... Well, I can't deal with this because the serialization/deserialization is happening behind the scenes and all I know is I will get an argument of type Tournament (or return it in the other case) but this assumes the process is going to be successfull.

How can I deal with this? What if I wanted to return some other kind of response for a badly formatted tournament JSON instead of having an exception thrown during a very particular point of the serialization/deserialization?

Is this possible? Also, what is the standard approach for these scenarios? What response would be appropriate for a failure during JSON processing?

1

The proper HTTP error code on input is 400: Bad Request. In the response you could go with 500.

If there is an error in marshalling or unmarshalling, an exception will be thrown which you can handle by registering an ExceptionMapper (scoll down to the Exception Mapping section). You can then determine what kind of error to throw. The JAX-RS package has a class WebApplicationException which allows you to return the common HTTP error codes. If you need to get really fancy, you can use the ResponseBuilder to fine tune the response.

I personally find it very helpful to write the javax.ws.rs.core.Application myself and override the getClasses() method like so:

public Set<java.lang.Class<?>> getClasses()
{
    Set<Class<?>> classes = new HashSet<>();

    /* add filters */
    classes.add(AuthorizationFilter.class);
    /* add resources */
    classes.add(HomeResource.class);
    classes.add(RequestsResource.class);

    /* add object serializers */
    classes.add(JsonMarshaller.class);
    classes.add(HtmlWriter.class);

    return classes;
}

Put Jersey in an embedded Jetty application (or similar) if you want to be XML-free.

This will take a lot of the mystery out of how things work. The kind of issue you are running into is why I tend to avoid the "we've done everything for you so you don't have to understand it" packages for JAX-RS. If you implement your own MessageBodyReader and MessageBodyWriter classes, you can still use a package that does all the heavy lifting but have some control over these kind of details.

  • I don't see how I could ever catch those exceptions in the methods, as you say. Could you provide an example or be more specific? – dabadaba Jun 22 '16 at 14:42
  • @dabadaba Sorry, you are right. Need more coffee I guess. I'll fix the answer. – JimmyJames Jun 22 '16 at 14:49
  • This is a good answer. However, I wouldn't want to map all occurrences of exceptions that happen in the server. Only those that happen during marshaling or unmarshaling. For example, during the unmarshalling process I can get a NPE because a JSON node is missing. I would want to deal with that NPE when creating a tournament through the service, but if the NPE comes from another place that has nothing to do with this, I wouldn't want it mapped to anything. – dabadaba Jun 22 '16 at 16:44
  • @dabadaba If you really want to do it only in the un/marshalling, you probably want to create a your own MessageBodyReader and MessageBodyWriter classes that call to your binding framework and throw a WebApplicationException from there. BTW, are you sure the framework you are using doesn't throw the right error code? – JimmyJames Jun 22 '16 at 16:55
  • Yes I am sure. NPE can be thrown if a retrieved node is null (it's missing) and then I try calling a method on it. How about this?: I create a custom exception MalformedJsonException and I edit my deserializers and serializers and make them throw it if the JSON format is not what's expected. Then I register an ExceptionMapper<MalformedJsonException>. Does this make sense? Would this be a good approach? – dabadaba Jun 22 '16 at 16:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.