1
votes

Got some trouble with a Scala Play app having a dependency on a Java library deployed to a local Maven repository using Gradle. I've setup a test project with a simple Gradle Java module containing one class, and a simple Scala Play project using this class. The Java class looks like:

public class TestClass {

    public String testMethod(){

        return "Some content we will change later.";
    }
}

With a build.gradle setup to deploy JARs to local Maven repo:

apply plugin: 'java'
apply plugin: 'maven'

sourceCompatibility = 1.7

project.group = 'play-update-maven-snapshot'
version = '1.0-SNAPSHOT'

Running gradle install drops the JAR in the local repo:

$ ls ~/.m2/repository/play-update-maven-snapshot/gradle-java/1.0-SNAPSHOT/
gradle-java-1.0-SNAPSHOT.jar    maven-metadata-local.xml
gradle-java-1.0-SNAPSHOT.pom

On the Scala/Play/SBT side, build.properties is updated to:

sbt.version=0.13.1

To pick up the changes noted in https://github.com/sbt/sbt/issues/321.

With build.sbt configured, according to the current SBT docs, for grabbing artifacts from local Maven repositories:

name := "play-scala"

version := "1.0-SNAPSHOT"

resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"

libraryDependencies ++= Seq(
    jdbc,
    anorm,
    cache
)

libraryDependencies+= "play-update-maven-snapshot" % "gradle-java" % "1.0-SNAPSHOT"

play.Project.playScalaSettings

And Application.scala is updated to look like:

package controllers

import play.api.mvc._

object Application extends Controller {
    def index = Action {
        Ok(views.html.index(new TestClass().testMethod()))
    }
}

And a hacked index.scala.html to simply display what is passed to it:

@(message: String)

@main("Welcome to Play") {

    message

}

We have our simple test environment. Starting play does not show any dependency errors:

$ play run
[info] Loading project definition from /<redacted>/play-update-maven-snapshot/play-scala/project
[info] Set current project to play-scala (in build file:/<redacted>/play-update-maven-snapshot/play-scala/)
[info] Updating {file:/<redacted>/play-update-maven-snapshot/play-scala/}play-scala...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.

--- (Running the application from SBT, auto-reloading is enabled) ---

[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

(Server started, use Ctrl+D to stop and go back to the console...)

Visiting localhost:9000 unfortunately give this:

[info] Compiling 5 Scala sources and 1 Java source to /<redacted>/play-update-maven-snapshot/play-scala/target/scala-2.10/classes...
[error] /<redacted>/play-update-maven-snapshot/play-scala/app/controllers/Application.scala:8: not found: type TestClass
[error]     Ok(views.html.index(new TestClass().testMethod()))

It feels like this may have something to do with the old issue of SBT/Ivy caching local SNAPSHOTs, referenced above. However, deleting the Ivy cache with rm -Rf ~/.ivy2/cache/play-update-maven-snapshot does not seem to do anything.

Any pointers would be greatly appreciated. There's a GitHub project with the source here: https://github.com/timfulmer/play-update-maven-snapshot.

Edit 1:

Made sure JAR is actually in local repo:

$ ls -n ~/.m2/repository/play-update-maven-snapshot/gradle-java/1.0-SNAPSHOT/gradle-java-1.0-SNAPSHOT.jar
-rw-r--r--  1 501  20  634 Feb  4 11:53 /Users/<redacted>/.m2/repository/play-update-maven-snapshot/gradle-java/1.0-SNAPSHOT/gradle-java-1.0-SNAPSHOT.jar

Updated build.sbt from

resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"

to

resolvers += Resolver.mavenLocal

Still no joy.

Edit 2:

Got really desperate :)

$ jar xvf ~/.m2/repository/play-update-maven-snapshot/gradle-java/1.0-SNAPSHOT/gradle-java-1.0-SNAPSHOT.jar 
  created: META-INF/
 inflated: META-INF/MANIFEST.MF
 inflated: TestClass.class
$ cat ./TestClass.class 
????3
<init>()VCodeLineNumberTableLocalVariableTablethis
                                              LTestClass;
testMethod()Ljava/lang/String;
SourceFileTestClass.java
                    "Some content we will change later.
TestClassjava/lang/Object!/*??

Looks like everything up to the local Maven repo is correct.

Thanks,

-- Tim

1
~/.m2/repository is Gradle's default for the local Maven repository location. If this isn't what you got, perhaps it found another settings.xml telling it otherwise. - Peter Niederwieser
not sure if file:// is necessary. Also there is predefined local maven repository: Resolver.mavenLocal - 4e6
@4e6 Thanks for the pointer. I updated the question & GitHub project with your suggestion. Unfortunately, it does not seem to have fixed this issue. - Tim Fulmer
play has own cache in ${PLAY_HOME}/repository/<cache> . You need to remove all from ${PLAY_HOME}/repository/ and leave only local. Or you can run project sbt run instead of play run - Andrzej Jozwik
I found out the problem was that my play compile picks up jars from the repo in the play directory. Intellij picks it up from the local ivy2 repo. So whenever I wanted to update the external module, First I removed the jars from both the repos, then ran clean install on the external module (maven), made sure the class was updated in both the repos (play directory and ivy2) by extracting the jars. then I ran play clean update compile in my play project. The configs of build.sbt are same as those in your first edit.(added resolver of local maven repo and added libraryDependencies of the module) - Aditya Pawade

1 Answers

2
votes

Dunno if this was an issue with earlier versions of the stack, but on a recent project with the exact same setup I did not run into this issue again. At the time it felt like something in the paths was getting cached once set incorrectly.

Being careful to follow the steps above in the order given with latest versions seems to make everything happy.

If you do run into this, please see the advice in the comments above. Aditya Pawade has some ideas on where the pesky files could be hiding.

Cheers,

-- Tim