javaspringspring-batchdatabase-migration

Migrating batch parameter data from Spring Batch 4.3 to Spring Batch 5.0


I am migrating a Spring application to Spring batch 4.3 to 5.0, following this guide.

While the guide is clear on how to migrate the database schema, I also have to migrate data from the old tables to the new ones and have failed to find instructions on how to do so on the internet.

In particular, Spring seems to fail based on how I migrated data to the BATCH_JOB_EXECUTION_PARAMS table.

The rows that I am migrating from the same-name table in 4.3 all contain either STRING or LONG as their parameter type (in the old TYPE_CD column, which I mapped to the new PARAMETER_TYPE column).

I am running the application as a "Java Application" run configuration in Eclipse. This is the error I get:

15:46:45.139 [main] DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [SELECT JOB_EXECUTION_ID, PARAMETER_NAME, PARAMETER_TYPE, PARAMETER_VALUE, IDENTIFYING
FROM BATCH_JOB_EXECUTION_PARAMS
WHERE JOB_EXECUTION_ID = ?
]
15:46:45.225 [main] DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Should roll back transaction but cannot - no transaction available
15:46:45.225 [main] ERROR o.s.batch.core.launch.support.CommandLineJobRunner - Job Terminated in error: java.lang.ClassNotFoundException: LONG
java.lang.RuntimeException: java.lang.ClassNotFoundException: LONG
    at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao.lambda$getJobParameters$2(JdbcJobExecutionDao.java:472)
    at org.springframework.jdbc.core.JdbcTemplate$RowCallbackHandlerResultSetExtractor.extractData(JdbcTemplate.java:1762)
    at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:733)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:658)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:723)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:754)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:783)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:799)
    at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao.getJobParameters(JdbcJobExecutionDao.java:484)
    at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao$JobExecutionRowMapper.mapRow(JdbcJobExecutionDao.java:510)
    at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao$JobExecutionRowMapper.mapRow(JdbcJobExecutionDao.java:495)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61)
    at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:733)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:658)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:723)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:754)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:767)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:825)
    at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao.getLastJobExecution(JdbcJobExecutionDao.java:342)
    at org.springframework.batch.core.explore.support.SimpleJobExplorer.getLastJobExecution(SimpleJobExplorer.java:109)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
    at jdk.proxy2/jdk.proxy2.$Proxy48.getLastJobExecution(Unknown Source)
    at org.springframework.batch.core.JobParametersBuilder.getNextJobParameters(JobParametersBuilder.java:362)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:362)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:558)

Spring seems unable to map the parameter type to a Java class. I have tried changing the values to String and long to reflect how the types are called in the java language, but this resulted in the same error.

This makes me wonder in what format parameters types are now supposed to be stored in the table. I know you have to implement specific mappers for custom types, but from my understanding, spring should be automatically able to map the old String, Date, Long and Double batch parameter types to java classes.

The guide mentions that the new parameter format is parameterName=parameterValue,parameterType,identificationFlag, but since the table has separate colums for parameter name, type and value, I don't think this format reflects what the parameter type is supposed to look like in the database.

Can anyone who had to do a similar migration in the past provide any information on how they mapped their old data into the BATCH_JOB_EXECUTION_PARAMS table, or other pieces of advice I should be aware of regarding the migration of data from this or any of the other Spring Batch tables?


Solution

  • In Spring Batch 5.0, the PARAMETER_TYPE column in the BATCH_JOB_EXECUTION_PARAMS table is expected to be a Java class name.

    You need to update the BATCH_JOB_EXECUTION_PARAMS table to use the fully-qualified class names for the PARAMETER_TYPE column

    example:

    UPDATE BATCH_JOB_EXECUTION_PARAMS
    SET PARAMETER_TYPE = CASE
        WHEN TYPE_CD = 'LONG' THEN 'java.lang.Long'