package de.huepattl.playground.rest;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.Random;
import javax.ejb.Stateless;
import javax.json.Json;
import javax.json.JsonObject;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
* This resource is to demonstrate REST with more complex data such as XML and
* JSON. In many cases, JSON and XML server-side code is identical but because
* we demonstrate some differences here, I decided to have it in different
* resource classes and unit tests.<p>
* Basically, we show the three different ways of using JSON as an exchange
* format with JAX-RS here (client and/or server):
* <p>
* <ol>
* <li>Use plain JSON string.</li>
* <li>Use JAXB-annotated POJOs.</li>
* <li>Use more generic {@link JsonObject}.</li>
* </ol>
*
* @author blazko
* @since 2014-07-15
*/
@Path("employee")
@Stateless
@Produces(MediaType.APPLICATION_JSON)
public class JsonExamplesResource {
/**
* HTTP POST request to create a new {@link EmployeeEntity} instance. In
* real live, such service method would delegate to an internal (technically
* agnostic) business service that would then return the (probably)
* persisted employee object.<p>
* In most cases, we would directly use that POJO (annotated with JAXB
* annotations - used here for JSON as well) and marshall it to JSON for
* passing the result to the calling client.<p>
* Only in cases where the public bean would have a quite different
* projection/scope I would recommend to use a mapping to an external
* representation (data transfer object/DTO).
*
* @param name Employee name.
* @param isoDateOfBirth Date of birth as ISO string (see
* {@link BasicExamplesResource} on reasons why).
*
* @return New employee instance including ID.
* @throws DateTimeParseException Well, no ISO date was passed.
*/
@POST
@Path("create")
public EmployeeEntity create(@FormParam("name") final String name,
@FormParam("date-of-birth") final String isoDateOfBirth) throws DateTimeParseException {
/*
* We need to convert to legacy Date using instant until JAX-RS can
* handle Java 8 types...
*/
LocalDate ldBirth = LocalDate.parse(isoDateOfBirth, DateTimeFormatter.ISO_LOCAL_DATE);
Instant iBirth = ldBirth.atStartOfDay(ZoneId.systemDefault()).toInstant();
Random r = new Random(123);
EmployeeEntity newEmployee = new EmployeeEntity(r.nextLong(), name, Date.from(iBirth));
return newEmployee;
}
/**
* This HTTP GET method returns an employee as JSON object - but not by
* letting JAXB marshal it or not by even using a string but with help of
* {@link JsonObject}. {@link JsonObject} allows to create custom
* representations of JSON ojects by providing a solid builder mechanism.
*
* @param id Employee ID to retrieve instance for.
*
* @return Employee using custom JSON representation via {@link JsonObject}.
*/
@GET
@Path("get")
public JsonObject get(@QueryParam("id") long id) {
// Dummy... imagine we loaded this one from the database...
EmployeeEntity employee = new EmployeeEntity(id, "Spot", new Date());
JsonObject jsonObject = Json.createObjectBuilder()
.add("id", employee.getId())
.add("name", employee.getName())
.add("date-of-birth", LocalDateTime.ofInstant(
Instant.ofEpochMilli(employee.getDateOfBirth().getTime()),
ZoneId.systemDefault()).toLocalDate().toString()).build();
return jsonObject;
}
}