Hi, Chris!
First of all thanks for the M4, is it a wonderful release. I only now got to check it out, and it rocks. I configured reasonably complicated application without a single XML. Love it.
The only annoyance I encountered is the same old PersistenceExceptionTranslationPostProcessor.
The following won't work:
It fails, because PersistenceExceptionTranslationPostProcessor must find at least one PersistenceExceptionTranslator in the ApplicationContext. In the above code it is not the case, because the LocalContainerEntityManagerFactoryBean, which is the PersistenceExceptionTranslator is not exposed, but used internally in the @Bean method.Code:@Bean public EntityManagerFactory entityManagerFactory() { LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); ... return (EntityManagerFactory) getObject(localContainerEntityManagerFactoryBean); } @Bean public JpaTransactionManager transactionManager() { return new JpaTransactionManager(entityManagerFactory()); } @Bean public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() { return new PersistenceExceptionTranslationPostProcessor(); }
So, let's try to expose the LocalContainerEntityManagerFactoryBean as a bean itself:
This looks reasonable, but fails withCode:@Bean public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean() { LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); ... return localContainerEntityManagerFactoryBean; } @Bean public EntityManagerFactory entityManagerFactory() { return (EntityManagerFactory) getObject(localContainerEntityManagerFactoryBean()); } @Bean public JpaTransactionManager transactionManager() { return new JpaTransactionManager(entityManagerFactory()); } @Bean public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() { return new PersistenceExceptionTranslationPostProcessor(); }
There is a workaround, to cache localContainerEntityManagerFactoryBean in field variable and to use it in transactionManager creation.Code:java.lang.ClassCastException: $Proxy30 cannot be cast to org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
Besides, exposing LocalContainerEntityManagerFactoryBean as a @Bean registers entityManagerFactory bean implicitly, preventing me from declaring the EntityManagerFactory as a @Bean.
The working solution looks like the following:
Note the local variable, the name of LocalContainerEntityManagerFactoryBean creation method and the creation of JpaTransactionManager.Code:private LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean; @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); ... this.localContainerEntityManagerFactoryBean =localContainerEntityManagerFactoryBean; return localContainerEntityManagerFactoryBean; } @Bean public JpaTransactionManager transactionManager() { return new JpaTransactionManager((EntityManagerFactory) getObject(localContainerEntityManagerFactoryBean)); } @Bean public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() { return new PersistenceExceptionTranslationPostProcessor(); }
This is ugly.



