Error handling in play framework - scala

I am developing a REST API using play framework. I would like to implement a centralized error handling for all my actions.
What is the best way to achieve this?

An alternative way do this is to use a filter, e.g:
object ExceptionFilter extends EssentialFilter {
def apply(nextFilter: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader) = {
val next: Iteratee[Array[Byte], Result] = nextFilter(requestHeader)
// Say your backend throws an ItemNotFound exception.
next recoverWith {
case e: ItemNotFound => Iteratee.ignore[Array[Byte]]
.map(_ => Results.NotFound("Item not in the database!"))
}
}
}
}
Then hook that up in your global settings:
object Global extends WithFilters(CSRFFilter(), ExceptionFilter) with GlobalSettings
This potentially allows you to do something with the request body if needed. I agree in most cases using GlobalSettings.onError is probably the easiest approach.

You should have a look at the GlobalSettings: https://www.playframework.com/documentation/2.3.x/ScalaGlobal
Especially, it allows you to override:
def onError(request: RequestHeader, ex: Throwable)
def onHandlerNotFound(request: RequestHeader)
def onBadRequest(request: RequestHeader, error: String)
onError is probably the one you are looking for, but the others may be useful too :)

Related

How convert Cats Effect 3 to Future

I'm trying to combine Playframework with Cats Effect 3 Tagless Final style.
I'm stuck on the transformation to the Future. Play's Action requires either just value or Future, which I want to reach, for async processing.
def method = authed { _ =>
val program: EitherT[IO, Throwable, Int] = ???
program
}
def authed[F[_]: Async](fa: Request => F[Result]): Action = {
???
}
In cats effect 2 it was possible via _.toIO.unsafeToFuture but now it's changed.
According to the doc I must use Dispatcher. Found the initial idea on Github but a new signature is F[Future[A]]
def beforeF[F[_]: Effect, A](fa: F[A]): Future[A] = fa.ioIO.unsafeToFuture()
// Note: Using a `Dispatcher` resource is cheap - don't worry about it
def preferredAfterF[F[_]: Async, A](fa: F[A]): F[Future[A]] = Dispatcher[F].use(_.unsafeToFuture(fa))
Does anyone have success?
Contruct your routes so that they have access to a Disptacher object as a dependency, then the lifecycle will be appropriate
class MyRoute[F[_]: MonadThrow](disp: Dispatcher[F]) {
def method = authed { _ =>
val program: EitherT[IO, Throwable, Int] = ???
disp.unsafeToFuture(program.value)
}
}
(this might require some fiddling using allocated and the IORuntime's unsafeRunSync on a Dispatcher[IO] resource, depending on how your application is wired)

Playspec Mock actor for unit test

Hi I am trying to test this functionality within the controller, I need to mock "MyActor" for doing the unit test.
def populateArraylist[T](hashSet: HashSet[T]): util.ArrayList[T] = {
val list = new util.ArrayList[T]()
hashSet.foreach(x => list.add(x))
list
}
#ApiOperation("Get the state of a something”)
def get(ID: String, dateID: String): Action[AnyContent] = Action.async
{
implicit request =>
(MyShardProvider.shard ? MyActor.EntityPayload(
Id,
MySecondActor.GetStateRequest(dateId)))
.mapTo[GetStateResponse]
.map(x => {
Ok(new String(JacksonSerializer.toBytes(new GetResponse(
x.state.identifier,
populateArraylist(x.data.transactionList.processedKeys)
))))
})
}
I think what you want to do is to mock the shard actor, or else you will have to actually run cluster and sharding when the unit test executes.
Easiest way is probably to either make the MyShardProvider.shard something you inject or can override (depending on how you are doing injection in your play app) in the test case to provide the ActorRef of a TestProbe instead.
That you have MyShardProvider.shard at all looks a bit fishy though, you should never have a singleton that contains an actor system, instead you should inject instances as shown in the Play docs here: https://www.playframework.com/documentation/2.6.x/ScalaAkka

ActionBuilder is returning requestBody as null

I'm developing a scala Web application with play framework, the first time i used filter in order to validate the request but i had no result then i tried to use action builder i had to override 2 methods here is my ActionBuilder Object
object MyJsonAction extends ActionBuilder[Request, Response] with Results {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
println (request.body)// returning null everytime why ?
block(request)
}
override def parser = { // what does this method do, i think the problem started from here :/ ?
null;
}
override protected def executionContext = {
null;
}
}
Well, there are no much resource with play framework just simple examples and there is no example briefly explain what those methods are doing, they tell that you can get request body without telling you how ! everything is ambiguous ! im stuck with it since 3 days a go, and i have no idea what should i do now. thanks
An ActionBuilder is an object that build an Action. An Action combines a BodyParser[T], which reads the request body and constructs a T, with a function Request[T] => Future[Result] to process the T.
The default ActionBuilder does this in a very simple way. It chains together the BodyParser's result and feeds it to the function. If you make a custom ActionBuilder then you can override this process, perhaps by injecting your own logic before or after the function call.
If you're making your own ActionBuilder I'd suggest starting with something like the following as a template:
#Singleton
class MyJsonAction #Inject() (
bodyParsers: PlayBodyParsers,
ec: ExecutionContext) extends ActionBuilder[Request, JsValue] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
println(request.body) // DO SOMETHING HERE
block(request)
}
override def parser = bodyParsers.json
override protected def executionContext = ec
}
Then you can use it in your controllers like this:
class MyController #Inject() (myJsonAction: MyJsonAction) {
def index = myJsonAction { req: Request[JsValue] => ??? }
}
The important piece is the parser: BodyParser[A] it takes the incoming bytes and convert them into a type A.
For instance BodyParser[JsValue] will produce a body of type JsValue. It is used to read Json.
If you are trying to validate an object, maybe an action builder is not the right place to start. You may focus more on the BodyParsers and the json validation

In Play 2.4 with DI, how to use a service class in "Secured" trait?

Here's an authorisation example from Play Documentation (version 2.0.4; I tried to find a newer version of this document but couldn't):
trait Secured {
def username(request: RequestHeader) = request.session.get(Security.username)
def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Auth.login)
def withAuth(f: => String => Request[AnyContent] => Result) = {
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
}
def withUser(f: User => Request[AnyContent] => Result) = withAuth { username => implicit request =>
UserDAO.findOneByUsername(username).map { user =>
f(user)(request)
}.getOrElse(onUnauthorized(request))
}
}
Overall this is pretty straightforward, and I'd like to go with something like this.
Now, in Play 2.4 the recommended way is not to use singletons anymore (like UserDAO above), but classes and runtime DI instead (see migration guide, or DI docs).
For example, my service and repository classes are defined like this:
class AuthService #Inject()(accountRepo: AccountRepository) { }
class AccountRepository { }
With Play 2.4 and DI in use, what is the recommended / "correct" / simplest way to get hold of a service or DAO (like AuthService in my case, or UserDAO in the doc example) in a trait like Secured?
Or are you nowadays supposed to implement authorisation for controllers in a whole another way than using such trait?
I can make it work along these lines:
trait Secured {
val authService = GuiceUtils.inject[AuthService]
// ...
}
Using a helper like this:
object GuiceUtils {
lazy val injector = new GuiceApplicationBuilder().injector()
def inject[T: ClassTag]: T = injector.instanceOf[T]
}
But according to an answer in a related question:
In Play you could use the injector directly as long as the Application
trait is in scope. But this isn't considered good practice in
production code.
If that is true, what is considered good practice in this use case?
I think the simplest approach would be to declare the authService in your trait but keep it abstract, then have the controller which extends it handle the injection (I believe this is how MessagesApi/I18nSupport injection works). So you could do:
trait Secured {
val authService: AuthService
...
}
controller Application #Inject()(override val authService: AuthService) extends Controller with Secured {
...
}

Custom Actions with multiple implicit arguments

Our Play application uses Slick as a data access layer. This means that in almost every action in our app we need to have both the current Request and Slick's database Session implicitly available on the scope.
I want to write a custom Action to do this so we only need one line to do this. What I want to do is write it in such a way that I can write something like this:
def someAction = DBAction { implicit request, session =>
// body with implicit request and session on scope
But this is not valid syntax. Using a tuple does not work because it cannot implicitly unpack the tuple in action body. Is it possible to create a custom action that passes multiple implicit arguments to the body? How do I do this?
You cannot implicit 2 variables like that.
But your Custom action can return a WrappedRequest (an object which encapsulates the request and your session), and you can define an implicit conversion between this wrapped request and your Session.
Try this example, derived from this class.
sealed case class DBRequest(session: Session, private val request: Request[AnyContent])
extends WrappedRequest(request)
trait DBController extends Controller {
// Implicit conversion from DBRequest to Session
implicit def session(implicit request: DBRequest) = request.session
def DBAction(action: DBRequest => Result) = Action { request =>
database.withSession { session =>
action(DBRequest(session, request))
}
}
}
object MyController extends Controller with DBController {
def myAction = DBAction { implicit request =>
println(session)
}
}
#senia was right, currying needs to be used to do this. This is actually addressed in the Play docs but it's a recent addition I missed.
For future reference for people looking for this, my custom action now looks like this:
def DBAction(action: Request[AnyContent] => Session => Result) = {
Action { request =>
database.withSession { session =>
action(request)(session)
}
}
}
Which I can then use in the following way:
def someAction = DBAction { implicit request => implicit session => /* body */ }