Spring Data, multiple datasources, Not a Managed Type exception
I've been trying to get multiple database systems working within the same spring boot project for longer than it should take. I keep running into the following exception and need to have more eyes to nudge me towards the fix.
I apologize for the sheer volume of code below, however as I am unsure where the issue actually occurs I listed it all below.
One note: I am using a proprietary ERP's database as one of the endpoints. This endpoint is an Oracle database and is read only. If required we can switch that to a MySQL endpoint, however my use case requires the ERP's endpoint in order for the project to be successful.
Resources used:
- https://scattercode.co.uk/2016/01/05/multiple-databases-with-spring-boot-and-spring-data-jpa/
- https://scattercode.co.uk/2013/11/18/spring-data-multiple-databases/
- http://www.baeldung.com/spring-data-jpa-multiple-databases
- https://www.infoq.com/articles/Multiple-Databases-with-Spring-Boot
- https://medium.com/@joeclever/using-multiple-datasources-with-spring-boot-and-spring-data-6430b00c02e7
- Spring Boot Configure and Use Two DataSources
- https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-two-datasources
I'm sure my answer may still reside in one of the above, however I'm too close to the problem now, which is where I need assistance.
Exception:
java.lang.IllegalArgumentException: Not a managed type: class com.xxx.ddbo.suiteanalytics.objects.ReturnsReasonBrand
Code:
application.properties
#Global properties for spring configuration
logging.level.org.apache=ERROR
logging.level.org.springframework=WARN
logging.level.org.hibernate=INFO
logging.level.org.hibernate.type=INFO
#Spring configuration
spring.jpa.show-sql=true
spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.type=info
spring.jpa.generate-ddl=false
spring.jpa.database=default
## DATABASE CONFIGURATIONS
#Properties for PostgreSQL connection
spring.postgresql.datasource.url=xxxxxxxx
spring.postgresql.datasource.username=xxxxxxxx
spring.postgresql.datasource.password=xxxxxxxx
spring.postgresql.datasource.driver-class-name=org.postgresql.Driver
spring.postgresql.datasource.tomcat.max-active=50
#Properties for NetSuite SuiteAnalytics ODBC connection
#Sandbox URL
spring.suiteanalytics.datasource.url=xxxxxxxx
#Production URL
#spring.suiteanalytics.datasource.url=xxxxxxxx
spring.suiteanalytics.datasource.username=xxxxxxxx
spring.suiteanalytics.datasource.password=xxxxxxxx
spring.suiteanalytics.datasource.driver-class-name=com.netsuite.jdbc.openaccess.OpenAccessDriver
spring.suiteanalytics.datasource.tomcat.max-active=50
DdboApplication.java (ddbo)
@EnableJpaRepositories
@SpringBootApplication
@ComponentScan("com.xxx.ddbo")
public class DdboApplication implements CommandLineRunner{
@Autowired
private ReturnReasonsBrandRepository rrRepo;
@Autowired
private CustomListValuesRepository customListValuesRepository;
public static void main(String[] args) {
SpringApplication.run(DdboApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
CustomSegments cs = new CustomSegments(rrRepo);
cs.printReturnReasonBrand();
CustomLists cl = new CustomLists(customListValuesRepository);
cl.printCustomListValues();
}
}
PostgresqlConfig.java (ddbo.postgresql.configuration)
@Configuration
@EnableJpaRepositories(
basePackages = "com.xxx.ddbo.postgresql.interfaces",
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager"
)
public class PostgresqlConfig {
@Primary
@Bean(name = "dataSource")
@ConfigurationProperties(prefix="spring.postgresql")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("dataSource") DataSource dataSource) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
return builder
.dataSource(dataSource)
.properties(properties)
.packages("com.xxx.ddbo.postgresql.interfaces")
.persistenceUnit("foo")
.build();
}
@Primary
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
CustomListValuesRepository.java (ddbo.postgresql.interfaces)
@Repository
public interface CustomListValuesRepository extends JpaRepository<CustomListValues,CustomListValuePkey>{
}
CustomLists.java (ddbo.postgresql.logic)
@Component
public class CustomLists {
private final CustomListValuesRepository customListValuesRepository;
@Autowired
public CustomLists(CustomListValuesRepository customListValuesRepository) {
this.customListValuesRepository = customListValuesRepository;
}
public void printCustomListValues(){
List<CustomListValues> values = customListValuesRepository.findAll();
for(CustomListValues value: values){
System.out.println(value.getValueText());
}
}
}
CustomLists.java (ddbo.postgresql.objects)
@Entity
@Table(name = "custom_lists")
public class CustomLists {
@Id
@Column
private String listIntId;
@Column
private String mongoId;
public CustomLists(String listIntId) {
this.listIntId = listIntId;
}
public CustomLists() {
}
public String getListIntId() {
return listIntId;
}
public void setListIntId(String listIntId) {
this.listIntId = listIntId;
}
public String getMongoId() {
return mongoId;
}
public void setMongoId(String mongoId) {
this.mongoId = mongoId;
}
}
CustomListValuePkey (ddbo.postgresql.objects)
@Embeddable
public class CustomListValuePkey implements Serializable {
@Column
private String listId;
@Column
private String valueIntId;
public String getListId() {
return listId;
}
public void setListId(String listId) {
this.listId = listId;
}
public String getValueIntId() {
return valueIntId;
}
public void setValueIntId(String valueIntId) {
this.valueIntId = valueIntId;
}
}
CustomListValues.java (ddbo.postgresql.objects)
@Entity
@Table(name = "custom_list_values")
public class CustomListValues implements Serializable {
@EmbeddedId
private CustomListValuePkey pkey;
@Column
private String valueText;
@ManyToOne
@JoinColumn(name = "listIntId")
private CustomLists listId;
public CustomLists getListId() {
return listId;
}
public void setListId(CustomLists listId) {
this.listId = listId;
}
public String getValueText() {
return valueText;
}
public void setValueText(String valueText) {
this.valueText = valueText;
}
public CustomListValuePkey getPkey() {
return pkey;
}
public void setPkey(CustomListValuePkey pkey) {
this.pkey = pkey;
}
}
SuiteAnalyticsConfig.java (ddbp.suiteanalytics.configuration)
@Configuration
@PropertySource({"classpath:application.properties"})
@EnableJpaRepositories(
basePackages = "com.xxx.ddbo.suiteanalytics.interfaces",
entityManagerFactoryRef = "suiteanalyticsEntityManagerFactory",
transactionManagerRef = "suiteanalyticsTransactionManager"
)
public class SuiteAnalyticsConfig {
@Bean(name = "nsDataSource")
@ConfigurationProperties(prefix="spring.suiteanalytics")
public DataSource nsDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "nsEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean nsEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("nsDataSource") DataSource nsDataSource) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
return builder
.dataSource(nsDataSource)
.properties(properties)
.packages("com.xxx.ddbo.suiteanalytics.interfaces")
.persistenceUnit("ReturnReasonsBrand")
.build();
}
@Bean(name = "nsTransactionManager")
public PlatformTransactionManager nsTransactionManager(
@Qualifier("nsEntityManagerFactory") EntityManagerFactory nsEntityManagerFactory) {
return new JpaTransactionManager(nsEntityManagerFactory);
}
}
ReturnReasonsBrandRepository.java (ddbo.suiteanalytics.interfaces)
@Repository
public interface ReturnReasonsBrandRepository extends JpaRepository<ReturnsReasonBrand,Integer> {
// ReturnsReasonBrand findOneByRrBrandId(Integer id);
}
CustomSegments.java (ddbo.suiteanalytics.logic)
@Component
public class CustomSegments {
private final ReturnReasonsBrandRepository rrRepo;
@Autowired
public CustomSegments(ReturnReasonsBrandRepository rrRepo) {
this.rrRepo = rrRepo;
}
public void printReturnReasonBrand(){
List<ReturnsReasonBrand> brand = rrRepo.findAll();
for(ReturnsReasonBrand rrBrand : brand){
System.out.println(rrBrand.getRrBrandName());
}
}
}
ReturnReasonsBrand.java (ddbo.suiteanalytics.objects)
@Entity
@Table(name = "rr_brand")
public class ReturnsReasonBrand {
@Id
@Column(name = "RR_BRAND_ID")
private Integer rrBrandId;
@Column(name = "RR_BRAND_NAME")
private String rrBrandName;
public Integer getRrBrandId() {
return rrBrandId;
}
public void setRrBrandId(Integer rrBrandId) {
this.rrBrandId = rrBrandId;
}
public String getRrBrandName() {
return rrBrandName;
}
public void setRrBrandName(String rrBrandName) {
this.rrBrandName = rrBrandName;
}
}
Full stack trace:
2018-03-14 09:53:17.773 INFO 14512 --- [ main] com.xxx.ddbo.DdboApplication : Starting DdboApplication on xxx with PID xxx (started by roberth in xxx)
2018-03-14 09:53:17.775 INFO 14512 --- [ main] com.xxx.ddbo.DdboApplication : No active profile set, falling back to default profiles: default
2018-03-14 09:53:18.740 INFO 14512 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: CustomListValues
...]
2018-03-14 09:53:18.808 INFO 14512 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final}
2018-03-14 09:53:18.809 INFO 14512 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
2018-03-14 09:53:18.810 INFO 14512 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist
2018-03-14 09:53:18.848 INFO 14512 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2018-03-14 09:53:19.130 INFO 14512 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
2018-03-14 09:53:19.365 INFO 14512 --- [ main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException
2018-03-14 09:53:19.366 INFO 14512 --- [ main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@3249a1ce
2018-03-14 09:53:19.503 WARN 14512 --- [ main] org.hibernate.mapping.RootClass : HHH000038: Composite-id class does not override equals(): com.xxx.ddbo.postgresql.objects.CustomListValuePkey
2018-03-14 09:53:19.503 WARN 14512 --- [ main] org.hibernate.mapping.RootClass : HHH000039: Composite-id class does not override hashCode(): com.xxx.ddbo.postgresql.objects.CustomListValuePkey
2018-03-14 09:53:19.698 INFO 14512 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: ReturnReasonsBrand
...]
2018-03-14 09:53:35.120 INFO 14512 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
2018-03-14 09:53:36.268 INFO 14512 --- [ main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
2018-03-14 09:53:36.434 WARN 14512 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ddboApplication': Unsatisfied dependency expressed through field 'rrRepo'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'returnReasonsBrandRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.xxx.ddbo.suiteanalytics.objects.ReturnsReasonBrand
2018-03-14 09:53:41.730 ERROR 14512 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ddboApplication': Unsatisfied dependency expressed through field 'rrRepo'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'returnReasonsBrandRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.xxx.ddbo.suiteanalytics.objects.ReturnsReasonBrand
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
at com.xxx.ddbo.DdboApplication.main(DdboApplication.java:26) [classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'returnReasonsBrandRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.xxx.ddbo.suiteanalytics.objects.ReturnsReasonBrand
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
... 18 common frames omitted
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.xxx.ddbo.suiteanalytics.objects.ReturnsReasonBrand
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:210) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:70) ~[spring-data-jpa-1.11.10.RELEASE.jar:na]
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:68) ~[spring-data-jpa-1.11.10.RELEASE.jar:na]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:173) ~[spring-data-jpa-1.11.10.RELEASE.jar:na]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:106) ~[spring-data-jpa-1.11.10.RELEASE.jar:na]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:88) ~[spring-data-jpa-1.11.10.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:198) ~[spring-data-commons-1.13.10.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277) ~[spring-data-commons-1.13.10.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263) ~[spring-data-commons-1.13.10.RELEASE.jar:na]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:101) ~[spring-data-jpa-1.11.10.RELEASE.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
... 28 common frames omitted
1 answer
-
answered 2018-03-13 20:27
GSSwain
entityManagerFactory -> packages
should point to the package of your managed entities. Here you are pointing tocom.xxx.ddbo.suiteanalytics.interfaces
instead ofcom.xxx.ddbo.suiteanalytics.objects
which contains all the entities to be managed by the entity manager. Update the package name innsEntityManagerFactory
inSuiteAnalyticsConfig
.return builder .dataSource(dataSource) .properties(properties) .packages("com.xxx.ddbo.suiteanalytics.objects") .persistenceUnit("foo") .build();
Make sure you also update the package name for
entityManagerFactory
inPostgresqlConfig
toddbo.postgresql.objects
packageThe configuration properties for the datasources should also have datasource as per the config file, e.g.
@ConfigurationProperties(prefix="spring.postgresql.datasource")
Finally remove the
@EnableJpaRepositories
fromDdboApplication
.