We are experienced a strane bug when using field based validation with lazily initialized entities. I have an Employee entity which is contained in an EmployeeGroup. Our code looks like:
Code:
@Entity
public class Employee {
@Id
private int id;
@Valid
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
private EmployeeGroup group;
private String name;
public Employee() {
super();
}
public Employee(int id) {
super();
this.id = id;
}
public EmployeeGroup getGroup() {
return group;
}
public void setGroup(EmployeeGroup group) {
this.group = group;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Code:
@Entity
public class EmployeeGroup {
@Id
private int id;
@NotNull
private String name;
@OneToMany(mappedBy = "group", fetch = FetchType.LAZY)
private Set<Employee> employees = new HashSet<Employee>();
public EmployeeGroup() {
super();
}
public EmployeeGroup(int id, String name, Set<Employee> employees) {
super();
this.id = id;
this.name = name;
this.employees = employees;
}
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Our test code looks like:
Code:
@Override
protected void onSetUpBeforeTransaction() throws Exception {
super.onSetUpBeforeTransaction();
startNewTransaction();
EntityManager entityManager = createContainerManagedEntityManager();
employee = new Employee(EMPLOYEE_ID);
employees.add(employee);
employeeGroup = new EmployeeGroup(EMPLOYEE_GROUP_ID, GROUP, employees);
employee.setGroup(employeeGroup);
entityManager.persist(employeeGroup);
entityManager.persist(employee);
setComplete();
endTransaction();
}
public void testSaveChangedEmployee() throws Exception {
EntityManager entityManager = createContainerManagedEntityManager();
Employee findEmployee = entityManager.find(Employee.class, EMPLOYEE_ID);
assertNotNull(findEmployee);
findEmployee.setName("Hans");
findEmployee.getGroup().getEmployees().add(findEmployee);
entityManager.persist(findEmployee);
setComplete();
endTransaction();
}
With this test code we're getting an Validationexception because the validator accesses the employe group proxies fields (which are always null) via refelection directly instead of using the getter methods. When I move the validation annotations to the getter methods everything works fine. So we have a workaround for the problem, but to us this strange behavior looks like breaking the transparency of using lazy initialized entities. One might even consider this as a bug! What do you think?
Best regards,
Matthias