How to using annotation #RefreshScope with spingboot : connectionFactory? - spring-boot

how to refresh connectionFactory or connectionpool,such as dataSource,JedisConnectionFactory... when the springboot application is running?
(I used springcould-config to update my configs)
#Bean
#ConfigurationProperties(prefix = "spring.redis.pool")
public JedisPoolConfig getRedisConfig() {
JedisPoolConfig config = new JedisPoolConfig();
return config;
}
#Bean(name = "redisConnection")
public JedisConnectionFactory getConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
JedisPoolConfig config = getRedisConfig();
factory.setPoolConfig(config);
factory.setPassword(password);
factory.setHostName(hostName);
factory.setPort(port);
factory.setDatabase(database);
return factory;
}
...
pseudocode:
onChangeListener function then
refreshScope.refresh("redisConnection");
but it does not work,however, some files with #Value("${spring.redis.host}")
it change

Related

unable run Quartz JDBCJobStore with AbstractRoutingDataSource

I have implemented the application using Spring RoutingDataSource.
Spring -> DS1,
DS2
Based on the logged in URL I am changing the Data Source. it is working fine.
Coming to the quartz, I am unable to change the data source dynamically. Always jobs are getting scheduled on default data source.
#Configuration
public class SchedulerConfig {
#Autowired
private DataSource dataSource;
#Autowired
private QuartzProperties quartzProperties;
#Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) {
Properties properties = new Properties();
properties.putAll(quartzProperties.getProperties());
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setJobFactory(jobFactory);
factory.setDataSource(dataSource);
factory.setGlobalJobListeners(jobListener());
factory.setQuartzProperties(properties);
return factory;
}
#Bean
public JobListenerSupport jobListener() {
return new JobListener();
}
}
Data Source Routing Configuration::
#Component
public class DataSourceRouting extends AbstractRoutingDataSource {
private DataSourceOneConfig dataSourceOneConfig;
private DataSourceTwoConfig dataSourceTwoConfig;
private DataSourceContextHolder dataSourceContextHolder;
public DataSourceRouting(DataSourceContextHolder dataSourceContextHolder, DataSourceOneConfig dataSourceOneConfig,
DataSourceTwoConfig dataSourceTwoConfig) {
this.dataSourceOneConfig = dataSourceOneConfig;
this.dataSourceTwoConfig = dataSourceTwoConfig;
this.dataSourceContextHolder = dataSourceContextHolder;
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put(DataSourceEnum.tenant1, dataSourceOneDataSource());
dataSourceMap.put(DataSourceEnum.tenant2, dataSourceTwoDataSource());
this.setTargetDataSources(dataSourceMap);
this.setDefaultTargetDataSource(dataSourceTwoDataSource());
}
#Override
protected Object determineCurrentLookupKey() {
return dataSourceContextHolder.getBranchContext();
}
public DataSource dataSourceOneDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(dataSourceOneConfig.getUrl());
dataSource.setUsername(dataSourceOneConfig.getUsername());
dataSource.setPassword(dataSourceOneConfig.getPassword());
return dataSource;
}
public DataSource dataSourceTwoDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(dataSourceTwoConfig.getUrl());
dataSource.setUsername(dataSourceTwoConfig.getUsername());
dataSource.setPassword(dataSourceTwoConfig.getPassword());
return dataSource;
}
}
Data Soruce Config ::
#RequiredArgsConstructor
#DependsOn("dataSourceRouting")
public class DataSourceConfig {
private final DataSourceRouting dataSourceRouting;
#Bean
#Primary
public DataSource dataSource() {
return dataSourceRouting;
}
#Bean(name = "entityManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dataSource()).packages("com.model.entity").build();
}
#Bean(name = "transcationManager")
public JpaTransactionManager transactionManager(
#Autowired #Qualifier("entityManager") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return new JpaTransactionManager(entityManagerFactoryBean.getObject());
}
}

Data Migration from One Db to another using Spring batch and Spring boot

Im new to spring framework and I Want to migrate data from One DB to another using Spring boot n Batch
Im trying to read from an Mysql db with an item reader and write it to an Oracle db using an item writer of the same job.
Im able to read the data from the Mysql db but unable to write it to Oracle Db as the writer is trying it write it in Mysql Db itself.
Im not sure why the connection is not switching to Oracle db.
Please help me over here what im doing wrong.
Application properties
server.port=8082
spring.batch.job.enabled= false
spring.datasource.url = jdbc:mysql://localhost:3306/projectdb1
spring.datasource.username = root
spring.datasource.password = Mech_2015
spring.datasource.driverClassName = com.mysql.jdbc.Driver
#second db2 ...
db2.datasource.url = jdbc:oracle:thin:#localhost:1521:xe
db2.datasource.username = system
db2.datasource.password = Mech_2015
db2.datasource.driverClassName = oracle.jdbc.driver.OracleDriver
Entity Managers
package com.techprimers.springbatchexample1.entity.manger;
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "radiusEntityManager", transactionManagerRef = "radiusTransactionManager", basePackages = "com.techprimers.springbatchexample1.repository.userrepo")
public class RadiusConfig {
private final PersistenceUnitManager persistenceUnitManager;
public RadiusConfig(ObjectProvider<PersistenceUnitManager> persistenceUnitManager) {
this.persistenceUnitManager = persistenceUnitManager.getIfAvailable();
}
#Bean
#ConfigurationProperties("spring.jpa")
public JpaProperties radiusJpaProperties() {
return new JpaProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties radiusDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties(prefix = "spring.datasource.properties")
public DataSource radiusDataSource() {
return (DataSource) radiusDataSourceProperties().initializeDataSourceBuilder().type(DataSource.class).build();
}
#Bean(name = "radiusEntityManager")
public LocalContainerEntityManagerFactoryBean radiusEntityManager(JpaProperties radiusJpaProperties) {
EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(radiusJpaProperties);
return builder.dataSource(radiusDataSource()).packages(User.class).persistenceUnit("userDs").build();
}
#Bean
public JpaTransactionManager radiusTransactionManager(EntityManagerFactory radiusEntityManager) {
return new JpaTransactionManager(radiusEntityManager);
}
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties radiusJpaProperties) {
JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(radiusJpaProperties);
return new EntityManagerFactoryBuilder(jpaVendorAdapter, radiusJpaProperties.getProperties(),
this.persistenceUnitManager);
}
private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(jpaProperties.isShowSql());
adapter.setDatabase(jpaProperties.getDatabase());
adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
return adapter;
}
}
package com.techprimers.springbatchexample1.entity.manger;
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "esbEntityManager", transactionManagerRef = "esbDetailsTransactionManager", basePackages = "com.techprimers.springbatchexample1.repository.userdetails")
public class EsbConfig {
private final PersistenceUnitManager persistenceUnitManager;
public EsbConfig(ObjectProvider<PersistenceUnitManager> persistenceUnitManager) {
this.persistenceUnitManager = persistenceUnitManager.getIfAvailable();
}
#Bean
#ConfigurationProperties("db2.jpa")
public JpaProperties esbJpaProperties() {
return new JpaProperties();
}
#Bean
#ConfigurationProperties("db2.datasource")
public DataSourceProperties esbDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties(prefix = "db2.datasource.properties")
public DataSource esbDataSource() {
return (DataSource) esbDataSourceProperties().initializeDataSourceBuilder().type(DataSource.class).build();
}
#Bean(name = "esbEntityManager")
public LocalContainerEntityManagerFactoryBean esbEntityManager(JpaProperties esbJpaProperties) {
EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(esbJpaProperties);
return builder.dataSource(esbDataSource()).packages(UserDetails.class).persistenceUnit("userDetailDs").build();
}
#Bean
public JpaTransactionManager esbTransactionManager(EntityManagerFactory esbEntityManager) {
return new JpaTransactionManager(esbEntityManager);
}
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties esbJpaProperties) {
JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(esbJpaProperties);
return new EntityManagerFactoryBuilder(jpaVendorAdapter, esbJpaProperties.getProperties(),
this.persistenceUnitManager);
}
private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(jpaProperties.isShowSql());
adapter.setDatabase(jpaProperties.getDatabase());
adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
return adapter;
}
}
Batch Config
package com.techprimers.springbatchexample1.config;
#Configuration
#EnableBatchProcessing
public class SpringBatchConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringBatchConfig.class);
#Bean
#Primary
#Qualifier("radiusDatasource")
#ConfigurationProperties(prefix = "spring.datasource")
DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
#ConfigurationProperties(prefix = "db2.datasource")
#Qualifier("esbDatasource")
DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
public InspectionProcessor processor() {
return new InspectionProcessor();
}
#Bean
public JdbcCursorItemReader<User> reader() {
JdbcCursorItemReader<User> cursorItemReader = new JdbcCursorItemReader<>();
cursorItemReader.setDataSource(mysqlDataSource());
cursorItemReader.setSql("SELECT ID,CNAME,SID,CREATEDDATE,COMPLETEDDATE FROM INSPECTION");
cursorItemReader.setRowMapper(new InspectionDetailRowmapper());
return cursorItemReader;
}
private static final String QUERY_INSERT_STUDENT = "INSERT "
+ "INTO inspect(id,cname,completeddate,createddate,lastupdateddate,sid) " + "VALUES (?,?,?,?,?,?)";
#Bean
ItemWriter<UserDetails> databaseItemWriter(DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate) {
LOGGER.info("Starting writer");
JdbcBatchItemWriter<UserDetails> databaseItemWriter = new JdbcBatchItemWriter<>();
databaseItemWriter.setDataSource(oracleDataSource());
databaseItemWriter.setJdbcTemplate(jdbcTemplate);
LOGGER.info(" writer");
databaseItemWriter.setSql(QUERY_INSERT_STUDENT)
ItemPreparedStatementSetter<UserDetails> valueSetter = new UserDetailsPreparedStatementSetter();
databaseItemWriter.setItemPreparedStatementSetter(valueSetter);
return databaseItemWriter;
}
#Bean
Step dataMigrationStep(ItemReader<User> reader, ItemProcessor<User, UserDetails> processor,
ItemWriter<UserDetails> databsaeItemWriter, StepBuilderFactory stepBuilderFactory) {
return stepBuilderFactory.get("dataMigrationStep").<User, UserDetails>chunk(5).reader(reader)
.processor(processor).writer(databsaeItemWriter).build();
}
#Bean
Job dataMigrationJob(JobBuilderFactory jobBuilderFactory, #Qualifier("dataMigrationStep") Step dataMigrationStep) {
return jobBuilderFactory.get("csvFileToDatabaseJob").incrementer(new RunIdIncrementer()).flow(dataMigrationStep)
.end().build();
}
}
Your writer does not inject properly the database where to write your data
this
#Bean
ItemWriter<UserDetails> databaseItemWriter(DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate)
instead of
#Bean
ItemWriter<UserDetails> databaseItemWriter(#Qualifier("esbDatasource") DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate)

Spring multiple datasource without primary

I have a problem, I need to create two DataSource but I cannot use #Primary because in other module I also have two DataSource and then in third module I include both modules, so there are two primary modules.
I wanted to use #Qualifier but it does not work.
#Bean(name = "secondDataSourceProperties")
#ConfigurationProperties("second")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
}
#Bean(name = "secondDataSource")
#ConfigurationProperties("second.configuration")
public DataSource secondDataSource(#Qualifier("secondDataSourceProperties") DataSourceProperties dataSourceProperties) {
HikariDataSource ds = dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
ds.setConnectionTestQuery("SELECT 1");
ds.setConnectionInitSql("SELECT 1");
ds.setPoolName("jdbc/second");
return ds;
}
#Bean(name = "secondTransactionManager")
public DataSourceTransactionManager secondDataSourceTransactionManager(#Qualifier("secondDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
#Bean
#ConfigurationProperties("first")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
}
#Bean(name = "firstDataSource")
#ConfigurationProperties("first.configuration")
public DataSource firstDataSource(#Qualifier("firstDataSourceProperties") DataSourceProperties dataSourceProperties) {
HikariDataSource ds = dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
ds.setConnectionTestQuery("SELECT 1");
ds.setConnectionInitSql("SELECT 1");
ds.setPoolName("jdbc/first");
return ds;
}
#Bean(name = "firstTransactionManager")
public DataSourceTransactionManager firstDataSourceTransactionManager(#Qualifier("firstDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
Error I'm getting is:
No qualifying bean of type
'org.springframework.boot.autoconfigure.jdbc.DataSourceProperties'
available: expected single matching bean but found 5:
secondDataSourceProperties,firstDataSourceProperties,3DataSourceProperties,4DataSourceProperties,spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
I use DataSource like that in code:
#Autowired
#Qualifier("first")
private DataSource dataSource;
and
#Transactional(value = "firstTransactionManager")
How about just doing the following? Without #Qualifier mess? The name of the method for #Bean is by default used as the "qualifier" of the bean.
#Bean
#ConfigurationProperties("first")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("second")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
public DataSource firstDataSource(DataSourceProperties firstDataSourceProperties) {
HikariDataSource ds = firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
ds.setConnectionTestQuery("SELECT 1");
ds.setConnectionInitSql("SELECT 1");
ds.setPoolName("jdbc/first");
return ds;
}
#Bean
public DataSource secondDataSource(DataSourceProperties secondDataSourceProperties) {
HikariDataSource ds = secondDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
ds.setConnectionTestQuery("SELECT 1");
ds.setConnectionInitSql("SELECT 1");
ds.setPoolName("jdbc/second");
return ds;
}
#Bean
public DataSourceTransactionManager firstTransactionManager(DataSource firstDataSource) {
return new DataSourceTransactionManager(firstDataSource);
}
#Bean
public DataSourceTransactionManager secondTransactionManager(DataSource secondDataSource) {
return new DataSourceTransactionManager(secondDataSource);
}
You can just autowire with this name only;
#Autowire
private DataSource firstDateSource;
and
#Transactional("secondTransactionManager")
Helped adding
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
Or if you use #SpringBootApplication
#SpringBootApplication(scanBasePackages={"a.b.c"}, exclude = {DataSourceAutoConfiguration.class})

Spring boot application with custom config does not load on server(websphere) startup

I have a spring boot application which connects to two data sources using mybatis. Spring boot does not load on server startup, I have checked the logs during the server startup and I do not see any spring boot related messages in it. The application status is displayed as Started in the WAS console after the server startup.
The application does not work until I restart it, and during the application restart, I can see the spring boot related messages in the logs. The application works fine after its restarted.
Server version: IBM WebSphere Application Server Network Deployment (8.5.5.14)
Java version: 8.0.2.10 (IBM WebSphere SDK Java Technology Edition)
#SpringBootApplication
#ComponentScan(basePackages="org.sample.solve.*")
#MapperScan("org.sample.solve.sa.db.mappers")
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
Configuration :
package org.sample.solve.sa;
import .....
#Configuration
public class MybatisDBConfig {
private final Logger log = LoggerFactory.getLogger(this.getClass());
public static final String SQL_SESSION_FACTORY_NAME_1 = "sqlSessionFactory1";
public static final String SQL_SESSION_FACTORY_NAME_2 = "sqlSessionFactory2";
public static final String MAPPERS_PACKAGE_TSC = "org.sample.solve.sa.db.mappers"; // mapper interface package
public static final String MAPPERS_PACKAGE_SERVICES_DB = "org.sample.solve.sa.db.services_db.mappers"; // mapper interface package
#Profile("local")
#Bean(name = "tscDB")
#Primary
#ConfigurationProperties(prefix = "sp.firstDatasource")
public DataSource dataSource1() {
DataSource dataSource = null;
try {
dataSource = DataSourceBuilder.create().build();
log.info("tsc datasource");
}catch(Exception excep) {
excep.printStackTrace();
}
return dataSource;
}
#Profile("local")
#Bean(name = "servicesDB")
#ConfigurationProperties(prefix = "sp.secondDatasource")
public DataSource dataSource2() {
DataSource dataSource = null;
try {
dataSource = DataSourceBuilder.create().build();
log.info("services datasource");
}catch(Exception excep) {
excep.printStackTrace();
}
return dataSource;
}
#Profile({"dev", "fvt", "uat", "prod"})
#Bean(name = "tscDB")
#Primary
public DataSource primaryDataSource() {
System.out.println("sacpDS_JNDI : jdbc/QAServiceSACP");
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource("jdbc/QAServiceSACP");
return dataSource;
}
#Profile({"dev", "fvt", "uat", "prod"})
#Bean(name = "servicesDB")
public DataSource secondaryDataSource() {
System.out.println("servicesDS_JNDI : jdbc/servicesDS");
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource("jdbc/servicesDS");
return dataSource;
}
#Bean(name = SQL_SESSION_FACTORY_NAME_1)
#Primary
public SqlSessionFactory sqlSessionFactory1(#Qualifier("tscDB") DataSource dataSource1) throws Exception {
SqlSessionFactory sqlSessionFactory = null;
try {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setTypeAliasesPackage("org.sample.solve.sa.pojo");
Resource[] mapperLocations = new Resource[] { new ClassPathResource("SASolveMapper.xml") };
sqlSessionFactoryBean.setMapperLocations(mapperLocations);
sqlSessionFactoryBean.setDataSource(dataSource1);
sqlSessionFactory = sqlSessionFactoryBean.getObject();
sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);
sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);
}catch(Exception excep) {
excep.printStackTrace();
throw new Exception(excep.getMessage());
}
return sqlSessionFactory;
}
#Bean(name = SQL_SESSION_FACTORY_NAME_2)
public SqlSessionFactory sqlSessionFactory2(#Qualifier("servicesDB") DataSource dataSource2) throws Exception {
SqlSessionFactory sqlSessionFactory = null;
try {
SqlSessionFactoryBean diSqlSessionFactoryBean = new SqlSessionFactoryBean();
diSqlSessionFactoryBean.setTypeAliasesPackage("org.sample.solve.sa.pojo");
Resource[] mapperLocations = new Resource[] {new ClassPathResource("ServicesDBMapper.xml")};
diSqlSessionFactoryBean.setMapperLocations(mapperLocations);
diSqlSessionFactoryBean.setDataSource(dataSource2);
sqlSessionFactory = diSqlSessionFactoryBean.getObject();
sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);
sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);
}catch(Exception excep) {
excep.printStackTrace();
throw new Exception(excep.getMessage());
}
return sqlSessionFactory;
}
#Bean
#Primary
public MapperScannerConfigurer mapperScannerConfigurer1() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage(MAPPERS_PACKAGE_TSC);
configurer.setSqlSessionFactoryBeanName(SQL_SESSION_FACTORY_NAME_1);
return configurer;
}
#Bean
public MapperScannerConfigurer mapperScannerConfigurer2() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage(MAPPERS_PACKAGE_SERVICES_DB);
configurer.setSqlSessionFactoryBeanName(SQL_SESSION_FACTORY_NAME_2);
return configurer;
}
}
And I am setting the active profile using a servlet initializer.
I've noticed the same when I tried to create a scheduled job (spring boot app in was server). The job did not start until I poked the application by calling rest service or do something else. Unfortunately I don't know what to do to make it work.

How to get the current info of the JedisPool

When I use spring-data-redis inject RedisConnectionFactory and setup the poolConfig, how can I get the infomation of the pool in runtime, because I found the factory does not expose the pool. Thank you advance.^.^
my code is :
#Bean
public RedisConnectionFactory jedisConnectionFactory() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(128);
poolConfig.setJmxEnabled(true);
poolConfig.setMaxTotal(8);
poolConfig.setMinIdle(2);
JedisConnectionFactory factory = new JedisConnectionFactory(poolConfig);
factory.setHostName("localhost");
factory.setPort(6379);
factory.setUsePool(true);
return factory;
}

Resources