Skip to content

Commit cc51669

Browse files
committed
better error print for jooby run
1 parent 4a59918 commit cc51669

5 files changed

Lines changed: 87 additions & 18 deletions

File tree

modules/jooby-maven-plugin/src/main/java/io/jooby/maven/RunMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public class RunMojo extends AbstractMojo {
160160
joobyRun.start();
161161
} catch (MojoExecutionException | MojoFailureException x) {
162162
throw x;
163-
} catch (Exception x) {
163+
} catch (Throwable x) {
164164
throw new MojoFailureException("jooby-run resulted in exception", x);
165165
}
166166
}

modules/jooby-netty/src/main/java/io/jooby/netty/Netty.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ public class Netty extends Server.Base {
128128
}
129129

130130
@Nonnull @Override public synchronized Server stop() {
131-
System.out.println("ssss");
132131
fireStop(applications);
133132
if (acceptor != null) {
134133
acceptor.shutdownGracefully();

modules/jooby-run/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<dependency>
1717
<groupId>io.jooby</groupId>
1818
<artifactId>jooby</artifactId>
19+
<version>${jooby.version}</version>
1920
<!-- Scope MUST BE provided. See io.jooby.run.ServerRef -->
2021
<scope>provided</scope>
2122
</dependency>

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

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.slf4j.LoggerFactory;
1616

1717
import java.io.IOException;
18+
import java.lang.reflect.InvocationTargetException;
1819
import java.nio.file.ClosedWatchServiceException;
1920
import java.nio.file.Files;
2021
import java.nio.file.Path;
@@ -65,25 +66,73 @@ private static class AppModule {
6566
this.contextClassLoader = contextClassLoader;
6667
}
6768

68-
public void start() {
69+
public Exception start() {
6970
try {
70-
System.setProperty("___jooby_run_hook__", SERVER_REF);
71-
// Track the number of restarts
72-
System.setProperty("joobyRun.counter", Integer.toString(counter++));
73-
7471
module = loader.loadModule(conf.getProjectName());
7572
ModuleClassLoader classLoader = module.getClassLoader();
7673
Thread.currentThread().setContextClassLoader(classLoader);
7774

75+
if (counter == 0) {
76+
// main class must exists
77+
module.getClassLoader().loadClass(conf.getMainClass());
78+
}
79+
80+
System.setProperty("___jooby_run_hook__", SERVER_REF);
81+
// Track the number of restarts
82+
System.setProperty("joobyRun.counter", Integer.toString(counter++));
83+
7884
module.run(conf.getMainClass(),
7985
new String[]{"server.port=" + conf.getPort(), "server.join=false"});
80-
81-
} catch (Exception x) {
82-
logger.error("execution of {} resulted in exception", conf.getMainClass(),
83-
withoutReflection(x));
86+
} catch (ClassNotFoundException x) {
87+
String message = x.getMessage();
88+
if (message.trim().startsWith(conf.getMainClass())) {
89+
logger.error(
90+
"Application class: '{}' not found. Possible solutions:\n 1) Make sure class exists\n 2) Class name is correct (no typo)",
91+
conf.getMainClass());
92+
// We must exit the JVM, due it is impossible to guess the main application.
93+
return new ClassNotFoundException(conf.getMainClass());
94+
} else {
95+
printErr(x);
96+
}
97+
} catch (Throwable x) {
98+
printErr(x);
8499
} finally {
85100
Thread.currentThread().setContextClassLoader(contextClassLoader);
86101
}
102+
// In theory: application started successfully, then something went wrong. Still, users
103+
// can fix the problem and recompile.
104+
return null;
105+
}
106+
107+
private void printErr(Throwable source) {
108+
Throwable cause = withoutReflection(source);
109+
System.out.println("CAUSE " + cause);
110+
StackTraceElement[] stackTrace = cause.getStackTrace();
111+
int truncateAt = stackTrace.length;
112+
for (int i = 0; i < stackTrace.length; i++) {
113+
StackTraceElement it = stackTrace[i];
114+
if (it.getClassName().equals("org.jboss.modules.Module")) {
115+
truncateAt = i;
116+
}
117+
}
118+
if (truncateAt != stackTrace.length) {
119+
StackTraceElement[] cleanstack = new StackTraceElement[truncateAt];
120+
System.arraycopy(stackTrace, 0, cleanstack, 0, truncateAt);
121+
cause.setStackTrace(cleanstack);
122+
}
123+
logger.error("execution of {} resulted in exception", conf.getMainClass(), cause);
124+
125+
// is fatal?
126+
if (isFatal(source) || isFatal(cause)) {
127+
sneakyThrow0(source);
128+
}
129+
}
130+
131+
private boolean isFatal(Throwable cause) {
132+
return cause instanceof InterruptedException
133+
|| cause instanceof LinkageError
134+
|| cause instanceof ThreadDeath
135+
|| cause instanceof VirtualMachineError;
87136
}
88137

89138
public void restart() {
@@ -97,10 +146,13 @@ public void close() {
97146
}
98147

99148
private Throwable withoutReflection(Throwable cause) {
100-
while (cause instanceof ReflectiveOperationException) {
101-
cause = cause.getCause();
149+
Throwable it = cause;
150+
Throwable prev = cause;
151+
while (it instanceof InvocationTargetException) {
152+
prev = it;
153+
it = it.getCause();
102154
}
103-
return cause;
155+
return it == null ? prev : it;
104156
}
105157

106158
private void unloadModule() {
@@ -192,9 +244,9 @@ public boolean addResource(Path path) {
192244
/**
193245
* Start the application.
194246
*
195-
* @throws Exception If something goes wrong.
247+
* @throws Throwable If something goes wrong.
196248
*/
197-
public void start() throws Exception {
249+
public void start() throws Throwable {
198250
this.watcher = newWatcher();
199251
try {
200252
logger.debug("project: {}", toString());
@@ -205,8 +257,14 @@ public void start() throws Exception {
205257
ExtModuleLoader loader = new ExtModuleLoader(finders);
206258
module = new AppModule(logger, loader, Thread.currentThread().getContextClassLoader(),
207259
options);
208-
module.start();
209-
watcher.watch();
260+
Exception error = module.start();
261+
if (error == null) {
262+
watcher.watch();
263+
} else {
264+
// exit
265+
shutdown();
266+
throw error;
267+
}
210268
} catch (ClosedWatchServiceException expected) {
211269
logger.trace("Watcher.close resulted in exception", expected);
212270
}
@@ -277,4 +335,9 @@ private void onFileChange(DirectoryChangeEvent.EventType kind, Path path) {
277335
}
278336
}
279337
}
338+
339+
@SuppressWarnings("unchecked")
340+
private static <E extends Throwable> void sneakyThrow0(final Throwable x) throws E {
341+
throw (E) x;
342+
}
280343
}

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,12 @@
287287
<version>${jooby.version}</version>
288288
</dependency>
289289

290+
<dependency>
291+
<groupId>io.jooby</groupId>
292+
<artifactId>jooby-run</artifactId>
293+
<version>${jooby.version}</version>
294+
</dependency>
295+
290296
<dependency>
291297
<groupId>io.jooby</groupId>
292298
<artifactId>jooby-gradle-plugin</artifactId>

0 commit comments

Comments
 (0)