Our application need to deal with multiple databases. We tried to configure multiple data sources through Hibernate configuration and added two configurations one for database 1 and second for database 2. This configuration fails with following Exception
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainController': Unsatisfied dependency expressed through field 'dataDAO'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataDAO': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.hibernate.SessionFactory' available: expected single matching bean but found 2: sessionFactory1,sessionFactory2
Nov 29, 2019 5:08:11 PM org.springframework.web.context.ContextLoader initWebApplicationContext
SEVERE: Context initialization failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainController': Unsatisfied dependency expressed through field 'dataDAO'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataDAO': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.hibernate.SessionFactory' available: expected single matching bean but found 2: sessionFactory1,sessionFactory2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
This is my Configuration class :
package com.pack1.config;
import java.beans.PropertyVetoException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.pack1.routing.MyRoutingDataSource;
#Configuration
#ComponentScan("com.pack1")
#EnableWebMvc
#EnableTransactionManagement
// Load to Environment
#PropertySources({#PropertySource("classpath:ds/datasource-cfg.properties")})
public class ApplicationContextConfig implements WebMvcConfigurer
{
// The Environment class serves as the property holder
// and stores all the properties loaded by the #PropertySource
#Autowired
private Environment env;
private Logger logger = Logger.getLogger(getClass().getName());
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
// Returns Routing DataSource (MyRoutingDataSource)
#Autowired
#Bean(name = "dataSource")
public DataSource getDataSource(DataSource dataSource1, DataSource dataSource2) {
System.out.println("## Create DataSource from dataSource1 & dataSource2");
MyRoutingDataSource dataSource = new MyRoutingDataSource();
Map<Object, Object> dsMap = new HashMap<Object, Object>();
dsMap.put("PUBLISHER_DS", dataSource1);
dsMap.put("ADVERTISER_DS", dataSource2);
dataSource.setTargetDataSources(dsMap);
return dataSource;
}
#Bean(name = "dataSource1")
public DataSource getDataSource1() throws SQLException, PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// See: datasouce-cfg.properties
dataSource.setDriverClass(env.getProperty("ds.database-driver1"));
dataSource.setJdbcUrl(env.getProperty("ds.url1"));
dataSource.setUser(env.getProperty("ds.username1"));
dataSource.setPassword(env.getProperty("ds.password1"));
System.out.println("## getDataSource1: " + dataSource);
return dataSource;
}
private Properties getHibernateProperties1()
{
// set hibernate properties
Properties props = new Properties();
props.setProperty("ds.hibernate.dialect1", env.getProperty("ds.hibernate.dialect1"));
props.setProperty("ds.hibernate.show_sql1", env.getProperty("ds.hibernate.show_sql1"));
return props;
}
// need a helper method
// read environment property and convert to int
private int getIntProperty1(String propName) {
String propVal = env.getProperty(propName);
// now convert to int
int intPropVal = Integer.parseInt(propVal);
return intPropVal;
}
#Bean
public LocalSessionFactoryBean sessionFactory1() throws SQLException, PropertyVetoException{
// create session factorys
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
// set the properties
sessionFactory.setDataSource(getDataSource1());
sessionFactory.setPackagesToScan(env.getProperty("ds.hibernate.packagesToScan1"));
sessionFactory.setHibernateProperties(getHibernateProperties1());
return sessionFactory;
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager1(SessionFactory sessionFactory1) {
// setup transaction manager based on session factory
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory1);
return txManager;
}
#Bean(name = "dataSource2")
public DataSource getDataSource2() throws SQLException, PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// See: datasouce-cfg.properties
dataSource.setDriverClass(env.getProperty("ds.database-driver2"));
dataSource.setJdbcUrl(env.getProperty("ds.url2"));
dataSource.setUser(env.getProperty("ds.username2"));
dataSource.setPassword(env.getProperty("ds.password2"));
System.out.println("## getDataSource2: " + dataSource);
return dataSource;
}
private Properties getHibernateProperties2()
{
// set hibernate properties
Properties props = new Properties();
props.setProperty("ds.hibernate.dialect2", env.getProperty("ds.hibernate.dialect2"));
props.setProperty("ds.hibernate.show_sql2", env.getProperty("ds.hibernate.show_sql2"));
return props;
}
// need a helper method
// read environment property and convert to int
private int getIntProperty2(String propName) {
String propVal = env.getProperty(propName);
// now convert to int
int intPropVal = Integer.parseInt(propVal);
return intPropVal;
}
#Bean
public LocalSessionFactoryBean sessionFactory2() throws SQLException, PropertyVetoException{
// create session factorys
LocalSessionFactoryBean sessionFactory1 = new LocalSessionFactoryBean();
// set the properties
sessionFactory1.setDataSource(getDataSource2());
sessionFactory1.setPackagesToScan(env.getProperty("ds.hibernate.packagesToScan2"));
sessionFactory1.setHibernateProperties(getHibernateProperties2());
return sessionFactory1;
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManage2(SessionFactory sessionFactory1) {
// setup transaction manager based on session factory
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory1);
return txManager;
}
}
Dao class :
package com.pack1.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
#Repository
public class DataDAO extends JdbcDaoSupport {
#Autowired
#Qualifier(value="t1")
private SessionFactory firstDBSessionFactory;
public List<Publisher> queryPublishers() {
// get the current hibernate session
Session currentSession = firstDBSessionFactory.getCurrentSession();
// create a query
Query<Publisher> theQuery =
currentSession.createQuery("from Publisher", Publisher.class);
// execute query and get result list
List<Publisher> customers = theQuery.getResultList();
// return the results
return customers;
return customers;
}
#Autowired
#Qualifier(value="t2")
private SessionFactory secondDBSessionFactory;
#Transactional(propagation= Propagation.REQUIRED, readOnly=true, value="t2")
public List<Advertiser> queryAdvertisers() {
// get the current hibernate session
Session currentSession = secondDBSessionFactory.getCurrentSession();
// create a query
Query<Advertiser> theQuery =
currentSession.createQuery("from Advertiser", Advertiser.class);
// execute query and get result list
List<Advertiser> customers = theQuery.getResultList();
// return the results
return customers;
}
}
public List<String> queryDashboard() {
return null;
}
}
Properties file :
# DataSource (PUBLISHER System).
ds.database-driver1=com.mysql.jdbc.Driver
ds.url1=jdbc:mysql://127.0.0.1:3306/pan_db
ds.username1=hbstudent
ds.password1=hbstudent
# DataSource (ADVERTISER System).
ds.database-driver2=com.mysql.jdbc.Driver
ds.url2=jdbc:mysql://127.0.0.1:3306/voter_db
ds.username2=hbstudent
ds.password2=hbstudent
#
# Hibernate properties1
#
ds.hibernate.dialect1=org.hibernate.dialect.MySQLDialect
ds.hibernate.show_sql1=true
ds.hibernate.hbm2ddl.auto1=update
#
# Hibernate properties2
#
ds.hibernate.dialect2=org.hibernate.dialect.MySQLDialect
ds.hibernate.show_sql2=true
ds.hibernate.hbm2ddl.auto2=update
SpringWebAppInitializer class :
package com.pack1.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
public class SpringWebAppInitializer implements WebApplicationInitializer
{
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ApplicationContextConfig.class);
ctx.setServletContext(servletContext); // ②
Dynamic servlet = servletContext.addServlet("dispatcher",new DispatcherServlet(ctx)); // ③
servlet.addMapping("/*");
servlet.setLoadOnStartup(1);
servletContext.addFilter("name", CharacterEncodingFilter.class)
.addMappingForUrlPatterns(null, false, "/*");
}
/*#Override
public void onStartup(ServletContext servletContext) throws ServletException
{
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(ApplicationContextConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
//
dispatcher.setInitParameter("contextClass", appContext.getClass().getName());
servletContext.addListener(new ContextLoaderListener(appContext));
// UTF8 Charactor Filter.
FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class);
fr.setInitParameter("encoding", "UTF-8");
fr.setInitParameter("forceEncoding", "true");
fr.addMappingForUrlPatterns(null, true, "/*");
}*/
}
WebMvcConfigurerAdapter Class :
package com.pack1.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.pack1.intercepter.DataSourceIntercepter;
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
// Default..
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new DataSourceIntercepter())//
.addPathPatterns("/publisher/*", "/advertiser/*");
}
}
following exception is :
INFO: Server startup in [8,376] milliseconds
Dec 05, 2019 12:05:18 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping for GET /multiple_DB1/
Dec 05, 2019 12:05:22 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping for GET /multiple_DB1/
Dec 05, 2019 12:05:23 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping for GET /multiple_DB1/
I am new to using multiple Datasource in Spring MVC. Please help me Coding in Hibernate Configuration class .
You will need multiple configuration files for each database and one of them needs to be declared as Primary. I am providing you some examples to have an idea what you need.
PrimaryDB is declared the primary database for the project. Primary means that the JPA by default will be executed on the primary database.
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "primaryEntityManagerFactory",
basePackages = {"com.example.repositories.primary"})
public class PrimaryDBConfig {
#Primary
#Bean(name = "primaryDatasource")
#ConfigurationProperties(prefix = "primary.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder, #Qualifier("primaryDatasource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("com.example.entities.primary")
.persistenceUnit("primary").build();
}
#Primary
#Bean(name = "primaryTransactionManager")
public PlatformTransactionManager transactionManager(
#Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
A second configuration file about our second database FooDB
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "fooEntityManagerFactory",
basePackages = {"com.example.repositories.foo"})
public class FooDBConfig {
#Bean(name = "fooDatasource")
#ConfigurationProperties(prefix = "foo.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "fooEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder, #Qualifier("fooDatasource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("com.example.entities.crf")
.persistenceUnit("foo").build();
}
#Bean(name = "fooTransactionManager")
public PlatformTransactionManager transactionManager(
#Qualifier("fooEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
In addition, you will need to add the following on application.properties, because Spring will listen to the default data source configuration.
primary.datasource.url= URL
primary.datasource.username=username
primary.datasource.password=password
foo.datasource.url=URL
foo.datasource.username=username
foo.datasource.password=password
Find below Configuration file
package com.yogendra.configuration;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class DatabaseConfiguration {
#Autowired
private Environment env;
#Bean("datasource1")
public DataSource dataSource1() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("app1.db.driverClassName"));
dataSource.setUrl(env.getProperty("app1.db.URL"));
dataSource.setUsername(env.getProperty("app1.db.username"));
dataSource.setPassword(env.getProperty("app1.db.password"));
return dataSource;
}
#Bean("datasource2")
public DataSource dataSource2() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("app2.db.driverClassName"));
dataSource.setUrl(env.getProperty("app2.db.URL"));
dataSource.setUsername(env.getProperty("app2.db.username"));
dataSource.setPassword(env.getProperty("app2.db.password"));
return dataSource;
}
#Bean("jdbc1")
public JdbcTemplate jdbcTemplate1() {
return new JdbcTemplate(dataSource1());
}
#Bean("jdbc2")
public JdbcTemplate jdbcTemplate2() {
return new JdbcTemplate(dataSource2());
}
#Bean("session1")
public LocalSessionFactoryBean sessionFactory1() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource1());
sessionFactory.setPackagesToScan(new String[] { "com.yogendra" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean("session2")
public LocalSessionFactoryBean sessionFactory2() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource2());
sessionFactory.setPackagesToScan(new String[] { "com.yogendra" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean("tx1")
public HibernateTransactionManager transactionManager1() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory1().getObject());
return transactionManager;
}
#Bean("tx2")
public HibernateTransactionManager transactionManager2() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory2().getObject());
return transactionManager;
}
#SuppressWarnings("serial")
private Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto", "none");
setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
setProperty("hibernate.show_sql", "true");
}
};
}
}
And here is properties files
app1.db.driverClassName=org.postgresql.Driver
app1.db.URL=jdbc:postgresql://localhost/test_db
app1.db.username=postgres
app1.db.password=postgres
app2.db.driverClassName=org.postgresql.Driver
app2.db.URL=jdbc:postgresql://localhost/test_db2
app2.db.username=postgres
app2.db.password=postgres
You can find working code here
See how you can use the sessionFactory
#Autowired
#Qualifier("session2")
SessionFactory sessionFactory;
#GetMapping(value = "/test2")
#Transactional("tx2")
public void test2() {
List<String> cities = sessionFactory.getCurrentSession().createSQLQuery("select city from address")
.list();
System.out.println("------------ citties ------------ " + cities);
}
Related
Am developing a simple message broker with rabbitmq
Below is the Error am getting of "No Beans of 'Connectionfactory' type found"
My Code is as below with all the correct importations.
Code
package com.producer.demo;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class MQConfig {
public static final String message_queue = "message_queue";
#Bean
public Queue queue(){
return new Queue(message_queue);
}
#Bean
public TopicExchange exchange(){
return new TopicExchange("message_exchange");
}
#Bean
public Binding binding(Queue queue, TopicExchange topicExchange){
return BindingBuilder.bind(queue)
.to(topicExchange)
.with("routing_key");
}
#Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
#Bean
public AmqpTemplate template(ConnectionFactory connectionFactory){
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(messageConverter());
return template;
}
}
By default Spring boot manages the Connection, Channel and ConnectionFactory for you. You can specify properties in your application.properties file
spring.rabbitmq.host= 127.0.0.1
spring.rabbitmq.port= 5672
spring.rabbitmq.username= guest
spring.rabbitmq.password= guest
The second option is that you can define the required bean in your MQConfig configuration file
The below code is an example of the same. I don’t advise you to customize unless you need to.
...
#Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
I face the below issue though I have correctly defined SimpleJobLauncher
Description:
Field jobLauncher in com.abcplusd.application.BatchConfig required a bean of type 'org.springframework.batch.core.launch.support.SimpleJobLauncher' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.batch.core.launch.support.SimpleJobLauncher' in your configuration.
The following are my source code..
package com.abcplusd.application;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
#Configuration
#EnableScheduling
public class BatchScheduler {
#Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
#Bean
public MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean(ResourcelessTransactionManager resourcelessTransactionManager) throws Exception {
MapJobRepositoryFactoryBean factoryBean = new MapJobRepositoryFactoryBean(resourcelessTransactionManager);
factoryBean.afterPropertiesSet();
return factoryBean;
}
#Bean
public JobRepository jobRepository(MapJobRepositoryFactoryBean factoryBean) throws Exception{
return (JobRepository) factoryBean.getObject();
}
#Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
return launcher;
}
}
and
package com.abcplusd.application;
import com.abcplusd.application.batch.Process;
import com.abcplusd.application.batch.Reader;
import com.abcplusd.application.batch.Writer;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.Date;
#Configuration
#EnableBatchProcessing
#Import({BatchScheduler.class})
public class BatchConfig {
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
public SimpleJobLauncher jobLauncher;
#Scheduled(cron = "0 0/1 * 1/1 * ?")
public void sendSMSForBookMark() throws Exception {
System.out.println(" Job Started at :"+ new Date());
JobParameters param = new JobParametersBuilder().addString("JobID",
String.valueOf(System.currentTimeMillis())).toJobParameters();
JobExecution execution = jobLauncher.run(job(), param);
System.out.println("Job finished with status :" + execution.getStatus());
}
public Job job() {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
public Step step1() {
return stepBuilderFactory.get("step1")
.<String, String> chunk(1)
.reader(new Reader())
.processor(new Process())
.writer(new Writer())
.build();
}
}
Help me to solve this issue.
It works fine when removed #Configuration from BatchScheduler class.
So answer is
package com.abcplusd.application;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
#EnableScheduling
public class BatchScheduler {
#Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
#Bean
public MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean(ResourcelessTransactionManager resourcelessTransactionManager) throws Exception {
MapJobRepositoryFactoryBean factoryBean = new MapJobRepositoryFactoryBean(resourcelessTransactionManager);
factoryBean.afterPropertiesSet();
return factoryBean;
}
#Bean
public JobRepository jobRepository(MapJobRepositoryFactoryBean factoryBean) throws Exception{
return (JobRepository) factoryBean.getObject();
}
#Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
return launcher;
}
}
I am trying to use two datasources, one for metadata tables from spring batch and other is my application database to read/process/write. when I am trying to use both it is giving the following exception.
java.lang.IllegalStateException: To use the default BatchConfigurer the context must contain no more thanone DataSource, found 2
at org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.getConfigurer(AbstractBatchConfiguration.java:108) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration.initialize(SimpleBatchConfiguration.java:114) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$ReferenceTargetSource.createObject(SimpleBatchConfiguration.java:142) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.aop.target.AbstractLazyCreationTargetSource.getTarget(AbstractLazyCreationTargetSource.java:86) ~[spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192) ~[spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at com.sun.proxy.$Proxy43.getJobInstances(Unknown Source)
----------
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import com.springbatch_sample.domain.Person;
#Configuration
#EnableBatchProcessing
public class BatchConfiguration {
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Bean
#Primary
public DataSource hsqldbDataSource() throws SQLException {
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new org.hsqldb.jdbcDriver());
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:9001/xdb");
dataSource.setUsername("sa");
dataSource.setPassword("sa");
return dataSource;
}
#Bean
public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
#Bean
#Qualifier("mysqlDataSource")
public DataSource mysqlDataSource() throws SQLException {
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new com.ibm.db2.jcc.DB2Driver());
dataSource.setUrl("jdbc:db2://xxxx");
dataSource.setUsername("user");
dataSource.setPassword("pswd");
//DatabasePopulatorUtils.execute(databasePopulator(), dataSource);
return dataSource;
}
#Bean
public FlatFileItemReader<Person> reader() {
FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
reader.setResource(new ClassPathResource("sample-data.csv"));
reader.setLineMapper(new DefaultLineMapper<Person>() {{
setLineTokenizer(new DelimitedLineTokenizer() {{
setNames(new String[] { "firstName", "lastName" });
}});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}});
}});
return reader;
}
#Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
#Bean
public JdbcBatchItemWriter<Person> writer() throws SQLException {
JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>();
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());
writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");
writer.setDataSource(hsqldbDataSource());
return writer;
}
// end::readerwriterprocessor[]
// tag::jobstep[]
#Bean
public Job importUserJob(JobCompletionNotificationListener listener) throws SQLException {
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1())
.end()
.build();
}
#Bean
public Step step1() throws SQLException {
return stepBuilderFactory.get("step1")
.<Person, Person> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
// end::jobstep[]
}
Use of multiple DataSources in Spring Batch
Check out this link.
Same question, and I solved my problem by that link.
So I'm trying to run an example here Spring MVC and Spring JDBC Transaction Tutorial
According to the article the location for Eclipse is here :
So I did it also in Netbeans :
But it gave me errors :
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to load bean class: org.o7planning.springmvcjdbc.config.ApplicationContextConfig;
nested exception is java.io.FileNotFoundException: class path resource [ds/datasource-cfg.properties] cannot be opened because it does not exist
and
java.io.FileNotFoundException: class path resource [ds/datasource-cfg.properties] cannot be opened because it does not exist
org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:158)
I've been reading some post on SO about .properties resource accessing in netbeans but nothing seems work. The errors are only coming from those (accessing parts). The codes are overall just fine.
The "classpath:ds/datasource-cfg.properties" is declared in the following class. ApplicationContextConfig.java
package org.o7planning.springmvcjdbc.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#ComponentScan("org.o7planning.springmvcjdbc.*")
#EnableTransactionManagement
// HERE ..!!!
// Load to Environment.
#PropertySources({ #PropertySource("classpath:ds/datasource-cfg.properties") })
public class ApplicationContextConfig {
// The Environment class serves as the property holder
// and stores all the properties loaded by the #PropertySource
#Autowired
private Environment env;
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean(name = "dataSource")
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
// See: datasouce-cfg.properties
dataSource.setDriverClassName(env.getProperty("ds.database-driver"));
dataSource.setUrl(env.getProperty("ds.url"));
dataSource.setUsername(env.getProperty("ds.username"));
dataSource.setPassword(env.getProperty("ds.password"));
System.out.println("## getDataSource: " + dataSource);
return dataSource;
}
#Bean(name = "transactionManager")
public DataSourceTransactionManager getTransactionManager() {
DataSourceTransactionManager txManager = new DataSourceTransactionManager();
DataSource dataSource = this.getDataSource();
txManager.setDataSource(dataSource);
return txManager;
}
}
So where to put this resources folder in netbeans ?
Ok, I found it :
I comment this :
//#PropertySources({ #PropertySource("classpath:ds/datasource-cfg.properties") })
Then I add this
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
In the class that extends WebMvcConfigurerAdapter
I am new to spring and hibernate.I was trying to connect my web application with Facebook.I have done this using the java script provided by Facebook but I want to connect Facebook using Spring Social. For this purpose I have to declare a properties file under scr/main/resource folder.I have done this but I am not using any xml file. I have a class which loads all the properties and Dao files.I don't know the method of loading the properties file of Facebook.
My Applicationconfig class is
package net.codejava.spring.config;
import java.util.Properties;
import javax.sql.DataSource;
import net.codejava.spring.dao.UserDAO;
import net.codejava.spring.dao.UserDAOImpl;
import net.codejava.spring.model.User;
import org.apache.commons.dbcp2.BasicDataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#ComponentScan("net.codejava.spring")
#EnableTransactionManagement
public class ApplicationContextConfig {
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean(name = "dataSource")
public DataSource getDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/testing");
dataSource.setUsername("root");
dataSource.setPassword("4261");
return dataSource;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
return properties;
}
/*private Properties getFacebookProperties(){
Properties properties = new Properties();
properties.put("spring.social.facebook.appId", "809280815833386");
properties.put("spring.social.facebook.appSecret","24035c462c9d1fca367ff813436b15d8");
return properties;
}*/
#Autowired
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.addProperties(getHibernateProperties());
sessionBuilder.addAnnotatedClasses(User.class);
return sessionBuilder.buildSessionFactory();
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(
SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(
sessionFactory);
return transactionManager;
}
#Autowired
#Bean(name = "userDao")
public UserDAO getUserDao(SessionFactory sessionFactory) {
return new UserDAOImpl(sessionFactory);
}
}
My application.properties file is
spring.social.facebook.appId=appId
spring.social.facebook.appSecret=appSecret
Please provide the solution
You can do something like this:
#Configuration
#ComponentScan("net.codejava.spring")
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class ApplicationContextConfig {
#Value("${spring.social.facebook.appId}")
private String facebookAppID;
}