Skip to content

Commit c846fbe

Browse files
committed
jooby-run: class changes are not reflected on restarts fix #3075
- we need to `relink` jars module after unload
1 parent 7517053 commit c846fbe

File tree

4 files changed

+54
-18
lines changed

4 files changed

+54
-18
lines changed

jooby/src/main/java/io/jooby/SneakyThrows.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
package io.jooby;
77

8+
import edu.umd.cs.findbugs.annotations.NonNull;
9+
810
/**
911
* Collection of throwable interfaces to simplify exception handling on lambdas.
1012
*
@@ -1174,13 +1176,12 @@ Consumer8<V1, V2, V3, V4, V5, V6, V7, V8> throwingConsumer(
11741176
* @return A dummy RuntimeException; this method never returns normally, it <em>always</em> throws
11751177
* an exception!
11761178
*/
1177-
public static RuntimeException propagate(final Throwable x) {
1179+
public static @NonNull RuntimeException propagate(final Throwable x) {
11781180
if (x == null) {
11791181
throw new NullPointerException("x");
11801182
}
11811183

1182-
sneakyThrow0(x);
1183-
return null;
1184+
throw sneakyThrow0(x);
11841185
}
11851186

11861187
/**
@@ -1206,7 +1207,7 @@ public static boolean isFatal(Throwable x) {
12061207
* @throws E Exception to throw.
12071208
*/
12081209
@SuppressWarnings("unchecked")
1209-
private static <E extends Throwable> void sneakyThrow0(final Throwable x) throws E {
1210+
private static <E extends Throwable> E sneakyThrow0(final Throwable x) throws E {
12101211
throw (E) x;
12111212
}
12121213
}

modules/jooby-run/src/main/java/io/jooby/internal/run/JoobyModuleFinder.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,18 @@ public class JoobyModuleFinder implements ModuleFinder {
3030
private final Set<Path> classes;
3131
private final Set<Path> resources;
3232
private final Set<Path> jars;
33-
private final String name;
33+
private final String main;
34+
private final Set<Path> watchDirs;
3435

35-
public JoobyModuleFinder(String name, Set<Path> classes, Set<Path> resources, Set<Path> jars) {
36-
this.name = name;
36+
public JoobyModuleFinder(
37+
String name, Set<Path> classes, Set<Path> resources, Set<Path> jars, Set<Path> watchDirs) {
38+
this.main = name;
3739
this.classes = classes;
3840
this.resources = resources;
3941
this.jars = new LinkedHashSet<>(resources.size() + 1);
4042
this.jars.add(joobyRunHook(getClass()));
4143
this.jars.addAll(jars);
44+
this.watchDirs = watchDirs;
4245
}
4346

4447
/**
@@ -59,17 +62,36 @@ static Path joobyRunHook(Class loader) {
5962

6063
@Override
6164
public ModuleSpec findModule(String name, ModuleLoader delegateLoader) {
62-
if (this.name.equals(name)) {
65+
var resources = resources(name);
66+
if (resources == null) {
67+
return null;
68+
}
69+
return ModuleSpecHelper.create(name, resources, dependencies(name, true));
70+
}
71+
72+
public Set<String> dependencies(String name) {
73+
return dependencies(name, false);
74+
}
75+
76+
private Set<String> dependencies(String name, boolean addResources) {
77+
if (this.main.equals(name)) {
6378
// class only; depends on resources + jars
64-
return ModuleSpecHelper.create(name, classes, Set.of(RESOURCES, JARS));
65-
} else if (RESOURCES.equals(name)) {
66-
// resources only;
67-
return ModuleSpecHelper.create(name, resources, emptySet());
79+
return addResources ? Set.of(RESOURCES, JARS) : Set.of(JARS);
6880
} else if (JARS.equals(name)) {
69-
// jars only; depends on resources
70-
return ModuleSpecHelper.create(name, jars, Set.of(RESOURCES));
81+
// jars depends on main when reflection is required (hibernate, jackson, quartz);
82+
return addResources ? Set.of(RESOURCES, main) : Set.of(main);
7183
}
84+
return emptySet();
85+
}
7286

87+
private Set<Path> resources(String name) {
88+
if (this.main.equals(name)) {
89+
return classes;
90+
} else if (RESOURCES.equals(name)) {
91+
return resources;
92+
} else if (JARS.equals(name)) {
93+
return jars;
94+
}
7395
return null;
7496
}
7597

@@ -79,6 +101,8 @@ public String toString() {
79101
+ classes.stream().map(Path::toString).collect(joining(File.pathSeparator))
80102
+ "\nresources: "
81103
+ resources.stream().map(Path::toString).collect(joining(File.pathSeparator))
104+
+ "\nwatchDirs: "
105+
+ watchDirs.stream().map(Path::toString).collect(joining(File.pathSeparator))
82106
+ "\njars: "
83107
+ jars.stream().map(Path::getFileName).map(Path::toString).collect(joining(", "));
84108
}

modules/jooby-run/src/main/java/io/jooby/internal/run/JoobyModuleLoader.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,27 @@
66
package io.jooby.internal.run;
77

88
import org.jboss.modules.Module;
9-
import org.jboss.modules.ModuleFinder;
109
import org.jboss.modules.ModuleLoader;
1110

11+
import io.jooby.SneakyThrows;
12+
1213
public class JoobyModuleLoader extends ModuleLoader {
1314

14-
public JoobyModuleLoader(ModuleFinder finder) {
15+
public JoobyModuleLoader(JoobyModuleFinder finder) {
1516
super(finder);
1617
}
1718

18-
public void unload(String name, final Module module) {
19+
protected JoobyModuleFinder joobyModuleFinder() {
20+
return (JoobyModuleFinder) getFinders()[0];
21+
}
22+
23+
public void unload(String name, Module module) {
1924
super.unloadModuleLocal(name, module);
25+
var finder = joobyModuleFinder();
26+
// relink any dependency
27+
finder.dependencies(name).stream()
28+
.map(super::findLoadedModuleLocal)
29+
.forEach(SneakyThrows.throwingConsumer(super::relink));
2030
}
2131

2232
public String toString() {

modules/jooby-run/src/main/java/io/jooby/run/JoobyRun.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@ public void start() throws Throwable {
373373
.collect(Collectors.joining(File.pathSeparator));
374374
System.setProperty("jooby.run.classpath", classPathString);
375375
var finder =
376-
new JoobyModuleFinder(options.getProjectName(), classes, resources, dependencies);
376+
new JoobyModuleFinder(
377+
options.getProjectName(), classes, resources, dependencies, watchDirs.keySet());
377378

378379
module =
379380
new AppModule(

0 commit comments

Comments
 (0)