I'd argue that using exceptions for control flow is something of an
anti-pattern, even in Java.

In this case a better mechanism might be to use polymorphism. For instance:

(defprotocol Validatable
  (validation-errors [x] "Return the validation errors for x."))

(defn valid? [x]
  (empty? (validation-errors x)))

Then you can define a general function to validate and store that item in a
database:

(defn store-valid [db x]
  (if (valid? x)
    (store db x)
    (validation-error-response x)))

- James


On 19 March 2013 16:43, Julien Dreux <julien.dr...@gmail.com> wrote:

> Hi all,
>
> Coming from a Java background, I am having a hard time understanding how
> validation error propagation should work in clojure web APIs.
>
> To be clear, this is similar to how my Java web service would be setup:
>
> /** Method that validates the model, accesses the DB. If something went
> wrong, throw an exception */
> public void validateAndCreateUser(User u) throws ValidationException,
> EmailAlreadyInUseException, ... {
>   ...
>   if(...) {
>     throw new ValidationException(fieldName);
>   } else if (...) {
>     throw new EmailAlreadyInUseException(u.getEmail());
>   }
> }
>
> /** Endpoint method, catches & formats the exceptions thrown by the db
> method. **/
> @POST("/api/user/create")
> public Response createUser (User u)  {
>   ..
>   try{
>     validateAndCreateUser(u);
>     return Response.ok();
>   } catch (Exception e) {
>     return generateExceptionResponse(e); //Method that maps exceptions to
> responses.
>   }
> }
>
> For all of Java's clunkiness, this had the benefit of not having to write
> tons of if/else statements for validation handling. Exception were just
> thrown from anywhere, bubbling back up to inital call, and if not handled
> in the endpoint method, a specialized class mapped them into a proper
> response. The exceptions contained all the information needed to generate
> 'rich' error messages back to the client.
>
> Being a Clojure newbie, I wonder what a good pattern is for a similar
> situation. So far, I have a method that validates models based on a schema,
> that returns
>
> {:success true}
>
> or
>
> {:success false :errors ["error 1" "error 2" ...]}
>
> But I don't know how to avoid having to write if/else conditions of the
> sort in each function between my endpoint and db functions.
>
> (if (validation :success)
>   (follow-normal-path)
>   (handle-validation-errors validation))
>
>
> Any guidance appreciated.
>
> Cheers,
>
> Julien
>
> --
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to