0
votes

Can I use ConstraintViolation or ConstraintViolationException objects in my async callback return values with RPC (GWT 2.5) ?

I have first tried ConstraintViolation and GWT didn't want that because (I think) ConstraintViolation does not have a parameterless constructor.

I then tried ConstraintViolationException and it does not work either, for another reason (see below trace).

Do I absolutely have to catch exceptions (ConstraintViolationException) instead of using return values ?

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 UPDATE: I'm out of ideas. I have tried copying ConstraintViolationImpl (hibernate-validator-4.1.0's) in my own source file, sending that over the wire. Won't work because "com.google.gwt.user.client.rpc.SerializationException: Type 'com.mycompany.common.gwt.ui.shared.GwtConstraintViolation' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded". More information below (Eclipse Development Mode console).

[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 is defined as 'public class GwtConstraintViolation implements ConstraintViolation, IsSerializable' (Content is copy-paste from Hibernate Validator). I have commented out the Object field because I know GWT does not like that.

1
Have you tried adding a default constructor to you own implementation of ConstraintViolationException? - Bob
I have dropped the exceptions altogether and am returning a Set of ConstraintViolation (this is the same, ConstraintViolationException being nothing other than a wrapper class). Yep, GwtConstraintViolation has a parameterless constructor. - Toto
It appears GWT's CustomSerializer for ConstraintViolationImpl discards a fair amount of info (see github.com/vaadin/gwt/blob/master/user/src/org/hibernate/…). It seems some of these fields are required for my Editor/Driver generated code to display error messages correctly (I have tested validating the same constraints client side, they work. Then, client-size, I builded "fake" incomplete ConstrainViolation from the complete ConstraintViolation objects: did not work). I will have to see what fields I can work without. - Toto
For my ConstraintViolation s to display ok, I need not only the path and message set but also the "rootbean". I ended up creating my custom implementations for PathImpl and Node, otherwise I couldn't get GWT to serialize them. In the end it did not work either (error message not displayed) even 'though by comparing "native" ConstraintViolation objects and deserialized ones, every field seems identical. Only difference is deserialized objects were not GWT's PathImpl but mine (same for nodes). I will have to build ConstraintViolation strictly client side (from server-side info), but this sucks. - Toto

1 Answers

0
votes

No, according to the GWT documentation, you can throw exceptions from RPC methods.

The exact handling depends on the type of the exception:

  • for checked exceptions it's enough to have them listed as throws in the method signature
  • unchecked exceptions are wrapped into an InvocationException. The original exception is logged on server-side.

I guess in your case the ConstraintViolationException is an unchecked exception. It should be "catchable" as InvocationException on the client side. The stacktrace you posted should only be the log output on server side.

If you want to further handle the unchecked exception on client side, I would suggest you to wrap it into an own checked exception and throw that from your RPC method.