Skip to content

Commit

Permalink
chore: Add possibility to register shutdown commands for development …
Browse files Browse the repository at this point in the history
…mode (#20054) (#20080)
  • Loading branch information
vaadin-bot authored Sep 28, 2024
1 parent 155fe15 commit 4e99d87
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
*/
package com.vaadin.flow.internal;

import java.io.Closeable;
import java.util.Optional;
import java.util.Set;

import com.vaadin.flow.di.Lookup;
import com.vaadin.flow.server.Command;
import com.vaadin.flow.server.VaadinContext;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.startup.VaadinInitializerException;
Expand Down Expand Up @@ -49,7 +51,7 @@ public interface DevModeHandlerManager {
* @param classes
* classes to check for npm- and js modules
* @param context
* servlet context we are running in
* Vaadin Context we are running in
*
* @throws VaadinInitializerException
* if dev mode can't be initialized
Expand Down Expand Up @@ -97,6 +99,14 @@ void initDevModeHandler(Set<Class<?>> classes, VaadinContext context)
*/
void setApplicationUrl(String applicationUrl);

/**
* Registers a command that will run when DevModeHandler is shut down
*
* @param command
* the command to run
*/
void registerShutdownCommand(Command command);

/**
* Gets the {@link DevModeHandler}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.vaadin.base.devserver;

import com.vaadin.flow.server.Command;
import jakarta.servlet.annotation.HandlesTypes;

import java.io.Closeable;
Expand Down Expand Up @@ -66,7 +67,7 @@ private static final class DevModeHandlerAlreadyStartedAttribute

private DevModeHandler devModeHandler;
private BrowserLauncher browserLauncher;
final private Set<Closeable> watchers = new HashSet<>();
private final Set<Command> shutdownCommands = new HashSet<>();

private String applicationUrl;
private boolean fullyStarted = false;
Expand Down Expand Up @@ -107,7 +108,6 @@ public void initDevModeHandler(Set<Class<?>> classes, VaadinContext context)

ApplicationConfiguration config = ApplicationConfiguration
.get(context);

startWatchingThemeFolder(context, config);
watchExternalDependencies(context, config);
setFullyStarted(true);
Expand All @@ -121,7 +121,7 @@ private void watchExternalDependencies(VaadinContext context,
File frontendFolder = FrontendUtils.getProjectFrontendDir(config);
File jarFrontendResourcesFolder = FrontendUtils
.getJarResourcesFolder(frontendFolder);
watchers.add(new ExternalDependencyWatcher(context,
registerWatcherShutdownCommand(new ExternalDependencyWatcher(context,
jarFrontendResourcesFolder));

}
Expand All @@ -146,7 +146,8 @@ private void startWatchingThemeFolder(VaadinContext context,
for (String themeName : activeThemes) {
File themeFolder = ThemeUtils.getThemeFolder(
FrontendUtils.getProjectFrontendDir(config), themeName);
watchers.add(new ThemeLiveUpdater(themeFolder, context));
registerWatcherShutdownCommand(
new ThemeLiveUpdater(themeFolder, context));
}
} catch (Exception e) {
getLogger().error("Failed to start live-reload for theme files", e);
Expand All @@ -158,15 +159,16 @@ public void stopDevModeHandler() {
devModeHandler.stop();
devModeHandler = null;
}
for (Closeable watcher : watchers) {
for (Command shutdownCommand : shutdownCommands) {
try {
watcher.close();
} catch (IOException e) {
getLogger().error("Failed to stop watcher "
+ watcher.getClass().getName(), e);
shutdownCommand.execute();
} catch (Exception e) {
getLogger().error("Failed to execute shut down command {}",
shutdownCommand.getClass().getName(), e);
}
}
watchers.clear();
shutdownCommands.clear();

}

@Override
Expand Down Expand Up @@ -196,6 +198,22 @@ private void setDevModeStarted(VaadinContext context) {
new DevModeHandlerAlreadyStartedAttribute());
}

private void registerWatcherShutdownCommand(Closeable watcher) {
registerShutdownCommand(() -> {
try {
watcher.close();
} catch (Exception e) {
getLogger().error("Failed to stop watcher {}",
watcher.getClass().getName(), e);
}
});
}

@Override
public void registerShutdownCommand(Command command) {
shutdownCommands.add(command);
}

/**
* Shows whether {@link DevModeHandler} has been already started or not.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@

package com.vaadin.flow.spring;

import com.vaadin.base.devserver.DevModeHandlerManagerImpl;
import com.vaadin.flow.server.Command;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextEvent;

import java.io.Closeable;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

Expand Down Expand Up @@ -78,6 +83,23 @@ void devModeStartupListener_contextDestroyAfterSpringContextClosed_shouldNotThro
"Expecting DevModeHandler to be stopped by DevModeHandlerManager, but it was not");
}

@Test
void shutdownCommandsShouldBeExecutedOnStoppingDevModeHandlerManager() {
AtomicReference<Boolean> watcherClosed = new AtomicReference<>(false);
DevModeHandlerManager devModeHandlerManager = new DevModeHandlerManagerImpl();

Closeable mockWatcher = () -> watcherClosed.set(true);
devModeHandlerManager.registerShutdownCommand(() -> {
try {
mockWatcher.close();
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
});
devModeHandlerManager.stopDevModeHandler();
Assertions.assertTrue(watcherClosed.get());
}

private static class MockDevModeHandlerManager
implements DevModeHandlerManager {

Expand Down Expand Up @@ -117,6 +139,11 @@ public void launchBrowserInDevelopmentMode(String url) {
@Override
public void setApplicationUrl(String applicationUrl) {
}

@Override
public void registerShutdownCommand(Command command) {

}
}

@TestConfiguration
Expand Down

0 comments on commit 4e99d87

Please sign in to comment.