Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
I'm re-writing the front end of our web application framework to use Vaadin instead of emitting its own HTML. Our framework has, for the most part, married up quite well with Vaadin's object model - I've only really needed to write adaptors with a few lines of code to get 70% of the functionality.
My framework has the concept of Forms and Instances (of those forms). Instances have a set of InstanceElements (instances of FormElements) which are the elements that are emitted to the browser. A simple example of a FormElement in our framework might be some simple markup with some dynamic content:
the corresponding InstanceElement is associated with an Instance and is capable of evaluating that dynamic content. Consider that the dynamic content might be something like java.lang.System.currentTimeMillis().
After a user has submitted new form data to the application, the dynamic content may have changed. I have code that'll work out which Components need repainting (and call requestRepaint() on them), but I have no means of invoking that code. Ideally I'd have a hook allowing me to invoke this code just after new values have been set from the browser and just after other events (such as button clicks), but just before the server submits changes back to the browser.
I took a look at TransactionListener and HttpServlerRequestListener, but both of these listeners are invoked just after the repaint. I've read AbstractCommunicationManager's doHandleUidlRequest(Request, Response, Callback) method and can't see anything obvious.
Any pointers would be greatly appreciated.
If you want to invoke some method on every HTTP request, the TransactionListener is the way to go.
The transactionStart method is invoked before every server request and therefore before changeVariables or render (repaint) function in any Component:
Ideally I'd have a hook allowing me to invoke this code just after new values have been set from the browser and just after other events (such as button clicks), but just before the server submits changes back to the browser.
This can / should made in component level. The changeVariables function is invoked for every component whose client-side state was changed. You should pick up the component (you have your own?) and override this to emit the events that eventually force the re-evaluation and call the requestRepaint.
( Note: The above is meant for components that you create yourself. In case of a stock components (like the Button) this is of course as simple as listening the events (Button.ClickListener interface). There are addListener methods for different types of events.)
The paintContent is invoked later by the event framework for every component that has been marked "dirty" using the requestRepaint() function.
Thanks for the response Sami. Unfortunately because the TransactionListener's end is called after Vaadin has repainted all the dirty components it doesn't suit. This is because some components may become dirty even if their values have not changed by the client.
But it's not so bad. I've found my own framework's code that works out what is dirty is reasonably efficient... so I'll invoke it for component that is updated. Ideally I'd only call it once at the end, but it probably won't matter that it runs more than once.
Glad you found a way around. Calling requestRepaint is quite cheap operation; it just marks the component in question and so that the data gets transfered to client in paint cycle. Even if components that do not necessarily need repainting it might be ok as log as they do not have lot of changes. Of course, this is a clear point of optimization if the app gets sluggish.