Hi

Few thoughts.
For ROP it would be good if some object validation was performed locally (field not null, in proper format etc.), yet some validation is much better performed on server (duplicate detection, related objects validation etc.). I have looked at this problem and I found a problem : if client validation passes and server fails then on the server a ValidationException is created. This is good, but on its way to client the exception is toStringed() and looses its properties, becomes useless on client.

I have looked at this issue and came up with a patch (see bottom of the email). What I've done is not even close to "nice" but it works. Please tell me if you have a better idea on how to solve it, I can implement it and send another patch.

Another problem is that the "mandatory" flags set in cayenne modeller are not respected in client validation (basically client side validation does nothing by default). Is there a JIRA for this ?

With regards
Marcin


Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/ cayenne/remote/hessian/service/HessianService.java
===================================================================
--- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/ cayenne/remote/hessian/service/HessianService.java (revision 673550) +++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/ cayenne/remote/hessian/service/HessianService.java (working copy)
@@ -19,6 +19,7 @@

 package org.apache.cayenne.remote.hessian.service;

+import java.io.ByteArrayOutputStream;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
@@ -32,6 +33,8 @@
 import org.apache.cayenne.remote.hessian.HessianConfig;
 import org.apache.cayenne.remote.service.HttpRemoteService;

+import com.caucho.hessian.io.BasicSerializer;
+import com.caucho.hessian.io.Hessian2Output;
 import com.caucho.hessian.io.SerializerFactory;
 import com.caucho.services.server.Service;
 import com.caucho.services.server.ServiceContext;
@@ -89,4 +92,15 @@
     public void destroy() {
         destroyService();
     }
+
+    @Override
+    public boolean isThrowableSerialisable(Throwable th) {
+ //this is a ugly hack, but how otherwise check if the serialisation will succeed?
+        try {
+ createSerializerFactory().getSerializer(th.getClass()).writeObject(th, new Hessian2Output(new ByteArrayOutputStream()));
+        return true;
+        } catch (Throwable error){
+            return false;
+        }
+    }
 }
Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/ cayenne/remote/service/BaseRemoteService.java
===================================================================
--- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/ cayenne/remote/service/BaseRemoteService.java (revision 673550) +++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/ cayenne/remote/service/BaseRemoteService.java (working copy)
@@ -20,7 +20,9 @@
 package org.apache.cayenne.remote.service;

 import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
 import java.io.PrintWriter;
+import java.io.Serializable;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -38,6 +40,9 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;

+import com.caucho.hessian.io.BasicSerializer;
+import com.caucho.hessian.io.Hessian2Output;
+
 /**
* A generic implementation of an RemoteService. Subclasses can be customized to work with
  * different remoting mechanisms, such as Hessian or JAXRPC.
@@ -156,19 +161,34 @@
             th = Util.unwindException(th);
             logObj.info("error processing message", th);

- // This exception will probably be propagated to the client.
-            // Recast the exception to a serializable form.
-            Exception cause = new Exception(th.getLocalizedMessage());
-
             StringBuilder wrapperMessage = new StringBuilder();
             wrapperMessage.append("Exception processing message ")
                 .append(message.getClass().getName())
                 .append(" of type ").append(message.toString());

+ // This exception will probably be propagated to the client. + // if the exception should be passed as is (to allow for example validation), but unfortunatelly some exceptions (or their causes) are not serialisable, for example SQLException thrown by derby
+            if (isThrowableSerialisable(th)) {
+ throw new CayenneRuntimeException(wrapperMessage.toString(), th);
+            }
+ // if the exception cannot be serialised recast the toString-ed exception. + Exception cause = new Exception(th.getClass() + " " +th.getLocalizedMessage()); throw new CayenneRuntimeException(wrapperMessage.toString(), cause);
         }
     }
-
+
+    /**
+     * An ugly check if the throwable can be serialised.
+     */
+    public boolean isThrowableSerialisable(Throwable th) {
+        try {
+ new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(th);
+        return true;
+        } catch (Throwable error){
+            return false;
+        }
+    }
+
     protected RemoteSession createRemoteSession(
             String sessionId,
             String name,

Reply via email to