Adapting a Spring-class based Persistence-Layer for use with Axon?

Hello,

in the past, yes it’s true, I have already asked whether it is possible to “mix” a Persistence-Layer primarily based on the Spring classes (@beans) together with Axon, i.e. to use those beans…

  1. org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean,
  2. org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter,
  3. org.springframework.orm.jpa.JpaTransactionManager

as base for an Axon application through slight modifications like “joint-”, “hinge-” or “adapter-” class(es) or other idioms.

I don’t mean to create a duplicate. In the other thread I was even more greenhornish and mistook two concepts. Which is why I hope you allow me to pose the question correct here. Thank you very much, if so.

For the question from above take for instance the following persistence-layer Java Config:
(I know it may not be actually functioning, but it’s at least an apt scaffold)

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{
	
	@Autowired
	private Environment env;
  
	
	@Bean
	public DataSource dataSource(){
			DriverManagerDataSource dataSource = new DriverManagerDataSource();
			dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
			dataSource.setUrl("jdbc:mysql://localhost:3306/spring_jpa");
			dataSource.setUsername( "tutorialuser" );
			dataSource.setPassword( "tutorialmy5ql" );
			return dataSource;
	}
	
	@Bean
	private HibernateJpaVendorAdapter vendorAdaptor() {
			HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
			vendorAdapter.setShowSql(true);
			return vendorAdapter;
	}
	
	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
	
			LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
			entityManagerFactoryBean.setJpaVendorAdapter(vendorAdaptor());
			entityManagerFactoryBean.setDataSource(dataSource());
			entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
			entityManagerFactoryBean.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);             
			entityManagerFactoryBean.setJpaProperties(jpaHibernateProperties());
	
			return entityManagerFactoryBean;
	 }
	
   @Bean
   public PlatformTransactionManager transactionManager() {
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
      return transactionManager;
   }
   
   
	// http://www.java2s.com/example/java-api/org/springframework/dao/annotation/persistenceexceptiontranslationpostprocessor/persistenceexceptiontranslationpostprocessor-0-0.html
	@Bean
	public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
			return new PersistenceExceptionTranslationPostProcessor();
	}
	
	
	Properties additionalProperties() {
			Properties properties = new Properties();
			properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
			properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
				
			return properties;
	}
	
}

But the important thing is that the above will at least not work in an Axon application for the following reason alone (which is the thing that is important for this thread):

In Event Bus & Event Store - Axon Reference Guide
there is the quote

So Axon would need at least a @bean called entityManagerProvider() that returns the entityManager from the Spring-persistence unit, that is, from LocalContainerEntityManagerFactoryBean in the example above (I think this choice is typical, is it not?)

In the old thread it was discussed to solve this by a somewhat hacky construction/idiom, which would first define a class like the following (see the org.axonframework.common.jpa.EntityManagerProvider interface)

public class MyEntityManagerProvider implements ContainerManagedEntityManagerProvider {

    private EntityManager entityManager;

    @Override
    public EntityManager getEntityManager() {
        return entityManager;
    }

    @PersistenceContext(unitName = "myPersistenceUnit")
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

And then create a @bean like so:

@Bean
MyEntityManagerProvider entityManagerProvider() { 
    em = new MyEntityManagerProvider();
    return em.getEntityManager();
}

Now, my question is, whether there is maybe a better solution for this? I could use the ContainerManagedEntityManagerProvider class for instance as well and provide the @PersistenceContext via @Qualifier in its setEntityManager()-method ? Not sure if that works or if I have to create an own implementation of the interface for a custom choice of the persistence-unit. Probably I would have.

Also: Are there other such “joint-”/“hinge-” or “adapter-” classes in order to mix or use a run-off-the-mill Spring Persistence-Layer together with Axon ? Or will it work with just that one “caveat” ?

Thanks !

No worries there @uberSpotz! I don’t see it as a duplicate right now, nor would you be in the wrong to rehash the predicament. If you’re facing an issue, it’s fine to share, IMO.

As we’re talking about Spring-world, I guess you are using Spring Boot.
Is that the case?
If so, are you also using axon-spring-boot-starter dependency?

If both answers return true, I would actually anticipate Axon’s JpaAutoConfiguration to automatically construct an EntityManagerProvider provider bean.
You can see that bit of code here, by the way.

You are, of course, free to make your own EntityManagerProvider bean and expose it in the Application Context, but I think you shouldn’t be required to…

Am I missing something obvious from your post?
If so, please point me to those things; I’ll gladly help.