ParameterMultiMap validation

41 views
Skip to first unread message

Conor Reedy

unread,
May 24, 2016, 9:44:07 AM5/24/16
to spray.io User List
Is there a way to handle rejections for a paramterMultiMap in the same way the parameters directive handles rejections?

parameters("one", "two") { (one: String, two: String) => 

  /* code that can assume all params are correct */

}

The problem I'm having is handling missing params in the MultiMap.  If I write code that assumes the params are correct I will be getting exceptions thrown.  I would like a way to reject the request up front so the following code can be simpler.

Thanks for your time,
Conor

Age Mooij

unread,
May 24, 2016, 9:54:24 AM5/24/16
to spray...@googlegroups.com
What kind of rejections are you thinking of? What is your definition of "correct"? Do you mean marking some params as optional or providing default values?

Perhaps some example code illustrating the exact problem might help us help you better.

Age

--
You received this message because you are subscribed to the Google Groups "spray.io User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to spray-user+...@googlegroups.com.
Visit this group at https://groups.google.com/group/spray-user.
To view this discussion on the web visit https://groups.google.com/d/msgid/spray-user/9815e6a0-8fd2-489b-a964-b185b3108871%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Conor Reedy

unread,
May 24, 2016, 10:12:27 AM5/24/16
to spray.io User List
Sorry if I'm doing this wrong...

This is the actual code I'm using the handle this route.  What I want to happen is much like the parameters directive where the params are cast to variables in the directive so the following code can assume they are present.  In this way the "validation" of the params in assumed and won't need to be handled in the route directly.  In this the correct params would be extracted and the following code would be able to handle the params directly (instead of being wrapped in an Option or Try).

I guess what I'm trying to get at here is how to properly reject a route where the parameters are not valid.  Is there a built in way of doing this?  I can't seem to figure out how to properly reject something without throwing an exception and have the exception handler deal with it.  To me it seems like the rejections get run after the exception handler (is this correct)?

// there are imports but I haven't included them
class RangeTransactionHandler extends ConfigurableHttpHandler {

  import context.dispatcher

  override val route =
    parameterMultiMap { params =>  // in this I just get the extracted map without any validation 

      val accountIds = gets("accountId", params)
      val startDate   = get ("startDate", params)
      val endDate    = get ("endDate", params  )

      val request    = GetTransactionsRequest(accountIds,
                         GzoConfig.environment,
                         toLocalDate(startDate),
                         toLocalDate(endDate)).getItems.getTransactions


      onComplete(request) { value =>
        value match {
          case Success(value) => complete(JsonResponse(value.map(_.toJson).toVector, Vector()))
          case Failure(ex)    => complete(JsonResponse(Vector(), Vector(ex.getMessage)))

Age Mooij

unread,
May 24, 2016, 10:45:04 AM5/24/16
to spray...@googlegroups.com
On 24 May 2016, at 16:12, Conor Reedy <ofrequisi...@gmail.com> wrote:

Sorry if I'm doing this wrong...

This is the actual code I'm using the handle this route.  What I want to happen is much like the parameters directive where the params are cast to variables in the directive so the following code can assume they are present.  In this way the "validation" of the params in assumed and won't need to be handled in the route directly.  In this the correct params would be extracted and the following code would be able to handle the params directly (instead of being wrapped in an Option or Try).

So you don't want the normal behavior of the spray parameter directive for optional parameters? What is the problem with producing an Option for an optional parameter?

I guess what I'm trying to get at here is how to properly reject a route where the parameters are not valid.  Is there a built in way of doing this?  I can't seem to figure out how to properly reject something without throwing an exception and have the exception handler deal with it.  To me it seems like the rejections get run after the exception handler (is this correct)?

You can use the reject directive from any point in your route to reject a route with a specific (or even custom) rejection.


You could also use the validate directive if your rejections are simple enough:


AFAIK you could also nest the parametersMultiMap directive inside the parameters directive so you could first extract and validate the two dates before moving on to handling the account ids in the inner route. that would get you something like this:

parameters(`startDate.as[LocalDate], `endDate.as[LocalDate]) { (sd, ed) =>
  validate(....) { // end date is after start date
    parameterMultiMap { params =>
      ...
    }
  }
}

Where the unmarshalling from raw String to LocalDate would come from a custom Deserializer. See examples in the docs:



Hope this helps
Age



// there are imports but I haven't included them
class RangeTransactionHandler extends ConfigurableHttpHandler {

  import context.dispatcher

  override val route =
    parameterMultiMap { params =>  // in this I just get the extracted map without any validation 

      val accountIds = gets("accountId", params)
      val startDate   = get ("startDate", params)
      val endDate    = get ("endDate", params  )

      val request    = GetTransactionsRequest(accountIds,
                         GzoConfig.environment,
                         toLocalDate(startDate),
                         toLocalDate(endDate)).getItems.getTransactions


      onComplete(request) { value =>
        value match {
          case Success(value) => complete(JsonResponse(value.map(_.toJson).toVector, Vector()))
          case Failure(ex)    => complete(JsonResponse(Vector(), Vector(ex.getMessage)))
      }
    }
  }
}


On Tuesday, May 24, 2016 at 9:44:07 AM UTC-4, Conor Reedy wrote:
Is there a way to handle rejections for a paramterMultiMap in the same way the parameters directive handles rejections?

parameters("one", "two") { (one: String, two: String) => 

  /* code that can assume all params are correct */

}

The problem I'm having is handling missing params in the MultiMap.  If I write code that assumes the params are correct I will be getting exceptions thrown.  I would like a way to reject the request up front so the following code can be simpler.

Thanks for your time,
Conor

-- 
You received this message because you are subscribed to the Google Groups "spray.io User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to spray-user+...@googlegroups.com.
Visit this group at https://groups.google.com/group/spray-user.

Conor Reedy

unread,
May 24, 2016, 11:12:31 AM5/24/16
to spray.io User List
Age, that's brilliant!

Nesting the directives is something I had not thought of and brings with it the ability to do exactly what I want!

Thanks so much for the help!
Reply all
Reply to author
Forward
0 new messages