Search code examples
http-status-code-404bean-validationnumberformatexceptionhttp-status-code-400cxfrs

CXF REST Bean Validation gives a 404 Not Found instead of 400 Bad Request


I have a CXF RS Rest Resource which looks like this :

public class SomeRestResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("path")
    public Response getResource(

        @DecimalMin(value = "0.01", message="Weight should be minimum {value}.")
        @Digits( integer = 5, fraction = 2, message = "Weight should be maximum of {integer} integer and {fraction} fractional digits." )
        @QueryParam("weight") double weight)

        // do some operations with weight here...
        }      
     }

I am expecting the REST client to enter the weight as a double with minimum value of 0.01 and a maximum value of 5 digits and 2 fractions in the format xxxxx.yy.

When I test this REST resource using the value of weight as 0, it gives me a 400 BAD REQUEST with the message Weight should be maximum of 0.01 which is correct!

But, when I enter the value of weight as AB, it gives me a 404 NOT FOUND at the client side, and fails with the following Java exception :

Caused by: java.lang.NumberFormatException: For input string: "AB"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1241)
at java.lang.Double.valueOf(Double.java:504)
at org.apache.cxf.common.util.PrimitiveUtils.read(PrimitiveUtils.java:75)
at org.apache.cxf.jaxrs.utils.InjectionUtils.handleParameter(InjectionUtils.java:361)

Shouldn't it recognize the input type as not a double and validate against the datatype as well? What should I do so that it returns a 400 for input strings like AB as well?


Solution

  • There is an ugly workaround for this which is to keep the datatypes for all the query parameters in the REST resource to String and then apply validation on those Strings using regular expressions. For instance, for the above mentioned scenario for a double with minimum value of 0.01 and a maximum value of 5 digits and 2 fractions in the format xxxxx.yy, it can be done in the following way :

    public class SomeRestResource {
    
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("path")
    public Response getResource(
    
        @NotNull @Pattern(regexp = "^[0-9]{0,5}[.]{0,1}[0-9]{0,2}$")
        @QueryParam("weight") String weight)
    
        // do some operations with weight here...
        }      
     }
    

    Now, if a REST client enters the value of AB for weight, it will give a 400 BAD REQUEST.