Taking the several threads as reference I ended up with the following solution:
I am using Spring-Boot 1.2.3.RELEASE (which is the current ga at the moment)
My use case was that described in this bug (DATAREST-373).
I needed to be able to encode the password of a User
@Entity
upon create, and have special logic upon save. The create was very straightforward using @HandleBeforeCreate
and checking the @Entity
id for 0L
equality.
For the save I implemented a Hibernate Interceptor which extends an EmptyInterceptor
@Component
class UserInterceptor extends EmptyInterceptor{
@Autowired
PasswordEncoder passwordEncoder;
@Override
boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {
if(!(entity instanceof User)){
return false;
}
def passwordIndex = propertyNames.findIndexOf { it == "password"};
if(entity.password == null && previousState[passwordIndex] !=null){
currentState[passwordIndex] = previousState[passwordIndex];
}else{
currentState[passwordIndex] = passwordEncoder.encode(currentState[passwordIndex]);
}
return true;
}
}
Using spring boot the documentation states that
all properties in spring.jpa.properties.* are passed through as normal JPA properties (with the prefix stripped) when the local EntityManagerFactory is created.
As many references stated, we can defined our interceptor using spring.jpa.properties.hibernate.ejb.interceptor
in our Spring-Boot configuration. However I couldn't get the @Autowire PasswordEncoder
to work.
So I resorted to using HibernateJpaAutoConfiguration and overriding protected void customizeVendorProperties(Map<String, Object> vendorProperties)
. Here is my configuration.
@Configuration
public class HibernateConfiguration extends HibernateJpaAutoConfiguration{
@Autowired
Interceptor userInterceptor;
@Override
protected void customizeVendorProperties(Map<String, Object> vendorProperties) {
vendorProperties.put("hibernate.ejb.interceptor",userInterceptor);
}
}
Autowiring the Interceptor
instead of allowing Hibernate to instantiate it was the key to getting it to work.
What bothers me now is that the logic is split in two, but hopefully once DATAREST-373 is resolved then this wont be necessary.