Open Artur- opened 2 months ago
Acceptance Criteria:
onHotswap
that is called from hotswap-agent-vaadin-plugin
onHotswap
method implementation delegates to corresponding hot swap methods in Flow and Hilla, depending on what is used in a project. - 5 SP (includes the previous point)hotswap-agent-vaadin-plugin
has still VaadinIntegration
class, but the logic in there is called only if the onHotswap
method is not found in Vaadin, otherwise the plugin does nothing, just calls the onHotswap
method. This is needed for backwards compatibility between further versions of HA plugin and older Vaadin versions (before 24.5) - 5 SPHillaPlugin
is removed (basically remove the whole module hilla-dev
) - 3 SPLet's not pick these changes to older maintained Vaadin branches. If this feature will be needed for older Vaadin versions or requested by Customers, let's do it, otherwise ignore it for now and let VaadinIntegration
class do the job.
Currently, Vaadin hotswap plugin reacts on @OnClassFileEvent
to update the route registry and @OnClassLoadEvent(REDEFINE)
to clear reflection cache and to trigger a browser page reload.
Hilla plugin reacts on OnClassLoadEvent(DEFINE and REDEFINE)
.
Vaadin plugin tries to batch file change events, instead of executing the logic immediately. I wonder if this could be applied to the other events as well.
So a common interface that should be implemented by Flow and Hilla (and in the future potentially also other parts of the platform) could be something like
public interface VaadinHotSwapper {
default void onClassFileEvent(VaadinService vaadinService,
Set<Class<?>> addedClasses, Set<Class<?>> modifiedClasses,
Set<Class<?>> removedClasses) {
}
default void onClassFileEvent(VaadinSession session,
Set<Class<?>> addedClasses, Set<Class<?>> modifiedClasses,
Set<Class<?>> removedClasses) {
}
default void onClassLoadEvent(VaadinService vaadinService,
boolean redefined, Set<Class<?>> classes) {
}
default void onClassLoadEvent(VaadinSession vaadinSession,
boolean redefined, Set<Class<?>> classes) {
}
default void onResourceFileEvent(VaadinService vaadinService,
Set<URI> addedResources, Set<URI> modifiedResources,
Set<URI> removedResources) {
}
default void onResourceFileEvent(VaadinSession vaadinSession,
Set<URI> addedResources, Set<URI> modifiedResources,
Set<URI> removedResources) {
}
}
I also added to the interface a method to react to @OnResourceFileEvent
.
The three events should be called for both application (VaadinService
) and active sessions (VaadinSession
) in case changes to classes may impact session related components (e.g. SessionRouteRegistry
).
On the Flow side, there will be a Hotswapper
component as well, that will be the entry point called by the agent whose aim is to dispatch the events to the VaadinHotSwapper
implementations (fetched with Lookup
?). The Hotswapper
should be initialized at VaadinService
initialization (only in development mode) and will implement SessionInitListener
and SessionDestroyListener
to track VaadinSession
s.
Why is it that OnClassFileEvent is used? Isn't that what often leads to race conditions as you do not know when the file has been compiled and is available on the classpath?
Vaadin plugin tries to batch file change events, instead of executing the logic immediately. I wonder if this could be applied to the other events as well.
When you edit the UI, I wonder if it isn't more important to get the changes in the browser as quickly as possible? I am not sure when you would edit multiple files at once.
In any case, the batching should be done in Vaadin then and not in the caller, so we can change it later on if needed
Why is it that OnClassFileEvent is used? Isn't that what often leads to race conditions as you do not know when the file has been compiled and is available on the classpath?
I don't know the reason. We should perhaps ask the guy who pushed this commit :wink:
Anyway, I think you are right on the potential issues with the file events.
Also, the DELETE
event doesn't seem to work properly; if I rename a class, I get a CREATE, MODIFY and DELETE
, but if I just delete it an exception is raised in Hotswap agent and the event does not reach the plugin.
So it would probably make sense to only react on @OnClassLoadEvent
and, for the current route registry updated logic consider DEFINE
as an added class and REDEFINED
as modified.
That said, we can most likely also drop the @OnResourceFileEvent
, unless it can be helpful in cases like updating the translation property files.
About batching, probably the reason was that with file events you can get different events for the same file (e,g, CREATE, MODIFY and DELETE
as said previously) for a single change, but the order seems not to be predictable.
So, as you propose, lets every single event to be propagated to the Vaadin component, and possibly handle a queue there
Describe your motivation
The Hotswap agent plugin at https://github.com/HotswapProjects/HotswapAgent/tree/master/plugin/hotswap-agent-vaadin-plugin implements support for hot reloading of various parts of Flow but it has the issue that it tries to support all Flow versions at the same time, and that it is an external project so it is always lagging behind when Flow gets new features. As it tries to support many Flow versions, the code becomes quite complex.
Describe the solution you'd like
Implement the same approach already tested in Hilla here https://github.com/vaadin/hilla/blob/main/packages/java/endpoint/src/main/java/com/vaadin/hilla/Hotswapper.java#L34 and here https://github.com/vaadin/hilla/blob/main/packages/java/hilla-dev/src/main/java/com/vaadin/hilla/devmode/hotswapagent/HillaPlugin.java
In other words, make the Hotswap Agent plugin call a Flow method when hotswapping has taken place without doing any filtering or trying to figure out what needs to be done. Let the
onHotswap
method in Flow decide what needs to be done due to reloading of the given class(es).This would have many benefits:
onHotswap
and different Flow versions can implement the method in different waysonHotswap
will become much simpler than what is in the hotswap agent plugin