【问题标题】:GWT server side validation and RPC serializationGWT 服务器端验证和 RPC 序列化
【发布时间】:2017-03-24 15:07:41
【问题描述】:

我可以在我的异步回调返回值中使用 ConstraintViolation 或 ConstraintViolationException 对象与 RPC (GWT 2.5) 吗?

我首先尝试了 ConstraintViolation,而 GWT 不希望这样做,因为(我认为)ConstraintViolation 没有无参数构造函数。

然后我尝试了 ConstraintViolationException,但由于另一个原因,它也不起作用(请参阅下面的跟踪)。

我是否绝对必须捕获异常 (ConstraintViolationException) 而不是使用返回值?

com.google.gwt.user.client.rpc.SerializationException: Type 'org.hibernate.validator.engine.ConstraintViolationImpl' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = ConstraintViolationImpl{interpolatedMessage='{contact.validcompanyorperson}', propertyPath=, rootBeanClass=class com.mycompany.shared.foo.bar.MyBean, messageTemplate='{contact.validcompanyorperson}'}
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:667)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
    at com.google.gwt.user.client.rpc.core.java.util.Collection_CustomFieldSerializerBase.serialize(Collection_CustomFieldSerializerBase.java:44)
    at com.google.gwt.user.client.rpc.core.java.util.HashSet_CustomFieldSerializer.serialize(HashSet_CustomFieldSerializer.java:39)
    at com.google.gwt.user.client.rpc.core.java.util.HashSet_CustomFieldSerializer.serializeInstance(HashSet_CustomFieldSerializer.java:51)
    at com.google.gwt.user.client.rpc.core.java.util.HashSet_CustomFieldSerializer.serializeInstance(HashSet_CustomFieldSerializer.java:28)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeImpl(ServerSerializationStreamWriter.java:788)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:669)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
    at javax.validation.ConstraintViolationException_CustomFieldSerializer.serialize(ConstraintViolationException_CustomFieldSerializer.java:49)
    at javax.validation.ConstraintViolationException_CustomFieldSerializer.serializeInstance(ConstraintViolationException_CustomFieldSerializer.java:72)
    at javax.validation.ConstraintViolationException_CustomFieldSerializer.serializeInstance(ConstraintViolationException_CustomFieldSerializer.java:28)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeImpl(ServerSerializationStreamWriter.java:788)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:669)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:153)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:587)
    at com.google.gwt.user.server.rpc.RPC.encodeResponse(RPC.java:605)
    at com.google.gwt.user.server.rpc.RPC.encodeResponseForSuccess(RPC.java:471)
    at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:563)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
    at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1083)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:640)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

20161114 更新:我没主意了。我尝试在自己的源文件中复制 ConstraintViolationImpl (hibernate-validator-4.1.0's),然后通过网络发送。不起作用,因为“com.google.gwt.user.client.rpc.SerializationException: Type 'com.mycompany.common.gwt.ui.shared.GwtConstraintViolation' 未包含在可以通过此序列化的类型集中无法加载 SerializationPolicy 或其 Class 对象”。更多信息如下(Eclipse 开发模式控制台)。

[DEBUG] [foo_bar] - Rebinding com.mycompany.IHM.client.gwt.foo.client.service.FooService
    [DEBUG] [foo_bar] - Invoking generator com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator
        [DEBUG] [foo_bar] - Generating client proxy for remote service interface 'com.mycompany.IHM.client.gwt.foo.client.service.FooService'
            [DEBUG] [foo_bar] - Analyzing 'com.mycompany.IHM.client.gwt.foo.client.service.FooService' for serializable types
                [DEBUG] [foo_bar] - Analyzing methods:
                    [DEBUG] [foo_bar] - public abstract java.util.Set<com.mycompany.commun.gwt.ui.shared.GwtConstraintViolation<com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean>> getConstraintViolations2(com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean saisie)
                        [DEBUG] [foo_bar] - Return type: java.util.Set<com.mycompany.commun.gwt.ui.shared.GwtConstraintViolation<com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean>>
                            [DEBUG] [foo_bar] - java.util.Set<com.mycompany.commun.gwt.ui.shared.GwtConstraintViolation<com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean>>
                                [DEBUG] [foo_bar] - Verifying instantiability
                                    [DEBUG] [foo_bar] - java.util.TreeSet<com.mycompany.commun.gwt.ui.shared.GwtConstraintViolation<com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean>>
                                        [DEBUG] [foo_bar] - Checking parameters of 'java.util.TreeSet<com.mycompany.commun.gwt.ui.shared.GwtConstraintViolation<com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean>>'
                                            [DEBUG] [foo_bar] - Checking type argument 0 of type 'java.util.TreeSet<E>' because it is directly exposed in this type or in one of its subtypes
                                                [DEBUG] [foo_bar] - com.mycompany.commun.gwt.ui.shared.GwtConstraintViolation<com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean>
                                                    [DEBUG] [foo_bar] - Verifying instantiability
                                                        [DEBUG] [foo_bar] - com.mycompany.commun.gwt.ui.shared.GwtConstraintViolation<com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean>
                                                            [DEBUG] [foo_bar] - Analyzing the fields of type 'com.mycompany.commun.gwt.ui.shared.GwtConstraintViolation<com.mycompany.IHM.client.gwt.foo.shared.pack.MyBean>' that qualify for serialization
                                                                [DEBUG] [foo_bar] - private javax.validation.Path propertyPath
                                                                    [DEBUG] [foo_bar] - javax.validation.Path
                                                                        [DEBUG] [foo_bar] - Verifying instantiability
                                                                            [DEBUG] [foo_bar] - com.google.gwt.validation.client.impl.PathImpl
                                                                                [DEBUG] [foo_bar] - Analyzing the fields of type 'com.google.gwt.validation.client.impl.PathImpl' that qualify for serialization
                                                                                    [WARN] [foo_bar] - Field 'private final java.util.List<javax.validation.Path.Node> nodes' will not be serialized because it is final

GwtConstraintViolation 被定义为“公共类 GwtConstraintViolation 实现 ConstraintViolation, IsSerializable”(内容是从 Hibernate Validator 复制粘贴)。我已经注释掉了 Object 字段,因为我知道 GWT 不喜欢这样。

【问题讨论】:

  • 您是否尝试过为自己的 ConstraintViolationException 实现添加默认构造函数?
  • 我已经完全放弃了异常,并返回了一组 ConstraintViolation(这是一样的,ConstraintViolationException 只不过是一个包装类)。是的,GwtConstraintViolation 有一个无参数的构造函数。
  • GWT 的 ConstraintViolationImpl 的 CustomSerializer 似乎丢弃了大量信息(请参阅 github.com/vaadin/gwt/blob/master/user/src/org/hibernate/…)。我的编辑器/驱动程序生成的代码似乎需要其中一些字段才能正确显示错误消息(我已经测试验证客户端相同的约束,它们工作。然后,客户端大小,我从完整构建“假”不完整 ConstrainViolation ConstraintViolation 对象:不起作用)。我将不得不看看我可以在没有哪些领域工作。
  • 为了让我的 ConstraintViolation 显示正常,我不仅需要路径和消息集,还需要“rootbean”。我最终为 PathImpl 和 Node 创建了自定义实现,否则我无法让 GWT 序列化它们。最后,即使通过比较“本机” ConstraintViolation 对象和反序列化对象,它也不起作用(未显示错误消息),每个字段似乎都是相同的。唯一的区别是反序列化的对象不是 GWT 的 PathImpl 而是我的(节点相同)。我将不得不严格地在客户端(来自服务器端信息)构建 ConstraintViolation,但这很糟糕。

标签: java gwt bean-validation gwt-rpc


【解决方案1】:

不,根据GWT documentation,您可以从 RPC 方法中抛出异常。

具体的处理方式取决于异常的类型:

  • 对于已检查的异常,只需在方法签名中将它们列为throws 就足够了
  • 未经检查的异常被包装到InvocationException 中。原始异常记录在服务器端。

我猜在你的情况下ConstraintViolationException 是一个未经检查的异常。它应该在客户端作为 InvocationException “可捕获”。您发布的堆栈跟踪应该只是服务器端的日志输出。

如果您想在客户端进一步处理未经检查的异常,我建议您将其包装到自己的已检查异常中并从您的 RPC 方法中抛出。

【讨论】:

  • 这都是真的(我知道这一点),但这不是我的问题所在。我想做的就是在我的 RPC 方法签名中包含 ConstraintViolation、ConstraintViolationException 或任何其他具有等效功能的类型,而不会弄乱我当前的 onFailure / onSuccess 逻辑。我的印象是 GWT RPC 方法可以抛出 GWT 拒绝作为返回值的类型? (令我惊讶的是,这非常违反直觉)。是的,我正在尝试更新我的代码以使用异常,因为无论如何我似乎别无选择(很快就会添加更新)。
  • 您是否尝试在您的方法的throws-Part 中列出 ConstraintViolationException?
  • 它给了我同样的错误:((我得到一个 StatusCodeException 客户端而不是预期的 ConstraintViolationException)。我不明白,即使 GWT 官方示例(参见gwtproject.org/doc/latest/DevGuideValidation.html)也是这样工作的!
  • 如何将 ConstraintViolationException 包装在您自己的已检查异常中?
  • 是的,我看到它已在另一个线程 (stackoverflow.com/a/7870455/1130594) 中提出,非常好的建议(我认为它会起作用),我正在尝试。仍然感到惊讶 GWT 页面文档完全忽略了这个问题。随便:)
猜你喜欢
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
  • 2013-03-09
  • 1970-01-01
  • 2012-04-18
  • 2012-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多