How to throw messages to http response from case class require? - spray

Given a case class with any require
case class Foo(id: Int, value: Int) {
require(value < 0 "value must be bigger than zero")
}
Is possible to throw this messages to http?
val routes = pathPrefix("foos") {
pathEnd {
post {
entity(as[Foo]) { foo =>
saveFoo(foo) match {
case Success(p) => {
complete(StatusCodes.Created)
}
case Failure(f) => {
println(f.getMessage) // unknown error
complete(BadRequest, f.getMessage)
}
}
}
}
}

The Akka-HTTP infrastructure will already convert all errors occurring during unmarshalling into a 400 (BadRequest) error, and the exception message will be automatically used.
With your same code I am getting that behaviour for free. Small changes I made:
the business logic error is now a 500, to avoid confusion
the case class requirement is now consistent with the message (> is required instead of <).
case class Foo(id: Int, value: Int) {
require(value > 0, "value must be bigger than zero")
}
def saveFoo(foo: Foo): Try[Unit] = Success(())
val route = pathPrefix("foos") {
pathEnd {
post {
entity(as[Foo]) { foo =>
saveFoo(foo) match {
case Success(p) => {
complete(StatusCodes.Created)
}
case Failure(f) => {
println(f.getMessage) // unknown error
complete(StatusCodes.InternalServerError, f.getMessage)
}
}
}
}
}
}

Related

How to composite functions and persist the progress

I have a sequence of asynchronous methods defined like so:
func step1(input: Step1InputData, completion: (Step1OutputData -> Void)) { /* do something */ }
func step2(input: Step1OutputData, completion: (Step2OutputData -> Void)) { /* do something */ }
// etc...
As you can see, the output of step1 is the input of step2. These types all implement the StepData protocol:
protocol StepData {}
class Step1InputData : StepData { }
class Step1OutputData : StepData { }
class Step2OutputData : StepData { }
Finally, I have this custom operator:
infix operator => { associativity left }
func => <P:StepData, Q:StepData, R:StepData> (left:((P, Q -> Void) -> Void), right:((Q, R -> Void) -> Void)) -> ((P, R -> Void) -> Void) {
return { (x, completion) in
left(x, { y in
right(y, completion)
})
}
}
... which means I can write the following:
let combinedStep = step1 => step2
Which is great because it's super readable, and crucially it enforces type safety between the steps.
The problem is that I want to be able to persist the progress of a combinedStep. For example, step1 could be an image upload and step2 could be a local storage write. If step2 fails, the next time I try, I want to pick up where I left off, rather than re-uploading the image. Of course, there could be any number of steps chained together.
I could come up with a system that has an array of steps and manages the passing of data between steps and would be able to persist the progress, however, I can't think of a way to do this while still keeping the compile-time type safety.
Can someone with more experience of functional programming point me in the right direction?
I would suggest you look into frameworks like PromiseKit, BrightFutures, and ReactiveCocoa.
Those framework are in the same problem and solution space as you, asynchronous operations that need to be composed, and they all provide multiple ways to handle errors and retries.
If you like any of those you could adopt them in place of your custom implementation, and leverage the support of a big community of developers. Or you could just find inspiration from their code to bring back in your.
Enjoy
I think you need to make your operator right associative and pass an enum in the completion handler to allow for failure.
enum StepResult<Output> {
case Success(Output)
case Failure((StepResult<Output>->Void)->Void)
static func toFailHandlerWithInput<Input>(input: Input, processor: (Input,(StepResult<Output>)->Void)->Void) -> StepResult<Output> {
let handler : ((StepResult<Output>->Void)->Void) = { completion in
processor(input) { pout in
completion(pout)
}
}
return .Failure(handler)
}
}
infix operator => { associativity right }
func =><Input,Intermediate,Output>(left: (Input,(StepResult<Intermediate>)->Void)->Void, right: (Intermediate,(StepResult<Output>)->Void)->Void) -> (Input,(StepResult<Output>)->Void)->Void {
var mergedOp : ((Input,(StepResult<Output>)->Void)->Void)!
mergedOp = { input,completion in
left(input) { intermediate in
switch intermediate {
case .Success(let output):
right(output, completion)
case .Failure:
let failure = StepResult.toFailHandlerWithInput(input, processor: mergedOp)
completion(failure)
}
}
}
return mergedOp
}
var counter1 = 0
func step1(input: Int, completion: (StepResult<Double>)->Void) {
print("performing step 1...")
counter1 += 1
if ( counter1 > 1 ) {
print("Step 1 will succeed...")
let result = 2.0 * Double(input + counter1)
completion(.Success(result))
} else {
print("Step 1 fails...")
completion(StepResult.toFailHandlerWithInput(input, processor: step1))
}
}
var counter2 = 0
func step2(input: Double, completion: (StepResult<Double>)->Void) {
print("performing Step 2...")
counter2 += 1
if ( counter2 > 2 ) {
print("Step 2 will succeed...")
let result = 3 * input + Double(counter2)
completion(.Success(result))
} else {
print("Step 2 fails...")
completion(StepResult.toFailHandlerWithInput(input, processor: step2))
}
}
var counter3 = 0
func step3(input: Double, completion: (StepResult<Double>)->Void) {
print("performing Step 3...")
counter3 += 1
if ( counter3 > 1 ) {
print("Step 3 will succeed...")
let result = 4 * input + Double(counter3)
completion(.Success(result))
} else {
print("Step 3 fails...")
completion(StepResult.toFailHandlerWithInput(input, processor: step3))
}
}
func comboHandler(result: StepResult<Double>) {
switch result {
case .Success(let output):
print("output: \(output)")
case .Failure(let failHandler):
failHandler(comboHandler) // call again until success
}
}
let combinedSteps = step1 => step2 => step3
combinedSteps(5) { result in
comboHandler(result)
}
The answer to the specific question I asked here, in case it is useful to anyone else turned out to be to take a similar approach to Memoization. Strictly speaking, it is caching, rather than memoization, but the concept of wrapping the step function in another function that takes a cache key parameter is the same.

Is there a way to specify an error code for an ErrorType value in Swift?

In my app I am using a custom error type ProgrammerError with three error values .Messiness, .Procrastination and .Arrogance (these are just examples). Later in the code I need to cast the errors to NSError. The NSError objects have code properties starting from 0 following the order or error values I declared: 0, 1, 2 etc.
enum ProgrammerError: ErrorType {
case Messiness
case Procrastination
case Arrogance
}
(ProgrammerError.Messiness as NSError).code // 0
(ProgrammerError.Procrastination as NSError).code // 1
(ProgrammerError.Arrogance as NSError).code // 2
My question is: Is there a way to set different error codes for the enumeration values? For example, can I set Messiness to have code value of 100 instead of 0?
You can implement var _code: Int { get } property.
enum ProgrammerError: ErrorType {
case Messiness
case Procrastination
case Arrogance
var _code: Int {
switch self {
case .Messiness:
return 100
case .Procrastination:
return 101
case .Arrogance:
return 102
}
}
}
(ProgrammerError.Messiness as NSError).code // 100
(ProgrammerError.Procrastination as NSError).code // 101
(ProgrammerError.Arrogance as NSError).code // 102
You can also implement var _domain: String { get } if you need.
But I must warn you, these methods are undocumented so they might stop working in future.
Or, you may try explicit conversion.
extension FileActionError {
func getCode() -> Int {
switch self {
case .BadFileNodeIndex: return 1
case .BadFileNodePath: return 2
}
}
func toNSError() -> NSError {
return NSError(domain: "", code: getCode(), userInfo: [NSLocalizedDescriptionKey: "\(self)"])
}
}
Might not what you expected.

Why does authenticate directive lead to "Error: type mismatch"?

I'm getting this error in my spray project.
Error:(41, 28) type mismatch;
found : spray.routing.authentication.ContextAuthenticator[co.s4n.authentication.entities.Usuario]
(which expands to) spray.routing.RequestContext => scala.concurrent.Future[scala.util.Either[spray.routing.Rejection,co.s4n.authentication.entities.Usuario]]
required: spray.routing.directives.AuthMagnet[?]
authenticate(validateToken) {
^
This is my TokenValidator trait
trait TokenValidator {
def validateToken: ContextAuthenticator[Usuario] = {
ctx =>
val header = ctx.request.headers.find(_.name == "Access_Token")
if (header isDefined) {
doAuth(header.get)
}
else {
Future(Left(AuthenticationFailedRejection(AuthenticationFailedRejection.CredentialsMissing, List())))
}
}
def doAuth(header: HttpHeader): Future[Authentication[Usuario]] = {
Dao.validateToken(header.value).map {
case Some(usuario) => Right(usuario)
case None => Left(AuthenticationFailedRejection(AuthenticationFailedRejection.CredentialsRejected, List()))
}
}
}
and this is the line where I¡m getting that error
//#DELETE
//localhost:9090/authenticacion/users/{{userEmail}}
val `users/{{email}}` =
pathPrefix(`path-prefix`) {
pathPrefix(`users-path-prefix` / Segment) {
emailRef => {
delete {
authenticate(validateToken) { **HERE!!!!**
usuario =>
.....
}
}
}
}
}
Does anyone know what am I doing wrong?
Thak you all in advance!
The only thing I was missing was to have ExecutionContext in scope and import ExecutionContext.Implicits.global worked fine.
It's to let Futures work as they declare an implicit ExecutionContext parameter.
I know it's a long time since the actual question came, but the way to go with this for Spray is to determine the execution context with the tools that Spray provides:
implicit def executionContext = actorRefFactory.dispatcher

sendResponse within grails webflow

I would like to check if a user is allowed to start a flow by checking if parameters are valid. If not I will send an error 404. But in the webflow de error response won't be send.
The webflow always returns status 200.
Does somebody have a solution for this problem?
def shortShopFlow = {
onStart {
log.info("starting a new shoppingCart traject")
Boolean isValidShop = shopService.isValidShop(params.code as String, params.token as String)
sessionFactory.currentSession.clear()
if (!params.code || !isValidShop) {
response.sendError(404)
return
}
}
You can do something:
MyController{
def shortShopFlow = {
onStart {
log.info("starting a new shoppingCart traject")
Boolean isValidShop = shopService.isValidShop(params.code as String, params.token as String)
sessionFactory.currentSession.clear()
if (!params.code || !isValidShop) {
return 404();
}
on('404').to ('pageNotFound');
}
pageNotFound{
redirect(action: 'fourZeroFour');
}
def fourZeroFour = {
response.sendError(404);
}
}
Hope this helps.
Minhaj

Criteria building in GORM

if (params.filters) {
def o = JSON.parse(params.filters);
def groupOp = o.groupOp
def fields = o.rules.field
def values = o.rules.data
def op = o.rules.op
println fields
println values
if(groupOp == "AND") {
fields.eachWithIndex {a, i ->
println op[i]
if(op[i].equals( "eq")) {
and{ eq(fields[i], values[i])}
}
if(op[i].equals("ne")) {
and{ ne(fields[i], values[i])}
}
if(op[i].equals("ge")) {
def valu = Double.valueOf( values[i]);
and{ ge(fields[i], valu)}
}
}
}
if(groupOp == "OR") {
fields.eachWithIndex {a, i ->
println op[i]
if(op[i].equals( "eq")) {
println 'eq';
or{ eq(fields[i], values[i])}
}
if(op[i].equals("ne")) {
println 'ne';
or{ ne(fields[i], values[i])}
}
if(op[i].equals("ge")) {
def valu = Double.valueOf( values[i]);
or{ ge(fields[i], valu)}
}
}
}
}
where params.filters is following JSON text.
{
"groupOp":"OR",
"rules":[
{
"field":"foo1",
"op":"le",
"data":"9.5"
},
{
"field":"foo2",
"op":"eq",
"data":"12345-123"
},
{
"field":"foo3",
"op":"cn",
"data":"IDM"
}
]
}
This data is coming from JQuery data grid.
Is there a better way of doing this?
In the code I have just listed only 3 operators, but in real I have 14 operations.
You can use String as Criteria operation, like:
A.withCriteria {
'eq' (id, 1)
}
so you might come to something like
A.withCriteria {
(groupOp) {
for (???) {
(op[i]) (fields[i], parsedVals[i])
}
}
}
Anyway you'll need to sanitize the web-submitted query for only allowed subset of operations. You don't want to receive end execute arbitrary sqlRestriction, right? :D So the code is going to be more complex then this anyway.
Note: wrapping and{} or or {} around single statement has no point, you need to put it around whole block of if-s.
I suggest that you have a look at the source code of the FilterPane plugin. Its service does essentially what you are doing and may give you some ideas for enhancements.

Resources