1

Overflowers

I'm trying to get ObjectDB (2.7.6_01, latest) with Spring Data JPA (2.1.4, seemingly latest).

The docs for Spring Data JPA say that a version 2.1 JPA provider is needed. AFAIKT ObjectDB's JPA provider is 2.0 ... not sure if this is the problem or not.

But my problem is this exception:

Caused by: java.lang.IllegalArgumentException: com.objectdb.jpa.EMF is not an interface

Which is causing:

EntityManagerFactory interface [class com.objectdb.jpa.EMF] seems to conflict with Spring's EntityManagerFactoryInfo mixin - consider resetting the 'entityManagerFactoryInterface' property to plain [javax.persistence.EntityManagerFactory]

I'm happy that the ObjectDB entity manager factory is being picked properly by my code, but Spring's CGLIB wrapper around this class (EMF) is not working out.

Anyone got any ideas?

Gradle dependencies:

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compile files('libs/objectdb-jee.jar')
    compileOnly 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

Then, either of these two @Beans (one or the other, not both) cause the same EMF exception above:

@Bean
public JpaVendorAdapter jpaVendorAdapter() {

    final ObjectdbJpaVendorAdapter vendorAdapter = new ObjectdbJpaVendorAdapter();

    return vendorAdapter;
}

Or

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

    final ObjectdbJpaVendorAdapter vendorAdapter = new ObjectdbJpaVendorAdapter();

    vendorAdapter.setShowSql(true);
    vendorAdapter.setGenerateDdl(false);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);

    factory.setPackagesToScan("com.example.demo.persistence");
    factory.setDataSource(dataSource());
    factory.afterPropertiesSet();

    return factory;
}

I've got a no-op DataSource @Bean to keep some facet of Spring happy, but I don't think it's playing an active role in this problem.

No spring.jpa.* set at all.

Cheers

RichColours
  • 670
  • 1
  • 4
  • 15
  • I don't know the complete answer to your question, but I can speculate. The exception you are seeing is what java.lang.Proxy.getProxyClass throws when you pass it a class instead of an interface. I think that somehow you're configuring Spring with the ObjectDB EntityManagerFactory implementation class, and Spring is trying to create a proxy for that. The error message is suggesting that you tell Spring to proxy the EntityManagerFactory interface instead. – Willis Blackburn Jan 26 '19 at 14:30
  • Hi Willis - I had got this far with deciphering the error message. But I don't know yet if any vendor EntityManagerFactory is meant to be an interface or not. Ultimately, it needs to be a class, else it wouldn't do anything. – RichColours Jan 27 '19 at 17:00
  • Also I've found found how to change that interface, like one of the exceptions suggests. – RichColours Jan 27 '19 at 17:00
  • Please try to follow the instructions on https://www.objectdb.com/forum/2328 or alternatively post a complete test case that fails for further review. – ObjectDB Jan 31 '19 at 11:15
  • Thanks for that, I have tried nearly everything from that forum post including the JpaVendorAdapter bean etc. Give me a few days, i'll post up a git repo of a complete, non-working setup. – RichColours Feb 01 '19 at 12:10

1 Answers1

1

The Beans that you have to provide are much more simple:

@Bean
@ConfigurationProperties("app.datasource")
public DataSource dataSource() {
   return DataSourceBuilder.create().build();
}

@Bean(name="entityManagerFactory")
public EntityManagerFactory getEntityManagerFactoryBean() {
   // this is the important part - here we use a local objectdb file
   // but you can provide connection string to a remote objectdb server
   // in the same way you create objectdb EntityManagerFactory not in Spring
   return Persistence.createEntityManagerFactory("spring-data-jpa-test.odb");
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
   JpaTransactionManager txManager = new JpaTransactionManager();
   txManager.setEntityManagerFactory(emf);
   return txManager;
}

With the above (and the proper dependencies in your pom.xml) there is no need for any additional configuration (i.e. no need for any configuration in application.properties).

A simple working example can be found here.

Amir Kirsh
  • 12,564
  • 41
  • 74