0

I can't make method level validation right. Or I don't understand how it works.

My application class is below. Very simple. It contains MethodValidationPostProcessor bean definition. It also runs Greeter service.

@SpringBootApplication
public class App implements CommandLineRunner {
    private final Greeter greeter;

    public App(Greeter greeter) {
        this.greeter = greeter;
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder().main(App.class).sources(App.class).web(false).run(args).close();
    }

    @Bean
    public org.springframework.validation.beanvalidation.MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }

    @Override
    public void run(String... args) throws Exception {
        final Input input = new Input();
        input.setName("j");
        final String messageFromInput = greeter.getMessageFromInput(input);

        final String messageFromString = greeter.getMessageFromString("j");
    }
}

Greeter service below. Here I do expect to validate input and output.

@Service
@Validated
public class Greeter {
    String getMessageFromInput(@Valid @NotNull Input name) {
        return "[From Input] Greetings! Oh mighty " + name + "!";
    }

    String getMessageFromString(@Size(min = 4) String name) {
        return "[From String] Greetings! Oh mighty " + name + "!";
    }
}

Input DTO is very simple as well.

public class Input {
    @NotEmpty
    @Size(min = 3)
    private String name;

    // Getters, setters and toString ommited.
}

Since the name in both cases, direct String and DTO, is only one letter I expect this setup to throw exception. Unfortunately, nothing happens and application completes successfully. It works with controller's methods. But I would like it to work with any bean's methods.

2
  • 1
    Don't use Greeter as a constructor argument. I guess this is triggering early creation of the bean, making it not a candidate for proxy creation anymore and hence validation isn't applied. Create a @Bean method which creates the CommandLineRunner and inject the Greeter as a method argument instead. Also make your methods public as AOP will only work on public methods. Commented Mar 13, 2017 at 7:17
  • You're right about the early bean creation. When I moved the runner to a bean factory method with Greeter as an argument it works fine. It seems that Greeter's public methods access is irrelevant. Now when you mentioned about it, I remember info in log file saying that Greeter is not eligible candidate for proxy. Now I know what the implications are. Commented Mar 13, 2017 at 7:56

1 Answer 1

2

You are injecting your Greeter bean as a constructor argument into the class annotated with @SpringBootApplication which is a @Configuration class. To satisfy that dependency the Greeter is created very early on in the startup process of the ApplicationContext and as such will remove it as a candidate for proxy creation.

Instead of injecting it as a constructor argument move your CommandLineRunner logic to a @Bean annotated method and simply inject the Greeter as a dependency. This will delay the creation of the bean and as such make it available for proxying.

@Bean
public CommandLineRunner runner(Greeter greeter) {
    return new CommandLineRunner() {

        @Override
        public void run(String... args) throws Exception {
            final Input input = new Input();
            input.setName("j");
            final String messageFromInput = greeter.getMessageFromInput(input);

            final String messageFromString = greeter.getMessageFromString("j");
        }
    };
}

Another thing is that your methods of the Greeter should be, due the the nature of proxies, public.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.