本文介绍了为什么 Tomcat 无法显示实际的堆栈跟踪?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用GWT,我已将我的服务器部署到Tomcat.这工作正常,但是当 GWT 抛出异常时,Popup 会向客户端显示异常的堆栈跟踪.

在开发模式下,这工作正常.在 Tomcat 中,我得到以下堆栈跟踪.

为什么以及如何解决这个问题?

Unknown.Le(StackTraceCreator.java:168)Unknown.Jd(StackTraceCreator.java:421)Unknown.NT(Exception_FieldSerializer.java:16)Unknown.g1(SerializerBase.java:55)未知.b1(SerializerBase.java:112)Unknown.D$(AbstractSerializationStreamReader.java:119)Unknown.uAc(CustomException_FieldSerializer.java:39)Unknown.uBc(ServerSideException_FieldSerializer.java:12)Unknown.f1(SerializerBase.java:46)Unknown._0(SerializerBase.java:92)Unknown.D$(AbstractSerializationStreamReader.java:119)Unknown.B_(RequestCallbackAdapter.java:216)未知._o(Request.java:287)

使用@Christian Kuetbach 的回答后,我现在得到的是:

Unknown.com_google_gwt_core_client_impl_StackTraceCreator$CollectorEmulated_$fillInStackTrace__Lcom_google_gwt_core_client_impl_StackTraceCreator$CollectorEmulated_2Ljava_lang_Throwable_2V(StackTraceCreator.java:168)Unknown.java_lang_Throwable_Throwable__Ljava_lang_String_2Ljava_lang_Throwable_2V(StackTraceCreator.java:421)Unknown.com_google_gwt_user_client_rpc_StatusCodeException_StatusCodeException__ILjava_lang_String_2V(StatusCodeException.java:35)Unknown.com_google_gwt_user_client_rpc_impl_RequestCallbackAdapter_$onResponseReceived__Lcom_google_gwt_user_client_rpc_impl_RequestCallbackAdapter_2Lcom_google_gwt_http_client_Request_2Lcom_google_gwt_http_client_Response_2V(RequestCallbackAdapter.java:209)Unknown.com_google_gwt_http_client_Request_$fireOnResponseReceived__Lcom_google_gwt_http_client_Request_2Lcom_google_gwt_http_client_RequestCallback_2V(Request.java:287)Unknown.com_google_gwt_http_client_RequestBuilder$1_onReadyStateChange__Lcom_google_gwt_xhr_client_XMLHttpRequest_2V(RequestBuilder.java:395) Unknown.anonymous(XMLHttpRequest.java:287)

请帮忙!

解决方案

在 GWT 文档中找到所有信息有点困难,您需要设置去混淆日志记录,所以这里是简短版本:

在您的模块文件 (.gwt.xml) 中,添加:

<inherits name="com.google.gwt.logging.Logging"/><set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED"/><set-property name="compiler.stackMode" value="emulated"/><set-configuration-property name="compiler.emulatedStack.recordLineNumbers"值=真"/>

在客户端,使用类似

import java.util.logging.Logger;私有静态记录器 rootLogger = Logger.getLogger("");...rootLogger.log(Level.SEVERE, "我的消息", e);

您不必在客户端创建 RemoteLoggingServiceAsync 实例 - 它由记录器自动使用,因为我们指定了 <set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED"/>.

在服务器端,配置RemoteLoggingServiceImpl.您必须告诉它,它在哪里找到符号映射,在使用 GWT 编译器参数 -extra/path/to/myExtraDir 编译时将生成符号映射.我个人使用这种方法来覆盖 RemoteLoggingServiceImpl,以允许从 web.xml 的 <init-param>s

指定目录

package mypackage.server;公共类 ConfigurableRemoteLoggingServiceImpl 扩展 RemoteLoggingServiceImpl {@覆盖public void init(final ServletConfig config) 抛出 ServletException {超级初始化(配置);最终字符串symbolMapsDirectory =config.getInitParameter("symbolMapsDirectory");setSymbolMapsDirectory(symbolMapsDirectory);}}

web.xml中,像这样注册

<servlet-name>remoteLogging</servlet-name><servlet-class>mypackage.server.ConfigurableRemoteLoggingServiceImpl</servlet-class><初始化参数><param-name>symbolMapsDirectory</param-name><param-value>/path/to/myExtraDir/mymodulename/symbolMaps</param-value></init-param></servlet><servlet-mapping><servlet-name>remoteLogging</servlet-name><url-pattern>/mymodulename/remote_logging</url-pattern></servlet-mapping>

用你自己的值替换/path/to/myExtraDirmymodulenamemypackage,不要忘记调用GWT编译器使用 -extra 参数(请注意,您不不必使用 -style PRETTY 或 DETAILED,它也适用于 OBF).保留所有生成的符号映射:没有它们,反混淆将不起作用.由于每个新版本都会自动获得一个唯一的名称,因此您可以在构建时将它们全部收集到一个安全的中心位置.

Using GWT, I have deployed my server into Tomcat. This works fine, but when GWT throws an exception, a Popup shows the client the stack trace of the exception.

In dev mode, this works fine. In Tomcat, I get the below stack trace.

Why and how do you fix this?

After using @Christian Kuetbach's answer, here is what I get now:

Please Help!

解决方案

It's a bit difficult to find all the information in the GWT docs, which you need to setup de-obfuscated logging, so here's the short version:

In your module file (.gwt.xml), add:

<inherits name="com.google.gwt.logging.Logging"/>
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="compiler.stackMode" value="emulated" />
<set-configuration-property name="compiler.emulatedStack.recordLineNumbers"
     value="true" />

On the client side, use something like

import java.util.logging.Logger;

private static Logger rootLogger = Logger.getLogger("");
...
rootLogger.log(Level.SEVERE, "My message", e);

You don't have to create a RemoteLoggingServiceAsync instance on the client side - it's used automatically by the logger, because we specified <set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />.

On the server side, configure the RemoteLoggingServiceImpl. You will have to tell it, where it finds the symbolMaps, which will be generated when compiling with the GWT compiler argument -extra /path/to/myExtraDir. I personally use the approach to override RemoteLoggingServiceImpl, to allow specifying the directory from web.xml's <init-param>s

package mypackage.server;

public class ConfigurableRemoteLoggingServiceImpl extends RemoteLoggingServiceImpl {

  @Override
  public void init(final ServletConfig config) throws ServletException {
    super.init(config);

    final String symbolMapsDirectory =
        config.getInitParameter("symbolMapsDirectory");
    setSymbolMapsDirectory(symbolMapsDirectory);
  }
}

In web.xml, register it like

<servlet>
    <servlet-name>remoteLogging</servlet-name>
    <servlet-class>mypackage.server.ConfigurableRemoteLoggingServiceImpl</servlet-class>

  <init-param>
    <param-name>symbolMapsDirectory</param-name>
    <param-value>/path/to/myExtraDir/mymodulename/symbolMaps</param-value>
  </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>remoteLogging</servlet-name>
    <url-pattern>/mymodulename/remote_logging</url-pattern>
</servlet-mapping>

Replace /path/to/myExtraDir, mymodulename and mypackage with your own values, and don't forget to call the GWT compiler with the -extra argument (Note that you you don't have to use -style PRETTY or DETAILED, it also works with OBF). Keep all generated symbolMaps: Without them, deobfuscation will not work. As every new version gets a unique name automatically, you can collect them all in a safe central place when building.

这篇关于为什么 Tomcat 无法显示实际的堆栈跟踪?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 20:11