3

We use SpringBoot with Spring Rest and Jackson. We use Java 8 LocalDateTime.

RestController.

@RestController
@RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public class SimpleRestController {

    @Autowired
    private RestService restService;

    @RequestMapping("/api/{id}")
    public ResponseEntity<RestObject> getModel(@PathVariable Long id) {
        RestObject restObject = restService.getModel(id);
        HttpStatus httpStatus = HttpStatus.OK;

        if (restObject == null) {
            httpStatus = HttpStatus.NO_CONTENT;
        }

        return new ResponseEntity<>(restObject, httpStatus);
    }
}

RestObject to be returned by the controller.

import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.time.LocalDateTime;

@XmlRootElement
public class RestObject implements Serializable {

    private LocalDateTime timestamp;
    private String title;
    private String fullText;
    private Long id;
    private Double value;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public LocalDateTime getTimestamp() {
        return timestamp;
    }

    //Other getters and setters.
}

It works well when I send a GET request with Accept=application/json header. This is the response.

{
  "timestamp": "2017-06-09 15:58:32",
  "title": "Rest object",
  "fullText": "This is the full text. ID: 10",
  "id": 10,
  "value": 0.22816149915219197
}

However Accept=application/xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<restObject>
    <fullText>This is the full text. ID: 10</fullText>
    <id>10</id>
    <timestamp/>
    <title>Rest object</title>
    <value>0.15697306201038086</value>
</restObject>

Timestamp field is empty. How to make it work?

5
  • LocalDateTime is from Java 8 or jodatime? Commented Jun 9, 2017 at 14:09
  • Java 8 - java.time Commented Jun 9, 2017 at 14:10
  • Java 8 LocalDateTime is not supported. use Joda LocalDateTime or write a converter. This might help stackoverflow.com/questions/29424551/… Commented Jun 9, 2017 at 14:11
  • 1
    @Hugo Thanks for edit! Commented Jun 9, 2017 at 14:25
  • I know this is not helpful wrt the question, but as a caution to new developers: Never ever ever EVER use LocalDateTime. For anything. Daylight saving is still a thing, and in the fall transition the same hour number occurs twice. Without the offset they cannot be told apart, the sequence of timestamps within those two hours will be irreversibly mixed up. You don't want a timestamp that doesn't preserve sequence. If you think you do, you're wrong. The whole construct is inherently unsafe. If you can get away with LocalDate, congrats. If you need time, you need proper time. Commented Nov 19, 2024 at 11:13

1 Answer 1

4

Here comes the solution!

This is the response

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<restObject>
    <fullText>This is the full text. ID: 10</fullText>
    <id>10</id>
    <timestamp>2017-06-09 16:31:01</timestamp>
    <title>Rest object</title>
    <value>0.0021564103099468435</value>
</restObject>

1) Add class DateTimeAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.time.LocalDateTime;

public class DateTimeAdapter extends XmlAdapter<String, LocalDateTime> {

    public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT);

    public LocalDateTime unmarshal(String v) throws Exception {
        return LocalDateTime.parse(v, DATE_TIME_FORMATTER);
    }

    public String marshal(LocalDateTime v) throws Exception {
        return DATE_TIME_FORMATTER.format(v);
    }
}

2) Update RestObject class. Add @XmlJavaTypeAdapter(DateTimeAdapter.class) annotation on the LocalDateTime field.

import com.ca.training.rest.server.config.DateTimeAdapter;
import com.fasterxml.jackson.annotation.JsonFormat;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.Serializable;
import java.time.LocalDateTime;

import static com.ca.training.rest.server.config.DateTimeAdapter.DATE_FORMAT;

@XmlRootElement
public class RestObject implements Serializable {

    private LocalDateTime timestamp;
    private String title;
    private String fullText;
    private Long id;
    private Double value;

    @XmlJavaTypeAdapter(DateTimeAdapter.class)
    @JsonFormat(pattern = DATE_FORMAT)
    public LocalDateTime getTimestamp() {
        return timestamp;
    }

    //Other getters and setters.
}

I took the idea from here http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html and here JAXB: Isn't it possible to use an XmlAdapter without @XmlJavaTypeAdapter?

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.