Skip to content

Instantly share code, notes, and snippets.

@theigl
Last active July 16, 2018 10:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theigl/6ff4a505eac8f166b9bd079017884474 to your computer and use it in GitHub Desktop.
Save theigl/6ff4a505eac8f166b9bd079017884474 to your computer and use it in GitHub Desktop.
HotswapAgent and Wicket
autoHotswap=false
extraClasspath=\
./src/main/resources;\
./src/main/java;\
../other-module-1/target/classes;\
../other-module-2/target/classes;\
disabledPlugins=Hibernate,Spring,Tomcat,ResteasyRegistry
pluginPackages={PACKAGE_OF_WICKET_PLUGIN_JAVA}
LOGGER=info
import org.hotswap.agent.annotation.Init;
import org.hotswap.agent.annotation.OnClassLoadEvent;
import org.hotswap.agent.annotation.OnResourceFileEvent;
import org.hotswap.agent.annotation.Plugin;
import org.hotswap.agent.command.Scheduler;
import org.hotswap.agent.javassist.CannotCompileException;
import org.hotswap.agent.javassist.CtClass;
import org.hotswap.agent.javassist.NotFoundException;
import org.hotswap.agent.logging.AgentLogger;
import org.hotswap.agent.util.PluginManagerInvoker;
import java.lang.reflect.Method;
/**
* Wicket support for hotswap
*/
@Plugin(name = "Wicket Plugin", testedVersions = "8.0.0")
public class WicketPlugin {
private static final AgentLogger LOGGER = AgentLogger.getLogger(WicketPlugin.class);
@Init
Scheduler scheduler;
@Init
ClassLoader appClassLoader;
private Object wicketApplication;
@OnClassLoadEvent(classNameRegexp = "org.apache.wicket.protocol.http.WebApplication")
public static void init(CtClass ctClass) throws NotFoundException, CannotCompileException {
String src = PluginManagerInvoker
.buildInitializePlugin(WicketPlugin.class);
src += PluginManagerInvoker.buildCallPluginMethod(WicketPlugin.class,
"registerApplication", "this", "java.lang.Object");
ctClass.getDeclaredConstructor(new CtClass[0]).insertAfter(src);
LOGGER.info("Initialized Wicket plugin");
}
public void registerApplication(Object wicketApplication) {
this.wicketApplication = wicketApplication;
LOGGER.info("Plugin {} initialized for application {}", getClass(),
wicketApplication);
}
@OnResourceFileEvent(path = "/", filter = ".*.properties")
public void clearLocalizerCaches() {
scheduler.scheduleCommand(this::clearCache);
}
private void clearCache() {
LOGGER.debug("Refreshing Wicket resource bundles.");
try {
final Object localizer = getLocalizer();
final Method clearCacheMethod = resolveClass("org.apache.wicket.Localizer")
.getDeclaredMethod("clearCache");
clearCacheMethod.invoke(localizer);
} catch (Exception e) {
LOGGER.error("Error clear Wicket resource bundles cache", e);
}
}
private Object getLocalizer() {
try {
final Method getResourceSettingsMethod = resolveClass("org.apache.wicket.Application")
.getDeclaredMethod("getResourceSettings");
final Method getLocalizerMethod = resolveClass("org.apache.wicket.settings.ResourceSettings")
.getDeclaredMethod("getLocalizer");
final Object resourceSettings = getResourceSettingsMethod.invoke(wicketApplication);
return getLocalizerMethod.invoke(resourceSettings);
} catch (Exception e) {
LOGGER.error("Error getting Wicket localizer", e);
return null;
}
}
private Class<?> resolveClass(String name) throws ClassNotFoundException {
return Class.forName(name, true, appClassLoader);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment