1

Am trying to build a REST post web service with a request body. Using swagger and jersey for the same .

I have defined following for one of the attributes of the Body : ( contrived example )

 petType:
            description: Type of Pet
            type: string
            enum:
                - CAT
                - DOG

I would like to throw a http 400 exception in case of the incoming request not containing CAT or DOG.

However I am never getting a chance to handle the data and throw a Http 400 . Instead in Postman I get a Http 500 . Stacktrace :

Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type au.com.xyz.PetRequest$PetTypeEnum from String "DONKEY": value not one of declared Enum instance names: [CAT, DOG] at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@12b7aa1a; line: 4, column: 14] (through reference chain: au.com.xyz.PetPromoRequest["petType"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:74)
at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1410)
at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:926)
at com.fasterxml.jackson.databind.deser.std.EnumDeserializer._deserializeAltString(EnumDeserializer.java:189)
at com.fasterxml.jackson.databind.deser.std.EnumDeserializer.deserialize(EnumDeserializer.java:126)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:504)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:104)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1583)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:964)

So it looks like even before I get a chance to validate Jackson / swagger / jersey are doing some stuff - which I ideally dont want them to !

Any thoughts please ?

UPDATE: Based on answer from Natasha have tried the following and it still does not work

option#1 Added @Priority annotation to the exception mapper:

@Provider
@Priority(1)
public class AppExceptionMapper implements ExceptionMapper<AppException> {

This did not work .

option#2 Added the following in web.xml:

 <servlet>
    <servlet-name>jersey</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.disableAutoDiscovery</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

I keep getting the same exception:

Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type au.com.xyz.PetRequest$PetTypeEnum from String "DONKEY": value not one of declared Enum instance names: [CAT, DOG] at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@12b7aa1a; line: 4, column: 14] (through reference chain: au.com.xyz.PetPromoRequest["petType"]) at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:74) at com.f

akila
  • 667
  • 2
  • 7
  • 21

1 Answers1

2

You can disable Jersey's auto discovery feature : resourceConfig.property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true); where resourceConfig is of type org.glassfish.jersey.server.ServerConfig.

Here's an existing thread for Jersey's exception handler : Jersey unable to catch any Jackson Exception

UPDATE:

For resolving Jackson error : value not one of declared Enum instance names

You can throw desired exception using @JsonCreator :

public enum PET {
    CAT("cat"),
    DOG("dog");

    private static MappingChange.Map<String, PET> FORMAT_MAP = Stream
            .of(PET.values())
            .collect(Collectors.toMap(s -> s.formatted, Function.identity()));

    private final String formatted;

    PET(String formatted) {
        this.formatted = formatted;
    }

    @JsonCreator // This is the factory method and must be static
    public static PET fromString(String string) {
               // Throw desirable exception here
        return Optional
                .ofNullable(FORMAT_MAP.get(string))
                .orElseThrow(() -> new IllegalArgumentException(string));
                
    }
}

Existing Thread: Deserializing an enum with Jackson

Rudy Vissers
  • 5,267
  • 4
  • 35
  • 37
nitashathakur
  • 430
  • 3
  • 9
  • Thanks Natasha based on your feedback I have tried a few more options but they have not worked . Please see my edited feedback based on your input – akila Apr 10 '19 at 20:42
  • Hey Akila, I have updated the answer. Try the same and let us know. – nitashathakur Apr 11 '19 at 06:53