Till May this year, I was using GWT 2.5.1 and simple DevMode and was able to send obfuscated exceptions with stack traces to server and deobfuscate them there using symbol maps as per this brilliant article. This helped me a lot.
Since June I successfully switched to GWT 2.6.1 and SuperDevMode which provides quite decent experience comparing to simple DevMode and is simpler to use.
However, I noticed that my stack traces are not deobfuscated correctly on the server no more. I keep getting obfuscated stack traces even after deobfuscation.
Following is the related contents of *.gwt.xml file:
<module rename-to="somemodule">
<!-- inherits, stylesheet, entry-point, source elements are going here -->
<add-linker name="xsiframe" />
<extend-property name="locale" values="uk" />
<set-property-fallback name="locale" value="uk" />
<set-property name="compiler.stackMode" value="emulated" />
<set-configuration-property name="compiler.emulatedStack.recordLineNumbers" value="true" />
<set-property name="gwt.logging.logLevel" value="INFO" />
<set-property name="gwt.logging.enabled" value="TRUE" />
<set-property name="gwt.logging.developmentModeHandler" value="ENABLED" />
<set-property name="gwt.logging.systemHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<set-property name="gwt.logging.consoleHandler" value="ENABLED" />
<set-property name="gwt.logging.firebugHandler" value="ENABLED" />
</module>
Following is server-side code that handles client side exceptions:
import static com.google.gwt.user.client.rpc.RpcRequestBuilder.STRONG_NAME_HEADER;
import com.google.gwt.core.client.impl.SerializableThrowable;
import com.google.gwt.logging.server.StackTraceDeobfuscator;
// ....
@Override
public void logClientException(final SerializableThrowable ex, final String userAgent, final String platform, final String moduleName) {
final HttpServletRequest request = getThreadLocalRequest();
final String symbolMapsDirectory = "webapps/" + getTomcatWebappFolder(request.getServletContext()) + "/WEB-INF/deploy/" + moduleName + "/symbolMaps";
final String permutationName = request.getHeader(STRONG_NAME_HEADER);
final Throwable original = new StackTraceDeobfuscator(symbolMapsDirectory).deobfuscateThrowable(ex.getThrowable(), permutationName);
logClientException(original, userAgent, platform);
}
Did I omit something when transferred from GWT 2.5.1 to GWT 2.6.1?
Thanks a lot in advance for any help!
This is an unfortunate known issue. See here and here.
The problem is that with each recompile an entire new incremental directory tree gets created (see the compile-1, compile-2 etc subdirs). Hence the runnning application server (the one that hosts your servlets) will not be able to pick up the right compile-x/extras/<module-name>/symbolMaps directory to use with a call to setSymbolMapsDirectory (as @Vadim pointed out). And of course, is a quite a PITA to copy such symbolMaps in the expected directory each time you recompile (and I'm not even sure if it will work wrt permutation names).
This was the same for GWT-RPC at the beginning of the SuperDevMode era, but with the difference that the codeserver (SDM) now exposes all those *.gwt.rpc output files directly and if the gwt.codeserver.port java flag is used, your servlets will download policy files automatically (only in localhost, and with GTW >= 2.5.1).
Anyway, the point is to let the codeserver expose/serve also the symbolMaps files (which is already somehow does, by hitting http://localhost:9876/sourcemaps/<module-name>/gwtSourceMap.json but only for sourcemaps and not in a StackTraceCreator comprehensible way) in some way, as descibed in the first issue.
Fortunately stacktraces are not that bad to live with on development.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With