2

I have the following simple test

import org.springframework.web.client.RestTemplate;
import pages.TimezonePage;

class GETSimple
{
    private RestTemplate restTemplate;
    private String URL = "http://worldtimeapi.org/api/timezone/America/Los_Angeles";

    @BeforeEach
    void setUp()
    {
        restTemplate = new RestTemplate();
    }

    @Test
    void GETasPOJO()
    {
        TimezonePage response = restTemplate.getForObject(URL, TimezonePage.class);
        assertEquals("PDT", response.getAbbreviation());
        assertTrue(response.getDst());
    }
}

which works fine with TimezonePage class that has getters and setters.
The relevant portion of the pom.xml is below

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.10.3</version>
</dependency>

I created a Java 14 record TimezoneRecord with the same variables as TimezonePage but without getters and setters. Then I replaced the get call with

TimezoneRecord response = restTemplate.getForObject(URL, TimezoneRecord.class);

There was no syntax error. When running the test, I received the following exception

org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class pages.TimezoneRecord]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `pages.TimezoneRecord` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

Is there any way to resolve it? Or I cannot use jackson with records as POJOs? Thanks, Vladimir

Vladimir
  • 630
  • 3
  • 12
  • 26

1 Answers1

-2

The source code for DateTimeDeserializer shows it uses the timezone from DeserializationContext which is provided by ObjectMapper during deserialization. If you look at ObjectMapper API, you will see there is a method for setting the TimezonePage:

public ObjectMapper setTimeZone(TimeZone tz)

Thus you can use this method to configure your ObjectMapper and set the timezone to the correct one.

For what concerns the default value, it seems the Javadoc says one thing, but the code shows another.

Javadoc for ObjectMapper.setTimeZone(TimeZone tz):

/** * Method for overriding default TimeZone to use for formatting. * Default value used is {@link TimeZone#getDefault()}. */ However, the code sets the timezone explicitly on:

protected final static BaseSettings DEFAULT_BASE = new BaseSettings(
    ...
    // TimeZone.getDefault()
    TimeZone.getTimeZone("GMT"),
    ...

So, apparently, it actually uses GMT, and not the default JVM default.

I would say that probably the best choice would be not relying on this and set it by yourself on ObjectMapper.setTimeZone(TimeZone tz).

Alireza Zabetan
  • 29
  • 1
  • 1
  • 5
  • 1
    Alireza Zabetan, My question was about using Java record instead of a POJO. Code for the timezones was just an example to illustrate the problem. Your answer does not address it. – Vladimir Apr 25 '20 at 03:46