Java Date ISO8601 - iso8601

I have the the following class used with JPA and JAX-RS:
import java.util.Date;
public class UserModel implements Serializable{
private Date created;
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
When I access this class via Response resource I get the "created" in ISO8601 format:
2013-08-21T22:06:36+02:00
However when I access it in Java code (System.out.println) I get it in the following format:
Wed Aug 21 22:06:36 CEST 2013
Is there any way to get it always in ISO8601 format?
Apparently for java automatically transforms Date format to the latter one.

Here is how I solved it:
I have changed the following:
public Date getCreated() {
return created;
}
to
public String getCreated() {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
return df.format(created);
}

Related

FeignClient is changing the format of LocalDate passed to it

I'm have a #FeignClient in my app:
#FeignClient(name="${mongo.service.id}", url="${mongo.service.url}")
public interface MongoCustomerClaimInterface {
#GetMapping(path = "/api/customerClaim/countClaims/{businessDate}")
List<TransactionClaimStatusData> countClaimsByStatusToBusinessDate(
#PathVariable #DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
LocalDate businessDate);
}
I call the feign method and passing it a formatted LocalDate variable, and printing it to the log:
LocalDate businessDate = getBusinessDate();
LocalDate formattedDate = LocalDate.parse(businessDate.toString(),
DateTimeFormatter.ISO_DATE);
log.info("formattedDate: " + formattedDate);
claimStatusDataList = mongoCustomerClaimInterface.countClaims(formattedDate);
The call generates 404 error and log:
2020-24-02 18:10:25.433 INFO DashboardServiceImpl - formattedDate: 2020-02-23
2020-24-02 18:10:25.440 DEBUG
RequestMappingHandlerMapping:
Looking up handler method for path /api/customerClaim/countClaims/2/23/20
RequestMappingHandlerMapping:
Did not find handler method for [/api/customerClaim/countClaims/2/23/20]
Although I pass a date in the format yyyy-mm-dd so it will match:
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
Feign somehow changes the date and then no matching url is found
How can I prevent Feign from doing this and configure a uniform formatter?
So apparently Feign isn't working with all of SpringMvc annotations. #DateTimeFormat, as great as it is, is a SpringMvc annotation and NOT a FeignClient annotation.
I solved this by doing several things:
Created a MessageConvertersConfiguration class in my MvcConfig class.
In it, I created a LocalDate & LocalDateTime converter bean and added it to the converters list that this configurer uses when an http message arrives:
#Configuration
public class MvcConfig {
#Configuration
#EnableWebMvc
public class MessageConvertersConfiguration implements WebMvcConfigurer {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter(localDateTimeConverter()));
}
#Bean
public ObjectMapper localDateTimeConverter() {
ObjectMapper mapper = new ObjectMapper();
SimpleModule localDateTimeModule = new SimpleModule();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy'T'HH:mm:ss");
localDateTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
localDateTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
localDateTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));
localDateTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
mapper.registerModules(localDateTimeModule);
return mapper;
}
}
}
Created a configuration class for my feign client. In it, I instantiated a SpringMvcContract. Because Feign is created before SpringMvc, the converters we just defined won't affect feign without this contract:
#Configuration
public class FeignConfig {
#Bean
public Contract feignContract() {
return new SpringMvcContract();
}
}
Eventually, I added to configuration attribute to my FeignClient:
#FeignClient(name="${mongo.service.id}", url="${mongo.service.url}", configuration = FeignConfig.class)
public interface MongoCustomerClaimInterface {
#GetMapping(path = "/api/customerClaim/countClaimsByStatusToBusinessDate/{businessDate}")
List<TransactionClaimStatusData> countClaimsByStatusToBusinessDate(#PathVariable #DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate businessDate);
}

How to supply LocalDateTime to a jpa/hibernate query?

I'm building a query in my #RepositoryRestResource
where the query looks like this:
#Query("Select DISTINCT comp from InsuranceCompany comp " +
"LEFT JOIN comp.orders ord " +
"wHERE ord.invoiced = false " +
"and (:date is null or :date >= ord.completionTime)"
)
public Page<InsuranceCompany> method(LocalDateTime date, Pageable pageable);
But it throws the following excpetion
Failed to convert from type [java.lang.String] to type [java.time.LocalDateTime] for value '2020-02-14T15:50:24'
when I call the end point with:
GET /method?date=2020-02-14T15:50:24
Mark it with #DateTimeFormat to have Spring converted it correctly:
public Page<InsuranceCompany> method(#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime date,
Pageable pageable);
Spring by default cannot convert REST parameters to LocalDateTime. You need to provide information on the format of the date, at a parameter level with the #DateTimeFormat annotation, or globally using the DateTimeFormatterRegistrar.
This article explains the two alternatives: https://www.baeldung.com/spring-date-parameters
Option 1: Setting the date/time format globally for all Spring Boot App REST Endpoints
You can configure spring globally to use a certain date / date-time format for your REST endpoints. Suggesting that you use the default Jackson for handling JSON mapping, you can create a configuration class as follows where you set the formats:
#Configuration
public class DateTimeSerializationConfiguration implements Jackson2ObjectMapperBuilderCustomizer {
private static final DateTimeFormatter DATE_FORMATTER = ISO_LOCAL_DATE;
private static final DateTimeFormatter DATE_TIME_FORMATTER = ISO_DATE_TIME;
private static final DateTimeFormatter TIME_FORMATTER = ofPattern("HH:mm");
#Bean
public Formatter<LocalDate> localDateFormatter() {
return new Formatter<LocalDate>() {
#Override
public LocalDate parse(String text, Locale locale) {
return LocalDate.parse(text, DATE_FORMATTER);
}
#Override
public String print(LocalDate object, Locale locale) {
return DATE_FORMATTER.format(object);
}
};
}
#Bean
public Formatter<LocalDateTime> localDateTimeFormatter() {
return new Formatter<LocalDateTime>() {
#Override
public LocalDateTime parse(String text, Locale locale) {
return LocalDateTime.parse(text, DATE_TIME_FORMATTER);
}
#Override
public String print(LocalDateTime object, Locale locale) {
return DATE_TIME_FORMATTER.format(object);
}
};
}
#Bean
public Formatter<LocalTime> localTimeFormatter() {
return new Formatter<LocalTime>() {
#Override
public LocalTime parse(String text, Locale locale) {
return LocalTime.parse(text, TIME_FORMATTER);
}
#Override
public String print(LocalTime object, Locale locale) {
return TIME_FORMATTER.format(object);
}
};
}
#Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.serializers(
new LocalDateSerializer(DATE_FORMATTER),
new LocalDateTimeSerializer(DATE_TIME_FORMATTER),
new LocalTimeSerializer(TIME_FORMATTER));
jacksonObjectMapperBuilder.deserializers(
new LocalDateDeserializer(DATE_FORMATTER),
new LocalDateTimeDeserializer(DATE_TIME_FORMATTER),
new LocalTimeDeserializer(TIME_FORMATTER));
}
}
Then, you can create controller methods like this:
#RestController
public class BookingController {
private final YourService yourService;
#Autowired
public BookingController(YourService yourService) {
this.yourService = yourService;
}
#GetMapping("/your/api/endpoint")
public YourObject yourControllerMethod(#RequestParam LocalDate date, Pageable pageable) {
return yourService.yourServiceMethod(date, pageable);
}
// Or: with LocalDateTime
#GetMapping("/your/api/endpoint")
public YourObject yourControllerMethod(#RequestParam LocalDateTime dateTime, Pageable pageable) {
return yourService.yourServiceMethod(dateTime, pageable);
}
}
Option 2: Setting the date/time format for each REST Endpoint individually
If you prefer to set the format for each endpoint individually, you have to annotate the request parameter with #DateTimeFormat and specify the expected format. The example below shows different examples on how to accomplish this:
#RestController
public class BookingController {
private final YourService yourService;
#Autowired
public BookingController(YourService yourService) {
this.yourService = yourService;
}
#GetMapping("/your/api/endpoint")
public YourObject yourControllerMethod(#RequestParam #DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, Pageable pageable) {
return yourService.yourServiceMethod(date, pageable);
}
// Or: with LocalDateTime
#GetMapping("/your/api/endpoint")
public YourObject yourControllerMethod(#RequestParam #DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTime, Pageable pageable) {
return yourService.yourServiceMethod(dateTime, pageable);
}
// Or: with your custom pattern
#GetMapping("/your/api/endpoint")
public YourObject yourControllerMethod(#RequestParam #DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate date, Pageable pageable) {
return yourService.yourServiceMethod(date, pageable);
}
}

How to insert Date object with the latest mongojack?

so in my object, I have private Date date; when I insert I got this exception:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: JsonGenerator of type org.mongojack.internal.object.document.DocumentObjectGenerator not supported: org.mongojack.internal.DateSerializer is designed for use only with org.mongojack.internal.object.BsonObjectGenerator or org.mongojack.internal.stream.DBEncoderBsonGenerator or com.fasterxml.jackson.databind.util.TokenBuffer (through reference chain: com.test.DocumentWrapper["date"])
I am trying to set up the mongo TTL by using that date field.
I have had the same issue recently: to store date as Date object into MongoDB via MongoJack.
First of all, I used MongoJack 2.10.0 version.
And it requires to create own Serializer and Deserializer.
public class Serializer extends JsonSerializer<DateTime> {
#Override
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeObject(new Date(value.getMillis()));
}
}
public class Deserializer extends JsonDeserializer<DateTime> {
private static final DateDeserializer DATE_DESERIALIZER = new DateDeserializer();
#Override
public DateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Date date = DATE_DESERIALIZER.deserialize(p, ctxt);
return date == null ? null : new DateTime(date);
}
}
.....
#JsonSerialize(using = Serializer.class)
#JsonDeserialize(using = Deserializer.class)
private DateTime testDate;
public DateTime getTestDate() {
return testDate;
}
public void setTestDate(DateTime testDate) {
this.testDate = testDate;
}
......
In my case, I converted Date into joda DateTime to keep consistency with my code but it's possible to change to another type (LocalDateTime, OffsetDateTime, etc.)
To solve this issue, please use the 2.10.0 version which has fixed this bug.

How to use #Inject and CDI for enterprise beans with JAX-RS 2.0 (Resteasy)

I have some problem finding out how get JAX-RS 2.0 to work with CDI on wildfly 10. I got some answer on another post that was a mix of JAX-RS 1.0/2.0 and they used other dependencies than the included libraries in Wildfly.
My objective is to inject a singleton enterprise bean that encapsulate business logic that resides in the same jar into my REST resource. The REST resource class is supposed to be request scoped and only deal with REST functionality (request and response). My POJO classes are JAXB notated.
How can I use JAX-RS 2.0 with the include CDI libraries in Wildfly 10?
The bean interface
#Local
public interface DateBean {
Date getLocalFormatDate();
}
The bean
#Singleton
public class DateBeanImpl implements DateBeanLocal {
private static final Logger LOG = Logger.getLogger("org.test.logger");
public DateBean() {
LOG.fine("DateBean");
}
#Override
public Date getLocalFormatDate() {
Calendar cal = Calendar.getInstance();
TimeZone localZone = TimeZone.getDefault();
cal.setTimeZone(localZone);
Date localTime = cal.getTime();
return localTime;
}
}
The REST resource
#Path("classroom")
#Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class ClassRoomResource {
private static final Logger LOG = Logger.getLogger("org.clearbyte.logger");
#Inject private DateBean dateBean;
public ClassRoomResource() {
LOG.fine("ClassRoomResource");
}
#GET
#Path("{id}/getDummy")
public ClassRoom getDummy(#PathParam("id") long id) {
ClassRoom room = new ClassRoom();
room.setRoomName("Dummy");
room.setRoomNr(id);
return room;
}
#GET
#Path("localDate")
#Produces({MediaType.TEXT_HTML})
public Response getLocalformatDate() {
LOG.fine("DateBean variable: " +dateBean);
Date localDate = dateBean.getLocalDate();
LOG.fine("Local date: " +localDate);
return Response.status(Response.Status.OK)
.entity(localDate.toString())
.build();
}
}
The Resteasy implementation of JAX-RS 2.0 are included in Wildlfy 10, so there is no need to add further dependencies.
The interface doesn’t need #Localwhen is resides in the same jar/war for CDI to find it. To make the enterprise bean singleton in CDI use the #ApplicationScope, you can omit the #Singleton notation if you don't need a managed bean with read/write synchronisation.
#ApplicationScoped
public class DateBeanImpl implements DateBean {
private static final Logger LOG = Logger.getLogger("org.test.logger");
public DateBean() {
LOG.fine("DateBean");
}
#Override
public Date getLocalFormatDate() {
//DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
TimeZone localZone = TimeZone.getDefault();
cal.setTimeZone(localZone);
Date localTime = cal.getTime();
return localTime;
}
}
The make the REST resource request scoped use the #RequestScoped notation. Notice that the #Inject inject the interface and not the implementation of the bean.
#RequestScoped
#Path("classroom")
#Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class ClassRoomResource {
private static final Logger LOG = Logger.getLogger("org.clearbyte.logger");
#Inject private DateBean dateBean;
...
No configuration of the web.xml is necessary if you a extend the jax-rs Application class.
#ApplicationPath("rest")
public class ClassRoomApp extends Application {
private final Set<Class<?>> resources = new HashSet<>();
public ClassRoomApp() {
resources.add(ClassRoomResource.class);
}
#Override
public Set<Class<?>> getClasses() {
return resources;
}
}

Date conversation error during jaxb marshall on a JPA object using eclipselink

I stuck on this Date conversation error for quite some time ...
I am using eclipselinks, openJPA under TomcatEE environment, and trying to use jaxb doing marshalling. I met a problem for marshall one JPA object, which contains Date, TimeStamp elements.
The exception message is ---
javax.xml.bind.MarshalException
- with linked exception:
[Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [3/19/12 12:00 AM], of class [class org.apache.openjpa.util.java$util$Date$proxy], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[createTs-->createTs/text()]] with descriptor [XMLDescriptor(xxx.xxxx.xxx.xxxx.entities.ApplicationEntity --> [])], could not be converted to [class java.util.Date].]
The strange thing is jaxb converting works OK for some customers, but not some other customer. I tried to put #XmlElement(type=Date.class) for this field crtTs, It doesn't work.
Thanks for your help in advance.
LL
I have been able to reproduce the issue you are seeing. You can use the following bug to track our progress on this issue:
http://bugs.eclipse.org/383639
WORK AROUND
DateAdapter
You could use an XmlAdapter to convert the problematic date into a proper java.util.Date.
package forum11145711;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class DateAdapter extends XmlAdapter<Date, Date>{
#Override
public Date unmarshal(Date date) throws Exception {
return date;
}
#Override
public Date marshal(Date date) throws Exception {
if(null == date) {
return date;
}
return new Date(date.getTime());
}
}
Root
The #XmlJavaTypeAdapter annotation is used to leverage the XmlAdapter:
package forum11145711;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
public class Root {
private Date date;
#XmlJavaTypeAdapter(DateAdapter.class)
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
MyDate
Below is the subclass of java.util.Date I'm using in this example.
package forum11145711;
import java.util.Date;
public class MyDate extends Date {
}
Demo
Below is some demo code you can use to prove that everything works:
package forum11145711;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Root root = new Root();
root.setDate(new MyDate());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<date>2012-06-27T10:39:49.081</date>
</root>