2

I have set up a batch configuration with the datasource and transaction manager. For that I had to override the default configurer. But while trying to run the job from the test then it fails to start due to jdbc exception. It seems it can not initialize the meta tables.

Here is the configuration for batch

@Autowired
private JobBuilderFactory jobBuilderFactory;

@Autowired
private StepBuilderFactory stepBuilderFactory;


@Bean
public BatchConfigurer batchConfigurer(DataSource dataSource,
                                       JpaTransactionManager jpaTransactionManager) {
    return new DefaultBatchConfigurer(dataSource) {
        @Override
        public PlatformTransactionManager getTransactionManager() {
            return jpaTransactionManager;
        }
    };
}

Here is the configuration for JPA

@Bean
public DataSource dataSource() {
    final DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(datasourceEnv.getProperty("jdbc.driverClassName"));
    dataSource.setUrl(datasourceEnv.getProperty("jdbc.url"));
    dataSource.setUsername(datasourceEnv.getProperty("jdbc.username"));
    dataSource.setPassword(datasourceEnv.getProperty("jdbc.password"));
    return dataSource;
}

public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(dataSource());
    em.setPackagesToScan("my.repository");
    em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    em.setJpaProperties(additionalProperties());
    return em;
}

@Bean
JpaTransactionManager transactionManager(final EntityManagerFactory entityManagerFactory) {
    final JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
}

private Properties additionalProperties() {
    final Properties hibernateProperties = new Properties();
    hibernateProperties.setProperty("hibernate.hbm2ddl.auto", datasourceEnv.getProperty("hibernate.hbm2ddl.auto"));
    hibernateProperties.setProperty("hibernate.dialect", datasourceEnv.getProperty("hibernate.dialect"));
    hibernateProperties.setProperty("hibernate.show_sql", datasourceEnv.getProperty("hibernate.show_sql"));
    return hibernateProperties;
}

This is the exception in the output

Caused by: org.h2.jdbc.JdbcSQLException: Table "BATCH_JOB_INSTANCE" 
not found; SQL statement:
SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where 
JOB_NAME = ? and JOB_KEY = ? [42102-197]
    at 
org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.Parser.readTableOrView(Parser.java:5920)
at org.h2.command.Parser.readTableFilter(Parser.java:1430)
at 
org.h2.command.Parser.parseSelectSimpleFromPart(Parser.java:2138)
at org.h2.command.Parser.parseSelectSimple(Parser.java:2287)
at org.h2.command.Parser.parseSelectSub(Parser.java:2133)
at org.h2.command.Parser.parseSelectUnion(Parser.java:1946)
at org.h2.command.Parser.parseSelect(Parser.java:1919)
at org.h2.command.Parser.parsePrepared(Parser.java:463)
at org.h2.command.Parser.parse(Parser.java:335)
at org.h2.command.Parser.parse(Parser.java:307)
at org.h2.command.Parser.prepareCommand(Parser.java:278)
at org.h2.engine.Session.prepareLocal(Session.java:611)
at org.h2.engine.Session.prepareCommand(Session.java:549)
at 
org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1247)
at org.h2.jdbc.JdbcPreparedStatement.<init>
(JdbcPreparedStatement.java:76)
at 
org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:304)
at 
... 68 more

I tried by adding runscript with the database url. But in that case the reverse error generates. Then it says table already exists.

Caused by: org.h2.jdbc.JdbcSQLException: Table "BATCH_JOB_INSTANCE" 
already exists; SQL statement:
-- Autogenerated: do not edit this file

CREATE TABLE BATCH_JOB_INSTANCE  (
JOB_INSTANCE_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
VERSION BIGINT ,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_KEY VARCHAR(32) NOT NULL,
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
)  [42101-197]
at 
org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.ddl.CreateTable.update(CreateTable.java:86)

Here is the datasource config

jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
jdbc.username=sa
jdbc.password=
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create-drop

Here is the application.properties

spring.batch.initialize-schema=always

And yes, the application.properties is under this directory

src/test/resources/application.properties

Here is the batch test

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {ArticleBatchConfiguration.class, 
JobLauncherTestUtils.class, JPAConfig.class})
public class BatchTest {


   @Autowired
   private JobLauncherTestUtils jobLauncherTestUtils;

   @Autowired
   private CustomerRepository customerRepository;

   @Test
   public void givenChunksJob_WhenJobEnds_ThenStatusCompleted() throws 
   Exception {
        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        Assert.assertEquals(ExitStatus.COMPLETED, 
           jobExecution.getExitStatus());
        List<Customer> customers = customerRepository.findAll();
        Assert.assertThat(customers.size(), Is.is(2));
   }
}
Sajol
  • 51
  • 4
  • Possible duplicate of https://stackoverflow.com/questions/51199254/create-tables-automatically-by-calling-sql-file-in-spring-batch – Mahmoud Ben Hassine Feb 13 '19 at 09:31
  • @MahmoudBenHassine Tried this `spring.batch.initialize-schema=always` still doesn't work. Same `Caused by: org.h2.jdbc.JdbcSQLException: Table "BATCH_JOB_INSTANCE" not found; SQL statement:` error is thrown. – Sajol Feb 13 '19 at 10:22
  • Are you sure this property is added to the application properties of your test (with maven it should go in `src/test/resources/application.properties`)? How do you run your test? Please share your test config to see what could go wrong – Mahmoud Ben Hassine Feb 13 '19 at 10:31
  • Updated the post with the datasource, application.properties and test case. – Sajol Feb 13 '19 at 10:40
  • @MahmoudBenHassine Strange part is if I run the job using endpoint then it seems to be working fine. `application.properties` needed these `spring.batch.initialize-schema=always` `spring.main.allow-bean-definition-overriding=true` and `spring.batch.job.enabled=false`. And this is how I am invoking from the controller `jobLauncher.run(job, jobParameters)`. Don't know why the test is not working with the same `application.properties`. – Sajol Feb 13 '19 at 13:00
  • I can't see neither. However, since you defined datasource properties in your `application.properties` file, you don't need to declare the datasource bean yourself, Spring Boot will do it for you. This is probably the cause of the issue. Spring Boot is initializing a datasource but Batch is using another one, hence it does not find meta-data tables. – Mahmoud Ben Hassine Feb 13 '19 at 16:17

0 Answers0