I am using Jackson to interpret JSON responses from an API that I am writing. I would like, as a standard throughout my API, to throw errors from the API to the program with something like:
{"errorMessage":"No such username."}
So I want my response processor to first check if the response is just a single errorMessage key, and if so to handle the error, and if not, then to interpret it as whatever response it was expecting from that command.
So here's my code:
public class ProcessingException extends Exception {
private String errorMessage;
public ProcessingException(){}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
and then, in my response handler:
@Override
public void useResponse(InputStream in) throws IOException, ProcessingException {
// turn response into a string
java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\\A");
String response = s.hasNext() ? s.next() : "";
ProcessingException exception;
try {
// Attempt to interpret as an exception
exception = mapper.readValue(response, ProcessingException.class);
}
catch(IOException e) {
// Otherwise interpret it as expected. responseType() is an abstract TypeReference
// which is filled in by subclasses. useResponse() is also abstract. Each subclass
// represents a different kind of request.
Object responseObj = mapper.readValue(response, responseType());
useResponse(responseObj);
return;
}
// I needed this out of the try/catch clause because listener.errorResponse might
// actually choose to throw the passed exception to be dealt with by a higher
// authority.
if (listener!=null) listener.errorResponse(exception);
}
This works beautifully, except under one circumstance - there are some requests that actually don't need to respond with anything, so they return {}
. For some reason, this response completely runs through the exception = mapper.readValue(response, ProcessingException.class);
line without triggering an IOException, so the program things that there is an error. But then when it tries to read what the error was, it throws a NullPointerException
when trying to read exception.getErrorMessage()
, because of course there is no error.
Why is it treating {}
as a valid ProcessingException
object?
Jackson doesn't have bean validation. But what you can do is to declare constructor as a JsonCreator that will be used to instantiate the new object and check/throw an exception in case if that field is null:
class ProcessingException {
private String errorMessage;
@JsonCreator
public ProcessingException(@JsonProperty("errorMessage") String errorMessage) {
if (errorMessage == null) {
throw new IllegalArgumentException("'errorMessage' can't be null");
}
this.errorMessage = errorMessage;
}
// getters, setters and other methods
}