2

I am executing some spring batch job and getting the following exception:

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDate` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (ByteArrayInputStream); line: 1, column: 447] (through reference chain: java.util.HashMap["TEST_FF_EXCEPTION"]-com.example.model.TestFFContext["cobDate"])

Assuming that it is some kind of date serialization issue, I have tried the following:

public class LocalDateDeserializer extends StdDeserializer<LocalDate> {

    public LocalDateDeserializer() {
        super(LocalDate.class);
    }

    @Override
    public LocalDate deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext)
            throws IOException {
        return LocalDate.parse(jsonParser.getText());
    }
}
    

public class LocalDateSerializer extends StdSerializer<LocalDate> {

    static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public LocalDateSerializer() {
        super(LocalDate.class);
    }

    @Override
    public void serialize(final LocalDate localDate, final JsonGenerator jsonGenerator,
                          final SerializerProvider serializerProvider) throws IOException {
        final String formattedDateTime = localDate.format(FORMATTER);
        jsonGenerator.writeString(formattedDateTime);
    }
}


public final class TestFFContext {

    private String name;

    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate cobDate;
    
    //no args constructor
    //all args constructor
    
}

But getting the following :

   Caused by: com.fasterxml.jackson.databind.JsonMappingException: Text '{' could not be parsed at index 0 (through reference chain: java.util.HashMap["TEST_FF_CONTEXT"]->com.example.model.TestFFContext["cobDate"])
        at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:394)
        at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:353)
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1711)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:371)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
        at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:116)
        at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:71)
        at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:712)
        at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:529)
        at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:364)
        at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:29)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3078)
        at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.deserialize(Jackson2ExecutionContextStringSerializer.java:71)
        at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.deserialize(Jackson2ExecutionContextStringSerializer.java:50)
        at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:325)
        at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:312)
        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:679)
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:712)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:768)
        at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.getExecutionContext(JdbcExecutionContextDao.java:114)
        at org.springframework.batch.core.repository.support.SimpleJobRepository.getLastJobExecution(SimpleJobRepository.java:278)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
        at com.sun.proxy.$Proxy155.getLastJobExecution(Unknown Source)
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:104)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
        at com.sun.proxy.$Proxy151.run(Unknown Source)

Anyone can give me any pointers what I am missing here?

it is tripping up in ExecutionContextRowMapper() when deserialising inputstream. This is only happening in the case of my bdd test. When running the spring boot app normally, I didnt need any custom serialization classes.

Sample json:

{
  "name": "TEST",
  "cobDate": "2020-07-28",
}

I create spring batch job parameter with cobDate from string and run job:

`execution = jobLauncher.run(job, parameters);`

After updating deserializer to use getValueAsString()

Caused by: com.fasterxml.jackson.databind.JsonMappingException: text (through reference chain: java.util.HashMap["TEST_FF_CONTEXT"]->com.example.model.TestFFContext["cobDate"])
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:394)
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:353)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1711)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:371)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:116)
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:71)
    at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:712)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:529)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:364)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:29)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3078)
    at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.deserialize(Jackson2ExecutionContextStringSerializer.java:71)
    at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.deserialize(Jackson2ExecutionContextStringSerializer.java:50)
    at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:325)
    at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:312)
    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:679)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:712)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:768)
    at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.getExecutionContext(JdbcExecutionContextDao.java:114)
    at org.springframework.batch.core.repository.support.SimpleJobRepository.getLastJobExecution(SimpleJobRepository.java:278)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy155.getLastJobExecution(Unknown Source)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy151.run(Unknown Source)
    at com.example.batch.MyJobRunner.runJob(MyJobRunner.java:61)
    at com.example.feed.AbstractProcessor.validateAndRun(AbstractProcessor.java:62)
    at com.example.feed.MySyncProcessor.execute(MySyncProcessor.java:25)
    at com.example.feed.AbstractProcessor.process(AbstractProcessor.java:44)
    at com.example.cukes.stepdefs.MyStepDef.theRequestIsProcessedSynchronously(MyStepDef.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at io.cucumber.java.Invoker.invoke(Invoker.java:27)
    at io.cucumber.java.JavaStepDefinition.execute(JavaStepDefinition.java:27)
    at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:63)
    at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:64)
    at io.cucumber.core.runner.TestStep.run(TestStep.java:49)
    at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:46)
    at io.cucumber.core.runner.TestCase.run(TestCase.java:51)
    at io.cucumber.core.runner.Runner.runPickle(Runner.java:67)
    at io.cucumber.junit.PickleRunners$NoStepDescriptions.run(PickleRunners.java:149)
    at io.cucumber.junit.FeatureRunner.runChild(FeatureRunner.java:83)
    at io.cucumber.junit.FeatureRunner.runChild(FeatureRunner.java:24)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at io.cucumber.junit.Cucumber.runChild(Cucumber.java:185)
    at io.cucumber.junit.Cucumber.runChild(Cucumber.java:83)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at io.cucumber.junit.Cucumber$RunCucumber.evaluate(Cucumber.java:219)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NullPointerException: text
    at java.util.Objects.requireNonNull(Objects.java:228)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1848)
    at java.time.LocalDate.parse(LocalDate.java:400)
    at com.example.util.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:28)
    at com.example.util.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:11)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369)
    ... 87 more
M06H
  • 1,675
  • 3
  • 36
  • 76
  • Can you show your deserializer for localdate and your json sample ? – Eklavya Aug 02 '20 at 10:28
  • added to question – M06H Aug 02 '20 at 10:31
  • 1
    Add [jackson-modules-java8](https://github.com/FasterXML/jackson-modules-java8) for `Java 8` support. See also: [Problem with deserialization of LocalDateTime in Junit test](https://stackoverflow.com/a/55108967/51591), [Force Jackson serialize LocalDate to Array](https://stackoverflow.com/a/62426300/51591) – Michał Ziober Aug 02 '20 at 22:24

2 Answers2

0

Use parser.getValueAsString() to get the json value for date and use formatter when parse the date string. And make sure you are importing right Deserializer on the field. I added a sample, you can use it

public class LocalDateDeserializer extends StdDeserializer<LocalDate> {

    private static final long serialVersionUID = 1608358311371702012L;

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public LocalDateDeserializer() {
        this(null);
    }

    protected LocalDateDeserializer(Class<LocalDate> type) {
        super(type);
    }

    @Override
    public LocalDate deserialize(JsonParser parser, DeserializationContext context)
            throws IOException, JsonProcessingException {
        return LocalDate.parse(parser.getValueAsString(), formatter);
    }

}
Eklavya
  • 17,618
  • 4
  • 28
  • 57
  • hmm getting `Caused by: com.fasterxml.jackson.databind.JsonMappingException: text (through reference chain: java.util.HashMap["TEST_FF_CONTEXT"]->com.example.model.TestFFContext["cobDate"])` – M06H Aug 02 '20 at 19:19
  • @M06H Are you using given deserializer ? – Eklavya Aug 02 '20 at 19:20
  • Can you give me full stacktrace of error in pastebin like https://paste.ubuntu.com/ – Eklavya Aug 02 '20 at 19:23
  • cannot access site from here, added to question – M06H Aug 02 '20 at 19:36
  • @M06H You are getting null pointer execption means data came in serializer is null, you are sending proper data right ? Means don't try to test for null ? – Eklavya Aug 02 '20 at 19:41
0

I solved this problem by configuring a custom JobRepository that could handle JSR-310: First add com.fasterxml.jackson.datatype:jackson-datatype-jsr310 in your classpath if you don't have it already Then, my main config class for Spring batch extends DefaultBatchConfigurer from which I can override createJobRepository. I pass it an ObjectMapper configured to handle JSR-310:

@Override
protected JobRepository createJobRepository() throws Exception {
    JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
    factory.setDataSource(dataSource);
    factory.setTransactionManager(getTransactionManager());
    Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();
    serializer.setObjectMapper(objectMapper());
    factory.setSerializer(serializer);
    factory.afterPropertiesSet();
    return factory.getObject();
}

@Bean
public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());
    return objectMapper;
}
Fenhryl
  • 1
  • 1