Reputation: 534
I'm writting my application using Spring MVC. I want to validate is e-mail exists in database when user is registering. I've written my own annotation constraint named UniqueEmail.
My User entity User.java:
@Entity
@Table(name="users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(name = "email", length = 100, nullable = false, unique = true)
@NotEmpty
@Email
@UniqueEmail(message = "E-mail is not unique")
private String email;
@Column(name = "password", nullable = false)
@NotEmpty
@Size(min = 5, message = "size must be more 5")
private String password;
}
My annotation constraint UniqueEmail.java:
@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = UniqueEmailValidator.class)
@Documented
public @interface UniqueEmail {
String message() default "Email is exist";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
My validator UniqueEmailValidator.java:
@Component
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
@Autowired
private UserService userService;
@Override
public void initialize(UniqueEmail uniqueEmail) {
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
try {
return userService.isExistEmail(s);
} catch (Exception e) {
System.out.println(e);
return false;
}
}
}
This code works in application.
When I run my test code its return NullPointerException. In my validation class userService is null.
I've read http://docs.spring.io/spring/docs/3.0.0.RC3/reference/html/ch05s07.html but cannot any solution.
Any idea?
Update
I use JUnit. UserClassTest.java
@ContextConfiguration("file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml")
public class UserClass {
private static Validator validator;
@BeforeClass
public static void setup() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
public void emailIsUnique() {
User user = new User();
user.setEmail("[email protected]"); // I've written exist email in DB.
Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "email");
assertEquals(1, constraintViolations.size());
assertEquals("E-mail is not unique", constraintViolations.iterator().next().getMessage());
}
}
Update
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="ru.yadoka"/>
<import resource="db/db-config.xml"/>
<!-- Apache tiles -->
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView"/>
</bean>
<!-- Mapping resources from theme -->
<mvc:resources mapping="/css/**" location="/resources/css/"/>
<mvc:resources mapping="/js/**" location="/resources/js/"/>
<mvc:resources mapping="/fonts/**" location="/resources/
<mvc:annotation-driven/>
Upvotes: 7
Views: 6390
Reputation: 2584
You can call injection all @Autowired service:
@Override
public void initialize(UniqueEmail uniqueEmail) {
org.springframework.web.context.support.SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
Upvotes: 3
Reputation: 19109
Don't you have a Validator configured in your bean context. If you are bootstrapping Validator via Validation.buildDefaultValidatorFactory(); you are bypassing the Spring mechanism and you get a Validator which is not aware of Spring beans and components. Hence injection is not working. In your test you want to get hold of the Spring provided Validator.
Upvotes: 3
Reputation: 3753
If your main code is working, then it should be straight forward to get your test working. You need to use @ContextConfiguration on your test class, see this for more details: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html
In general, there are 2 ways to test this:
For unit test, you need to create an instance of the UniqueEmailValidator and set a UserService on that instance (normally a mock UserServer).
For integration test, you need to have the spring context initialized as I mentioned above.
Upvotes: 0