Gradle PlayRun task: “Cannot invoke method getAt() on null object” when define assetsDirs property


(Eugene) #1

Can you someone help me with definition of this task:

task start(type: PlayRun) {
    applicationJar file('dest/build/playBinary/lib/api.jar')
    assetsJar file('dest/build/playBinary/lib/api-assets.jar')
    assetsDirs [file('dest/public')]
}

All paths are valid. When I run gradle start I always get following error in console:
> Cannot invoke method getAt() on null object

Here is my soft versions:

Groovy: 2.4.4
Ant: Apache Ant™ version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_05 (Oracle Corporation 25.5-b02)
OS: Linux 3.16.0-4-amd64 amd64
platform play: ‘2.4.8’, scala: '2.11’
Gradle Version: 2.14
Operating System: Linux 3.16.0-4-amd64 amd64

Here is my project, which I try run up:


(Stefan Oehme) #2

assetDirs [] looks to the Groovy compiler like an array access. If you want to assign a list you need an = sign.


(Eugene) #3

Thanks a lot for reply!

I’ve changed task definition
task start(type: PlayRun, dependsOn: makeapp) {
applicationJar file(‘dest/build/playBinary/lib/api.jar’)
assetsJar file(‘dest/build/playBinary/lib/api-assets.jar’)
assetsDirs = [file(‘dest/public’)]
}

and get other error: java.lang.NullPointerException
Here is stack trace:

Caused by: java.lang.NullPointerException
        at com.google.common.collect.Sets.newHashSet(Sets.java:219)
        at org.gradle.play.internal.run.DefaultPlayRunSpec.<init>(DefaultPlayRunSpec.java:37)
        at org.gradle.play.tasks.PlayRun.run(PlayRun.java:89)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:228)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:221)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:210)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:621)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:604)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)

assetsDirs should have type of Set according this docs, how I can correcly create set of file in gradle file?


(Stefan Oehme) #4

You’re missing the runtimeClasspath.


(Eugene) #5

And how I can do it?


(Eugene) #6

I have following gradle structure:
root
------api
------frontend

In the root gradle file I just want to build both child project and run it. And I almost did it, but encountered with that error! Why I can no just initialize set?


(Eugene) #7

Ok, I’ve changed configuration. Now I start api:runPlayBinary and locally it works perfect, but when doing same on jenkins, I can not access to my app. Here is console output from jenking:

Console output

[00:27:23] Using gulpfile ~/.jenkins/workspace/imaster/frontend/gulpfile.js
[00:27:23] Starting ‘clean’…
[00:27:23] Finished ‘clean’ after 64 ms
[00:27:23] Starting ‘copy:index’…
[00:27:23] Finished ‘copy:index’ after 36 ms
[00:27:23] Starting ‘build:prod’…
[00:27:28] gulp-inject 1 files into index.html.
[00:27:28] gulp-inject 1 files into index.html.
[00:27:28] gulp-inject 1 files into index.html.
[00:27:28] gulp-inject 1 files into index.html.
[00:27:28] Finished ‘build:prod’ after 5.59 s
:makefe
frontend was built successfully!
:api:createPlayBinaryAssetsJar
:api:compilePlayBinaryPlayRoutes
:api:compilePlayBinaryScala
:api:processPlayBinaryPlayResources
:api:createPlayBinaryJar
:api:playBinary
:makeapi
api was built successfully!
:makeapp
build done!
:api:runPlayBinary
e[35m— (Running the application, auto-reloading is enabled) —e[0m

[e[37minfoe[0m] p.c.s.NettyServer - Listening for HTTP on /0:0:0:0:0:0:0:0:8888
:startapi
started

BUILD SUCCESSFUL

Total time: 2 mins 10.939 secs
Build step ‘Invoke Gradle script’ changed build result to SUCCESS
Finished: SUCCESS

But when I try access to /0:0:0:0:0:0:0:0:8888 I get not found message in browser.

Can you help me with configure jenking?


(Janito Vaqueiro Ferreira Filho) #8

Hello,

I believe the cause of the problem is that Jenkins is running the build without (or with a limited) standard input. The runPlayBinary runs until an EOF character is read from the standard input. Since it can’t read from standard input or it reads an EOF character right away, it stops the server soon after it is started.

This actually makes sense. Jenkins is used mostly to automate tasks, and automated tasks in general should not expect user input. So I would suggest rethinking how you do what you’re trying to do.

One solution would be to have a Jenkins task that never ends (you’d have to manually stop it to stop the server). I’m not sure how to do this with Gradle besides changing the Gradle source code to not expect an EOF character. While easy, this could probably lead to unforeseen problems.

Another solution would be to have Jenkins build it (optionally publish it somewhere) and have a separate step to deploy it.

The easiest way to deploy it would be to run the runPlayBinary task manually when you want to run the server. I don’t know what is the proper way to deploy it, but I think it could be close to deploying it manually using activator instead of Gradle. See here about deploying Play applications.

What I would do in your case is use a Docker container. I don’t know how this might suit your needs, but I would keep the build inside Jenkins, then at the end of the build copy the repository to a Docker container, and start it in there.

There’s probably a better way to deploy (something similar to creating a distribution of the application), but I’m afraid I’m still learning about Play :confused:

Anyway, I hope this helps a little.