Issue:
I am facing the below issue in play 2.5 while compilation.
You do not have an implicit Application in scope. If you want to
bring the current running Application into context, please use
dependency injection.
Getting issue in line - DB.withConnection {^
Code snippet:
object User {
def getId(emailid: String): Option[Int] = {
DB.withConnection { implicit c =>
SQL("select id from user where email = {email}").on(
'email -> emailid).as(SqlParser.scalar[Int].singleOpt)
}
}
}
How do I fix the issue?
Make User a class and inject it where you need it.
class User #Inject() (db: Database) { ..}
And in your controller:
class MyController #Inject() (user: User) extends Controller {
// ..
user.getId
// ..
}
Read more here: https://www.playframework.com/documentation/2.5.x/ScalaDatabase
I think the problem you met is like this:
You do not have an implicit Application in scope: PlayFramework with Oracle
have a try that import the package of 'play.api.Play.current', namely add the following in your code file
import play.api.Play.current
have a good luck
Related
As a beginner to both scala and akka-http, I am trying to hook into the serialization aka marshalling process.
The project uses akka#2.5.2 and akka-http#10.0.10". Furthermore, it has the akka-http-spray-json dependency included.
In the codebase, we use Java.Util.Currency (It may be deprecated which is not important as I'd still like to know how to add a custom marshaller.)
Given this example controller:
def getCurrencyExample: Route = {
path("currencyExample") {
val currency: Currency = Currency.getInstance("EUR")
val code: String = currency.getCurrencyCode
val shouldBeFormated = collection.immutable.HashMap(
"currencyCode" -> code,
"currencyObject" -> currency
)
complete(shouldBeFormated)
}
}
I get a response like this where the currency object becomes empty:
{
currencyObject: { },
currencyCode: "EUR",
}
I expect something like:
{
currencyObject: "EUR",
currencyCode: "EUR",
}
The currency object should be transformed into a JSON string. And since I do not want to transform each response manually, I want to hook into marshalling process and have it done in the background.
I want to add a custom marhaller only for Java.Util.Currency objects, yet even reading up on the docs I am very unsure how to proceed.
There are multiple approaches described, and I am not sure which fits my need, or where to start.
I tried creating my own CurrencyJsonProtocol:
package com.foo.api.marshallers
import java.util.Currency
import spray.json.{DefaultJsonProtocol, JsString, JsValue, RootJsonFormat}
object CurrencyJsonProtocol extends DefaultJsonProtocol {
implicit object CurrencyJsonFormat extends RootJsonFormat[Currency] {
override def read(json: JsValue): Currency = {
Currency.getInstance(json.toString)
}
override def write(obj: Currency): JsValue = {
JsString(obj.getCurrencyCode)
}
}
}
yet the mere existence of the file breaks my project:
[error] RouteDefinitons.scala:90:16: type mismatch;
[error] found : scala.collection.immutable.HashMap[String,java.io.Serializable]
[error] required: akka.http.scaladsl.marshalling.ToResponseMarshallable
[error] complete(shouldBeFormated)
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
and I have no idea why. (It was crashing due to my package name being called marshaller. That completely broke the compilation of the project.
From what I understand, you have all the pieces, you just need to put them together.
Spray json provides support for marshalling common types, such as Int, String, Boolean, List, Map, etc. But it doesn't know how to marshall 'Currency'. And to solve that you have created a custom marshaller for 'Currency' objects. You just need to plug it in the right place. All that you have to do is import the marshaller from your CurrencyJsonProtocol into your Controller like below:
import CurrencyJsonProtocol._
Also make sure you have the below imports as well:
import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._
And spray-json should automatically pick that up.
To understand how it works, you need to understand about implicits in scala. Although it looks like magic when you come from java-world like me, I can assure you it's not.
I´m using Spray support for years. Maybe i should try another one. Anyway, in Spray, a custom formatter for a type is simple. An example of the squants.market.currency https://github.com/typelevel/squants
import squants.market.{ Currency, Money }
import squants.market._
trait MoneyJsonProtocol extends DefaultJsonProtocol {
implicit object CurJsonFormat extends JsonFormat[Currency] {
def write(currency: Currency): JsValue = JsString(currency.code)
def read(value: JsValue): Currency = value match {
case JsString(currency) =>
defaultCurrencyMap.get(currency) match {
case Some(c) => c
case None => // throw an exception, for example
}
case _ => // throw another exception, for example
}
}
implicit def toJavaBigDecimal(b: math.BigDecimal): java.math.BigDecimal = b.underlying
}
Do you have a JsonFormat[Currency]? If yes, just fix it...
If not, you should follow the doc and create:
as domain model, specific result type to hold the answer e.g. case class CurrencyResult(currency: Currency, code: String)
in trait JsonSupport: a JsonFormat[Currency]
in trait JsonSupport: a JsonFormat[CurrencyResult]
As an alternative to point 1 above, you can probably type your map as: Map[String, JsValue].
I have started using MacWire for the dependency injection of my Play app, and I am having problems trying to inject the database connection.
Before using DI, my code looked like this:
DB.withConnection { implicit connection =>
...
}
This is not working anymore after using DI. I get the following exception: java.lang.InstantiationException: play.api.db.DBApi.
My application loader:
class Loader extends ApplicationLoader {
def load(context: Context) = {
val components = new BuiltInComponentsFromContext(context) with Components
components.application
}
}
The main components of the app:
trait Components extends BuiltInComponents with I18nComponents
with RepositoryModule {
lazy val assets: Assets = wire[Assets]
lazy val router: Router = wire[Routes] withPrefix "/"
}
And the repository module:
trait RepositoryModule {
lazy val userRepository = wire[UserRepository]
}
How can I get and use a database connection pool and inject it so it can be used within the repository?
I solved it using the DBComponents and BoneCPComponents traits in the RepositoryModule. With them, I could get a Database object and inject it to the repositories. This is the code I'm using for the module:
trait RepositoryModule extends BuiltInComponents with DBComponents with BoneCPComponents {
lazy val database: Database = dbApi.database("default")
lazy val userRepository = wire[UserRepository]
}
The database "default" will use the db.default configurations in the application.conf. The main problem with this solution is that you need to get the connections from the pool and return them when you're done. I don't know if it can be improved to mimic the withConnection method.
An example of the user repository using the injected database:
class UserRepository(db: Database) {
def deleteAdults: Unit = {
val connection: Connection = db.getConnection()
val removed: Int = SQL("DELETE * FROM User WHERE age > 18").executeUpdate()(connection)
connection.close()
}
}
I have a Scala Play 2.2.2 application and as part of my Specification tests I would like to insert some fixture data for testing preferably in json format. For the tests I use the usual in-memory H2 database. How can I accomplish this? I have searched all the documentation but there is no mention to this anywhere.
Note that I would prefer not to build my own flavor of fixture implementation via the Global. There should be a non-hacky way to this right?
AFAIK there is no built-in stuff to do this, ala Rails, and it's hard to imagine what the devs could do without making Play Scala much more opinionated about the way persistence should be handled (which I'd personally consider a negative.)
I also use H2 for testing and employ plain SQL fixtures in a resource file and load them before tests using a couple of (fairly simple) helpers:
package object helpers {
import java.io.File
import java.sql.CallableStatement
import org.specs2.execute.{Result, AsResult}
import org.specs2.mutable.Around
import org.specs2.specification.Scope
import play.api.db.DB
import play.api.test.FakeApplication
import play.api.test.Helpers._
/**
* Load a file containing SQL statements into the DB.
*/
private def loadSqlResource(resource: String)(implicit app: FakeApplication) = DB.withConnection { conn =>
val file = new File(getClass.getClassLoader.getResource(resource).toURI)
val path = file.getAbsolutePath
val statement: CallableStatement = conn.prepareCall(s"RUNSCRIPT FROM '$path'")
statement.execute()
conn.commit()
}
/**
* Run a spec after loading the given resource name as SQL fixtures.
*/
abstract class WithSqlFixtures(val resource: String, val app: FakeApplication = FakeApplication()) extends Around with Scope {
implicit def implicitApp = app
override def around[T: AsResult](t: => T): Result = {
running(app) {
loadSqlResource(resource)
AsResult.effectively(t)
}
}
}
}
Then, in your actual spec you can do something like so:
package models
import helpers.WithSqlFixtures
import play.api.test.PlaySpecification
class MyModelSpec extends PlaySpecification {
"My model" should {
"locate items correctly" in new WithSqlFixtures("model-fixtures.sql") {
MyModel.findAll().size must beGreaterThan(0)
}
}
}
Note: this specs2 stuff could probably be better.
Obviously if you really need JSON you'll have to add extra machinery to deserialise your models and persist them in the database (often in your app you'll be doing these things anyway, in which case that might be relatively trivial.)
You'll also need:
Some evolutions to establish your DB schema in conf/evolutions/default
The evolution plugin enabled, which will build your schema when the FakeApplication starts up
The appropriate H2 DB config
I'm creating an application in Scala using Play 2.2. I'm using play-slick 0.5.0.8 as my MySQL DB connector. I have the following application controller:
package controllers
import models._
import models.database._
import play.api._
import play.api.mvc._
import play.api.Play.current
import play.api.db.slick._
object Application extends Controller {
// WORKS:
def test = DBAction {
implicit session => Ok(views.html.test(Cameras.findById(1)))
}
// DOES NOT WORK:
def photo = Action {
val p = PhotoFetcher.fetchRandomDisplayPhoto(someParametersBlah))
Ok(views.html.photo(p))
}
}
As you can see, the test DBAction works, and it's able to fetch a photo from the DB just fine. Unfortunately, the photo Action does not work.
My PhotoFetcher.fetchRandomDisplayPhoto(blah) does a bunch of different things. Buried inside of it is a call to Cameras.findById(blah), which should return a Camera object (which works in the test DBAction). However, with this configuration I get the following error:
could not find implicit value for parameter s: slick.driver.MySQLDriver.simple.Session
I have tried making the photo Action into a DBAction, like so:
def photo = DBAction {
implicit session => {
val p = PhotoFetcher.fetchRandomDisplayPhoto(someParametersBlah))
Ok(views.html.photo(p))
}
}
But that just results in the same missing session error. It's like PhotoFetcher doesn't know about the implicit session.
The other thing I've tried is importing slick.session.Database.threadLocalSession in my PhotoFetcher, but that only results in the following error:
SQLException: No implicit session available; threadLocalSession can only be used within a withSession block
If it's any help, this is a simplified version of my Cameras object:
package models.database
import models.Format.Format
import scala.slick.driver.MySQLDriver.simple._
case class Camera(id: Long,
otherStuff: String)
trait CamerasComponent {
val Cameras: Cameras
class Cameras extends Table[Camera]("cameras") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def otherStuff = column[String]("otherStuff", O.NotNull)
def * = id ~ otherStuff <> (Camera.apply _, Camera.unapply _)
val byId = createFinderBy(_.id)
val byOtherStuff = createFinderBy(_.otherStuff)
}
}
object Cameras extends DAO {
def insert(camera: Camera)(implicit s: Session) { Cameras.insert(camera) }
def findById(id: Long)(implicit s: Session): Option[Camera] = Cameras.byId(id).firstOption
def findByOtherStuff(otherStuff: String)(implicit s: Session): Option[Camera] = Cameras.byOtherStuff(model).firstOption
}
So, it seems as if I've gotten crossed-up somewhere. Right now it's only possible for me to access my DAO objects directly from a Controller DBAction, and not from inside of some different class. Any help would be appreciated. Thanks!
Does your definition of PhotoFetcher.fetchRandomDisplayPhoto.fetchRandomDisplayPhoto take an implicit session?
// PhotoFetcher
def fetchRandomDisplayPhoto(args: Blah*)(implicit s: Session) = {
// ...
val maybeCam = Cameras.findById(blah) // <- sees the implicit session
// ...
}
Or are you relying on a threadLocalsession in PhotoFetcher? (no implicit session argument for fetchRandomDisplayPhoto)?
While Slick's threadLocalSession is handy for quickly trying out stuff, it can lead to confusion and loss of clarity later on. It's best to just use explicit (implicit s: Session) parameter lists for all methods that call your Slick models. This also plays
well with DBAction, letting the framework manage sessions.
The downside is you have to have (implicit s: Session) on all your methods - there
are workarounds like this:
https://github.com/freekh/play-slick/issues/20
Scala isn't verbose and is very amenable to refactoring - so I'd recommend thinking
about crossing that bridge when you come to it, and use DBAction for all actions
that do database stuff; give all methods that call your database models an
implicit session, and see how much that mileage that gives you.
I have found following function calls in several frameworks which appear to me as if the framework extends some base classes. Some examples:
within(500 millis)
or
"Testcase description" in
{ .... }
First example returns a duration object with the duration of 500 milliseconds from akka and second is the definition of a testcase from scalatest.
I would like to know how this behavior is achieved and how it is called.
This is done with the "Pimp my library" technique.
To add non existing methods to a class, you define an implicit method that converts objects of that class to objects of a class that has the method:
class Units(i: Int) {
def millis = i
}
implicit def toUnits(i: Int) = new Units(i)
class Specs(s: String) {
def in(thunk: => Unit) = thunk
}
implicit def toSpecs(s: String) = new Specs(s)
See also "Where does Scala looks for Implicits?"
If I'm not mistaken, those pieces of code can be desugared as
within(500.millis)
and
"Testcase description".in({ ... })
This should make it easier to see what's going on.