1

I'm using spring batch for everyday jobs. It reads csv files then filling DB. I need to fill another DB with information about scv file in afterJob method.

This is configuration class.

@EnableBatchProcessing
@Configuration
public class BatchConfiguration {

@Autowired
public JobBuilderFactory jobs;

@Autowired
public StepBuilderFactory steps;

@Value("file://VMCOLLECTOR2/DataIn/mmvb_bonds_201803*.csv")
private Resource[] bondResources;

@Autowired
@Qualifier("hikariDataSource")
private DataSource dataSource;


@Bean
public Step bondEndOfDateStep() {
    return steps.get("bondEndOfDateStep")
            .<BondEndOfDateModel, BondEndOfDateModel> chunk(1000)
            .reader(multiResourceItemReader())
            .listener(new BondEndOfDateItemWriteListener())
            .writer(writer(dataSource))
            .build();
}
...

Once my application starts it works pretty. Every data is being written in BD and dataSource is autowired well. Then invokes afterJob method:

public class BondEndOfDateAfterJob extends JobExecutionListenerSupport {

@Autowired
@Qualifier("hikariDataSource")
private DataSource dataSource;

@Override
public void afterJob(JobExecution jobExecution) {
    try (Connection connection = dataSource.getConnection()) {

    } catch (SQLException e) {
        e.printStackTrace();
    }
}
}

In debug I can see that dataSource is null. It's not autowired. But in first case it was autowired. Here is log:

java.lang.NullPointerException: null
at SCV_Workflow.BondEndOfDateAfterJob.afterJob(BondEndOfDateAfterJob.java:20) ~[classes/:na]
at org.springframework.batch.core.listener.CompositeJobExecutionListener.afterJob(CompositeJobExecutionListener.java:60) ~[spring-batch-core-4.0.0.M1.jar:4.0.0.M1]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:352) ~[spring-batch-core-4.0.0.M1.jar:4.0.0.M1]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:141) [spring-batch-core-4.0.0.M1.jar:4.0.0.M1]
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:134) [spring-batch-core-4.0.0.M1.jar:4.0.0.M1]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) [spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) [spring-batch-core-4.0.0.M1.jar:4.0.0.M1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) [spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at com.sun.proxy.$Proxy44.run(Unknown Source) [na:na]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:214) [spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:231) [spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:123) [spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:117) [spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at SCV_Workflow.ParserApplication.main(ParserApplication.java:10) [classes/:na]

Here is dataSource Config Class:

@Configuration
public class HikariDS {

@Bean
@Primary
@ConfigurationProperties(prefix = "datasource.infoserver")
public DataSourceProperties dataSourceProperties(){
    return new DataSourceProperties();
}

@Bean(name = "hikariDataSource")
@Primary
public DataSource hikariDataSource() {
    DataSourceProperties dataSourceProperties = dataSourceProperties();
    HikariDataSource dataSource = new HikariDataSource();
    dataSource.setMaximumPoolSize(20);
    dataSource.setDataSourceClassName(dataSourceProperties.getDriverClassName());
    dataSource.addDataSourceProperty("url", dataSourceProperties.getUrl());
    dataSource.addDataSourceProperty("user", dataSourceProperties.getUsername());
    dataSource.addDataSourceProperty("password", dataSourceProperties.getPassword());
    dataSource.setInitializationFailFast(true);
    dataSource.setPoolName("springHikariPool");
    return dataSource;
}
}

Application works pretty except this detail that I very need.

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • @M.Deinum This doesn't look to be duplicate. Romanoc is not using new for creating object. It seems he is not importing HikariDS Configuration in BatchConfiguration – Niraj Sonawane Mar 14 '18 at 08:49
  • Yes he is. Line 4 in the `bondEndOfDateStep` that is `.listener(new BondEndOfDateItemWriteListener())`. Hence creating a new instance, unmanaged by spring, and thus making this a clear duplicate of the other question (explaining just that you shouldn't be doing that). – M. Deinum Mar 14 '18 at 08:55
  • @M.Deinum Thank you so much you didnt give answer so I had to work with my brain and found mistake. It was so easy and obvious but solution I didnt see. – Romanov Alexey Mar 15 '18 at 13:55

0 Answers0