Play Framework 2.4.0 - How to add an external java project dependency to play-java application project

1.3k Views Asked by At

I've created a play-java web application with the command:
activator new "c:\workspace\PlayServer"

I'm working in Eclipse and created in the same workspace another java project (regular java project) named "Common".

Now, i have the following project structure:

c:\workspace
   \--- Common (Java project)
      \--- src
           \--- comm
              \--- messages
   \--- PlayServer (Play-java 2.4.0 web application project)
      \--- app/controllers
      \--- app/views
      \--- conf
      \--- project

I would like to access the classes of "Common" project at "PlayServer". In Eclipse - i've added the "Common" project dependency to the Java build path of the play application project, and all the projects were build successfully and i can access all the classes of "Common" at the "PlayServer" play application project.

However, when I run or Debug the "PlayServer" with activator run command, i'm receving errors: [error] c:\workspace\PlayServer\app\controllers\Application.java;6
error: package comm.messages.WebMessage does not exist
[error] import comm.messages.WebMessage

Which means the playframework can't find the classes of "Common" java eclipse project. After searching a lot about this problem i've found in general, that there are 3 solutions to this:

1. Publish to my external java project to Ivy and resolve in the play project's build.sbt file as follows:

libraryDependencies ++= Seq(
  // Adding it here somehow..
)

But i didn't find any simple tutorial which can guide me how to publish my external java project and resolve it in play project's build.sbt file. The build sbt file is a bit mystery to me.

2. Directly reference my external project, in the play project's build.sbt. I tried to do the following at my build.sbt - which also didn't really work:

// Option 1:

lazy val core = ProjectRef(file("../Common"), "Common")
lazy val root = (project in file(".")).enablePlugins(PlayScala).dependsOn(common )

// Option 2:

lazy val common = RootProject(file("../common"))
lazy val root = (project in file(".")).enablePlugins(PlayScala).dependsOn(common )

// Option 3:

lazy val common = file("../common").getAbsoluteFile.toURI
lazy val root = (project in file(".")).enablePlugins(PlayScala).dependsOn(common )

I've read at the SBT documentation that i should add to the "Common" project a "build.sbt" file, but i don't know what to declare in it. In case the "Common" project must be also a SBT project, i know all the java sources should be in: "/src/main/java" but i saw at the SBT documentation that it is configurable. So, the main issue is that i still don't manage to make my external java project be compiled and recognized by my play web application.
For now i just created an empty build.sbt file at the "Common" project directory.


3. Create a lib/ directory in the root of my play project and then add jar files to that directory. This solution will require that each of my external java projects like "Common" will need to create "jar" file automatically in every build, and also to copy the generated jars to my "PlayServer" lib directory. Also, i've read that the "lib" solution is for unmanaged dependecies, therefore i'm not sure this solution is effective and correct, due to the fact that play framework uses SBT with ivy.

My question is: Which one of the methods is the most preffered and recommended to use? and how can i implement it?
I didn't success to find any best practices about this issue or any basic tutorials that can demonstrate how to do any of the above solutions.

1

There are 1 best solutions below

3
On

I've found this approach to work well following the documentation which explains the structure Play uses for packaging separate projects.

Two repositories with Git, one for common and one for PlayServer. Checkout Common to its own workspace but also checkout it into PlayServer's workspace within a folder named modules:

c:\workspace
   \--- Common (checked out from Git)
      \--- src
           \--- comm
              \--- messages
   \--- PlayServer (Play-java 2.4.0 web application project)
      \--- app/controllers
      \--- app/views
      \--- conf
      \--- project
      \--- modules
         \--- Common (checked out from Git)
            \--- src
                 \--- comm
                    \--- messages

(Note how Common is checked out twice, to its own workspace, and also within PlayServer/modules.)

In the .gitignore for the PlayServer app, you can tell it to ignore modules\Common as it's got its own separate Git repository.

The documentation explains on how to get the modules/Common and PlayServer to work together as separate projects, and there's a sample on GitHub showing how Play's subproject works. Note that this sample uses Play 2.3 however 2.4's Migration Guide doesn't mention any changes and therefore the same steps can be taken.

Update (see comments)

Build.sbt would be something like:

lazy val root = project.in(file("."))
  .aggregate(common)
  .dependsOn(common)

lazy val common = project.in(file("../common"))

Everything else is as per the sample I linked to above.