NullSafe and DTO validation for Bean Validation in service layer using Aspect.
$ ./mvnw clean install
<dependency>
<groupId>io.github.opensanca</groupId>
<artifactId>service-validator</artifactId>
<version>1.1.0</version>
</dependency>
compile 'io.github.opensanca:service-validator:1.1.0'
Service Validation provides a ServiceValidationAutoConfiguration.class
that allowed Auto Configuration mechanism.
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added. https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html
Service Validation provides a ServiceValidatorImport.class
that allowed easy way configure it.
@ComponentScan(basePackages={"seu.pacote","io.github.opensanca"})
OR
@Configuration
@ComponentScan
@Import(ServiceValidatorImport.class)
public class AppConfig {
//...
}
Because we use Bean Validation 1.1 JSR 349, you have to ensure there is a
provider for this specification available in your classpath, such as Hibernate Validator
or Apache BVal
. Note that if you are
using a JEE-compliant application server like WildFly
or TomEE
you already have one.
The absence of providers cause this error during Spring context startup:
javax.validation.ValidationException:
Unable to create a Configuration, because no Bean Validation provider could be found.
Add a provider like Hibernate Validator (RI) to your classpath.
OR
***************************
APPLICATION FAILED TO START
***************************
Description:
The Bean Validation API is on the classpath but no implementation could be found
Action:
Add an implementation, such as Hibernate Validator, to the classpath
Additionally, some Bean Validation providers may have dependencies of their own, like the Expression Language API, causing similar bootstrap errors like the following:
Caused by: javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'.
Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
We recommended to use Glassfish Web EL Implementation
in this case. Note that EL is also part of the JEE stack,
so you can safely ignore this if you're running a full-fledged application server.
public class DTO {
@NotNull
private String text;
@Max(10)
private Integer number;
public void setNumber(Integer number) {
this.number = number;
}
public void setText(String text) {
this.text = text;
}
}
Validate Javax Validations Constraints and NullSafe.
@Component
public class MyComponent {
@ServiceValidation
public void doSomething(final DTO dto) {
}
}
Validate Javax Validations Constraints only.
@Component
public class MyComponent {
@ServiceValidation(nullSafe = false)
public void doSomething(final DTO dto) {
}
}
Validate NullSafe arguments only.
@Component
public class MyComponent {
@ServiceValidation(javaxValidation = false)
public void doSomething(final DTO dto) {
}
}
@Component
public class MyComponent {
@ServiceValidation(nullSafe = false, javaxValidation = false) //Don't do this!
public void youDontNeedThis(DTO dto) {
}
}
There is an @ExceptionHandler
bundled in this library that automatically
translates ServiceValidationException
's to JSON. So you don't need to bother
writing your own should you decide to leverage this exception as an interface
with your API clients.
ServiceValidator provides custom org.hamcrest.Matchers
that allowed testing violations of
ServiceValidationErrorCollection.class
.
- errorCollectionHasSize
- errorCollectionHasViolation
import static io.github.opensanca.matchers.ServiceValidatorErrorMatcher.errorCollectionHasSize;
import static io.github.opensanca.matchers.ServiceValidatorViolationsMatcher.errorCollectionHasViolation;
@RunWith(SpringRunner.class)
public class CoolTest {
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void someCoolTest() {
exception.expect(ServiceValidationException.class);
exception.expect(errorCollectionHasSize(1));
exception.expect(errorCollectionHasViolation("DTO.text", "may not be null"));
exception.expect(errorCollectionHasViolation("DTO.text", "may not be empty"));
//
}
}