0

Gettings.

i'm trying to write my first spring boot test. testing the controller which is returning the model containing java.sql.Timestamp

related pom:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

the test is executed, but jackson2, which is used by org.junit.Assert i guess(?). can't deserialize the sql timestamp.

test:

@RunWith(SpringRunner.class)

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

public class CondoControllerTest {

    @Autowired

    private TestRestTemplate restTemplate;

    @Test
    public void condoItemsListTest() {

        ResponseEntity<Item[]> responseEntity = restTemplate.getForEntity("/condo/19/items/", Item[].class);

        Item[] itemsList = responseEntity.getBody();

        assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
        assertTrue(itemsList[0].getItemTitle() != null);
    }
}

error:

2016-10-20 13:25:52.728 DEBUG 10996 --- [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet        : Successfully completed request
2016-10-20 13:25:52.743 DEBUG 10996 --- [           main] o.s.web.client.RestTemplate              : GET request for "http://localhost:12763/api/condo/19/items/" resulted in 200 ()
2016-10-20 13:25:52.745 DEBUG 10996 --- [           main] o.s.web.client.RestTemplate              : Reading [class [Lcom.springapp.models.common.Item;] as "application/json;charset=ISO-8859-1" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@7f4701b1]

org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize value of type java.sql.Timestamp from String "Jul 10, 2016 12:37:10 PM": not a valid representation (error: Failed to parse Date value 'Jul 10, 2016 12:37:10 PM': Can not parse date "Jul 10, 2016 12:37:10 PM": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
 at [Source: java.io.PushbackInputStream@4aa22cc2; line: 1, column: 207] (through reference chain: Object[][0]->com.springapp.models.common.Item["timestamp"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.sql.Timestamp from String "Jul 10, 2016 12:37:10 PM": not a valid representation (error: Failed to parse Date value 'Jul 10, 2016 12:37:10 PM': Can not parse date "Jul 10, 2016 12:37:10 PM": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
 at [Source: java.io.PushbackInputStream@4aa22cc2; line: 1, column: 207] (through reference chain: Object[][0]->com.springapp.models.common.Item["timestamp"])

    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:228)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:213)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:95)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:884)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:868)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:622)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580)
    at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:312)
    at org.springframework.boot.test.web.client.TestRestTemplate.getForEntity(TestRestTemplate.java:231)
    at com.springapp.controllers.main.CondoControllerTest.condoItemsListTest(CondoControllerTest.java:34)
    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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    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.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    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 org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.sql.Timestamp from String "Jul 10, 2016 12:37:10 PM": not a valid representation (error: Failed to parse Date value 'Jul 10, 2016 12:37:10 PM': Can not parse date "Jul 10, 2016 12:37:10 PM": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
 at [Source: java.io.PushbackInputStream@4aa22cc2; line: 1, column: 207] (through reference chain: Object[][0]->com.springapp.models.common.Item["timestamp"])
    at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:74)
    at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1410)
    at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:926)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseDate(StdDeserializer.java:822)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseDate(StdDeserializer.java:791)
    at com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateBasedDeserializer._parseDate(DateDeserializers.java:172)
    at com.fasterxml.jackson.databind.deser.std.DateDeserializers$TimestampDeserializer.deserialize(DateDeserializers.java:309)
    at com.fasterxml.jackson.databind.deser.std.DateDeserializers$TimestampDeserializer.deserialize(DateDeserializers.java:294)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:101)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:357)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:196)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:20)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2913)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:225)
    ... 50 more

i guess the timestamp format is very typical. any workaround?

user1935987
  • 3,136
  • 9
  • 56
  • 108
  • 3
    IMHO you shouldn't be using `javax.sql` classes in your model.. You are now tying your model to sql... Just use a plain `java.util.Date` or joda-time. – M. Deinum Oct 20 '16 at 06:43
  • why? then i have to convert the format each after/before each sql request, isn't it? – user1935987 Oct 20 '16 at 06:45
  • 1
    No you don't... Are you using plain sql or are you using JPA? If the latter then you need to add `@Temporal(TemporalType.TIMESTAMP)`. And still you don't want your model tied to sql, just as you don't want your model tied to the web... – M. Deinum Oct 20 '16 at 06:46
  • 1
    Error message is rather obvious about reason of error - string representation of date has no matching format to parse. Try to register new format, e.g. http://stackoverflow.com/questions/12463049/date-format-mapping-to-json-jackson – Mikhail Kuchma Oct 20 '16 at 06:47
  • I'm using plain sql. – user1935987 Oct 20 '16 at 07:01
  • Right the error message is clear. It is more that the problem must be very common and have a solution. But I actually didn't knew that its not recommended to use javax.sql for POJO models. – user1935987 Oct 20 '16 at 07:03
  • So i shoul convert java,util.date to sql each DB request then? – user1935987 Oct 20 '16 at 07:18
  • Changing `javax.sql` to `java.util.Date` will not help. What you need to do is, configuring Jackson to understand/parse your format, or change your date format to a more common format that is supported by Jackson out of the box. – Ralph Oct 20 '16 at 07:44
  • this answer should help you http://stackoverflow.com/a/39743875/6503002 – amicoderozer Oct 20 '16 at 08:53

1 Answers1

0

Try using some @JsonXYZ method @JsonSerialize @JsonDeserialize or @JsonCreator

I used once @JsonCreator to solve a problem similar to this. Take a look :

https://github.com/timols/java-gitlab-api/issues/45