access two database from one spring boot application - java

I have two separate spring boot applications, app1 and app2. One is using mysql other one using postgresql as database source.
I need to access both database in app2 to query some data. Now, it would be easier if I can use the POJO from app1 to query and calculations when I am trying to access aap1's DB from app2. I found online that i can use multiple database in one spring boot application (https://www.baeldung.com/spring-data-jpa-multiple-databases).
Now, I am exporting the jar file from app1 with all the POJO and other classes and adding it to build path of app2. I am hoping this should work.
Then I tried everything what thay have mentioned in the above link
But I am getting following error
Description:
Parameter 0 of constructor in required a bean named 'entityManagerFactory' that could not be found.
Action:
Consider defining a bean named 'entityManagerFactory' in your
configuration.
Is it because I am using jar file instead of actual POJO?
Also, in app1, I am using "Sessionfactory" in DAO, though in app2, I am using cruderepository. Could this be issue?
Also, I have #EnableJpaRepositories annotation in main application.class. Should i comment it?
edit: After making suggested changes, I am getting following error:
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name '' defined in class path resource
[]: Unsatisfied dependency expressed through method ''
parameter 0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name '' defined in file

You need define the Bean like below:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws URISyntaxException {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(<your_datasource>);
entityManagerFactoryBean.setPackagesToScan(package_to_scan);
//additional config of factory
return entityManagerFactoryBean;
}
#Bean(name = "transactionManager")
public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactory) throws URISyntaxException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}

Related

Qualified bean must be of 'EntityManagerFactory' type in Spring Boot 3. Works with Spring Boot 2

I'm currently upgrading my project to Spring Boot 3 using a own JpaTransactionmanager configuration.
My code looks like following snippet:
#Configuration
#EnableJpaRepositories(
entityManagerFactoryRef = "myEntityManagerFactory",
transactionManagerRef = "myTransactionManager"
)
public class MyPersistenceConfig {
...
#Bean
public LocalContainerEntityManagerFactoryBean myEntityManagerFactory(DataSource dataSource) {
var emfBean = new LocalContainerEntityManagerFactoryBean();
// Some configuration removed
return emfBean;
}
#Bean
public JpaTransactionManager myTransactionManager(#Qualifier("myEntityManagerFactory") EntityManagerFactory emf) {
var transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
However, this code works in latest Spring Boot 2 but not with Spring Boot 3. Following (minimized) error is thrown on startup:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myEntityManagerFactory' defined in class path resource [<path>/<to>/MyPersistenceConfig.class]: Unable to resolve name [org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy] as strategy [org.hibernate.boot.model.naming.PhysicalNamingStrategy]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1751) ~[spring-beans-6.0.2.jar:6.0.2]
...
Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy] as strategy [org.hibernate.boot.model.naming.PhysicalNamingStrategy]
...
Caused by: org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:123) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
...
Caused by: java.lang.ClassNotFoundException: Could not load requested class : org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
at org.hibernate.boot.registry.classloading.internal.AggregatedClassLoader.findClass(AggregatedClassLoader.java:210) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
...
Besides IntelliJ says on the JpaTransactionManager-Bean: Could not autowire. Qualified bean must be of 'EntityManagerFactory' type..
According the LocalContainerEntityManagerFactoryBean-JavaDoc, it should produce a EntityManagerFactory-Bean (and actually did with Spring-ORM 5):
FactoryBean that creates a JPA EntityManagerFactory according to JPA's standard container bootstrap contract.
Is there anything that I'm missing?
The problem seems to be the org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy which has been deprecated since Spring Boot 2.6 and removed in Spring Boot 3 in favor of the CamelCaseToUnderscoresNamingStrategy.
See here:
https://docs.spring.io/spring-boot/docs/2.7.1/api/index.html?org/springframework/boot/orm/jpa/hibernate/SpringPhysicalNamingStrategy.html

Two Entity Managers in Spring Appliation (Arrango and JPA)

I am using two Spring Entity manager, Arrango and JPA for my application.
#EnableSwagger2
#ComponentScan(basePackages = "com.xyz.abc")
#EnableArangoRepositories(basePackages = {"com.xyz.abc"})
#EnableJpaRepositories(basePackages = {"com.xyz.abc"})
#EntityScan(basePackages = "com.xyz.abc")
#SpringBootApplication
#EnableEurekaClient
#EnableDiscoveryClient
#EnableProcessApplication
As can be seen, I am Enabling repository access. Now when I run my application, I get the following error.
The bean 'XYZRepository', defined in com.xyz.abc.core.data.repository.XYZRepository defined in #EnableJpaRepositories declared on MYControllerAPP, could not be registered. A bean with that name has already been defined in com.xyz.abc.core.data.repository.XYZRepository defined in #EnableArangoRepositories declared on MyControllerAPP and overriding is disabled.
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
When I add overriding bean definition to my application.yml file.
The error changes to:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'qualityService': Unsatisfied dependency expressed through field 'master'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'masterDataRepository' defined in com.xyz.abc.core.data.repository.MasterDataRepository defined in #EnableJpaRepositories declared on QualityControllerApp: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.xyz.abc.core.data.model.MasterData
this is my MasterDataRepository Interface:
interface MasterDataRepository extends ArangoRepository<MasterData, String>
{
//Hibernate
}
I think the base problem with:
#EnableArangoRepositories(basePackages = {"com.xyz.abc"})
#EnableJpaRepositories(basePackages = {"com.xyz.abc"})
You should to set different packages to different repository providers. You won't be able to use one Entity class with different repositories. Try to separate ArangoRepository entities and JpaRepository entities.

SpringBoot - How to avoid "Error creating bean with name 'entityManagerFactory'... " when some condition has true value

I have a SpringBoot application (version 1.5.22.RELEASE), and it's using a MariaDB database as datasource to get some data to populate a cache at startup. The data comes from a JPA Repositoy using a collection of a Entity. All the datasource parameters are in the application.properties file.
At this moment, I have to switch the cache datasource to a REST service instead the database. If I have a new property with the value in true, I must use the REST service because the DB will be off; otherwise (with the new property in false), I must use the database, because the REST service will be unavailable.
When I try to test my application with the property in true and the database unavailable, the application throws the following error, and the application doesn't start:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1630) ~[spring-beans-4.3.25.RELEASE.jar:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.25.RELEASE.jar:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) ~[spring-beans-4.3.25.RELEASE.jar:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) ~[spring-beans-4.3.25.RELEASE.jar:4.3.25.RELEASE]
Is there a way to avoid this error when the database isnĀ“t available and continue with the application startup?
Thanks in advance. I appreciate your help and feedback.
Yes, you can disable the database autoconfiguration by using code below:
#SpringBootApplication
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(PayPalApplication.class, args);
}
}
And then in the startup, you can connect to the database manually. Detect the availability of the database, fetch cache data or get a connection error, then switch to the backup service.

How do you create JDBC TokenStore in Spring Boot?

I tried to follow this answer to add JDBC TokenStore to my app.
https://stackoverflow.com/a/37595818/148844
It is working with an InMemoryTokenStore. I need to know where to put this code
#Bean(name = "OAuth")
#ConfigurationProperties(prefix="datasource.oauth")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
I tried to put it in
#Configuration
#EnableAuthorizationServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
But I got the error
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'OAuth2Configuration': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'OAuth': Requested bean is currently in creation: Is there an unresolvable circular reference?
So I moved it to the main class
#SpringBootApplication
#MapperScan("com.example.mapper")
public class ExampleApplication extends SpringBootServletInitializer {
But then it gave a different error
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: The url cannot be null
So where do I put that snippet to define the bean?
You need to have the database configuration properties in your application-{profile}.properties, in particular they need to be prefixed by datasource.oauth. Here profile will be any of the profiles that your application is running on (e.g: dev, stage, prod).
The error that is showing clearly says that there is no datasource.oauth.url=.. property in the specific properties file.

Spring: How can I debug a BeanCreationNotAllowedException?

I am trying to add a new Spring bean to one of my projects. The bean is defined and created in another package like so:
#Configuration
public class UtilityBeans {
public static String MY_BEAN_NAME = "my.bean.name";
#Bean(name = MY_BEAN_NAME)
public MyUtilBeanClass getMyBeanClass() {
return new MyUtilBeanClass();
}
}
I use it in my other package like this:
#Configuration
#Import({
UtilityBeans.class
)}
...
#Resource(name = UtilityBeans.MY_BEAN_NAME)
private MyUtilBeanClass myUtilBeans;
During runtime I get:
ERROR
Caused by: org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'my.bean.name': Singleton bean creation not allowed while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
...
The logs do not give me any useful information as the stack trace is all in Spring library. How can I find out what failed? Is it incorrect usage of resource or is it that the bean creation itself is wrong?
I am using Spring-4 with JDK8.
The issue here was that the bean was being created in 2 different points in my spring configuration due to some refactoring and the fix was to remove duplicate code. I had the same bean creation code:
#Bean(name = MY_BEAN_NAME)
public MyUtilBeanClass getMyBeanClass() {
return new MyUtilBeanClass();
}
... in another class I had half way refactored.
In this case my mistake was that I did not grep across all the log files being generated. The exceptions were being split and then buried into 2 different logs, one for a server start up and one for application runtime. The above exception was being posted to the application log. The other logs contained the relevant exception which stated that duplicate bean creation failed and the fix was to remove duplicate code.

Categories