How to catch customize exeception in Date JsonDeserializer? - java

Implementaion: Im trying to show the customize exception DATE_FORMAT_EXCEPTION with a message of Date format is wrong if error. But even i input a wrong format the customize exception wont show but there is error 400 Bad Request and i use Exception which catch all the error.
import java.io.IOException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import com.cartgatewayservice.RestModelException.DATE_FORMAT_EXCEPTION;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
public class DateDeserializer extends JsonDeserializer<Date> {
#Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
DateTimeFormatter localDateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String dateValue = p.getValueAsString();
try {
LocalDate localDate = LocalDate.parse(dateValue, localDateFormatter);
return convertToDateViaInstant(localDate);
} catch (Exception e) {
throw new DATE_FORMAT_EXCEPTION("Date format is wrong");
}
}
public Date convertToDateViaInstant(LocalDate dateToConvert) {
return Date.from(dateToConvert.atStartOfDay()
.atZone(ZoneId.systemDefault())
.toInstant());
}
}
import java.util.Date;
import com.cartgatewayservice.BodyConvertParameters.DateDeserializer;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.OptBoolean;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.springframework.format.annotation.DateTimeFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
#Data
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Builder
public class ProductEntity {
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
#JsonFormat(pattern = "yyyy-MM-dd", shape = JsonFormat.Shape.STRING, lenient = OptBoolean.FALSE)
#JsonDeserialize(using = DateDeserializer.class)
private Date productexpirationdate;
}
public class DATE_FORMAT_EXCEPTION extends RuntimeException {
private static final long serialVersionUID = 1L;
public DATE_FORMAT_EXCEPTION(String message) {
super(message);
}
}
#ControllerAdvice
public class RestAdviceException extends ResponseEntityExceptionHandler {
#ExceptionHandler(DATE_FORMAT_EXCEPTION.class)
public ResponseEntity<Object> handleFormatDateEntity(DATE_FORMAT_EXCEPTION ex, WebRequest request) {
return new ResponseEntity<Object>(new ERROR_DETAILS_EXCEPTION(ex.getMessage(), HttpStatus.BAD_REQUEST, LocalDateTime.now()),HttpStatus.NOT_FOUND);
..........
}
}

Related

Throw custom exception while deserializing the Date field using jackson in java

DTO:
#Getter
#Setter
#ToString
public class TestDto {
#NotNull
private String id;
#NotNull
#DateTimeFormat(pattern = "YYYY-MM-DD'T'hh:mm:ss.SSSZ")
private Instant timestamp;
}
When I give this input
{"timestamp":"4/23/2018 11:32 PM","id":"132"}
It gives BAD_REQUEST (which it should), but I want to handle this malformed date and throw an exception with my custom exception.
How can I add this?
Since OP requested feature is not supported yet: https://github.com/FasterXML/jackson-annotations/issues/130
Trying to do the same thing with a bit longer approach by using custom deserializer for a field timestamp
Custom exception class:
import com.fasterxml.jackson.core.JsonProcessingException;
public class MyException extends JsonProcessingException {
public MyException(String message) {
super(message);
}
}
Custom Deserializer class:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
public class InstantDeserializer extends StdDeserializer<Instant> {
public InstantDeserializer() {
this(null);
}
public InstantDeserializer(Class<?> vc) {
super(vc);
}
private SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD'T'hh:mm:ss.SSS'Z'");
#Override
public Instant deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
Date date = null;
try {
date = sdf.parse(node.asText());
} catch (Exception e) {
throw new MyException("Instant field deserialization failed");
}
return date.toInstant();
}
}
Updated TestDto class:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.Instant;
#Getter
#Setter
#ToString
public class TestDto {
#NotNull
private String id;
#NotNull
#JsonDeserialize(using = InstantDeserializer.class)
#DateTimeFormat(pattern = "YYYY-MM-DD'T'hh:mm:ss.SSS'Z'")
private Instant timestamp;
}
Invalid Input request:
{"timestamp":"4/23/2018 11:32 PM","id":"132"}
Response:
{
"timestamp": 1552845180271,
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Instant field deserialization failed; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Instant field deserialization failed (through reference chain: TestDto[\"timestamp\"])"
}
Valid Input Request:
{"timestamp":"2018-04-23T11:32:22.213Z","id":"132"}
Response:
{
"id": "132",
"timestamp": {
"epochSecond": 1514700142,
"nano": 213000000
}
}
If you do not like the way timestamp field is getting deserialized and would like to change that, this SO post will be helpful.

Jackson Json deserialize date string to java date

I have to read date string from json and set it to java object.
I have used the following annotations on my variable.
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
#JsonInclude(JsonInclude.Include.NON_NULL)
public class RequestObject {
#JsonProperty("doj")
#JsonDeserialize(using = CustomDateDeserializer.class, as=Date.class)
private Date doj;
public Date getDoj() {
return doj;
}
public void setDoj(Date doj) {
this.doj = doj;
}
}
Below is my Custom DateDeserializer.
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
#SuppressWarnings("serial")
public class CustomDateDeserializer extends JsonDeserializer<Date>{
#Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date = jsonParser.getText();
try{
return sdf.parse(date);
}catch(ParseException e){
throw new RuntimeException(e);
}
}
}
I am testing this using postman, below is my postman request.
{
"doj":"2017-12-27"
}
But I am getting the following error.
Caused by: java.lang.IllegalArgumentException: Invalid format: "2017-12-27" is too short
at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:945) ~[joda-time-2.9.1.jar:2.9.1]
at com.exxonmobil.ace.hybris.jaxb.DateAdapter.unmarshal(DateAdapter.java:45) ~[DateAdapter.class:?]
at com.exxonmobil.ace.hybris.jaxb.DateAdapter.unmarshal(DateAdapter.java:1) ~[DateAdapter.class:?]
at org.eclipse.persistence.internal.jaxb.XMLJavaTypeConverter.convertDataValueToObjectValue(XMLJavaTypeConverter.java:149) ~[org.eclipse.persistence.moxy-2.6.1.jar:?]
Could someone please let me know where I am going wrong.
Regards,
Farhan

Json Deserialize Date not working [duplicate]

This question already has answers here:
Parse json date string in android
(7 answers)
Closed 6 years ago.
In Json list i'm getting such a date: "lastModifiedDate":1459202400000". Serialize and Deserialize class they seem to be ok.
Entity class:
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.hibernate.validator.constraints.Email;
#Data
#ToString
#Entity
public class UserEntity implements Serializable {
#JsonSerialize(using=JsonDateSerializer.class)
#JsonDeserialize(using=JsonDateDeserializer.class)
#Column(name = "LastModifiedDate", columnDefinition="DATETIME", nullable = true, insertable = true, updatable = true)
private java.util.Date lastModifiedDate;
}
Deserializer class:
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.springframework.stereotype.Component;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.*;
#Component
public class JsonDateDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
#Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
try {
return dateFormat.parse(jsonParser.getText());
} catch (Exception e) {
throw new JsonParseException("Could not parse date", jsonParser.getCurrentLocation(), e);
}
}
What's wrong?
}
You are not parsing the date correctly. Right now you receive a date in milliseconds, so you have first to create a date before formatting, i.e.:
dateFormat.format(new Date(Long.parseLong(jsonParser.getText())));
Or if you just want to create the Date object from it, just skip the format part.

How to deserialize date format in spring hibernate?

i am writing a rest services where i am getting response as in format "1448994600000" for date but i need it to give response in date,month,year format.
if i send data by giving 12-2-2015 format it give me error
The request sent by the client was syntactically incorrect
In response i get "12333333333" format,i need it to response with 12-2-2015
i have used below code to deserialize it,but its not working what is going wrong in my code,Please guide me.
import java.io.Serializable;
import java.sql.Date;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonSerialize;
#JsonAutoDetect
#Entity
#Table(name = "DataValueTable")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class DataValueTable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "ID")
private long id;
#JsonSerialize(using=JsonDateSerializer.class)
#Column(name = "Time")
private Date time;
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
JsonDateSerializer.java
package com.beingjavaguys.model;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
import org.springframework.stereotype.Component;
/**
* Used to serialize Java.util.Date, which is not a common JSON
* type, so we have to create a custom serialize method;.
*
* #author Loiane Groner
* http://loianegroner.com (English)
* http://loiane.com (Portuguese)
*/
#Component
public class JsonDateSerializer extends JsonSerializer<Date>{
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
#Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}
method in my controller
/* Getting List of objects in Json format in Spring Restful Services */
#RequestMapping(value = "/list", method = RequestMethod.GET)
public #ResponseBody List getDatalist() {
List DataList = null;
try {
DataList = dataServices.getDataEntityList();
} catch (Exception e) {
e.printStackTrace();
}
return DataList;
}
update data
#RequestMapping(value = "/updateData", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
Status updateData(#RequestBody DataValueTable dataObject) {
try {
//response.addHeader("Access-Control-Allow-Origin","*");
dataServices.insertData(dataObject);
return new Status(1, "Data updated Successfully !");
} catch (Exception e) {
// e.printStackTrace();
return new Status(0, e.toString());
}
}
You can use implementation which has been introduced to java8
Import specific libraries
import java.time.LocalDate
import java.time.ZoneId
import java.time.format.DateTimeFormatter
LocalDate localDate= LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
String stamp = localDate.format(formatter);
If you need conversion from Date, you would do it as following
Date input = new Date();
LocalDate localDate = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
And the output could be sth like 13-01-2016

How to fix Race-condition, created duplicate class Error

When I start my tomcat server I get this error:
2015 10:25:50 PM org.mongodb.morphia.mapping.MappedClass getOrCreateInstance
SEVERE: Race-condition, created duplicate class: class com.calendar.model.watchers.AccountWatcher
From what I can tell it is coming from Morphia, but I'm unsure why it's happening or how to fix it.
The code in Morphia that the error appears to be coming from is this:
private Object getOrCreateInstance(Class<?> clazz) {
if (mapr.instanceCache.containsKey(clazz))
return mapr.instanceCache.get(clazz);
Object o = mapr.getOptions().objectFactory.createInstance(clazz);
Object nullO = mapr.instanceCache.put(clazz, o);
if (nullO != null)
if(log.isErrorEnabled())
log.error("Race-condition, created duplicate class: " + clazz);
return o;
}
The code for AccountWatcher is:
package com.calendar.model.watchers;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.mongodb.morphia.annotations.PreLoad;
import org.mongodb.morphia.annotations.PrePersist;
import com.calendar.exception.DataAccessException;
import com.calendar.model.Account;
import com.calendar.model.Partner;
import com.calendar.util.MongoUtils;
public class AccountWatcher {
final static Logger log = LoggerFactory.getLogger(AccountWatcher.class);
#PrePersist
void prePersist(Account account) {
if (account.getId() == null) {// This is for create
account.setId(MongoUtils.getGuid());
account.setDateCreated(new Date());
Partner owner = account.getOwner();
if (owner == null || StringUtils.isEmpty(owner.getId())) {
throw new DataAccessException("Owner :" + owner
+ " doesn't exist for account :" + account);
}
} else { // This is for update
}
account.setDateModified(new Date());
}
#PreLoad
void preLoad(Account account) {
if (log.isDebugEnabled()) {
log.debug("Account watcher #PreLoad executing ...");
}
}
}
And the code for the Account class is:
package com.calendar.model;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import lombok.Data;
import lombok.ToString;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize.Typing;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.EntityListeners;
import org.mongodb.morphia.annotations.Id;
import org.mongodb.morphia.annotations.Indexed;
import org.mongodb.morphia.annotations.Reference;
import com.calendar.model.serializers.PartnerDeSerializer;
import com.calendar.model.serializers.PartnerListSerializer;
import com.calendar.model.serializers.PartnerSerializer;
import com.calendar.model.watchers.AccountWatcher;
#ToString
#EntityListeners(AccountWatcher.class)
#Entity("accounts")
#Data
public class Account {
#Id
private String id;
private String name;
private String timezone;
#JsonSerialize(using = PartnerSerializer.class, typing = Typing.STATIC)
#JsonDeserialize(using = PartnerDeSerializer.class)
#Reference
private Partner owner;
#JsonSerialize(using = PartnerListSerializer.class, typing = Typing.STATIC)
#Reference
private List<Partner> associatedPartners;
#JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
private Date dateCreated;
#JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
private Date dateModified;
#Indexed(unique = true, dropDups = true)
private String externalId;
private Integer externalVersionNumber;
private List<EList> elists;
public Account() {
associatedPartners = new ArrayList<Partner>();
}
}
Thanks in advance for any help that can be provided.
ah, i see. I'm not sure why the decision was made to log that as an error (and conversely, why that logic isn't synchronized) but it's just a logging message. It's not a real problem unless, of course, your listener is mutable and having two instances is an actual problem.

Categories