Repository: spring-projects/spring-batch

Issue #3732: Jackson configuration in 4.2.4 broke deserialization
Created: 2020-06-22T18:42:55Z
Bug description
#3729 ported to 4.2.4 and pulled in springboot 2.3.1 broke old jobs context.
Environment
Spring Batch 2.3.1, jdk 11, PostgreSQL
Steps to reproduce

Configure and run a job with springboot 2.3.0.
call jobExplorer.getJobExecution(executionId) using execution id of a job ran in a previous step
Bump springboot to 2.3.1
call jobExplorer.getJobExecution(executionId) using execution id of a job ran in a previous step
Expect a stacktrace

java.lang.IllegalArgumentException: Unable to deserialize the execution context
  at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:328) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:312) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:679) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:712) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:768) ~[spring-jdbc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.getExecutionContext(JdbcExecutionContextDao.java:114) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  at org.springframework.batch.core.explore.support.SimpleJobExplorer.getJobExecutionDependencies(SimpleJobExplorer.java:232) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  at org.springframework.batch.core.explore.support.SimpleJobExplorer.getJobExecution(SimpleJobExplorer.java:141) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
  at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
  at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
  at com.sun.proxy.$Proxy123.getJobExecution(Unknown Source) ~[na:na]

SKIPPED trace
Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [map type; class java.util.HashMap, [simple type, class java.lang.String] -> [simple type, class java.lang.Object]]: missing type id property '@class'
 at [Source: (ByteArrayInputStream); line: 1, column: 2]
  at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.DeserializationContext.missingTypeIdException(DeserializationContext.java:1790) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.DeserializationContext.handleMissingTypeId(DeserializationContext.java:1319) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleMissingTypeId(TypeDeserializerBase.java:303) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:107) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserializeWithType(MapDeserializer.java:400) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482) ~[jackson-databind-2.11.0.jar:2.11.0]
  at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3479) ~[jackson-databind-2.11.0.jar:2.11.0]
  at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.deserialize(Jackson2ExecutionContextStringSerializer.java:123) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.deserialize(Jackson2ExecutionContextStringSerializer.java:102) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:325) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
  ... 128 common frames omitted

batch_job_execution_context table values change. All job executions before 886 blow up with above.

Expected behavior
No exception occurs in deserialization

Duplicate issue #3826: Jackson2ExecutionContextStringSerializer breaks backward compatibility
Created: 2021-01-05T04:26:41Z
Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [map type; class java.util.HashMap, [simple type, class java.lang.String] -> [simple type, class java.lang.Object]]: missing type id property '@class'
 at [Source: (ByteArrayInputStream); line: 1, column: 2]

data is generated by spring-batch 4.2.x
mysql> select * from BATCH_JOB_EXECUTION_CONTEXT;
+------------------+---------------+--------------------+
| JOB_EXECUTION_ID | SHORT_CONTEXT | SERIALIZED_CONTEXT |
+------------------+---------------+--------------------+
|                1 | {}            | NULL               |
|                2 | {}            | NULL               |
|                3 | {}            | NULL               |


Caused by DefaultTyping is introduced by 9a79b45, since the json is generated by spring-batch itself, attacker cannot tamper it, I think it's important to keep compatibility over security.

Closing comment (2021-01-05T12:45:27Z): Closing this as duplicate of #3732

I think it's important to keep compatibility over security.

Please check Michael's comment here.