SimpleDateFormat parses date string to wrong value - spring

I have a date input that reaches the Controller and it performs a conversion from String to Date.
The problem is, the mapping method always returns one day less than I'd expect. If I pass 30/12/2010 it returns a Date object with 29/12/2010 as its value.
I have solved it with a small method that adds a day after the Mapper but I don't know if it is the most correct way:
public class DateMapperImpl implements DateMapper {
#Override
public String dateToString(Date date, String format) {
return date != null ? new SimpleDateFormat(format).format(date) : null;
}
#Override
public Date stringToDate(String date, String format) {
try {
return date != null ? addDayDate(new SimpleDateFormat(format).parse(date)) : null;
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public Date addDayDate(Date fecha) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(fecha);
calendar.add(Calendar.DAY_OF_YEAR, 1);
return calendar.getTime();
}
}
Do you have any idea how to solve it properly?
SOLUTION
I already found the solution. In my case it has been necessary to add this method in the Application class.
#SpringBootApplication
public class BooksApplication {
public static void main(String[] args) {
SpringApplication.run(BooksApplication.class, args);
}
#PostConstruct
public void init(){
// Setting Spring Boot SetTimeZone
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
}
Thank you very much for the answers because they guided me to look for information with a different mindset.

Related

ThymeLeaf pass TimeStamp value

I am trying to pass timestamp value in the format of "2013-12-31 12:00:00.000007", my java model class will take this property as "java.sql.Timestamp".
I tried passing using following html code, but it does not take the value entered in the field, instead it takes null value.
<td><input id="updateDateTime" name="updateDateTime" type="text" th:field="*{updateDateTime}"/></td>
As well in Controller class, i tried using custom binder as below, but still produces null values to "updateDateTime"
#InitBinder
public void binder(WebDataBinder binder) {
binder.registerCustomEditor(Timestamp.class,
new PropertyEditorSupport() {
public void setAsText(String value) {
try {
Date parsedDate = new SimpleDateFormat("MM/dd/YYYY HH:mm:ss.SSSSSS").parse(value);
setValue(new Timestamp(parsedDate.getTime()));
} catch (ParseException e) {
setValue(null);
}
}
});
}

Choose Class in Birt is empty eventhough I have added jar in Datasource

Even though while creating dataset choose class window is empty. I am using Luna Service Release 2 (4.4.2).
From: http://yaragalla.blogspot.com/2013/10/using-pojo-datasource-in-birt-43.html
In the dataset class the three methods, “public void open(Object obj, Map map)”, “public Object next()” and “public void close()” must be implemented.
Make sure you have implemented these.
Here is a sample that I tested with:
public class UserDataSet {
public Iterator<User> itr;
public List<User> getUsers() throws ParseException {
List<User> users = new ArrayList<>();
// Add to Users
....
return users;
}
public void open(Object obj, Map<String, Object> map) {
try {
itr = getUsers().iterator();
} catch (ParseException e) {
e.printStackTrace();
}
}
public Object next() {
if (itr.hasNext())
return itr.next();
return null;
}
public void close() {
}
}

Custom WritableCompare displays object reference as output

I am new to Hadoop and Java, and I feel there is something obvious I am just missing. I am using Hadoop 1.0.3 if that means anything.
My goal for using hadoop is to take a bunch of files and parse them one file at a time (as opposed to line by line). Each file will produce multiple key-values, but context to the other lines is important. The key and value are multi-value/composite, so I have implemented WritableCompare for the key and Writable for the value. Because the processing of each file take a bit of CPU, I want to save the output of the mapper, then run multiple reducers later on.
For the composite keys, I followed [http://stackoverflow.com/questions/12427090/hadoop-composite-key][1]
The problem is, the output is just Java object references as opposed to the composite key and value. Example:
LinkKeyWritable#bd2f9730 LinkValueWritable#8752408c
I am not sure if the problem is related to not reducing the data at all or
Here is my main class:
public static void main(String[] args) throws Exception {
JobConf conf = new JobConf(Parser.class);
conf.setJobName("raw_parser");
conf.setOutputKeyClass(LinkKeyWritable.class);
conf.setOutputValueClass(LinkValueWritable.class);
conf.setMapperClass(RawMap.class);
conf.setNumMapTasks(0);
conf.setInputFormat(PerFileInputFormat.class);
conf.setOutputFormat(TextOutputFormat.class);
PerFileInputFormat.setInputPaths(conf, new Path(args[0]));
FileOutputFormat.setOutputPath(conf, new Path(args[1]));
JobClient.runJob(conf);
}
And my Mapper class:
public class RawMap extends MapReduceBase implements
Mapper {
public void map(NullWritable key, Text value,
OutputCollector<LinkKeyWritable, LinkValueWritable> output,
Reporter reporter) throws IOException {
String json = value.toString();
SerpyReader reader = new SerpyReader(json);
GoogleParser parser = new GoogleParser(reader);
for (String page : reader.getPages()) {
String content = reader.readPageContent(page);
parser.addPage(content);
}
for (Link link : parser.getLinks()) {
LinkKeyWritable linkKey = new LinkKeyWritable(link);
LinkValueWritable linkValue = new LinkValueWritable(link);
output.collect(linkKey, linkValue);
}
}
}
Link is basically a struct of various information that get's split between LinkKeyWritable and LinkValueWritable
LinkKeyWritable:
public class LinkKeyWritable implements WritableComparable<LinkKeyWritable>{
protected Link link;
public LinkKeyWritable() {
super();
link = new Link();
}
public LinkKeyWritable(Link link) {
super();
this.link = link;
}
#Override
public void readFields(DataInput in) throws IOException {
link.batchDay = in.readLong();
link.source = in.readUTF();
link.domain = in.readUTF();
link.path = in.readUTF();
}
#Override
public void write(DataOutput out) throws IOException {
out.writeLong(link.batchDay);
out.writeUTF(link.source);
out.writeUTF(link.domain);
out.writeUTF(link.path);
}
#Override
public int compareTo(LinkKeyWritable o) {
return ComparisonChain.start().
compare(link.batchDay, o.link.batchDay).
compare(link.domain, o.link.domain).
compare(link.path, o.link.path).
result();
}
#Override
public int hashCode() {
return Objects.hashCode(link.batchDay, link.source, link.domain, link.path);
}
#Override
public boolean equals(final Object obj){
if(obj instanceof LinkKeyWritable) {
final LinkKeyWritable o = (LinkKeyWritable)obj;
return Objects.equal(link.batchDay, o.link.batchDay)
&& Objects.equal(link.source, o.link.source)
&& Objects.equal(link.domain, o.link.domain)
&& Objects.equal(link.path, o.link.path);
}
return false;
}
}
LinkValueWritable:
public class LinkValueWritable implements Writable{
protected Link link;
public LinkValueWritable() {
link = new Link();
}
public LinkValueWritable(Link link) {
this.link = new Link();
this.link.type = link.type;
this.link.description = link.description;
}
#Override
public void readFields(DataInput in) throws IOException {
link.type = in.readUTF();
link.description = in.readUTF();
}
#Override
public void write(DataOutput out) throws IOException {
out.writeUTF(link.type);
out.writeUTF(link.description);
}
#Override
public int hashCode() {
return Objects.hashCode(link.type, link.description);
}
#Override
public boolean equals(final Object obj){
if(obj instanceof LinkKeyWritable) {
final LinkKeyWritable o = (LinkKeyWritable)obj;
return Objects.equal(link.type, o.link.type)
&& Objects.equal(link.description, o.link.description);
}
return false;
}
}
I think the answer is in the implementation of the TextOutputFormat. Specifically, the LineRecordWriter's writeObject method:
/**
* Write the object to the byte stream, handling Text as a special
* case.
* #param o the object to print
* #throws IOException if the write throws, we pass it on
*/
private void writeObject(Object o) throws IOException {
if (o instanceof Text) {
Text to = (Text) o;
out.write(to.getBytes(), 0, to.getLength());
} else {
out.write(o.toString().getBytes(utf8));
}
}
As you can see, if your key or value is not a Text object, it calls the toString method on it and writes that out. Since you've left toString unimplemented in your key and value, it's using the Object class's implementation, which is writing out the reference.
I'd say that you should try writing an appropriate toString function or using a different OutputFormat.
It looks like you have a list of objects just like you wanted. You need to implement toString() on your writable if you want a human-readable version printed out instead of an ugly java reference.

JavaFX Table Cell Formatting

TableColumn<Event,Date> releaseTime = new TableColumn<>("Release Time");
releaseTime.setCellValueFactory(
new PropertyValueFactory<Event,Date>("releaseTime")
);
How can I change the format of releaseTime? At the moment it calls a simple toString on the Date object.
If you want to preserve the sorting capabilities of your TableColumn, none of the solutions above is valid: if you convert your Date to a String and show it that way in your TableView; the table will sort it as such (so incorrectly).
The solution I found was subclassing the Date class in order to override the toString() method. There is a caveat here though: the TableView uses java.sql.Date instead of java.util.Date; so you need to subclass the former.
import java.text.SimpleDateFormat;
public class CustomDate extends java.sql.Date {
public CustomDate(long date) {
super(date);
}
#Override
public String toString() {
return new SimpleDateFormat("dd/MM/yyyy").format(this);
}
}
The table will call that method in order to print the date.
Of course, you need to change too your Date class in the TableColumn declaration to the new subclass:
#FXML
TableColumn<MyObject, CustomDate> myDateColumn;
Same thing when you attach your object attribute to the column of your table:
myDateColumn.setCellValueFactory(new PropertyValueFactory< MyObject, CustomDate>("myDateAttr"));
And finally, for the shake of clarity this is how you declare the getter in your object class:
public CustomDate getMyDateAttr() {
return new CustomDate(myDateAttr.getTime()); //myDateAttr is a java.util.Date
}
It took me a while to figure out this due to the fact that it uses java.sql.Date behind the scenes; so hopefully this will save other people some time!
Update for Java FX8:
(I'm not sure it is the good place for that answer, but I get the problem in JavaFX8 and some things have changed, like java.time package)
Some differences with the previous answers:
I keep the date type on the column, so I need to use both cellValueFactory and cellFactory.
I Make a generic reusable method to generate the cellFactory for all date columns.
I use java 8 date for java.time package! But the method could be easily reimplemented for java.util.date.
#FXML
private TableColumn<MyBeanUi, ZonedDateTime> dateColumn;
#FXML
public void initialize () {
// The normal binding to column
dateColumn.setCellValueFactory(cellData -> cellData.getValue().getCreationDate());
//.. All the table initialisation and then
DateTimeFormatter format = DateTimeFormatter .ofLocalizedDate(FormatStyle.SHORT);
dateColumn.setCellFactory (getDateCell(format));
}
public static <ROW,T extends Temporal> Callback<TableColumn<ROW, T>, TableCell<ROW, T>> getDateCell (DateTimeFormatter format) {
return column -> {
return new TableCell<ROW, T> () {
#Override
protected void updateItem (T item, boolean empty) {
super.updateItem (item, empty);
if (item == null || empty) {
setText (null);
}
else {
setText (format.format (item));
}
}
};
};
}
The advantages are that:
The column is typed with a "java8 Date" to avoid the sort problem evoqued by #Jordan
The method "getDateCell" is generic and can be used as an util function for all Java8 Time types (Local Zoned etc.)
I'd recommend using Java generics to create re-usable column formatter that takes any java.text.Format. This cuts down on the amount of boilerplate code...
private class ColumnFormatter<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
private Format format;
public ColumnFormatter(Format format) {
super();
this.format = format;
}
#Override
public TableCell<S, T> call(TableColumn<S, T> arg0) {
return new TableCell<S, T>() {
#Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setGraphic(new Label(format.format(item)));
}
}
};
}
}
Examples of usage
birthday.setCellFactory(new ColumnFormatter<Person, Date>(new SimpleDateFormat("dd MMM YYYY")));
amplitude.setCellFactory(new ColumnFormatter<Levels, Double>(new DecimalFormat("0.0dB")));
I needed to do this recently -
dateAddedColumn.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<Film, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Film, String> film) {
SimpleStringProperty property = new SimpleStringProperty();
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
property.setValue(dateFormat.format(film.getValue().getCreatedDate()));
return property;
}
});
However - it is a lot easier in Java 8 using Lamba Expressions:
dateAddedColumn.setCellValueFactory(
film -> {
SimpleStringProperty property = new SimpleStringProperty();
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
property.setValue(dateFormat.format(film.getValue().getCreatedDate()));
return property;
});
Hurry up with that Java 8 release oracle!
You can accomplish that through Cell Factories. See
https://stackoverflow.com/a/10149050/682495
https://stackoverflow.com/a/10700642/682495
Although the 2nd link is about ListCell, the same logic is totally applicable to TableCells too.
P.S. Still if you need some sample code, kindly will attach here.
An universal solution could be as simple as that:
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;
public interface AbstractConvertCellFactory<E, T> extends Callback<TableColumn<E, T>, TableCell<E, T>> {
#Override
default TableCell<E, T> call(TableColumn<E, T> param) {
return new TableCell<E, T>() {
#Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(convert(item));
}
}
};
}
String convert(T value);
}
And its sample usage:
TableColumn<Person, Timestamp> dateCol = new TableColumn<>("employment date");
dateCol.setCellValueFactory(new PropertyValueFactory<>("emploumentDateTime"));
dateCol.setCellFactory((AbstractConvertCellFactory<Person, Timestamp>) value -> new SimpleDateFormat("dd-MM-yyyy").format(value));
This is what i did and i worked perfectly.
tbColDataMovt.setCellFactory((TableColumn<Auditoria, Timestamp> column) -> {
return new TableCell<Auditoria, Timestamp>() {
#Override
protected void updateItem(Timestamp item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd/MM/yyyy")));
}
}
};
});
You can easily pipe Properties of different type and put a formatter or converter in between.
//from my model
ObjectProperty<Date> valutaProperty;
//from my view
TableColumn<Posting, String> valutaColumn;
valutaColumn.setCellValueFactory(
cellData -> {
SimpleStringProperty property = new SimpleStringProperty();
property.bindBidirectional(cellData.getValue().valutaProperty, new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN));
return property;
});
The StringConverter classes are another mechanism.
TextFieldTableCell has a constructor as follows: public TextFieldTableCell(StringConverter<T> converter).
... and StringConverters consist of subclasses such as LocalDateStringConverter. A default implementation would then be:
new TextFieldTableCell( new LocalDateStringConverter() );
... this is not bad, but the parameter-less LocalDateStringConverter uses dates of the format 'dd/mm/yyyy' both for parsing (fromString() method) and toString(). But there are other constructors where you can pass a FormatStyle or DateTimeFormatter.
From my experiments, however, StringConverters are slightly problematic in that it is difficult to catch the DateTimeParseException thrown by fromString() with an invalid date.
This can be remedied by creating your own StringConverter class, e.g.:
class ValidatingLocalDateStringConverter extends LocalDateStringConverter {
boolean valid;
#Override
LocalDate fromString(String value) {
valid = true;
if (value.isBlank()) return null;
try {
// NB wants ISO
return LocalDate.parse( value );
} catch ( DateTimeParseException e) {
valid = false;
}
return null;
}
#Override
String toString( LocalDate date ){
// NB returns ISO or the String "null" with null date value (!)
String s = date.toString();
return s.equals( 'null' )? '' : s;
}
}
Using this StringConverter solution will mean that dates are sorted according to chronological order, regardless of the String representation.

GWT - Tips Needed - Check and set parameter on the session. Is this the right way?

Im made a sort of autentication on my web application using GWT. So i make these functions in the GWTServiceImpl Class :
public class PageMenuLogin extends FlowPanel {
public PageMenuLogin() {
PageMenuLogin.getService().isSetSession(new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
InlineLabel err=new InlineLabel();
err.setText("Errore Di Connessione");
PageMenuLogin.this.add(err);
}
#Override
public void onSuccess(String result) {
if(result.compareTo("")==0) {
designLogin();
} else {
designLogout(result);
}
}
});
}
public final void designLogin() {
final InlineLabel menu_err=new InlineLabel("");
menu_err.setStyleName("menu_err");
this.add(menu_err);
Button menu_login_button=new Button("Login");
this.add(menu_login_button);
menu_login_button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
getService().checkLogin("nickname", "password", new AsyncCallback<Boolean>() {
#Override
public void onFailure(Throwable caught) {
menu_err.setText("Comunicazione Fallita");
}
#Override
public void onSuccess(Boolean result) {
if (result) {
// I LOAD THE PROFILE PAGE
} else {
menu_err.setText("Username e password non validi");
}
}
});
}
});
}
}
********************************************************************************
public class GWTServiceImpl extends RemoteServiceServlet implements GWTService {
HttpServletRequest request;
HttpSession session;
public String isSetSession() {
this.request = this.getThreadLocalRequest();
this.session=this.request.getSession();
if(this.session.getAttribute("nickname")==null) {
return "";
} else {
return (String)this.session.getAttribute("nickname");
}
}
public boolean checkLogin(String username, String password) {
if("i check on the database if the user exist") {
this.session.setAttribute("nickname", value);
return true;
}
return false;
}
}
On client side, i call the GWTServiceImpl functions (server side), i check the return values and i do some operations.
Is this the right way to work with session on GWT? Any suggestion/tips/helps would be appreciated :)
Thanks for your time!!!
EDIT
New GWTServiceImpl :
public class GWTServiceImpl extends RemoteServiceServlet implements GWTService {
HttpSession session;
public String isSetSession() {
HttpSession session=getThreadLocalRequest().getSession();
if(session.getAttribute("nickname")==null) {
return "";
} else {
return (String)session.getAttribute("nickname");
}
}
public boolean checkLogin(String nickname, String password) {
HttpSession session=getThreadLocalRequest().getSession();
Database mydb=Configuration.getDatabase();
mydb.connetti();
// faccio md5 ed escape
String log_check_user=nickname;
String log_check_pass=password;
// controllo che l'utente esista
ArrayList<String[]> db_result=null;
db_result=mydb.selectQuery("SELECT nickname FROM users WHERE nickname='"+log_check_user+"' AND password='"+log_check_pass+"'");
mydb.disconnetti();
if(!db_result.isEmpty()) {
session.setAttribute("nickname", nickname);
return true;
}
return false;
}
public boolean checkLogout() {
HttpSession session=getThreadLocalRequest().getSession();
session.invalidate();
return true;
}
}
Looks like it should work. I do a lot of work with GWT, although I often forego the use of the RemoteServiceServlet in favour of passing data back and forth via JSON.
A few suggestions, though. When you're calling a method or field within the same class, you don't need to include the this keyword. It doesn't hurt, but tends to make your code longer than it needs to be. Feel free to keep it though, if you find it makes things clearer for you.
Also, unless you've got methods that actually use the request, you don't need to create the request object; you can just do
session = getThreadLocalRequest().getSession();
A final suggestion: Since you're using the session in more than one method, it might be a good idea to initialize it right away; So, instead of initializing it in isSetSession(), you could just write HttpSession session = getThreadLocalRequest().getSession();, or initialize it in the class's constructor. As it stands now, if you happen to call checkLogin() before isSetSession(), you'll get a NullPointerException since session hasn't yet been initialized.

Resources