I have a field in my dataset defined as:
DataSourceDateTimeField dateField = new DataSourceDateTimeField("date");
and a StaticTextItem in DynamicForm defined as
StaticTextItem dateItem = new StaticTextItem("date", "Date");
I played a lot with different combinations of setDateFormatter, but datetime values are still rendered as something like 2011-08-23T20:00:00 (datasource receives it in json as a yyyy-MM-dd'T'HH:mm:ss.SSSZ field).
Is there some easy way to output datetime values to StaticTextItem? I assume using DynamicForm.fetchData().
UPD1. Data example.
Table row in PgSQL:
1 | "2011-09-29 12:10:05.010276+04" | "Europe"
Data sent by REST service:
{
"location":"Europe",
"id":1,
"date":"2011-09-29T08:10:05.010+0000"
}
Data fetched by SGWT from REST service (I dumped it with JSON.encode(XMLTools.selectObjects(data, "/").getJavaScriptObject()) in my implementation of transformResponse()) :
{
"location":"Europe",
"id":1,
"date":"2011-09-29T08:10:05"
}
Value as rendered in StaticTextField:
2011-09-29T08:10:05
So datetime values returned by server seem to conform the standard and also I have no warnings in Developer Console.
UPD2. May be I'm doing something wrong in my transformResponse() ?
protected void transformResponse(DSResponse response, DSRequest request, Object data) {
String json = JSON.encode(XMLTools.selectObjects(data, "/").getJavaScriptObject());
SC.logWarn("Response received");
SC.logWarn(json);
Record[] records = jsonToRecords(json);
//safe HTML text values
for (Record rec: records) {
for (DataSourceField field: getFields()) {
if (field.getType() == FieldType.TEXT) {
String textVal = rec.getAttribute(field.getName());
if (textVal != null) {
textVal = SafeHtmlUtils.htmlEscape(textVal);
}
rec.setAttribute(field.getName(), textVal);
}
}
}
response.setData(records);
response.setStartRow(0);
response.setEndRow(records.length);
response.setTotalRows(records.length);
}
/**
* Converts JS-array into SmartGWT records
*/
public static native ListGridRecord[] jsonToRecords(String jsonString) /*-{
var json = eval(jsonString);
return #com.smartgwt.client.widgets.grid.ListGrid::convertToListGridRecordArray(Lcom/google/gwt/core/client/JavaScriptObject;)(json);
}-*/;
Your problem is most likely that your date value is still a String, not an instance of Date. It should have been parsed into a Date when the JSON response was received - if it was not, there will be a warning in the SmartGWT Developer Console tell you so.
The format expected for date values in documented under DataSource.dataFormat - XML Schema date/datetime format is expected by default, and you can provide a FieldValueParser if you are unable to make your server produce this format.
Related
I try to implement an example of Spring Boot Batch Processing (CSV to h2 database). I want to add a new column named "age" to calculate a year according to birthdate. How can I define "age" column in lineMapper? I try to use public class UserProcessor implements ItemProcessor<UserDTO, User> return User DTO (id,person_id,first_name,last_name,email,gender,country,date, age)
Here is the sample csv file shown below.
id,person_id,first_name,last_name,email,gender,country,date
1,38c324d5-2d8f-4687-8862-30f15a19f26c,Melesa,Conquest,mconquest0#goodreads.com,Female,Poland,2022-09-13 09:13:05
2,082f0eff-e1ca-4f6e-8348-247b6a676547,Dodi,Jachtym,djachtym1#github.com,Polygender,Armenia,2022-03-02 09:26:13
I already defined date shown below in User Entity.
#JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime date;
I try to calculate age with this method shown below
public static int calculateAge(LocalDate birthDate, LocalDate currentDate) {
if ((birthDate != null) && (currentDate != null)) {
return Period.between(birthDate, currentDate).getYears();
} else {
return 0;
}
}
I want to get a table shown below in h2 database.
id,person_id,first_name,last_name,email,gender,country,date,age
1,38c324d5-2d8f-4687-8862-30f15a19f26c,Melesa,Conquest,mconquest0#goodreads.com,Female,Poland,2000-09-13 09:13:05,22
How can I do that?
LineMapper is not the place where data should be processed. The line mapper should only be used to map a single line from the input file to an instance of the domain object.
Such calculations or data transformations are typically done in an item processor where items are amended/enriched with additional data. Please check the Item processing section of the reference documentation for more details about this matter.
Once items are processed, the writer can select the new column and persist it in the database.
I am using Couchbase Lite SDK for android and saving an object instance of MyClass as a document in the database. MyClass has an attribute that stores the date in the java.util.Date. During run time, I fetch all the instances of MyClass saved in the database and store them in the ArrayList<MyClass>. When I insert a new document into the database and read the values from the database to show all the entered instances, the date field saved in the database is retrieved as a Long when I next try to fetch the details from the database. The code I use to load the details from the database is:
Code snippet 1:
for (Field field: fields) {
field.setAccessible(true);
if (properties.containsKey(field.getName())) {
if ("date".equals(field.getName())) {
Log.d("DebugTag", properties.get(field.getName()) + "");
long dateLong = (Long) properties.get(field.getName());
details.setDate(new Date(dateLong));
} else {
field.set(details, properties.get(field.getName()));
}
} else if("_id".equals(field.getName())) {
details.set_id(document.getId());
} else {
final String msg = "Field " + field.getName() + " not present in document ";
Log.e(TAG, msg);
}
}
You can see that I have added an additional check in case the field is date. This works perfectly fine. So, I save a new entry to database and come back to the page where I see all the entries made into the database.
Now, I have implemented a new functionality to update the details of a record in the database. For updating the record I have the following implementation:
Code snippet 2:
public static boolean updateDocument(Database database, String docID, Map<String, Object> map) {
if (null == database || null == map || null == docID) {
return false;
}
boolean success = true;
Document document = database.getDocument(docID);
try {
// Have to put in the last revision id as well to update the document.
// If we do not do this, this will throw exception.
map.put("_rev", document.getProperty("_rev"));
// Putting new properties in the document ...
document.putProperties(map);
} catch (CouchbaseLiteException e) {
Log.e(TAG, "Error putting property", e);
success = false;
}
return success;
}
After doing this when I try to reload the items, it gives me exception while reading the date field in my Code snippet 1 saying that the Date object cannot be typecasted as Long and the application crashes. Now, when I again open the application, it works perfectly fine with all the changes to the edited entry reflecting correctly. Can anyone let me know the reason for this? I suspect, until we close the database connection, the changes are not committed to the actual database location and the date field in the updated entry is kept in the cache as the Date object in my case.
PS: Although, I have found a workaround for this by setting the date as a Long object in the payload (map in function updateDocument() in Code snippet 2), it would still be interesting to understand the problem I faced.
Looking at this further, this could be reasons related to auto-boxing where long to Long conversion of primitive types to the object wrapper class is crashing the application when trying to save.
Have you tried:
long value = Long.parseLong((String)...);
More specifically in Code snippet 1:
long dateLong = Long.parseLong((String)properties.get(field.getName()));
IN order to test couchbase, I am needing to create servlet that edit in 1.000 JSON documents row '"flag": false' to '"flag":true'. How i can do this?
My view, that finds documents with row '"flag": false':
function (doc, meta) {
if (meta.type == "json" && doc.flag == false) {
emit(doc.flag, null);
}
}
My servlet, that print results:
doGet(....
View view = client.getView("des1", "flag");
Query query = new Query();
query.setIncludeDocs(true);
ViewResponse result = client.query(view, query);
for(ViewRow row : result) {
resp.getWriter().println(row.getId());
}
Sorry for my bad English)
You cannot edit the fields in the JSON document directly. What you must do is to retrieve the documents you want to update (you already get them from the view), convert them to a Java object, edit the "flag" property, serialize the Java object back to JSON and replace the document with the new one.
You can use GSON to take care of the conversion between a java object and json.
I am trying to deserialize the following incoming JSON data:
{"TimeTable":[{"PersonID":"100649771",
..,..,..,"xx":null},
{"PersonID":"100631701",
..,..,..,"xx":{"abc":1234,"xyz":5678}}],
"xxx":"","xxxx":0,"xxxxx":false}
But I am facing a problem while parsing using a custom deserialization block made up of:
jParser.nextToken();
while ((jParser.nextToken() != JsonToken.END_ARRAY)) {
String innerField = jParser.getCurrentName();
jParser.nextToken();
But in this way I am skipping the array contents While parsing for the second row in the array (as illustrated in the JSON sample above^).
UPDATE: Here is the method(PasteBin Link) which is trying to parse the JSON data coming in the described format. Is there a way I can bind the JSON data directly to my bean? (IMO it appeared way more complex to me as because of the JSON structure; Moreover I can't change the JSON structure nor the bean structure. So, I just dropped the idea of binding directly :| ) Anyways here(PasteBin Link) is the bean as well.
Following is the sample of the incoming JSON Data:
{"Schedules":[{"PersonID":"100649771",
"HasSchedule":false,
"TripType":null,
"StickerNumber":null,
"VehicleRegNo":null,
"ExpectedStartDate":null,
"ActualStartDate":null,
"ActualEndDate":null,
"PersonScheduledDate":null,
"Shift":null,
"ColdCall":null,
"PickupLocationCoord":null},
{"PersonID":"100631701",
"HasSchedule":true,
"TripType":"P",
"StickerNumber":"PC0409",
"VehicleRegNo":"ASJHAHSP1758",
"ExpectedStartDate":"16 Aug 2013, 10:00:00",
"ActualStartDate":"16 Aug 2013, 10:02:52",
"ActualEndDate":"16 Aug 2013, 14:14:12",
"PersonScheduledDate":null,
"Shift":"02:30 PM",
"ColdCall":"N",
"PickupLocationCoord":{"Latitude":92.01011101,"Longitude":48.01011101}}],
"ErrorMessage":"","ErrorCode":0,"HasError":false}
Please can anyone fireup some pointers for me here in order- to deserialize 'em correctly?
Thanks
UPDATED
Among other things, you are mixing up the two aproaches to read a JSON stream: using readTree() to get all your JSON data in a memory tree (like XML's DOM) but also using a JsonParser to read a JSON stream token by token (like XML's JAX). The following is a method that does almost the same using readTree(), which seems to be more appropriate to you as you are reading JSON already loaded in a String:
public List<VehicleInformationBean> getAllVehiclesInTree(String response) {
List<VehicleInformationBean> vehicleList = new ArrayList<VehicleInformationBean>();
try {
PersonInformationBean mPersonInformationBean;
DatabaseHelper mDatabaseHelper = DatabaseHelper.getInstance(sContext);
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = (ObjectNode) mapper.readTree(response);
if ((root.get(ServiceConstant.ErrorCode).asInt()) != 0 || !root.has(ServiceConstant.Schedules)) {
return vehicleList;
}
for(JsonNode element: root.get(ServiceConstant.Schedules)) {
VehicleInformationBean lstVehicleInformation = new VehicleInformationBean();
if (element.has(ServiceConstant.PersonID)) {
String personId = element.get(ServiceConstant.PersonID).asText();
mPersonInformationBean = mDatabaseHelper.getPersonDetailById(personId);
lstVehicleInformation.setPersonID(personId);
lstVehicleInformation.setName(mPersonInformationBean.getName());
lstVehicleInformation.setPickupLocation(mPersonInformationBean.getPickupLocation());
lstVehicleInformation.setDropLocation(mPersonInformationBean.getDropLocation());
}
lstVehicleInformation.setTripType(element.get(ServiceConstant.TripType).textValue());
lstVehicleInformation.setStickerNumber(element.get(ServiceConstant.StickerNumber).textValue());
lstVehicleInformation.setVehicleRegNo(element.get(ServiceConstant.VehicleRegNo).textValue());
lstVehicleInformation.setExpectedStartDate(element.get(ServiceConstant.ExpectedStartDate).textValue());
lstVehicleInformation.setActualStartDate(element.get(ServiceConstant.ActualStartDate).textValue());
lstVehicleInformation.setActualEndDate(element.get(ServiceConstant.ActualEndDate).textValue());
lstVehicleInformation.setPersonScheduledDate(element.get(ServiceConstant.PersonScheduledDate).textValue());
lstVehicleInformation.setShift(element.get(ServiceConstant.Shift).textValue());
if (element.has("PickupLocationCoord")) {
JsonNode coords = element.get("PickupLocationCoord");
if(coords.has(ServiceConstant.Latitude)) {
lstVehicleInformation.setLatitude(coords.get(ServiceConstant.Latitude).asDouble());
}
if(coords.has(ServiceConstant.Longitude)) {
lstVehicleInformation.setLongitude(coords.get(ServiceConstant.Longitude).asDouble());
}
} else if (element.has(ServiceConstant.ColdCall)) {
lstVehicleInformation.setColdCall(element.get(ServiceConstant.ColdCall).textValue());
}
vehicleList.add(lstVehicleInformation);
}
} catch (Exception e) {
// TODO doing something with exception or throw it if it can't be handled here
e.printStackTrace();
}
return vehicleList;
}
There are some validations and extra code you need to add to this method for it to do exactly what your original method does. This method only shows you the main idea of how to do it.
I have a Javabean with a date_observed field. Now I am trying to create a form where a user can search for entries between a start and end date.
Should I create another Javabean that extends this bean to have a start and end date field so that I can populate these field from request parameter?
I'd like to cleanly pass a bean to my Dao for SQL string generation and also have a way to do form validation if they enter incorrect date format.
Typically I would do
public void processDate_observed(HttpServletRequest request, Comment comment) {
String _date = FormUtil.getFieldValue(request, FIELD_DATE_OBSERVED);
if (!"".equals(_date) && _date != null) {
try {
Date date = DateUtil.parse(_date);
com.setDate_observed(date);
} catch (ParseException e) {
setError(FIELD_DATE_OBSERVED, e.getMessage());
}
}
}
But my Comment Javabean does not have fields for start_date and end_date
And for dao.search(comment)
public List<Evaluatee> search(Comment comment) {
SQL = ".... where date_observed > ? AND date_observed <= ?
ps.setDate(1, comment.EXTENDED FIELD???)
ps.setDate(2, comment.EXTENDED FIELD???)
...
}
What is the best practice here? Creat a whole new Javabean, extend my original bean or pass along the two date fields to Dao? But then how do you pass form validation back to form if I don't have the dates in a bean?
Is a good practice that in your DAO class you have a serch method with a start and end date as parameters.
public List<Evaluatee> search(String startDate, String endDate) {
///CODE GOES HERE
}
It's not necessary that the DAOs needs to have a Comment object as an argument, the rule is that for each table of the data base need to be a class with the same fields as in the table.