Spring Batch - Problemas de conexão com o banco de dados Postgres

Aug 25 2020

Até agora, eu estava usando o banco de dados H2 na memória com o Spring Batch. No entanto, agora mudei para conectar-me ao banco de dados postgres externo. Aqui estava meu objeto de conexão (com alguma ofuscação):

@Bean
public DataSource postgresDatasource() {
    DriverManagerDataSource datasource = new DriverManagerDataSource();
    datasource.setDriverClassName("org.postgresql.Driver");
    datasource.setUrl("jdbc:postgresql://x.x.x.x:xxxx/blah");
    datasource.setUsername("Joe");
    datasource.setPassword("password");
    return datasource;
}

Quando inicio meu aplicativo, recebo:

Causado por: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; gramática SQL incorreta [SELECT JOB_INSTANCE_ID, JOB_NAME de BATCH_JOB_INSTANCE onde JOB_NAME = ? e JOB_KEY = ?]; exceção aninhada é org.postgresql.util.PSQLException: ERRO: a relação "batch_job_instance" não existe

Em seguida, li que o Spring Batch usa o banco de dados para salvar metadados para sua funcionalidade de recuperação/repetição e, com bancos de dados incorporados, essas são tabelas que o Spring Batch configura por padrão. Ok, isso explicaria porque eu nunca tinha visto esse erro antes.

No entanto, ele disse que eu poderia definir esta propriedade:

spring.batch.initialize-schema=never

Então eu coloquei isso no meu arquivo application.properties. No entanto, ainda estou recebendo o erro. Eu ficaria grato por todas as idéias.

Respostas

TimothyClotworthy Aug 25 2020 at 19:24

Eu fui capaz de resolver isso sozinho. Por fim, eu precisava do repositório Spring Batch independente do meu banco de dados relacional de destino real. Então encontrei esta referência:

https://github.com/spring-projects/spring-batch/blob/342d27bc1ed83312bdcd9c0cb30510f4c469e47d/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java#L84

Consegui pegar a classe DefaultBatchConfigurer desse exemplo e fazer uma pequena alteração na fonte de dados adicionando o @Qualifier para fonte de dados incorporada/local:

@Autowired(required = false)
public void setDataSource(@Qualifier("dataSource") DataSource dataSource) {
    this.dataSource = dataSource;
    this.transactionManager = new DataSourceTransactionManager(dataSource);
}

Em seguida, no meu leitor Spring Batch (em minha outra classe de configuração em lote), fiz uma pequena alteração na fonte de dados adicionando o @Qualifier para fonte de dados postgres:

@Bean
public ItemReader<StuffDto> itemReader(@Qualifier("postgresDataSource")DataSource dataSource) {
return new JdbcCursorItemReaderBuilder<StuffDto>()
    .name("cursorItemReader")
    .dataSource(dataSource)
    .sql(GET_DATA)
    .rowMapper(new BeanPropertyRowMapper<>(StuffDto.class))
    .build();
}

Então, por último (ou primeiro, como fiz primeiro), nomeei explicitamente meus beans de fonte de dados para que o java pudesse diferenciá-los para usar como acima:

@Configuration
public class PersistenceContext {


    @Bean(name = "dataSource")
    public DataSource dataSource() {
        DriverManagerDataSource datasource = new DriverManagerDataSource();
        datasource.setDriverClassName("org.h2.Driver");
        datasource.setUrl("jdbc:h2:file:/tmp/test");
        datasource.setUsername("sa");
        datasource.setPassword("");
        return datasource;
    }

    @Bean(name = "postgresDataSource")
    public DataSource postgresDatasource() {
        DriverManagerDataSource datasource = new DriverManagerDataSource();
        datasource.setDriverClassName("org.postgresql.Driver");
        datasource.setUrl("jdbc:postgresql://x.x.x.x:xxxx/blah");
        datasource.setUsername("joe");
        datasource.setPassword("password");
        return datasource;    }
}

Depois de fazer tudo o que foi dito acima, o erro desapareceu e tudo funcionou.