Hugo
Hugo

Reputation: 720

Override DropWizard ConstraintViolation message

So I want to change the validation messages used to validate a model through a DropWizard resource.

I'm using java bean validation annotations. For example here is one of the fields I want to validate:

@NotEmpty(message = "Password must not be empty.")

I can test this works as expected using a validator.

However when I use DropWizard to do the validation on the resource it adds some extra stuff to that message. What I see is this - password Password must not be empty. (was null) and I've found the code that does this here - https://github.com/dropwizard/dropwizard/blob/master/dropwizard-validation/src/main/java/io/dropwizard/validation/ConstraintViolations.java

Specifically this method -

public static <T> String format(ConstraintViolation<T> v) {
    if (v.getConstraintDescriptor().getAnnotation() instanceof ValidationMethod) {
        final ImmutableList<Path.Node> nodes = ImmutableList.copyOf(v.getPropertyPath());
        final ImmutableList<Path.Node> usefulNodes = nodes.subList(0, nodes.size() - 1);
        final String msg = v.getMessage().startsWith(".") ? "%s%s" : "%s %s";
        return String.format(msg,
                             Joiner.on('.').join(usefulNodes),
                             v.getMessage()).trim();
    } else {
        return String.format("%s %s (was %s)",
                             v.getPropertyPath(),
                             v.getMessage(),
                             v.getInvalidValue());
    }
}

Is there any way I can override this behaviour? I just want to display the message that I set in the annotation...

Upvotes: 7

Views: 3671

Answers (3)

Sumant
Sumant

Reputation: 276

@ValidationMethod should be useful here. isn't it?

http://www.dropwizard.io/0.9.0/docs/manual/validation.html

@ValidationMethod(message="Password cannot be empty")
@JsonIgnore
public boolean isPasswordProvided() {
    return false if password not provided;
}

Upvotes: 0

Lukasz Wiktor
Lukasz Wiktor

Reputation: 20422

Here is a programmatic solution in dropwizard 0.8:

public void run(final MyConfiguration config, final Environment env) {
    AbstractServerFactory sf = (AbstractServerFactory) config.getServerFactory();
    // disable all default exception mappers
    sf.setRegisterDefaultExceptionMappers(false);
    // register your own ConstraintViolationException mapper
    env.jersey().register(MyConstraintViolationExceptionMapper.class)
    // restore other default exception mappers
    env.jersey().register(new LoggingExceptionMapper<Throwable>() {});
    env.jersey().register(new JsonProcessingExceptionMapper());
    env.jersey().register(new EarlyEofExceptionMapper());
} 

I think it's more reliable than a config file. And as you can see it also enables back all other default exception mappers.

Upvotes: 9

Natan
Natan

Reputation: 2858

ConstraintViolationExceptionMapper is the one which uses that method. In order to override it, you need to deregister it and register your own ExceptionMapper.

Remove the exception mapper(s)

Dropwizard 0.8

Add the following to your yaml file. Note that it will remove all the default exception mappers that dropwizard adds.

server:
    registerDefaultExceptionMappers: false

Dropwizard 0.7.x

environment.jersey().getResourceConfig().getSingletons().removeIf(singleton -> singleton instanceof ConstraintViolationExceptionMapper);

Create and add your own exception mapper

public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {

    @Override
    public Response toResponse(ConstraintViolationException exception) {
        // get the violation errors and return the response you want.
    }
}

and add your exception mapper in your application class.

public void run(T configuration, Environment environment) throws Exception {
  environment.jersey().register(ConstraintViolationExceptionMapper.class);
}

Upvotes: 8

Related Questions