Domanda

I have this on my app/scripts folder (I created this folder inside app/). I'm not sure how I can properly set the classpath here, thus I didn't even run this to know if it will actually connect to the database. How can I run this in a clean way from the command line?

package scripts

import scala.collection.TraversableOnce
import scala.collection.generic.SeqForwarder
import scala.io.Source
import scala.slick.jdbc.{StaticQuery => Q}
import scala.slick.session.Session
import scala.slick.session.Database
import play.api.db.DB
import tables.Campeonatos
import tables.Jogos
import org.postgresql.Driver
import play.api.test._
import play.api.test.Helpers._

// ...

class InsertJogosCSV extends App {
  val dao = new DAO()
  val application = FakeApplication()

  def insertJogos(csv: CSV)(implicit s: Session) = {
    val times = dao.getTimeIdByNameMap
    var count = 0
    csv foreach { case cols =>
      count += 1
      dao.insertJogo(cols, times)
    }
    count
  }

  val csvFilePath: String = args(0)
  val csv = new CSV(csvFilePath)
  csv.printLines
  running(application) {
    val realDatabase = Database.forDataSource(DB.getDataSource()(application))
    implicit val s = realDatabase.createSession
    insertJogos(csv)
  }
}
È stato utile?

Soluzione 2

You could achieve this by using the play test:console command at the root of your app. First you could probably move the code into a main method rather than extending App:

class InsertJogosCSV {
    def main(args: Array[String]) {
        val dao = new DAO()
        val application = FakeApplication()

        def insertJogos(csv: CSV)(implicit s: Session) = {....}

        ....
    }
}

then run the play test:console command and do the following

scala> import scripts.InsertJogosCSV
import scripts.InsertJogosCSV

scala> val insert = new InsertJogosCSV()
insert: scripts.InsertJogosCSV = scripts.InsertJogosCSV@7d5f9d2b

scala> insert.main
res0: .....

The play test:console by default adds everything from the app folder to your class path as well as the FakeApplication context that you need for your script. Hope that helps.

Similar question: https://stackoverflow.com/a/11297578/2556428

Altri suggerimenti

I've made a blog post explaining my final solution. Should work as an answer to the question.

http://blog.felipe.rs/2014/05/15/run-maintenance-scripts-in-the-context-of-a-running-play-framework-application/

I am using another approach , for similar task.

Create empty subproject in main playframework project.

In build.sbt it looks like

// Main project
lazy val root = (project in file(".")).enablePlugins(play.PlayScala).enablePlugins(com.typesafe.sbt.web.SbtWeb)
// Utils sbt project with scripts
lazy val sjutil = project.aggregate(root).dependsOn(root)

and sjutil/build.sbt like normal sbt project with extra deps if needed, for me it was akka-remote

name := "sjutil"

version := "1.0-SNAPSHOT"

scalaVersion := "2.11.1"

libraryDependencies +=   "com.typesafe.akka" %% "akka-remote" % "2.3.4"

You can place some App direct in sjutil/ folder

sjutil/actorsstarter.scala:

object actorsstarter {
  lazy val logger = play.api.Logger("actorsstarter")
  def main(args: Array[String]) {
     // read config from conf/application.conf of main project
     val remoteConfig = ConfigFactory.load.getConfig("botstarter")

     val system = ActorSystem("application",remoteConfig)
     val path = "akka.tcp://application@127.0.0.1:2553/user"
     ....
     logger.info("Started")
  }
}

after that you can run this script with:

./activator sjutil/run 

and make everything you can do with normal project: stage, dist and etc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top