0

I've been searching to find a way to customise exception thrown by Jackson bind on GAE.

The problem is that when I sent a string parameter where API method expects Integer throws a Jackson's InvalidFormatException. I want to customize the message thrown by the exception but I couldn't find a way. Please help with this.

For e.g:

@Api(
name = "echo",
version = "v1",
namespace =
@ApiNamespace(
    ownerDomain = "echo.example.com",
    ownerName = "echo.example.com",
    packagePath = ""
),
issuers = {
    @ApiIssuer(
        name = "firebase",
        issuer = "https://securetoken.google.com/YOUR-PROJECT-ID",
        jwksUri =
            "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system"
                + ".gserviceaccount.com"
    )
})

public class Echo {
   @ApiMethod(name = "echo")
   public Message echo(Message message, @Named("n") @Nullable Integer n) {
      return doEcho(message, n);
   }    
}

In the above code if the echo endpoint is hit with payload

enter image description here

then the response is

enter image description here

In this case is it possible to throw a custom exception or customize the message

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
Chaturasan
  • 23
  • 5

1 Answers1

0

To do that you need to register DeserializationProblemHandler

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.addHandler(new DeserializationProblemHandler() {
    @Override
    public Object handleWeirdStringValue(DeserializationContext ctxt, Class<?> targetType, String valueToConvert, String failureMsg) throws IOException {
        System.out.println("Handle parse problem for value = " + valueToConvert);
        throw new CanNotParseJsonException("Can not deserialise " + valueToConvert, null);
    }
});

Your exception should extend JsonMappingException in other case it will be wrapped. Example exception:

class CanNotParseJsonException extends JsonMappingException {

    public CanNotParseJsonException(String msg, Throwable problem) {
        super(null, msg, problem);
    }
}

See:

  1. Configure a Jackson's DeserializationProblemHandler in Spring environment
  2. Can't set ProblemHandler to ObjectMapper in Spring Boot
  3. Java Source
Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • I got the point what you are suggesting but my application is not Spring Boot based – Chaturasan Feb 16 '19 at 20:16
  • You do not need to have `Spring Boot` to make it work. You just need to configure `ObjectMapper` instance and it should work. I linked to some examples where `Spring Boot` is used but it is not required. – Michał Ziober Feb 17 '19 at 00:57
  • Ziober,I tried using Guice to configure it still it is not working `@Provides ObjectMapper ObjectMapperProvider() { ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.addHandler(new DeserializationProblemHandler() { @Override public Object handleWeirdStringValue(DeserializationContext ctxt, Class> targetType, String valueToConvert, String failureMsg) throws IOException { throw new JacksonBindingException("Can not deserialise " + valueToConvert, null); }}); return mapper;}` . I added this code in Guice module – Chaturasan Feb 17 '19 at 04:05
  • @Chaturasan, You need to be sure `Guice` uses this `ObjectMapper` which you have configured and for which created `ObjectMapperProvider` factory method. – Michał Ziober Feb 17 '19 at 15:10