2017-07-30 20 views
0

コントローラからコントローラへのサービスへのシンプルなフローがあります。また、適切な場所で一般的に将来のリカバリを使用して、例外を適切にカバーするようにしています。スカラリカバリを使用する必要がある場合:

コントローラのアクション:

def getSiblings(): Action[JsValue] = Action.async(parse.json) { request => 
    request.body.validate[Person] match { 
     case JsSuccess(person, _) => 
     peopleService.getSiblings(person).map(res => Ok(Json.toJson(res))) recover { 
      case t: Throwable => 
      logger.error("error running getSiblings: ", t) 
      InternalServerError 
     } 
     case JsError(errors) => Future(BadRequest(s"not a good person format ${errors.mkString}")) 
    } 
    } 

peopleService:

class PeopleService @Inject() extends LazyLogging { 

    def getSiblings(personToGetSiblings: Person): Future[List[SiblingResults]] = { 
    // isSibling is a method of a person that returnes a future and can fail 
    Future.sequence(listOfPeople.map(person => person.isSibling(personToGetSiblings))) recover { 
     case e: Exception => { 
     throw new RuntimeException("fail to get siblings with error: ", e) 
     } 
    } 
    } 

} 

case class SiblingResults (person: Option[Person]) 

とパーソン:

@Singleton 
class PersonA @Inject() (configuration: Configuration, peopleApi: PeopleApi) extends Person { 

    def isSibling(personToMatch: Person): Future[SiblingResults] = { 
    val res = for { 
     // areSiblings returnes a Future[Boolean] 
     areThey <- peopleApi.areSiblings(personToMatch, personInstance) recover { 
      case ex: Exception => throw new Exception("PeopleApi failed") 
     } 
    } yield areThey 

    if (res) Some(personInstance) else None 
    } 

    val personInstance = this 

... 

} 

これらの先物を回復するための正しい方法がどうなりますか?

答えて

0

Playのアクション構成を使用して、障害を処理します。このコードは、例外処理などの余分な配管工事がなくても、ビジネスロジックのみを処理するクリーンなものになります。例外をコントローラにバブルアップさせ、例外はActionBuilderによって最終的に処理されます。

ActionBuilder

import play.api.libs.json.Json 
import play.api.mvc.{ActionBuilder, Request, Result} 
import play.api.mvc.Results.Status 
import scala.concurrent.Future 


/** 
    * Created by chlr on 12/2/16. 
    */ 
object ErrRecoveryAction extends ActionBuilder[Request] { 

    def invokeBlock[A](request: Request[A], block: Request[A] => Future[Result]) = { 
    block(request) recover errorHandler 
    } 

    def errorHandler: PartialFunction[Throwable, Result] = { 
    // you can apply a different statuscode other than 500 depending on the type of exception matched. 
    case th: Throwable => 
     new Status(500).apply(Json.obj("error_message" -> th.getMessage, "error_class" -> th.getClass.getName)) 
    } 

} 

コントローラー使用

注そこには例外処理がコントローラにない、さらに例外処理を他のサービス・クラスで必要とされない方法。

def getSiblings(): Action[JsValue] = ErrRecoveryAction.async(parse.json) { 
    request => 
     peopleService 
      .getSiblings(request.body.as[Person]) 
      .map(res => Ok(Json.toJson(res))) 
} 
関連する問題