Category Archive: Play2

Подключение MongoDB(+GridFS) к Play2 (Scala)

В нашем новом проекте в качестве файлового хранилища мы решили использовать GridFS. GridFS эффективен для файлов размером свыше 16 МБ, поэтому мы решили хранить файлы менее 16 МБ в виде байтов в MongoDB. К тому же GridFS - это всего лишь надстройка над MongoDB, и размер документа MongoDB ограничен как раз 16 мегабайтами. Для начала нужно в build.sbt добавить зависимость на стандартный драйвер MongoDB:
"org.mongodb" % "mongo-java-driver" % "3.3.0"
Далее в application.conf прописать переменные, который мы будем использовать для подключения к MongoDB.
mongodb.uri="mongodb://192.168.99.100:27017"
mongodb.db="your_database_name"
И, собственно, реализация класса для работы с MongoDB и GridFS:
package services.file
import javax.inject.{Inject, Singleton}
import com.mongodb.client.gridfs.{GridFSBuckets, GridFSBucket}
import com.mongodb.{MongoClient, MongoClientURI}
import play.api.{Logger, Configuration}

@Singleton
class MongoService @Inject() (conf: Configuration) {
  val uri = conf.underlying.getString("mongodb.uri")
  val db = conf.underlying.getString("mongodb.db")
  Logger.debug("mongodb.uri = " + uri)
  Logger.debug("mongodb.db = " + db)
  val mongoClient = new MongoClient(new MongoClientURI(uri))
  val database = mongoClient.getDatabase(db)
  val wholeFileCollection = database.getCollection("whole-files")

  //GridFS
  val gridFSBucket: GridFSBucket = GridFSBuckets.create(database, "chunked-files")
}

Конвертирование кортежа со списком в JSON (Scala)

Всем привет! Меня перевели на новый проект, решили делать его на Play2(Scala). Я джавист и тяжело с моим багажом перестраиваться, прежние подходы в разработке не работают. Долго бился на конвертированием структуры в виде кортежа со списком (List). В итоге пришел к такому варианту:
implicit val questionReads = Json.reads[Question]
implicit val questionWrites = Json.writes[Question]
implicit val answerWrites = Json.writes[Answer]
implicit val answerReads = Json.reads[Answer]

implicit val questionWithAnswersWrites = new Writes[(Option[Question], List[Answer])] {
    override def writes(tuple: (Option[Question], List[Answer])) = Json.obj(
      "question" -> tuple._1,
      "answers" -> tuple._2
    )
  }

implicit val questionWithAnswerReads = new Reads[(Question, List[Answer])] {
    override def reads(json: JsValue) = JsSuccess((
      (json \ "question").as[Question],
      (json \ "answers").as[List[Answer]]
    ))
  }

def questionWithAnswers(id: Long) = Action {
    val answers: (Option[Question], List[Answer]) = questionService.questionWithAnswers(id)
    Ok(Json.toJson(answers))
  }

def saveWithAnswers = Action(BodyParsers.parse.json) { implicit request =>
    request.body.validate[(Question,List[Answer])].fold(
      error => {
        BadRequest(Json.obj("status" -> JsError.toJson(error)))
      },
      tuple => {
        questionService.update(tuple._1,tuple._2)
        Ok(Json.obj("status" -> "success"))
      }
    )
  }
Question и Answer - это case class'ы