Introducing Spring Batch fails Dao-Test - spring-boot

I am using Spring Batch in a Spring Boot application as below. Spring Batch and the application seem to work fine with that configuration.
However, with that configuration for a simple Dao-Test (not for Spring Batch) I get the following exception. Without the Spring Batch configuration the test is running fine. Update: The problem appears if I configure to use an own JobRepository with a transaction manager (below in class MyBatchConfigurer).
I tried to provide another transaction manager for Spring Batch but I am running from exception to exception.
org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3505)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1427)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1423)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
at com.sun.proxy.$Proxy165.flush(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:305)
at com.sun.proxy.$Proxy165.flush(Unknown Source)
at com.foo.dao.GenericDao.save(GenericDao.java:60)
at com.foo.dao.GenericDao$$FastClassBySpringCGLIB$$71a0996b.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 37 more
Test Setup
#SpringBootTest
#RunWith(SpringRunner.class)
#EntityScan(basePackages = "com.foo.entity")
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
#TestPropertySource("/mytest.properties")
#Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:/testdata.sql")
public class MyTest {
#Inject
private OrderDao sut;
#Test
public void test_findByAnotherFieldId() {
final Order order = // build an order ...
sut.save(order);
final Order result = sut.findByAnotherFieldId("valueOfOtherField");
assertThat(result).isEqualTo(order);
}
}
Spring Batch Job configuration
#Configuration
#EnableBatchProcessing
#Import(OracleDatabaseConfig.class)
#ComponentScan(basePackageClasses = MyBatchConfigurer.class)
public class BatchJobConfig {
// Injects...
#Qualifier("analyseOrdersJob")
#Bean
public Job analyseOrdersJob() {
return jobBuilderFactory.get("analyseOrdersJob").start(analyseOrdersStep()).build();
}
#Bean
public Step analyseOrdersStep() {
return stepBuilderFactory.get("analyseOrdersStep").<Order, String>chunk(4)
.reader(orderItemReader) //
.processor(orderItemProcessor) //
.writer(orderItemWriter) //
.build();
}
}
Spring Batch configuration
#Component
public class MyBatchConfigurer extends DefaultBatchConfigurer {
#Inject
private DataSource dataSource;
#Override
public JobRepository getJobRepository() {
try {
return extractJobRepository();
} catch (final Exception e) {
throw new BatchConfigurationException(e);
}
}
private JobRepository extractJobRepository() throws Exception {
final JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(getTransactionManager());
factory.afterPropertiesSet();
return factory.getObject();
}
}
ItemReader
#Component
#StepScope
public class OrderItemReader implements ItemReader<Order> {
#Inject
private OrderDao orderdao;
private int nextOrderIndex;
private List<Order> orders;
#PostConstruct
public void postConstruct() {
orders = orderdao.findAll();
}
#Override
public Order read() {
if (nextOrderIndex < orders.size()) {
final Order order = orders.get(nextOrderIndex);
nextOrderIndex++;
return order;
}
return null;
}
}
ItemWriter and ItemProcessor are similarly configured.

Related

kafkaendpointlistenerregistry.start() throws null pointer exception

I have a requirement where I want to start Kakfa consumer manually.
Code :
class Dummy implements
ConsumerSeekAware
{
#Autowired
KafkaListenerEndpointRegistry registry;
CountDownLatch latch;
#Autowired
ConcurrentKafkaListenerContainerFactory factory;
onIdleEvent(){
latch.countdown()
}
#KafkaListener(id="myContainer",
topics="mytopic",
autoStartup="false")
public void listen() {}
#Scheduled(cron=" some time ")
void do_some_consumption(){
latch = new CountDownLatch(1);
this.registry.getListenerContainer("myContainer").start();
latch.await();
do processing
this.registry.getListenerContainer("myContainer").stop()
}
}
I have made the bean of
ConcurrentKafkaListenerContainerFactory with all props in my other Config class which I am Autowiring here.
However, I get a null pointer exception when I start my container
using this.registry.getListenerContainer("myContainer").start()
java.lang.NullPointerException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
I just copied your code into a Spring Boot app (which auto configures the factories); and everything works perfectly as expected...
#SpringBootApplication
#EnableScheduling
public class So62412316Application {
public static void main(String[] args) {
SpringApplication.run(So62412316Application.class, args);
}
#Bean
public ApplicationRunner runner(KafkaTemplate<String, String> template) {
return args -> {
template.send("mytopic", "foo");
};
}
#Bean
public NewTopic topic() {
return TopicBuilder.name("mytopic").partitions(1).replicas(1).build();
}
}
#Component
class Dummy implements ConsumerSeekAware {
#Autowired
KafkaListenerEndpointRegistry registry;
CountDownLatch latch;
#Autowired
ConcurrentKafkaListenerContainerFactory factory;
#EventListener
public void onIdleEvent(ListenerContainerIdleEvent event) {
System.out.println(event);
latch.countDown();
}
#KafkaListener(id = "myContainer", topics = "mytopic", autoStartup = "false")
public void listen(String in) {
System.out.println(in);
}
#Scheduled(initialDelay = 5_000, fixedDelay = 60_000)
void do_some_consumption() throws InterruptedException {
latch = new CountDownLatch(1);
this.registry.getListenerContainer("myContainer").start();
latch.await();
this.registry.getListenerContainer("myContainer").stop();
}
}
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.listener.idle-event-interval=5000

spring boot and batch throw Invalid object name 'BATCH_JOB_INSTANCE'

I m stucked with spring boot in my app , it's dont want to run schema nor tables , only connect to my database SQL Server and query information, so I disabled this line in file application.properties
spring.batch.initialize-schema=never
spring.datasource.initialization-mode=never
but doesn´t work , I dont know what´s wrong, already configure my datasource, thanks in advance ,
I hope someone can help me, sorry my english is poor.
I am using spring boot 2.2.6, my code of DataSourceConfiguration
.....
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class DataSourceConfiguration {
#Bean
#Primary
#Qualifier("jobsDataSource")
public DataSource hsqldbDataSource() throws SQLException {
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new org.hsqldb.jdbcDriver());
dataSource.setUrl("jdbc:hsqldb:mem:mydb");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
#Bean
public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
#Bean
#Qualifier("sqlserverDataSource")
public DataSource sqlserverDataSource() throws SQLException {
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new net.sourceforge.jtds.jdbc.Driver());
dataSource.setUrl("jdbc:jtds:sqlserver://x.y.z.t:1433/mydb");
dataSource.setUsername("usersqlserver");
dataSource.setPassword("xxxxxx");
return dataSource;
}
#Bean
public JdbcTemplate sqlJdbcTemplate(#Qualifier("sqlserverDataSource") final DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
public PlatformTransactionManager transactionManager(){
return new ResourcelessTransactionManager();
}
#Bean
public BatchConfigurer configurer(#Qualifier("sqlserverDataSource") DataSource dataSource){
return new DefaultBatchConfigurer(){
#Override
protected JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager());
return factory.getObject();
// MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean = new MapJobRepositoryFactoryBean(transactionManager());
// mapJobRepositoryFactoryBean.setTransactionManager(transactionManager());
// return mapJobRepositoryFactoryBean.getObject();
}
#Override
protected JobLauncher createJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(createJobRepository());
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
};
}
}
Here is the error
Caused by: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]; nested exception is java.sql.SQLException: Invalid object name 'BATCH_JOB_INSTANCE'.
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:235) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1443) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:712) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:768) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.getJobInstance(JdbcJobInstanceDao.java:151) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.repository.support.SimpleJobRepository.isJobInstanceExists(SimpleJobRepository.java:91) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366) ~[spring-tx-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) ~[spring-tx-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at com.sun.proxy.$Proxy54.isJobInstanceExists(Unknown Source) ~[na:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at com.sun.proxy.$Proxy46.isJobInstanceExists(Unknown Source) ~[na:na]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.getNextJobParameters(JobLauncherCommandLineRunner.java:199) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:191) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:166) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:153) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:148) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:784) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
... 10 common frames omitted
Caused by: java.sql.SQLException: Invalid object name 'BATCH_JOB_INSTANCE'.
at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:372) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2988) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2421) ~[jtds-1.3.1.jar:1.3.1]
Thanks in advance
Spring Batch requires a few tables in your database to run. So you need to create those tables manually upfront or tell Spring Boot to do it for you.
Since you told Spring Boot to not create those tables for you by setting spring.batch.initialize-schema=never, then you need to create them yourself in your target datasource.
So in your case, you need to run the DDL script to create Spring Batch tables on your SQL server instance before running your job.
Alright,I have had removing this line and I did as you suggested and it´s worked, only that dao is NullpointerException, it´s interface and is used in the Itemprocessor:
#Bean
public BatchConfigurer configurer(#Qualifier("sqlserverDataSource") DataSource dataSource){
return new DefaultBatchConfigurer(){
// #Override
// protected JobRepository createJobRepository() throws Exception {
// JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
// factory.setDataSource(dataSource);
// factory.setTransactionManager(transactionManager());
// // factory.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
// //factory.setTablePrefix("dbo.tmpAccWebServ");
// //factory.setDatabaseType("SQLSERVER");
// //factory.setMaxVarCharLength(1000);
// return factory.getObject();
//// MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean = new MapJobRepositoryFactoryBean(transactionManager());
//// mapJobRepositoryFactoryBean.setTransactionManager(transactionManager());
//// return mapJobRepositoryFactoryBean.getObject();
// }
//
// #Override
// protected JobLauncher createJobLauncher() throws Exception {
// SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
// jobLauncher.setJobRepository(createJobRepository());
// jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
// jobLauncher.afterPropertiesSet();
// return jobLauncher;
// }
#Override
public void setDataSource(DataSource dataSource) {
// override to do not set datasource even if a datasource exist.
// initialize will use a Map based JobRepository (instead of database)
} //
};
}//
This is the code of CustomerItemProcessor
public class CustomerItemProcessor implements ItemProcessor<beangenerico,ThreadLocal<CopyOnWriteArrayList<beanCustomer>>> {
#Autowired
private CustomerDAO customerDAO;
private ThreadLocal<CopyOnWriteArrayList<beanCustomer>> listbean = new ThreadLocal<CopyOnWriteArrayList<beanCustomer>>();
public ThreadLocal<CopyOnWriteArrayList<beanCustomer>> process(beangenerico rangos) throws Exception {
System.out.println("entro a customitemprocessor");
listbean.set(new CopyOnWriteArrayList<beanCustomer>());
System.out.println("rangos:"+rangos.getIni()+"-"+rangos.getFin());
listbean = customerDAO.getAccAgentes(rangos);
if(listbean != null) {
//customer.setId(currentCustomer.getId());
return listbean;
} else {
return null;
}
}
#Autowired
public void setCustomerDAO(CustomerDAOImpl customerDAO) {
this.customerDAO = customerDAO;
}
}
This is the code of interface
public interface CustomerDAO {
ThreadLocal<CopyOnWriteArrayList<beanCustomer>> getAccAgentes(beangenerico bean);
}
This is the code if CustomerDAOImpl
#Repository
#Component
public class CustomerDAOImpl implements CustomerDAO{
private String SP_SQL = "{call mysp(?, ?)}";
#Autowired
#Qualifier("sqlserverDataSource")
DataSource dataSource;
#Autowired
JdbcTemplate jdbcTemplate;
public ThreadLocal<CopyOnWriteArrayList<beanCustomer>> getAccAgentes(beangenerico bean) {
...
//query resulset
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
}
Thanks in advance for your help.

Using Spring Scheduler to return rows from DB throws Null pointer Exception

I am using Spring scheduling to schedule a task that performs some DB operation every hour. This throws a NullPointerException every time I try to call a function that triggers DB specific operations.
Configuration File :
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="com.bt.rtddashboard")
/*#EnableJpaRepositories(basePackages = {
"com.bt.rtddashboard"
})*/
#EnableScheduling
#PropertySource("classpath:jdbc.properties")
public class RTDDashboardConfiguration extends WebMvcConfigurerAdapter {
#Resource
private Environment env;
#Bean(name = "dataSource", destroyMethod="close")
public DataSource getDataSource() {
//DB code
}
private Properties getHibernateProperties() {
//Hibernate code
}
#Bean(name = "sessionFactory")
#Scope("singleton")
public LocalSessionFactoryBean getSessionFactory() {
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getHibernateTransactionManager(SessionFactory factory) {
;
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("/").setCachePeriod(31556926);
}
#Scheduled(fixedRate=1000)
public void work() {
// task execution logic
System.out.println("Scheduled Task");
DashboardController controller=new DashboardController();
controller.performTask();
}
}
Dashboard Controller :
#RestController
public class DashboardController {
#Autowired
private InlineService service;
#RequestMapping(value="/rtd/getAllServers", method=RequestMethod.GET)
public ResponseEntity<List<ServerMonitor>> getAllServers(){
List<ServerMonitor> ilsList=new ArrayList<ServerMonitor>();
ResponseEntity<List<ServerMonitor>> response=null;
try{
ilsList=service.getAllServers();
response=new ResponseEntity<List<ServerMonitor>>(ilsList,HttpStatus.OK);
System.out.println("Scheduled Time");
}catch(Exception e){
}
return response;
}
public void performTask(){
System.out.println("Scheduled Task Starts in Contrroller");
List<IlsStats> ilsStats =new ArrayList<IlsStats>();
List<IlsStatsHistory> ilsStatsHisList=new ArrayList<IlsStatsHistory>();
try{
//get All the ILS Stats
ilsStats=service.getAllInlineStats();
System.out.println("No of rows to Copy : " + ilsStats.size());
ilsStatsHisList=formILSHistoryList(ilsStats);
int flag=service.insertInIlsStatsHistory(ilsStatsHisList);
//List<ServerMonitor> ilsList=service.getAllServers();
}catch(Exception e){
e.printStackTrace();
}
}
Here, ilsStats=service.getAllInlineStats(); throws NullPointerException.
Even though the rest webservice created on top of it is working fine.
Stack Trace :
Scheduled Task
Scheduled Task Starts in Contrroller
java.lang.NullPointerException
at com.bt.rtddashboard.controller.DashboardController.performTask(DashboardController.java:226)
at com.bt.rtddashboard.configuration.RTDDashboardConfiguration.work(RTDDashboardConfiguration.java:137)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
The same stack trace comes up every 1 sec now.
Creating an #Scheduled method in a configuration class is a very bad idea (imho). Next to that I also think that having a scheduler calling a controller method (a method tied to a web related component!) is generally a bad idea/design.
Nonetheless the problem is that you do new DashboardController(). That will obviously create a bean outside the scope of spring and will never be dependency injected. Instead inject the into the class and use that instance.
#Autowired
private DashboardController controller;
#Scheduled(fixedRate=1000)
public void work() {
controller.performTask();
}
Or even better just remove that method all together and simply place #Scheduled(fixedRate=1000) on the performTask method instead.

Spring MongoDB - org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.lang.Class

I am evaluating MongoDB and Spring Data MongoDB in a spring boot application for one of our upcoming project. I have a simple POJO which would be saved in MongoDB
#Document(collection = "customers")
public class CustomerDoc{
#org.springframework.data.annotation.Id
private String Id;
private String firstName;
private String lastName;
private MonetaryAmount amount;
public CustomerDoc(String firstName, String lastName, MonetaryAmount amount){
this.firstName = firstName;
this.lastName = lastName;
this.amount = amount;
}
}
The Spring configuration is
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
MongoClient mongoClient = new MongoClient("localhost", 27017);
return new SimpleMongoDbFactory(mongoClient, mongoDbName);
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(), mongoConverter());
}
#Bean
public MappingMongoConverter mongoConverter() throws Exception {
MongoMappingContext mappingContext = new MongoMappingContext();
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mappingContext);
mongoConverter.setMapKeyDotReplacement("\\:");
return mongoConverter;
}
In the configuration, I have to set the replacement key because without having it, I get exception:
org.springframework.data.mapping.model.MappingException: Map key java.lang.Class contains dots but no replacement was configured! Make sure map keys don't contain dots in the first place or configure an appropriate replacement!
This happens because of the MonetaryAmount object in the Customer class
The customer repository is :
public interface CustomerDocRepository extends MongoRepository<CustomerDoc, String>{
public List<CustomerDoc> findByFirstName();
}
Now if I try to save a customer object, I get this exception:
Exception in thread "main" java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:675)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:690)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at com.poc.mongodb.MongoDbApp.main(MongoDbApp.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.lang.Class.
at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:210)
at com.mongodb.DBObjectCodec.encodeMap(DBObjectCodec.java:220)
at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:196)
at com.mongodb.DBObjectCodec.encodeMap(DBObjectCodec.java:220)
at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:196)
at com.mongodb.DBObjectCodec.encodeMap(DBObjectCodec.java:220)
at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:196)
at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:128)
at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:61)
at com.mongodb.CompoundDBObjectCodec.encode(CompoundDBObjectCodec.java:48)
at com.mongodb.CompoundDBObjectCodec.encode(CompoundDBObjectCodec.java:27)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at com.mongodb.connection.InsertCommandMessage.writeTheWrites(InsertCommandMessage.java:101)
at com.mongodb.connection.InsertCommandMessage.writeTheWrites(InsertCommandMessage.java:43)
at com.mongodb.connection.BaseWriteCommandMessage.encodeMessageBodyWithMetadata(BaseWriteCommandMessage.java:129)
at com.mongodb.connection.RequestMessage.encodeWithMetadata(RequestMessage.java:160)
at com.mongodb.connection.WriteCommandProtocol.sendMessage(WriteCommandProtocol.java:212)
at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:101)
at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:67)
at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:37)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:159)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:286)
at com.mongodb.connection.DefaultServerConnection.insertCommand(DefaultServerConnection.java:115)
at com.mongodb.operation.InsertOperation.executeCommandProtocol(InsertOperation.java:76)
at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:141)
at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:133)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:230)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:221)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:133)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:60)
at com.mongodb.Mongo.execute(Mongo.java:781)
at com.mongodb.Mongo$2.execute(Mongo.java:764)
at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:333)
at com.mongodb.DBCollection.insert(DBCollection.java:328)
at com.mongodb.DBCollection.insert(DBCollection.java:319)
at com.mongodb.DBCollection.insert(DBCollection.java:289)
at com.mongodb.DBCollection.insert(DBCollection.java:255)
at com.mongodb.DBCollection.insert(DBCollection.java:239)
at org.springframework.data.mongodb.core.MongoTemplate$10.doInCollection(MongoTemplate.java:1054)
at org.springframework.data.mongodb.core.MongoTemplate$10.doInCollection(MongoTemplate.java:1049)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:462)
at org.springframework.data.mongodb.core.MongoTemplate.insertDBObjectList(MongoTemplate.java:1049)
at org.springframework.data.mongodb.core.MongoTemplate.doInsertBatch(MongoTemplate.java:935)
I am using mongo driver 3.2.2 Spring data MongoDB 1.9.1
Any help would be really appreciated

Autowired JpaRepository Save Ignored in custom FieldSetMapper

In brief, I am trying to use JpaRepositories in spring batch related classes. But due to some reason, only selects are working but Insert/updates are ignored.
I have a custom FieldSetMapper as below,
#Component
#StepScope // I have not seen step scope is used as this way!
public class ItemFieldSetMapper implements FieldSetMapper<CategoryItem> {
private CSVSchema schema;
private Task task;
Logger logger = Logger.getLogger(LocalPersist.class.getName());
#Autowired
private CSVColumnDao csvColumnDao;
#Autowired
private BasisCategoryDao basisCategoryDao;
#Override
public BasisCategoryItem mapFieldSet(FieldSet fieldSet) throws BindException {
// csvColumnDao.save(someobject) // This is ignored
}
}
Since I have to start the job asynchronously (Job is started form controller method)
I created a custom DefaultBatchConfigurer as below,
#Component
#EnableBatchProcessing
public class ProductImportBatchConfig extends DefaultBatchConfigurer {
#Autowired
private TaskExecutor taskExecutor; // This is coming form another bean defined in another configuration class.
/*#Autowired
private DataSource dataSource;*/
#Autowired
private PlatformTransactionManager transactionManager;
#Override
protected JobLauncher createJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(super.getJobRepository());
jobLauncher.setTaskExecutor(taskExecutor);
return jobLauncher;
}
#Override
public PlatformTransactionManager getTransactionManager() {
// TODO Auto-generated method stub
return transactionManager;
}
#Override
#Autowired
public void setDataSource(DataSource dataSource) {
DatabasePopulatorUtils.execute(dropDatabasePopulator(), dataSource);
DatabasePopulatorUtils.execute(createDatabasePopulator(), dataSource);
// TODO Auto-generated method stub
super.setDataSource(dataSource);
}
private DatabasePopulator dropDatabasePopulator() {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.setContinueOnError(true);
databasePopulator.addScript(new ClassPathResource("org/springframework/batch/core/schema-drop-mysql.sql"));
return databasePopulator;
}
private DatabasePopulator createDatabasePopulator() {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.setContinueOnError(true);
databasePopulator.addScript(new ClassPathResource("org/springframework/batch/core/schema-mysql.sql"));
return databasePopulator;
}
}
This is my Application class,
#Configuration
#ComponentScan
#EnableAutoConfiguration(exclude = { BatchAutoConfiguration.class })
public class Application extends SpringBootServletInitializer {
private static Class<Application> applicationClass = Application.class;
public static void main(String[] args) {
SpringApplication.run(applicationClass, args);
}
#Override
protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
#Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setCorePoolSize(6);
pool.setMaxPoolSize(30);
pool.setWaitForTasksToCompleteOnShutdown(false);
return pool;
}
}
What I have figured so far:
I went through many documentation to get my scenario working. This is the closest I got.
The issue is to do with #EnableBatchProcessing. It creates its own DataSourceTransactionManager which has no clue about jpa/hibernate and ignore inserts/updates.
As the suggested solution,
#Bean
public BatchConfigurer batchConfigurer(DataSource dataSource, EntityManagerFactory entityManagerFactory) {
return new BasicBatchConfigurer(dataSource, entityManagerFactory);
}
This seems to be not working because the constructor changed in newer versions.
It seems like, I have to get rid of the #EnableBatchProcessing and get the same transaction manager to work both in application and batch contexts.
Here are some trial and errors,
If I keep the #EnableBatchProcessing and use #EnableAutoConfiguration (exclude = { BatchAutoConfiguration.class })
The Batch tables are created and application runs correctly, But during the run time I get the following.
java.lang.StackOverflowError: null
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) ~[na:1.8.0_72]
at org.springframework.aop.framework.AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice(AdvisedSupport.java:487) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:193) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at com.sun.proxy.$Proxy126.getTransaction(Unknown Source) ~[na:na]
at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at com.sun.proxy.$Proxy126.getTransaction(Unknown Source) ~[na:na]
at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at com.sun.proxy.$Proxy126.getTransaction(Unknown Source) ~[na:na]
at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72]
Here is the properties file I am using,
spring.datasource.url = jdbc:mysql://localhost:3306/db
spring.datasource.username =root
spring.datasource.password =root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.validationQuery = SELECT 1
spring.datasource.timeBetweenEvictionRunsMillis = 3600
spring.datasource.minEvictableIdleTimeMillis = 3600
spring.datasource.testWhileIdle = true
spring.jpa.database = MYSQL
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto =update
spring.jpa.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming_strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.batch.job.enabled=false
spring.view.prefix=/WEB-INF/jsp/
spring.view.suffix=.jsp
But when I comment #EnableBatchProcessing the application complains for
JobBuilderFactory bean and etc. It seems like use of same transaction manager is not a practice and I have not see auto wiring of Jpa Repositories in batch related classes (Eg, ItemWriters and Readers etc.). But I want this scenario to work since this is a migration from a different implementation to spring batch.
I was confused with the injecting jpa transaction manager into the spring batch. This is how I was able to do it.
#Configuration
#EnableBatchProcessing
public class ProductImportBatchConfig implements BatchConfigurer {
private static final Log logger = LogFactory.getLog(DefaultBatchConfigurer.class);
#Autowired
private TaskExecutor taskExecutor;
#Autowired
private DataSource dataSource;
private PlatformTransactionManager transactionManager;
#Autowired
private LocalContainerEntityManagerFactoryBean entityManagerFactory;
private JobRepository jobRepository;
private JobLauncher jobLauncher;
private JobExplorer jobExplorer;
protected ProductImportBatchConfig() {
}
#Override
public JobRepository getJobRepository() {
return jobRepository;
}
#Override
public PlatformTransactionManager getTransactionManager() {
return transactionManager;
}
#Override
public JobLauncher getJobLauncher() {
return jobLauncher;
}
#Override
public JobExplorer getJobExplorer() {
return jobExplorer;
}
#Autowired
public void setDataSource(DataSource dataSource) {
if (this.dataSource == null) {
logger.error(null, new Throwable("This is not acceptable"));
}
DatabasePopulatorUtils.execute(dropDatabasePopulator(), this.dataSource);
DatabasePopulatorUtils.execute(createDatabasePopulator(), this.dataSource);
this.dataSource = dataSource;
EntityManagerFactory object = entityManagerFactory.getObject();
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(object);
this.transactionManager = jpaTransactionManager;
}
#PostConstruct
public void initialize() {
try {
if (dataSource == null) {
logger.warn("No datasource was provided...using a Map based JobRepository");
if (this.transactionManager == null) {
this.transactionManager = new ResourcelessTransactionManager();
}
MapJobRepositoryFactoryBean jobRepositoryFactory = new MapJobRepositoryFactoryBean(
this.transactionManager);
jobRepositoryFactory.afterPropertiesSet();
this.jobRepository = jobRepositoryFactory.getObject();
MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean(jobRepositoryFactory);
jobExplorerFactory.afterPropertiesSet();
this.jobExplorer = jobExplorerFactory.getObject();
} else {
this.jobRepository = createJobRepository();
JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
jobExplorerFactoryBean.setDataSource(this.dataSource);
jobExplorerFactoryBean.afterPropertiesSet();
this.jobExplorer = jobExplorerFactoryBean.getObject();
}
this.jobLauncher = createJobLauncher();
} catch (Exception e) {
throw new BatchConfigurationException(e);
}
}
public JobLauncher createJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(taskExecutor);
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
public JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager);
factory.afterPropertiesSet();
return factory.getObject();
}
// Batch related scripts
private DatabasePopulator dropDatabasePopulator() {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.setContinueOnError(true);
databasePopulator.addScript(new ClassPathResource("org/springframework/batch/core/schema-drop-mysql.sql"));
return databasePopulator;
}
private DatabasePopulator createDatabasePopulator() {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.setContinueOnError(true);
databasePopulator.addScript(new ClassPathResource("org/springframework/batch/core/schema-mysql.sql"));
return databasePopulator;
}
}

Resources