Doing timezone conversion while using BeanUtils.copyProperties - java

I have a Hibernate mapped model class as follows,
#Entity
#Table(name = "USER")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "User_SEQ")
#SequenceGenerator(sequenceName = "User_SEQ", allocationSize = 1, name = "User_SEQ")
private Integer id;
private Date createdOn;
}
I have another model class as follows which I use for the response from a REST API. The object of this class essentially gets serialized into JSON
public class UserDTO {
private Integer id;
private Date createdOn;
}
Since the variable names are the same, I am using BeanUtils.copyProperties to copy the value of all fields from User to UserDTO (Currently showing only 2 fields above for simplicity)
Data is stored in GMT in the database, hence the createdOn field contains the TIMESTAMP in GMT. I want to return the Date in local time zone e.g. "Europe/Copenhagen". For this I am using the following code (using apache commons),
java.util.Date defaultValue = null;
DateConverter dateConverter = new DateConverter(defaultValue);
dateConverter.setTimeZone(TimeZone.getTimeZone("Europe/Copenhagen"));
BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();
beanUtilsBean.getConvertUtils().register(dateConverter, java.util.Date.class);
BeanUtils.copyProperties(userDTO, user);
The code executes, but userDTO still contains the date in GMT. time zone conversion is not working. What am I missing here?
EDIT1:
I have tried checking by manually passing a date as follows,
#Test
public void testBeanUtilsDateConverter() throws Exception {
System.out.println("\ntestBeanUtilsDateConverter - Start");
Date date = new GregorianCalendar(2014, Calendar.FEBRUARY, 11, 18, 30, 10).getTime();
Date newDate = new Date();
DateConverter converter = new DateConverter();
converter.setTimeZone(TimeZone.getTimeZone("Europe/Copenhagen"));
BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();
beanUtilsBean.getConvertUtils().deregister(java.util.Date.class);
beanUtilsBean.getConvertUtils().register(converter, java.util.Date.class);
System.out.println(newDate);
BeanUtils.copyProperties(newDate, date);
System.out.println(date);
System.out.println(newDate);
System.out.println("testBeanUtilsDateConverter - End");
}
Output:
testBeanUtilsDateConverter - Start
Fri Jun 02 14:04:08 IST 2017
Tue Feb 11 18:30:10 IST 2014
Tue Feb 11 18:30:10 IST 2014
testBeanUtilsDateConverter - End
So the BeanUtils is definitely copying the date to the target, but the converter is either not getting called or not doing anything for some reason
EDIT2 - Using Custom Converter
class MyDateConverter implements Converter {
public MyDateConverter() {
System.out.println("Instantiating MyDateConverter");
}
#Override
public Object convert(Class Date, Object value) {
System.out.println("Inside convert()");
if (value == null) {
System.out.println("Value is null");
return (Date) null;
} else {
System.out.println("Doing date conversion");
Date date = new GregorianCalendar(2015, Calendar.JANUARY, 12, 9, 45, 15).getTime();
return date;
}
}
}
#Test
public void testCustomDateConverter() throws Exception {
System.out.println("\ntestCustomDateConverter - Start");
Date date = new GregorianCalendar(2014, Calendar.FEBRUARY, 11, 18, 30, 10).getTime();
Date newDate = new Date();
BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();
beanUtilsBean.getConvertUtils().deregister(java.util.Date.class);
beanUtilsBean.getConvertUtils().register(new MyDateConverter(), java.util.Date.class);
System.out.println(newDate);
BeanUtils.copyProperties(newDate, date);
System.out.println(date);
System.out.println(newDate);
System.out.println("testCustomDateConverter - End");
}
Output:
testCustomDateConverter - Start
Instantiating MyDateConverter
Fri Jun 02 14:04:09 IST 2017
Tue Feb 11 18:30:10 IST 2014
Tue Feb 11 18:30:10 IST 2014
testCustomDateConverter - End
Again the same result. The custom converter is getting instantiated, but the convert method is not called. I even tried a custom Long converter to check if it's something to do with using the Date class, but even that was not getting called. There is something missing in the registration part that BeanUtils is not able to call the overridden convert function.

Related

Cannot deserialize value of type java.sql.Timestamp from String

I have a bean class where I am setting the recReceived time using the below code. When I am executing the below code, I am getting error
Exception in thread "main" java.lang.IllegalArgumentException: Cannot
deserialize value of type java.sql.Timestamp from String
............
public static void main(String[] args) {
TestBean TestBean = new TestBean();
TestBean.setRecReceived(new Timestamp(System.currentTimeMillis()));
Gson gson = new Gson();
String jsonData = gson.toJson(TestBean); // Cannot ignore this part as it is sent from first server to second server
Map<String, Object> map = new ObjectMapper().readValue(jsonData, HashMap.class); //Received at server end
TestBean abc = (TestBean) convertMapToEntity(map, TestBean.class);
}
// Cannot edit this function
public static Object convertMapToEntity(Map<String, Object> object, Class<?> objClass) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
return objectMapper.convertValue(object, objClass);
}
// Bean class - Cannot edit this file
import java.sql.Timestamp;
public class TestBean {
Timestamp recReceived;
Timestamp responseSent;
// getter and setter
}
It will be really helpful if someone can help me let know what I am doing wrong in the code or can any change be done in code without touching the non editable function or file
Thanks in advance
You are seeing this exception :
java.lang.IllegalArgumentException: Cannot deserialize value of type
java.sql.Timestamp from String "Jun 15, 2022, 07:54:56 PM": not a
valid representation (error: Failed to parse Date value 'Jun 15, 2022,
07:54:56 PM': Cannot parse date "Jun 14, 2022, Jun 15, 2022, 07:54:56
PM": not compatible with any of standard forms
("yyyy-MM-dd'T'HH:mm:ss.SSSX", "yyyy-MM-dd'T'HH:mm:ss.SSS", "EEE, dd
MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
beacause your JSON is having the date format which is not compatible with standard date format that Jackson uses for deserializations.
Below are standard formats for a date which Jackson supports:
yyyy-MM-dd’T’HH:mm:ss.SSSZ
yyyy-MM-dd’T’HH:mm:ss.SSS
EEE, dd MMM yyyy HH:mm:ss zzz
yyyy-MM-dd
To fix this, you will use
.setDateFormat() method which configures Gson to serialize Date objects according to the pattern provided.
You will need to set one of above mentioned patterns which jackson support.
Here is the complete code:
public static void main(String[] args) throws JsonProcessingException {
TestBean TestBean = new TestBean();
TestBean.setRecReceived(new Timestamp(System.currentTimeMillis()));
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
Gson gson = gsonBuilder.create();
String jsonData = gson.toJson(TestBean); // Cannot ignore this part as it is sent from first server to second server
Map<String, Object> map = new ObjectMapper().readValue(jsonData, HashMap.class); //Received at server end
TestBean abc = (TestBean) convertMapToEntity(map, com.example.demo.dto.TestBean.class);
System.out.println(abc);
}
If you run above code, you should see output like this:
TestBean{recReceived=2022-06-14 04:01:56.279, responseSent=null}

How to parse properly Date string to java.util.Date when deserializing JSON to Java POJO with Jackson ObjectMapper

I am implementing an application that gets the data from certin endponts in json formats and tries to deserialize tem to Java Objects but I have problems with the parsing of the date in the JSON.This is how the Date looks like in the JSON: "/Date(1633122000000+0300)/" and I cannot find information in Google how to successfully parse this format.
{
"Date": "/Date(1633122000000+0300)/",
"Filled": 0,
"Needed": 0,
"Paid": 0
}
This is the pojo I use to deserialize the data to using Jackson ObjectMapper:
import java.util.Date;
#Data
#AllArgsConstructor
#NoArgsConstructor
public class TimeByDateSheet {
#JsonProperty("Date")
#JsonFormat(timezone = "GMT+03:00")
#JsonDeserialize(using = DateDeserializer.class, as=Date.class)
private Date date;
#JsonProperty("Filled")
private Long filled;
#JsonProperty("Needed")
private Long needed;
#JsonProperty("Paid")
private Integer paid;
}
And here is my DateDeserializer:
#SuppressWarnings("serial")
public class DateDeserializer extends JsonDeserializer<Date> {
#Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException, JsonProcessingException {
SimpleDateFormat simpleDateFormat =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz", Locale.getDefault());
String dateStr = jsonParser.getText();
Date date;
try{
date = simpleDateFormat.parse(dateStr);
}catch(ParseException e){
throw new RuntimeException(e);
}
return date;
}
}
But it does not work correctly. I get the following exception:
Connected to the target VM, address: '127.0.0.1:52760', transport: 'socket'
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: java.text.ParseException: Unparseable date: "/Date(1633035600000+0300)/" (through reference chain: java.util.ArrayList[0]->com.dataart.forecasts.pojo.timebydate.TimeByDateSheet["Date"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:392)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1821)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:315)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:176)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:355)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4675)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3630)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3613)
at com.dataart.forecasts.DataProcessor.deserializeTimeByDateSheetsList(DataProcessor.java:198)
at com.dataart.forecasts.ForecastReportApplication.main(ForecastReportApplication.java:50)
Caused by: java.lang.RuntimeException: java.text.ParseException: Unparseable date: "/Date(1633035600000+0300)/"
at com.dataart.forecasts.DateDeserializer.deserialize(DateDeserializer.java:28)
at com.dataart.forecasts.DateDeserializer.deserialize(DateDeserializer.java:16)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:313)
... 10 more
Caused by: java.text.ParseException: Unparseable date: "/Date(1633035600000+0300)/"
at java.base/java.text.DateFormat.parse(DateFormat.java:395)
at com.dataart.forecasts.DateDeserializer.deserialize(DateDeserializer.java:26)
... 13 more
Could someone help me, please. I searched a lot in internet but could not find a solution.
Thank you in advance! :)
It looks like there is a problem generating the JSON. I really don't think you want to have the dates formatted like that. Right now, you have some odd text surrounding a unix timestamp in milliseconds followed by a zone offset. You are also using the old and rather frowned-upon Date and SimpleDateFormat classes rather than the newer java.time API. However, it is possible to deserialize your date format. Here is one way:
public class DateDeserializer extends JsonDeserializer<Date> {
#Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException, JsonProcessingException {
Pattern pattern = Pattern.compile("/Date\\((\\d+)([+-]\\d+)\\)/");
Matcher matcher = pattern.matcher(jsonParser.getText());
if (matcher.find()) {
String timestamp = matcher.group(1);
String offset = matcher.group(2);
Instant instant = Instant.ofEpochMilli(Long.parseLong(timestamp));
ZonedDateTime zdt = instant.atZone(ZoneId.of(offset));
instant = zdt.toInstant();
return Date.from(instant);
} else {
throw new RuntimeException("Invalid format: " + jsonParser.getText());
}
}
}
java.time
For this answer I am assuming:
The time in your JSON may come with or without the UTC offset.
You can go all-in on java.time, the modern Java date and time API, and declare your variable to be of type Instant or OffsetDateTime, for example (not Date).
For JSON that comes with an offset such as +0300 declare your variable an OffsetDateTime. Then use the following deserializer.
public class OdtDeserializer extends JsonDeserializer<OffsetDateTime> {
private static final DateTimeFormatter JSON_DATE_FORMATTER = new DateTimeFormatterBuilder()
.appendLiteral("/Date(")
.appendValue(ChronoField.INSTANT_SECONDS)
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.appendOffset("+HHMM", "Z")
.appendLiteral(")/")
.toFormatter();
#Override
public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException {
String dateStr = jsonParser.getText();
return OffsetDateTime.parse(dateStr, JSON_DATE_FORMATTER);
}
}
For JSON that comes without offset like /Date(1636510000000)/ declare your variable Instant. Use a similar deserializer. Leave out the offset from the formatter. Parse into an Instant — the syntax is a bit different.
public class InstantDeserializerWIthoutOffset extends JsonDeserializer<Instant> {
private static final DateTimeFormatter JSON_DATE_FORMATTER = new DateTimeFormatterBuilder()
.appendLiteral("/Date(")
.appendValue(ChronoField.INSTANT_SECONDS)
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.appendLiteral(")/")
.toFormatter();
#Override
public Instant deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException {
String dateStr = jsonParser.getText();
return JSON_DATE_FORMATTER.parse(dateStr, Instant::from);
}
}
For JSON that may come with or without the offset still use Instant and just modify the formatter of the latter deserializer to include an optional offset:
private static final DateTimeFormatter JSON_DATE_FORMATTER = new DateTimeFormatterBuilder()
.appendLiteral("/Date(")
.appendValue(ChronoField.INSTANT_SECONDS)
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.optionalStart()
.appendOffset("+HHMM", "Z")
.optionalEnd()
.appendLiteral(")/")
.toFormatter();
If you cannot modify your POJO class and need to stay with Date, modify my Instant deserializer into a Date deserializer by changing the declaration and returning a Date like this:
String dateStr = jsonParser.getText();
Instant inst = JSON_DATE_FORMATTER.parse(dateStr, Instant::from);
return Date.from(inst);
Final solution catching both: /Date(1633035600000+0300)/ and /Date(-62135596800000)/ (the latter was also present at one place in oneof the JSONs). Thank you #DavidConrad
#Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
String dateString = jsonParser.getText();
Pattern pattern = Pattern.compile("/Date\\((-)?(\\d+)([+-]\\d+)?\\)/");
Matcher matcher = pattern.matcher(dateString);
if (!matcher.find()) {
throw new RuntimeException("Invalid format: " + dateString);
}
String timestamp = matcher.group(2);
String offset = matcher.group(3);
Instant instant = Instant.ofEpochMilli(Long.parseLong(timestamp));
if (nonNull(offset)) {
ZonedDateTime zdt = instant.atZone(ZoneId.of(offset));
instant = zdt.toInstant();
}
return Date.from(instant);
}
#DavidConrad Thank you, I will try your solution.
By the way, for now I made a workaround that works for me for now:
#Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
SimpleDateFormat dateFormattter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = jsonParser.getText();
String timeZone = dateStr.substring(dateStr.indexOf("+") + 1, dateStr.indexOf(")"));
String timeZoneShift = String.format("%s:%s",
timeZone.substring(0, timeZone.length()/2),
timeZone.substring(timeZone.length()/2));
dateFormattter.setTimeZone(TimeZone.getTimeZone(String.format("GMT+%s", timeZoneShift)));
Long millis = 0L;
if (dateStr.contains("+") && !dateStr.contains("-")) {
millis = Long.parseLong(dateStr.substring(dateStr.indexOf("(") + 1, dateStr.indexOf("+")));
} else if (dateStr.contains("+") && !dateStr.contains("-")) {
millis = Long.parseLong(dateStr.substring(dateStr.indexOf("(") + 1, dateStr.indexOf(")")));
}
Date date = new Date(millis);
String stringDate= dateFormattter.format(date);
try {
date = dateFormattter.parse(stringDate);
} catch (ParseException e) {
throw new RuntimeException(e);
}
return date;
}

Date format from Android (java) to Spring Boot

I'm working with Android Studio (java) to make the front part of my application, and I work with Spring Boot to the back part.
The SQL database uses TimeStamp.
So my problem is that when I send an object from front (Android) to back (Spring) throws an error:
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.util.Date from String "Feb 18, 2021 2:47:40 AM": not a valid representation (error: Failed to parse Date value 'Feb 18, 2021 2:47:40 AM': Cannot parse date "Feb 18, 2021 2:47:40 AM": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSX", "yyyy-MM-dd'T'HH:mm:ss.SSS", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd")); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type java.util.Date from String "Feb 18, 2021 2:47:40 AM": not a valid representation (error: Failed to parse Date value 'Feb 18, 2021 2:47:40 AM': Cannot parse date "Feb 18, 2021 2:47:40 AM": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSX", "yyyy-MM-dd'T'HH:mm:ss.SSS", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
at [Source: (PushbackInputStream); line: 1, column: 123] (through reference chain: com.prueba.dataproviders.model.Solicitud["fecha"])]
So I guess the problem its from Android sending information to Spring, but I don't know how to handle it...
MORE INFORMATION:
This is an example when I send information from Spring to Android:
{
"id": 23,
"fecha": "2021-02-18T02:47:40.000+00:00",
"estadoSolicitud": 1
}
I keep the attribute "fecha" which its a date in a Date variable.
But when I send the same object to back it sends:
{"estadoSolicitud":0,"fecha":"Feb 18, 2021 2:47:40 AM","id":23}
Thank you in advance <3
CODE:
At Spring Solicitud class:
#Entity
#Table(name = "solicitud")
public class Solicitud implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#GenericGenerator(name = "increment", strategy = "increment")
#Column(name = "id")
private int id;
#Column(name = "fecha", insertable = false)
private Date fecha;
#Column(name="estadoSolicitud")
private int estadoSolicitud; // "0 Pendiente, 1 Realizada 2 Rechazada
At Spring the the post method that receives the <Solicitud> object:
#RequestMapping(value = "/solicitudes/gestionarSolicitud/{estadoSol}", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<Object> setSolicitud(#RequestBody Solicitud solicitud, #PathVariable(value="estadoSol") int estadoSol ){
Optional<Solicitud> optionalSolicitud = solicitudService.gestionarSolicitud(solicitud, estadoSol);
if (optionalSolicitud.isPresent()) {
return new ResponseEntity<Object>(optionalSolicitud.get(), HttpStatus.OK);}
} else {
return new ResponseEntity<Object>(null , HttpStatus.OK);
}
}
At Android (front part) Solicitud Model:
public class Solicitud implements Serializable {
private int id;
private Date fecha;
private int estadoSolicitud; // 0 pendiente 1 Aceptada 2 Rechazada
//getters && setters...
}
At Android the request method that's request the post method to back:
public interface SolicitudService {
#POST("/solicitudes/gestionarSolicitud/{estadoSol}")
Call<Solicitud> gestionarSolitud( #Body Solicitud solicitud, #Path("estadoSol") int estadoSol);
}
At Android the function that uses the request method:
private void gestionarSolicitud(#NotNull Solicitud solicitud, int estadoSol) {
SolicitudService solicitudService = ApiClient.getClient().create(SolicitudService.class);
Call<Solicitud> call = solicitudService.gestionarSolitud(solicitud, estadoSol);
call.enqueue(new Callback<Solicitud>() {
#Override
public void onResponse(Call<Solicitud> call, Response<Solicitud> response) {
Solicitud solActualizada = response.body();
if (solActualizada != null && solActualizada.getEstadoSol() == estadoSol) {
if (estadoSol == 1)
Toast.makeText(context, "Usuario registrado correctamente", Toast.LENGTH_LONG).show();
else if (estadoSol == 2)
Toast.makeText(context, "Solicitud rechazada", Toast.LENGTH_LONG).show();
notifyDataSetChanged();
} else {
Toast.makeText(context, "Ups! Ha ocurrido un error", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<Solicitud> call, Throwable t) {
Toast.makeText(context, "Ups! Ha ocurrido un error del servidor.", Toast.LENGTH_LONG).show();
}
});
}
I think you have to try Joda Time library as a common middleware for your date fields.
You haven't shown any actual code, so a definitive answer isn't possible, but you need to make sure that whatever you are using to serialize your java objects to Json on the Android side properly serializes Dates to ISO-8601 format.
Most mainstream Json serializers, e.g. Gson, will do that by default.
The exception is saying that the value you are sending from client side(android) is having different data type, what you are fetching in back-end (Spring).
At both end the datatype must be same.
Please try this
Spring Code : You can mention the date format with JsonFormat annotation
String DATE_FORMAT_MM_DD_YYYY = "MM/dd/yyyy"
#JsonFormat(pattern = DATE_FORMAT_MM_DD_YYYY)
private Date fetching_date;
For Android Code : Get the date and you can change the date formats using below code
You can define the date formats like this :
const val DATE_FORMAT_yyyy_MM_dd_HH_mm_ss_a = "yyyy-MM-dd HH:mm:ss a"
const val DATE_FORMAT_MMM_dd_yyyy = "MMM dd, yyyy"
const val DATE_FORMAT_MMM_dd_yyyy_HH_MM_AA = "MMM dd, yyyy hh:mm aa"
const val DATE_FORMAT_YYYY_MM_DD = "yyyy-MM-dd"
//Convertion of one date format to another
fun convertDateFormat(oldFormat: String, newFormat: String, dateString: String): String {
var sdf = SimpleDateFormat(oldFormat)
try {
val date = sdf.parse(dateString)
sdf = SimpleDateFormat(newFormat, getLocalForDateFormat())
return sdf.format(date)
} catch (e: Exception) {
e.printStackTrace()
}
return ""
}
Send the date from android to back-end in request.

Spring: Date Binding in the format dd/MM/yyyy i.e. 31/12/1999

You may find this as duplicate question, still I'm not getting what is wrong with following code.
This code I found in several WebSites and in Spring Documentation , any ty-po here in my code ?
I want persist object in file (.ser) , which contains several 'Date' fields, and show details again in my jsp,
The formart requred to me is dd/MM/yyyy i.e. 31/12/1999.
It shows in the format "Wed Jun 01 00:00:00 IST 2016" before persisting in my controller.
I have used CustomDateEditor as follows:
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
dateFormat.setLenient(false);
webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
in above code I have used two parameters to registerCustomEditor() , is this ok ?
or how to do for multiple fields ,
webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
should I have to use this above line of code for every field.
I have tried for this one also but no success
webDataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport(){
#Override
public void setAsText(String text) throws IllegalArgumentException {
System.out.println(text+" setAsText");
try {
if( text != "")
//setValue(text);
setValue(new SimpleDateFormat("dd/MM/yyyy").parse(value));
} catch (Exception e) {
setValue(null);
}
}
#Override
public String getAsText() {
System.out.println(getValue()+" getValue");
return new SimpleDateFormat("dd/mm/yyyy").format((Date)getValue());
}
});
In my JSP , I used date picker as:
$('#id-scheme-start-date').datepicker({
dateFormat: 'dd/mm/yy',
});
I have another choice to use JSTL tag in JSP but I do not want to use this at several position.

How to accept Date params in a GET request to Spring MVC Controller?

I've a GET request that sends a date in YYYY-MM-DD format to a Spring Controller.
The controller code is as follows:
#RequestMapping(value="/fetch" , method=RequestMethod.GET)
public #ResponseBody String fetchResult(#RequestParam("from") Date fromDate) {
//Content goes here
}
The request is sent correctly as I'm checking with Firebug.
I get the error:
HTTP Status 400: The request sent by the client was syntactically incorrect.
How can I make the controller accept this format of Date?
Please help. What am I doing wrong?
Ok, I solved it.
Writing it for anyone who might be tired after a full day of non-stop coding & miss such a silly thing.
#RequestMapping(value="/fetch" , method=RequestMethod.GET)
public #ResponseBody String fetchResult(#RequestParam("from") #DateTimeFormat(pattern="yyyy-MM-dd") Date fromDate) {
//Content goes here
}
Yes, it's simple. Just add the DateTimeFormat annotation.
This is what I did to get formatted date from front end
#RequestMapping(value = "/{dateString}", method = RequestMethod.GET)
#ResponseBody
public HttpStatus getSomething(#PathVariable #DateTimeFormat(iso = DateTimeFormat.ISO.DATE) String dateString) {
return OK;
}
You can use it to get what you want.
... or you can do it the right way and have a coherent rule for serialisation/deserialisation of dates all across your application. put this in application.properties:
spring.mvc.date-format=yyyy-MM-dd
Below solution perfectly works for spring boot application.
Controller:
#GetMapping("user/getAllInactiveUsers")
List<User> getAllInactiveUsers(#RequestParam("date") #DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date dateTime) {
return userRepository.getAllInactiveUsers(dateTime);
}
So in the caller (in my case its a web flux), we need to pass date time in this("yyyy-MM-dd HH:mm:ss") format.
Caller Side:
public Flux<UserDto> getAllInactiveUsers(String dateTime) {
Flux<UserDto> userDto = RegistryDBService.getDbWebClient(dbServiceUrl).get()
.uri("/user/getAllInactiveUsers?date={dateTime}", dateTime).retrieve()
.bodyToFlux(User.class).map(UserDto::of);
return userDto;
}
Repository:
#Query("SELECT u from User u where u.validLoginDate < ?1 AND u.invalidLoginDate < ?1 and u.status!='LOCKED'")
List<User> getAllInactiveUsers(Date dateTime);
Cheers!!
If you want to use a PathVariable, you can use an example method below (all methods are and do the same):
//You can consume the path .../users/added-since1/2019-04-25
#GetMapping("/users/added-since1/{since}")
public String userAddedSince1(#PathVariable("since") #DateTimeFormat(pattern = "yyyy-MM-dd") Date since) {
return "Date: " + since.toString(); //The output is "Date: Thu Apr 25 00:00:00 COT 2019"
}
//You can consume the path .../users/added-since2/2019-04-25
#RequestMapping("/users/added-since2/{since}")
public String userAddedSince2(#PathVariable("since") #DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date since) {
return "Date: " + since.toString(); //The output is "Date: Wed Apr 24 19:00:00 COT 2019"
}
//You can consume the path .../users/added-since3/2019-04-25
#RequestMapping("/users/added-since3/{since}")
public String userAddedSince3(#PathVariable("since") #DateTimeFormat(pattern = "yyyy-MM-dd") Date since) {
return "Date: " + since.toString(); //The output is "Date: Thu Apr 25 00:00:00 COT 2019"
}
You can use :
public #ResponseBody String fetchResult(#RequestParam("from")#DateTimeFormat(pattern="yyyy-MM-dd") Date fromDate) {
//Your code...
}
2000-10-31T01:30:00.000-05:00 convert to Datetime (Joda)
#GetMapping("test/{dateTimeStart}")
public void getCheckDaily2(
#PathVariable(value = "dateTimeStart", required = false)
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
DateTime dateTimeStart){
body here...
}

Categories