ROP server side validation

From: Marcin Skladaniec (marcin.skladanie..cu.edu.au)
Date: Thu Jul 03 2008 - 04:13:43 EDT

  • Next message: Tore Halset (JIRA): "[jira] Assigned: (CAY-1084) openbase does not like our join syntax :("

    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();
          }
    +
    + ..verride
    + 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,



    This archive was generated by hypermail 2.0.0 : Thu Jul 03 2008 - 06:19:11 EDT