I had similar problem.
My message was defined as such:
import jakarta.validation.constraints.NotBlank;
public class ValidatedBook {
@NotBlank
public String name;
}
I sent messages on proper queue like those:
{
"name":"asd" # should pass
}
{
"name":"" # should fail
}
{
# should fail
}
And I had listener defined like this:
import jakarta.validation.Valid;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
@Component
@Validated
public class QueueReceiver {
@RabbitListener(queues = "queue", errorHandler = "errorHandler")
public void receive(@Valid @Payload ValidatedBook book) {}
}
which did not validate ValidatedBook object, messages always passed validation.
I checked that validation should throw exception with manually written validation:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<ValidatedBook>> things = validator.validate(book);
Book was simply not valid, when name was empty or null, yet @Valid
did nothing!
Solution to my problem was adding additional annotation @Validated
on class-level:
@Component
@Validated
public class QueueReceiver {
@RabbitListener(queues = "queue", errorHandler = "errorHandler")
void receiver(@Valid @Payload ValidatedBook object) {}
}
Now messages which should fail - fail with ConstraintViolationException (do not enter method), and I can easily catch exception in ErrorHandler
class (* implements RabbitListenerErrorHandler
).
No qualifying bean of type 'org.springframework.validation.SmartValidator' available
– Appling