I have a spring batch project and i need to integrate a jdbcTemplate in the JobExecutionListener. So i configured my datasource and jdbcTemplate as shown bellow:
import java.util.Objects;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
public class JdbcTemplateConfig {
@Bean("JdbcBI")
@Qualifier("JdbcBI")
public JdbcTemplate jdbcTemplate() {
final JdbcTemplate template = new JdbcTemplate();
template.setDataSource(dataSource());
return template;
}
@Bean
@ConfigurationProperties("spring.datasource.bi")
public DataSourceProperties biDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@Qualifier("bi")
@Primary
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(Objects.requireNonNull(biDataSourceProperties().getUrl()));
ds.setUsername(Objects.requireNonNull(biDataSourceProperties().getUsername()));
ds.setPassword(Objects.requireNonNull(biDataSourceProperties().getPassword()));
ds.setDriverClassName(Objects.requireNonNull(biDataSourceProperties().getDriverClassName()));
ds.setAutoCommit(true);
ds.setMaximumPoolSize(20);
return ds;
}
}
knowing that i declared my dataSource properties in the application.properties file:
spring.datasource.bi.url=jdbc:sqlserver://localhost;databaseName=SQLBI;useBulkCopyForBatchInsert=true;integratedSecurity=false;encrypt=false;trustServerCertificate=false
spring.datasource.bi.username=mongo_user
spring.datasource.bi.password=Azerty
spring.datasource.bi.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.hikari.data-source-properties.encrypt=false
and I'm using Spring boot version 3.2.2:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Yet, when i use the jdbcTemplate in the JobListener, it throws this error:
java.lang.NullPointerException: Cannot invoke "org.springframework.jdbc.core.JdbcTemplate.update(String, Object[])" because "this.jdbcTemplate" is null
and here is my JobExecutionListener class:
import org.apache.commons.lang3.StringUtils;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class CustomJobExecutionListener implements JobExecutionListener {
@Autowired
JdbcTemplate jdbcTemplate;
@Override
public void afterJob(JobExecution jobExecution) {
String query = "INSERT INTO tabler (Val, Vab, Vai) VALUES ('1', '2', '3')";
jdbcTemplate.update(query);
}
}
You have declared:
@Bean("JdbcBI")
@Qualifier("JdbcBI")
public JdbcTemplate jdbcTemplate() {
final JdbcTemplate template = new JdbcTemplate();
template.setDataSource(dataSource());
return template;
}
And when you are injecting the bean to another service you have to do it with @Qualifier
:
@Autowired
@Qualifier("JdbcBI")
private JdbcTemplate jdbcTemplate;