How to add modules to Play with Scala? - scala

Coming from Ruby on Rails, I used to just do a gem 'some_random_gem' and then bundle in the terminal and there were my dependencies. Now that I'm bumping my head against scala and play, I'm discovering that it might not be that easy on this playground.
I'm trying to runa sample application and this is the warning/error:
module not found: com.wingnest.play2#play21-frames-titan-plugin_2.10;1.3-module-2.4.4
Assume I do not know anything. Assume I have no experience and no scala background. I do have some, but can you give me a description on how to solve this?
I'm believe you will need the projects/build.scala file, so here it is:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "play21-frames-titan-simple-app"
val appVersion = "1.2-module-2.3.2"
val titanVersion = "0.4.2"
val appDependencies = Seq(
"com.wingnest.play2" % "play21-frames-titan-plugin_2.10" % "1.3-module-2.4.4",
"com.thinkaurelius.titan" % "titan-cassandra" % {titanVersion},
javaCore
)
val main = play.Project(appName, appVersion, appDependencies).settings(
resolvers += "Oracle Releases" at "http://download.oracle.com/maven/"
)
}

First off, there are two types of plugins.
sbt plugins are declared in project/plugins.sbt using addSbtPlugin("organization" % "plugin-name" % "version") - the same way that Play is enabled (Play is nothing more than an sbt plugin).
You can find more info about it in the sbt plugins documentation.
Play plugins are normal dependencies but must be activated in the conf/play.plugins file (create it if non-existent) using the <priority>:<qualified-plugin-name> syntax, e.g. 500:se.radley.plugin.salat.SalatPlugin.
Unfortunately, this part of Play is not documented.

Related

Plugins compile order in SBT

I'm trying to create an SBT plugin that provides common plugins and settings for my organization's projects (something like a Maven parent POM).
Since most of these settings should also be present in the commons project itself, I'm adding the sources as unmanagedSourceDirectories in plugins.sbt so the autoplugins I define for the proper project are also present on the meta-project (a neat trick I took from sbt-release plugin).
Things work just fine, except I still need to duplicate the addSbtPlugin entries when I want a plugin for booth my proper project and meta-project. If I don't do this, my proper-project won't compile since the plugins' classes are not loaded.
I tried moving all the shared plugin dependencies to a separate autoplugin assuming SBT would compile it and add the library dependencies to the meta-project so they would be there when my common plugin is compiled, but it doesn't work.
I would like to understand why this fails and if there is some way to thinker with the compilation order to somehow make it work. If not, I would gladly hear any alternatives you guys know to avoid having to maintain duplicate versions of all my shared plugins.
Here is a simplified version of my code:
project structure
/common
|-build.sbt
|-/project
| |-plugins.sbt
|-/src/main/scala/package
|-Dependencies.scala
|-MyCommonPlugin.scala
build.sbt
sbtPlugin := true
name := "common"
plugins.sbt
unmanagedSourceDirectories in Compile += baseDirectory.value.getParentFile / "src" / "main" / "scala"
Dependencies.scala
import sbt._
import sbt.Keys._
//Plugins I intend to share between build.sbt and plugins.sbt
object Dependencies extends AutoPlugin {
override def trigger = allRequirements
override lazy val projectSettings = super.projectSettings ++ Seq(
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.8.5")
)
}
MyCommonPlugin.scala
import sbt._
import sbt.Keys._
//this import fails! object sbt is not a member of package com.typesafe
import com.typesafe.sbt.GitBranchPrompt.{ projectSettings => gitBranchPromptSettings }
object MyCommonPlugin extends AutoPlugin {
override def trigger = allRequirements
override lazy val projectSettings =
super.projectSettings ++
gitBranchPromptSettings ++
Seq(
// My common settings
)
}
To make this code work I would need to repeat the addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.8.5") on plugins.sbt.

Migration from Play framework 2.0.4 to 2.2.0

I have an application build on top of the Play framework 2.0.4. I would like to migrate it to the newest version (which is currently 2.2.0).
So I've updated my local Play framework installation, all build files accordingly:
build.properties:
sbt.version=0.13.0
Build.scala:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "demagog"
val appVersion = "1.0.0"
val appDependencies = Seq(
javaCore,
"com.google.code.morphia" % "morphia" % "0.99",
"com.google.code.morphia" % "morphia-logging-slf4j" % "0.99",
"net.tanesha.recaptcha4j" % "recaptcha4j" % "0.0.7"
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
resolvers += "Morphia repository" at "http://morphia.googlecode.com/svn/mavenrepo/"
)
}
plugins.sbt:
// Comment to get more information during initialization
logLevel := Level.Warn
// The Typesafe repository
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
// Use the Play sbt plugin for Play projects
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.0")
Then I tried to "eclipsify" my project. So I run exactly these two commands:
play clean-all
play eclipse
and I get lots of errors like:
[error] ..\Api.java:11: error: package org.codehaus.jackson does not exist
import org.codehaus.jackson.JsonNode;
which is expected due to the fact I found in the Migration guide:
We have upgraded Jackson to version 2 which means that the package name is now com.fasterxml.jackson.core instead of org.codehaus.jackson.
But at the end of "play eclipse" command I get this error:
[error] (compile:compile) javac returned nonzero exit code
[error] Could not create Eclipse project files:
[error] Error evaluating task 'dependencyClasspath': error
So the project is not "eclipsified" and I can't use it nor edit in my Eclipse IDE. This compiling on backgroung outside of the Eclipse IDE is really painfull and prevents me from productive using Play framework :-/
You can delete all source code files, generate the IDE files and then restore the source code from version control.
Sadly that is how the eclipse (and idea) plugin work, you will have to have a working project before you can re-export the project from SBT to eclipse. So you will just have to work through the compilation errors without the usual support from eclipse.

Simple SBT Module in Play Project Causes Play to Crash for Unknown reason - play 2.1

https://github.com/jasongoodwin/play21-multimodule-demo has the code.
I've recreated this problem on 3 different projects. I don't know what's up.
once you put the aggregate and dependsOn in the build.scala file the project throws an error when trying to start play.
[info] Loading global plugins from /Users/jgoodwin/.sbt/plugins [info]
Loading project definition from
/Users/jgoodwin/Development/src/ninjakeyboard/test/tmp/play21-multimodule-demo/project
[error] java.lang.ExceptionInInitializerError [error] Use 'last' for
the full log. Project loading failed: (r)etry, (q)uit, (l)ast, or
(i)gnore? q
Build file
import sbt._ import Keys._ import play.Project._
object ApplicationBuild extends Build {
val appName = "multimodule-demo" val appVersion =
"1.0-SNAPSHOT" //val scalaVersion = "2.10.0"
val appDependencies = Seq(
// Add your project dependencies here,
jdbc,
anorm )
val buildSettings = (
scalaVersion := "2.10.0"
)
val main = play.Project(appName, appVersion, appDependencies, path =
file("web")).settings(
// Add your own project settings here ).aggregate(testmodule).dependsOn(testmodule)
val testmodule = Project(
"testmodule",
file("testmodlue"),
settings = buildSettings )
}
I noticed in your github build.scala that testmodule is declared (and initialized) after the main module, thus the null exception during project loading.
I made the same mistake and putting the modules in the right order made it work.
I just started playing with Play2 and Scala, but I believe the use of lazy val could also help.
Try to create a fresh project:
Run command: play new MyApp
Run play clean eclipse
Make dir modules (inside MyApp)
Run command play new MyModule
Run command play clean eclipse
Rename controller to MyModuleCon, and change the routes file
Run command play clean publish-local
Add to your MyApp Build.scala the dependency: "mymodule" % "mymodule_2.10" % "1.0-SNAPSHOT"
Rename main route to app.routes (because modules has also routes, although it can be deleted!)
On the main project run: play dependencies eclipse
Voila, you have your submodule, see my github: https://github.com/adis-me/PlayModuleExample
Just run play run and visit main project at: http://localhost:9000 and then visit the submodule: http://localhost:9000/module.
This should do the trick, for you, I think!
EDIT: 2013-03-27
Changing the above configuration to a real sub project setup, follow these steps:
Run on MyApp: play clean
Change MyApp's Build.scala file:
object ApplicationBuild extends Build {
val appName = "MyAppp"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
// Add your project dependencies here,
javaCore,
javaJdbc,
javaEbean
)
val subproject = play.Project(
"sub-project", appVersion, appDependencies, path = file("modules/MyModule")
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
).dependsOn(subproject).aggregate(subproject)
}
Run commands: play clean eclipse
Run commands: play run
That's it, you can no visit the same urls as above mentioned.
It can be that your idea does not recognize the classes from your subproject, just reference the MyModule project as referenced library for the main project, and you are good to go.
Good luck!

Include Scala and Java Nature in Play2 Eclipse Project with javaCore

I have an sbt play2 project that I want to configure for eclipse, to include both a Scala nature and Java nature automatically(in the generated .project file). I can do this inside of eclipse by manually adding the nature, but I want the eclipse plugin to do this for me automatically.
The plugin's default behavior is to add both natures UNLESS you include javaCore in your appDependencies, which I need to do. When you include javaCore, mainLang is set automatically to JAVA, and the Scala Nature is excluded in the configuration.
see: https://github.com/playframework/Play20/wiki/Migration under Changes to the Build File
Is there a way to override mainLang and set it to Scala? Or is there another way to include the Scala Nature along side the Java Nature?
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "SampleApp"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
javaCore, javaJdbc, javaEbean
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// Want to set mainLang = SCALA here, but don't know how
)
}
I use sbt for everything, so play commands are off limits (to avoid additional system dependencies)
Edit: I'm using play-sbt 2.1.0, Scala 2.10.1-RC1, and sbt 0.12.2
By looking at the Play sbt-eclipse source code (here and here), I managed to make it work using the following Build.scala file:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "SampleApp"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
javaCore, javaJdbc, javaEbean
)
import com.typesafe.sbteclipse.core._
import com.typesafe.sbteclipse.core.EclipsePlugin._
import scala.xml.transform.RewriteRule
val main = play.Project(appName, appVersion, appDependencies).settings(
EclipseKeys.projectFlavor := EclipseProjectFlavor.Scala,
EclipseKeys.projectTransformerFactories := Seq[EclipseTransformerFactory[RewriteRule]]()
)
}
Do not forget the 3 imports.
There should be a better way using directly eclipseCommandSettings("SCALA") but I did not find it.

Adding a managed dependency to Play 2 app

I want to add Jersey-client to my Play 2 app using SBT.
So, I added the dependency into my ApplicationBuild.scala file as follows:
object ApplicationBuild extends Build {
val appName = "wealcome-webapp"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
// Add your project dependencies here,
jdbc,
anorm,
"com.sun.jersey" % "jersey-client" % "1.16"
)
val main = play.Project(appName, appVersion, appDependencies).settings(
scalaVersion := "2.10.0"
)
}
So, in command-line I make : play reload update.
Thus, I expect to find Jersey's jars file into play-2.1-RC1/repository/local.
However, I find jars into play-2.1-RC1/repository/cache.
What should I do to make automatically the dependency goes into the local folder in order to expect my app to compile?
Is it normal to find jars file into the cache folder? What is exactly the role of cache?
If you are using an IDE make sure to run play eclipsify or play idea after making changes to your dependencies. Afterwards refreshing the project may be necessary. Then the class paths for the project files will be updated appropriately. Only SBT will be aware of your changes before you do this.