Form discard() getting triggered on form rendering - only v6.8.0 and v6.8.1

Hello,

Today I upgraded from v6.7.0 to v6.8.1 and all forms that are loaded started behaving in a strange way. Their ‘discard’ method is being called immediately after loading. I downgraded to v6.8.0 and the same problem was there. I ended up at v6.7.10 where the ‘discard’ method is not triggered automatically upon loading.

I found out because I am overriding ‘discard’ with a ConfirmationDialog (add-on) asking 'are you sure you want to discard…?". After the upgrade from 6.7.9 to 6.8.1 all my forms showed the confirmation dialog upon loading. Not good…

Any ideas? Is it a bug? I’m going back to 6.7.10 for now…

jim

I can’t resolve your issue, but I can assure you that forms work fine under 6.8.0 and 6.8.1 – at least we’ve had no such issues and we make extensive use of forms. You should check where discard() is being called from based on the call stack when debugging.

David thanks for taking the time to answer!

I have a breakpoint inside the overriden discard() method. After I replace the jar library, I clean the project, recompile and compile the widgetsets.

Here’s the stacktrace from 6.8.1:

Daemon Thread [http-bio-8080-exec-7]
 (Suspended (breakpoint at line 106 in GtmxForm))	
	GtmxForm.discard() line: 106	
	GtmxForm(AbstractField).attach() line: 1156	
	[b]
GtmxForm(Form).attach() line: 987	
[/b]
	VerticalLayout(AbstractComponentContainer).attach() line: 97	
	TabSheet(AbstractComponentContainer).attach() line: 97	
	GtmxPanel(AbstractComponentContainer).attach() line: 97	
	VerticalLayout(AbstractComponentContainer).attach() line: 97	
	VerticalLayout(AbstractComponent).setParent(Component) line: 560	
	HorizontalLayout(AbstractComponentContainer).addComponent(Component) line: 211	
	HorizontalLayout(AbstractOrderedLayout).addComponent(Component) line: 72	
	GtmxTreePanel.valueChange(Property$ValueChangeEvent) line: 194	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 60	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 37	
	Method.invoke(Object, Object...) line: 611	
	ListenerMethod.receiveEvent(EventObject) line: 510	
	EventRouter.fireEvent(EventObject) line: 164	
	Tree(AbstractComponent).fireEvent(Component$Event) line: 1219	
	Tree(AbstractField).fireValueChange(boolean) line: 937	
	Tree(AbstractField).setValue(Object, boolean) line: 569	
	Tree(AbstractSelect).setValue(Object, boolean) line: 666	
	Tree(AbstractSelect).changeVariables(Object, Map<String,Object>) line: 475	
	Tree.changeVariables(Object, Map<String,Object>) line: 454	
	CommunicationManager(AbstractCommunicationManager).changeVariables(Object, VariableOwner, Map<String,Object>) line: 1460	
	CommunicationManager(AbstractCommunicationManager).handleVariableBurst(Object, Application, boolean, String) line: 1404	
	CommunicationManager(AbstractCommunicationManager).handleVariables(AbstractCommunicationManager$Request, AbstractCommunicationManager$Response, AbstractCommunicationManager$Callback, Application, Window) line: 1329	
	CommunicationManager(AbstractCommunicationManager).doHandleUidlRequest(AbstractCommunicationManager$Request, AbstractCommunicationManager$Response, AbstractCommunicationManager$Callback, Window) line: 761	
	CommunicationManager.handleUidlRequest(HttpServletRequest, HttpServletResponse, AbstractApplicationServlet, Window) line: 296	
	ApplicationServlet(AbstractApplicationServlet).service(HttpServletRequest, HttpServletResponse) line: 501	
	ApplicationServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 722	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 305	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210	
	StandardWrapperValve.invoke(Request, Response) line: 224	
	StandardContextValve.invoke(Request, Response) line: 169	
	NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 472	
	StandardHostValve.invoke(Request, Response) line: 168	
	ErrorReportValve.invoke(Request, Response) line: 98	
	AccessLogValve.invoke(Request, Response) line: 927	
	StandardEngineValve.invoke(Request, Response) line: 118	
	CoyoteAdapter.service(Request, Response) line: 407	
	Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 987	
	Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 579	
	JIoEndpoint$SocketProcessor.run() line: 309	
	ThreadPoolExecutor$Worker.runTask(Runnable) line: 897	
	ThreadPoolExecutor$Worker.run() line: 919	
	TaskThread(Thread).run() line: 736	

and with version 6.7.10:

the breakpoint is not triggered but I placed another one at the forms ‘attach()’:

Daemon Thread [http-bio-8080-exec-10]
 (Suspended)	
Daemon Thread [http-bio-8080-exec-10]
 (Suspended)	
       ... (the top part is ommited for clarity)
	VerticalLayout(AbstractComponent).fireRequestRepaintEvent(Collection<RepaintRequestListener>) line: 892	
	VerticalLayout(AbstractComponent).childRequestedRepaint(Collection<RepaintRequestListener>) line: 859	
	GtmxPanel(AbstractComponent).fireRequestRepaintEvent(Collection<RepaintRequestListener>) line: 893	
	GtmxPanel(AbstractComponent).childRequestedRepaint(Collection<RepaintRequestListener>) line: 859	
	TabSheet(AbstractComponent).fireRequestRepaintEvent(Collection<RepaintRequestListener>) line: 893	
	TabSheet(AbstractComponent).childRequestedRepaint(Collection<RepaintRequestListener>) line: 859	
	VerticalLayout(AbstractComponent).fireRequestRepaintEvent(Collection<RepaintRequestListener>) line: 893	
	VerticalLayout(AbstractComponent).childRequestedRepaint(Collection<RepaintRequestListener>) line: 859	
	GtmxForm(AbstractComponent).fireRequestRepaintEvent(Collection<RepaintRequestListener>) line: 893	
	GtmxForm(AbstractComponent).childRequestedRepaint(Collection<RepaintRequestListener>) line: 859	
	FormLayout(AbstractComponent).fireRequestRepaintEvent(Collection<RepaintRequestListener>) line: 893	
	FormLayout(AbstractComponent).childRequestedRepaint(Collection<RepaintRequestListener>) line: 859	
	TextField(AbstractComponent).fireRequestRepaintEvent(Collection<RepaintRequestListener>) line: 893	
	TextField(AbstractComponent).childRequestedRepaint(Collection<RepaintRequestListener>) line: 859	
	TextField(AbstractComponent).requestRepaint() line: 847	
	TextField(AbstractComponent).attach() line: 638	
	TextField(AbstractField).attach() line: 1132	
	FormLayout(AbstractComponentContainer).attach() line: 97	
	[b]
GtmxForm(Form).attach() line: 988
[/b]	
	GtmxForm.attach() line: 76	
	VerticalLayout(AbstractComponentContainer).attach() line: 97	
	TabSheet(AbstractComponentContainer).attach() line: 97	
	GtmxPanel(AbstractComponentContainer).attach() line: 97	
	VerticalLayout(AbstractComponentContainer).attach() line: 97	
	VerticalLayout(AbstractComponent).setParent(Component) line: 560	
	HorizontalLayout(AbstractComponentContainer).addComponent(Component) line: 211	
	HorizontalLayout(AbstractOrderedLayout).addComponent(Component) line: 72	
	GtmxTreePanel.valueChange(Property$ValueChangeEvent) line: 194	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 60	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 37	
	Method.invoke(Object, Object...) line: 611	
	ListenerMethod.receiveEvent(EventObject) line: 512	
	EventRouter.fireEvent(EventObject) line: 164	
	Tree(AbstractComponent).fireEvent(Component$Event) line: 1219	
	Tree(AbstractField).fireValueChange(boolean) line: 922	
	Tree(AbstractField).setValue(Object, boolean) line: 559	
	Tree(AbstractSelect).setValue(Object, boolean) line: 666	
	Tree(AbstractSelect).changeVariables(Object, Map<String,Object>) line: 475	
	Tree.changeVariables(Object, Map<String,Object>) line: 454	
	CommunicationManager(AbstractCommunicationManager).changeVariables(Object, VariableOwner, Map<String,Object>) line: 1455	
	CommunicationManager(AbstractCommunicationManager).handleVariableBurst(Object, Application, boolean, String) line: 1399	
	CommunicationManager(AbstractCommunicationManager).handleVariables(AbstractCommunicationManager$Request, AbstractCommunicationManager$Response, AbstractCommunicationManager$Callback, Application, Window) line: 1318	
	CommunicationManager(AbstractCommunicationManager).doHandleUidlRequest(AbstractCommunicationManager$Request, AbstractCommunicationManager$Response, AbstractCommunicationManager$Callback, Window) line: 763	
	CommunicationManager.handleUidlRequest(HttpServletRequest, HttpServletResponse, AbstractApplicationServlet, Window) line: 296	
	ApplicationServlet(AbstractApplicationServlet).service(HttpServletRequest, HttpServletResponse) line: 501	
	ApplicationServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 722	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 305	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210	
	StandardWrapperValve.invoke(Request, Response) line: 224	
	StandardContextValve.invoke(Request, Response) line: 169	
	NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 472	
	StandardHostValve.invoke(Request, Response) line: 168	
	ErrorReportValve.invoke(Request, Response) line: 98	
	AccessLogValve.invoke(Request, Response) line: 927	
	StandardEngineValve.invoke(Request, Response) line: 118	
	CoyoteAdapter.service(Request, Response) line: 407	
	Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 987	
	Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 579	
	JIoEndpoint$SocketProcessor.run() line: 309	
	ThreadPoolExecutor$Worker.runTask(Runnable) line: 897	
	ThreadPoolExecutor$Worker.run() line: 919	
	TaskThread(Thread).run() line: 736	

Tha same page has two forms but the same thing happens with a page of one form.

Well, I wish I could answer it better, but this does appear to be something for the Vaadin team to address.

I’ve never overridden the attach() method (just detach() to save customized settings). But AbstractField does show this for attach():

    @Override
    public void attach() {
        super.attach();
        if (actionManager != null) {
            actionManager.setViewer(getWindow());
        }

        if (!isListeningToPropertyEvents) {
            addPropertyListeners();
            if (!isModified() && isReadThrough()) {
                // Update value from data source
                [b]
discard();
[/b]
            }
        }
    }

It does show the call to discard() in there. Perhaps that’s new and causing the issue? Is the discard causing something to break? Normally, it just means to forget any cached changes and revert to the original data values. Not sure why it is called if it’s not modified though, since it seems if it’s not modified there wouldn’t be anything to discard.

I hope a Vaadin person can answer this for you!

Great, the forums ate my reply. Here’s a tldr version:

This is an unfortunate (and unforeseen) consequence of the way
ticket #6155
was implemented. discard() is called on attach() to refresh the potentially changed datasource value, as detached fields no longer listen to their data source’s value change events so as to avoid memory leaks. It is a bit unintuitive but doing it cleaner would have required a more extensive AbstractField refactoring (which will hopefully be done someday.)

However, the relevant code in discard() could be refactored into a private helper method that can be then also called from attach(), restoring the 6.7 semantics. Please open a
ticket
for the issue.

But…can I open tickets? It says “TICKET_CREATE privileges are required to perform this operation”

Just create a user account to http://dev.vaadin.com/

Done, thanks!

http://dev.vaadin.com/ticket/9181

Should be fixed in 6.8.3.

However, I must say it seems to me it doesn’t really make sense to override discard() to ask for confirmation – this should probably be done in the code (eg. event listener) that calls discard(), not in discard() itself.