Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Datefield value changes on it's own
I am currenly using version 7.2.4 of the Vaadin framework and I am having an interesting problem with the date field.
I have two date fields on the screen, basically a start date and end date. The resolution for both fields are set to Month and the format for both fields is "MMM yyyy", just in case that make a difference. The code below is setup to first set the start date to a default value and then based on the value of the start fields, if necessary change the value of the end date. It also set the date start range and end range.
private void setBaseDates() {
if (this.df_BaseStart.getValue() == null) {
Calendar now = Calendar.getInstance();
Date start = SMSUtilities.genDate(now.get(Calendar.YEAR), (now.get(Calendar.MONTH)), 1);
this.df_BaseStart.setValue(start);
}
Date min = SMSUtilities.incrementDate(this.df_BaseStart.getValue(), TU.MONTH,1);
Date max = SMSUtilities.incrementDate(this.df_BaseStart.getValue(), TU.MONTH, 13);
if (this.df_BaseEnd.getValue() == null || this.df_BaseEnd.getValue().compareTo(min) < 0 || this.df_BaseEnd.getValue().compareTo(max) > 0) {
this.df_BaseEnd.setValue(min);
}
this.df_BaseEnd.setRangeStart(min);
this.df_BaseEnd.setRangeEnd(max);
}
But a few seconds after my code runs, the end date value is changed by something outside of my code. Below is the stack trace that I captured by putting a change trigger on the end date field. It seem to be set to todays date from what I can tell. Below is the stack trace I captured when the value change.
ProdSalesAnalysis$8.valueChange(Property$ValueChangeEvent) line: 321
GeneratedMethodAccessor36.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available
Method.invoke(Object, Object...) line: not available
ListenerMethod.receiveEvent(EventObject) line: 508
EventRouter.fireEvent(EventObject, ErrorHandler) line: 198
EventRouter.fireEvent(EventObject) line: 161
PopupDateField(AbstractClientConnector).fireEvent(EventObject) line: 984
PopupDateField(AbstractField<T>).fireValueChange(boolean) line: 1131
PopupDateField(AbstractField<T>).setValue(T, boolean) line: 542
PopupDateField(DateField).setValue(Date, boolean) line: 678
PopupDateField(DateField).changeVariables(Object, Map<String,Object>) line: 587
ServerRpcHandler.changeVariables(Object, VariableOwner, Map<String,Object>) line: 471
ServerRpcHandler.handleInvocations(UI, int, JSONArray) line: 289
ServerRpcHandler.handleRpc(UI, Reader, VaadinRequest) line: 168
UidlRequestHandler.synchronizedHandleRequest(VaadinSession, VaadinRequest, VaadinResponse) line: 93
UidlRequestHandler(SynchronizedRequestHandler).handleRequest(VaadinSession, VaadinRequest, VaadinResponse) line: 41
VaadinServletService(VaadinService).handleRequest(VaadinRequest, VaadinResponse) line: 1405
VaadinServlet.service(HttpServletRequest, HttpServletResponse) line: 237
VaadinServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 728
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 305
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
StandardWrapperValve.invoke(Request, Response) line: 222
StandardContextValve.invoke(Request, Response) line: 123
NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 472
StandardHostValve.invoke(Request, Response) line: 171
ErrorReportValve.invoke(Request, Response) line: 99
AccessLogValve.invoke(Request, Response) line: 953
StandardEngineValve.invoke(Request, Response) line: 118
CoyoteAdapter.service(Request, Response) line: 408
Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1023
Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 589
JIoEndpoint$SocketProcessor.run() line: 312
ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: not available
ThreadPoolExecutor$Worker.run() line: not available
TaskThread(Thread).run() line: not available
Can any one point me to what might be going on and how I can resolve the problem?
"It seem to be set to todays date from what I can tell." - So the resolution is changed back to "Day"? If not, and you mean it is set to current month and year, as long as df_BaseStart is null i think it is correct that df_BaseEnd is set to current month and year (unless SMSUtilities does something different what i think...)
Because you use a third party lib i can't try your code but following code runs without a problem for me:
DateField start = new DateField("Start");
DateField end = new DateField("End");
start.setResolution(Resolution.MONTH);
end.setResolution(Resolution.MONTH);
start.setValue(new Date(System.currentTimeMillis()));
Date min = new Date(System.currentTimeMillis());
Date max = new Date(System.currentTimeMillis() + 9876543210l);
end.setValue(min);
end.setRangeStart(min);
end.setRangeEnd(max);
If you need more help, you have to remove SMSUtilities from your code (and verify that the problem still exists) so that i can test it and give me further information, eg when is setBaseDates() called.
The code in the SMSUtilities that is being called is below: As you propullay surmised it is just creating a new date value based on the inputted parameters and is not effecting the date field directly.
/**
* Creates a date at midnight
* @param year
* @param month
* @param day
* @return
*/
public static Date genDate(Integer year, Integer month, Integer day) {
return genDate(year,month,day,0,0,0);
}
/**
* Creates a date with the specified values and returns it
* @param year
* @param month
* @param day
* @param hour
* @param min
* @param sec
* @return
*/
public static Date genDate(Integer year, Integer month, Integer day, Integer hour, Integer min, Integer sec) {
Calendar cal = new GregorianCalendar(year, month, day, hour, min, sec);
return cal.getTime();
}
/**
* Increments the supplied date value by the unit and amount
* specified.
*
* @param date
* @param unit
* @param amount
* @return
*/
public static Date incrementDate(Date date,TU unit, Integer amount) {
Calendar workDate = Calendar.getInstance();
workDate.setTime(date);
switch (unit) {
case YEAR:
workDate.add(Calendar.YEAR, amount);
break;
case MONTH:
workDate.add(Calendar.MONTH, amount);
break;
case DAY:
workDate.add(Calendar.DATE, amount);
break;
case HOUR:
workDate.add(Calendar.HOUR, amount);
break;
case MINUTE:
workDate.add(Calendar.MINUTE, amount);
break;
case SECOND:
workDate.add(Calendar.SECOND, amount);
break;
case MILLISECOND:
workDate.add(Calendar.MILLISECOND, amount);
break;
}
return workDate.getTime();
For some reason after the ValueChangeListener on the "df_BaseStart" calls setBaseDate(), about 30 seconds later something in the background resets the value of "df_BaseEnd". Basically the flow that happens is as follows:
- User inputs a date into "df_BaseEnd"
- The ValueChangeListener on "df_BaseEnd" calls "setBaseDate"
- "setBaseDate" reset the value of "df_BaseEnd" and the correct value is shown on the screen.
- "setBaseDate" exits and about 30 seconds later the value in "df_BaseEnd" is reset to "May 01 2015"
I removed the calls to SMSUtilities and now the "setBaseDate" section of code looks like the following:
private void setBaseDates() {
if (this.df_BaseStart.getValue() == null) {
Calendar now = Calendar.getInstance();
// Date start = SMSUtilities.genDate(now.get(Calendar.YEAR), (now.get(Calendar.MONTH)), 1);
Date start = new Date();
this.df_BaseStart.setValue(start);
}
// Date min = SMSUtilities.incrementDate(this.df_BaseStart.getValue(), TU.MONTH,1);
// Date max = SMSUtilities.incrementDate(this.df_BaseStart.getValue(), TU.MONTH, 13);
Date min = new Date(this.df_BaseStart.getValue().getTime() + 4938271605l);
Date max = new Date(min.getTime() + 9876543210l);
if (this.df_BaseEnd.getValue() == null || this.df_BaseEnd.getValue().compareTo(min) < 0 || this.df_BaseEnd.getValue().compareTo(max) > 0) {
this.df_BaseEnd.setValue(min);
}
this.df_BaseEnd.setRangeStart(min);
this.df_BaseEnd.setRangeEnd(max);
From what I can tell something in the background is being triggered after the ValueChangeEvent on "df_BaseDate" end that is reseting the value of "df_EndDate", and it is only being triggered when the user inputts a value in "df_BaseDate". It does not happen when I set the value to initilize the screen, like you are showing in your code sample.
For some reason after the ValueChangeListener on the "df_BaseStart" calls setBaseDate(), about 30 seconds later something in the background resets the value of "df_BaseEnd". Basically the flow that happens is as follows:
- User inputs a date into "df_BaseEnd"
- The ValueChangeListener on "df_BaseEnd" calls "setBaseDate"...
Is the Listener on BaseStart or BaseEnd (or both)?
From what I can tell something in the background is being triggered after the ValueChangeEvent on "df_BaseDate" end that is reseting the value of "df_EndDate", and it is only being triggered when the user inputts a value in "df_BaseDate".
Do you mean df_BaseStart with df_BaseDate?
Assuming the listener is on df-BaseStart and df_BaseDate is df_BaseStart i tried the following code:
public class DateRangeTestUI extends UI {
private DateField start;
private DateField end;
@WebServlet(value = "/*", asyncSupported = true)
@VaadinServletConfiguration(productionMode = false, ui = DateRangeTestUI.class)
public static class Servlet extends VaadinServlet {
}
@Override
protected void init(VaadinRequest request) {
start = new DateField("Start");
end = new DateField("End");
start.setResolution(Resolution.MONTH);
end.setResolution(Resolution.MONTH);
start.setImmediate(true);
end.setImmediate(true);
start.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
setBaseDates();
}
});
setContent(new VerticalLayout(start,end));
}
private void setBaseDates() {
if (this.start.getValue() == null) {
Date start = new Date();
this.start.setValue(start);
}
Date min = new Date(this.start.getValue().getTime() + 4938271605l);
Date max = new Date(min.getTime() + 9876543210l);
if (this.end.getValue() == null || this.end.getValue().compareTo(min) < 0 || this.end.getValue().compareTo(max) > 0) {
this.end.setValue(min);
}
// prevent IllegalStateException if 'start' is changed to something after 'end'
this.end.setRangeEnd(null);
this.end.setRangeStart(null);
this.end.setRangeStart(min);
this.end.setRangeEnd(max);
}
}
Works like expected. I don't have the problem you are describing.
So i think the error is somewhere in your environment. Try the UI (in a fesh clean Vaadin project without any addons etc...) i posted and look if the problem still occurs.
I found the issue. Because of other functions in my application, in my UI file I set the polling interval. That seems to be what is causing the date field to update it's value. Attached is a project that duplicates the problem.
Nope, your test-project works without any problems for me... I changed the end date and nothing changes it in the background. What Application-Server are you using? Wich JVM?
Also, if i only change start date, end date is adjusted and stays as it is...
I am using Java 7 update 45, but the project compiler compliance level is set to 1.6. I am not sure what you mean by Application-Server, but it is running on Tomcat 7.0.
Ok i was able to reproduce your problem, it only occurs when you change start date and did not change end date before (as i did in my previous test). I will have a look at it now
Congratulations, you found a bug :) In fact it only occurs when you set the Resolution of end date to month, if set to day, the problem does not occur. It is a client side bug as i can tell.
Please fill out a bug report, so the developers can fix it!
I have not found a quick workaround other than leave end date at day resolution (you can leave the MM YYYY pattern so it will at least look the same, allthough the date chooser will be at day resolution) but maybe using server push instead of client poll will help...
You can also set a debug breakpoint in changeVariables in DateField, then you will see, that on client poll, a wrong/the current date comes from the client.
The problem does not occur if the user just opened and closed the date chooser of end date (without choosing a date). So it looks like some client side initialization problem of the date field component.
If i have some more time tomorrow i will give it another look, im quite tired atm ;) Maybe i'll find another workaround.
Thank you for the help. Here is the ticket for the bug, in case you want to add any further comments.
https://dev.vaadin.com/ticket/17908
Thank you again.
Just found out, that the date range is also necessary to cause the bug. I updated your ticket.