14

I have problem with my Spring application built with Gradle. App includes MongoDB(MongoHQ from Heroku).

I managed how to push everything on heroku, I've added this code to my project:

@Configuration
public class MongoHQConfiguration {

    public @Bean MongoDbFactory mongoDbFactory() throws MongoException, UnknownHostException {
        return new SimpleMongoDbFactory(new MongoURI(System.getenv("MONGOHQ_URL")));
    }

    public @Bean MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate(mongoDbFactory());
    }
}

After changing buildpacks to one with gradle, I pushed everything on Heroku free account with MongoHQ Sandbox.

But after trying to run my app through web browser, I'm getting this error:

An error occurred in the application and your page could not be served. Please try again in a few moments.

If you are the application owner, check your logs for details.

heroku logs gives me this output:

2014-10-15T18:19:30.293964+00:00 heroku[web.1]: Starting process with command java -Xmx384m -Xss512k -XX:+UseCompressedOops -jar build/libs/*.jar

2014-10-15T18:19:30.797673+00:00 app[web.1]: Error: Unable to access jarfile build/libs/*.jar

2014-10-15T18:19:31.474525+00:00 heroku[web.1]: State changed from starting to crashed

2014-10-15T18:19:31.464753+00:00 heroku[web.1]: Process exited with status 1

2014-10-15T18:19:32.577398+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=tvmaniac.herokuap p.com request_id=7e8bfe6c-2669-405e-9bce-59fde09f71ef fwd="89.129.247.185" dyno= connect= service= status=503 bytes=

2014-10-15T18:19:34.016281+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=tvmani ac.herokuapp.com request_id=4300386e-dc5c-47ed-9878-0bee87128fc9 fwd="89.129.247.185" dyno= connect= service= status=503 bytes=

2014-10-15T18:19:41.988204+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=tvmaniac.herokuap p.com request_id=436db871-ea8c-428f-8cc7-160c3cb96a2d fwd="50.16.146.194" dyno= connect= service= status=503 bytes=

I think the problem is in Procfile, but I have no idea what should I add there, here's my current code:

default_process_types:

web: java $JAVA_OPTS -jar build/libs/*.jar

EDITED

Here's my build.gradle:

buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-release" }
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.8.RELEASE")
    }
}    

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

mainClassName = "com.shalastra.tvmaniac.TVManiacConfiguration"

jar {
    baseName = 'tvmaniac'
    version = '0.1.0'
}

repositories {
    mavenCentral()
    maven { url "http://repo.spring.io/libs-release" }
    maven { url "http://m2.neo4j.org" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")

    compile("org.springframework.boot:spring-boot-starter-actuator")
    testCompile("junit:junit")

    compile("org.springframework.data:spring-data-rest-webmvc")
    compile("org.springframework.data:spring-data-mongodb")

    compile("com.google.guava:guava:17.0")
    compile("org.apache.commons:commons-lang3:3.3.2")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.0'
}

task stage(dependsOn: ['clean', 'build', 'installApp'])

Thanks in advance for your help.

Forin
  • 1,549
  • 2
  • 20
  • 44
  • Why don't You add a task that copies the built artifact from `build/lib` to `project.rootDir` (renaming it appropriately) and start application from the root dir? It seems that there's no jar built. – Opal Oct 15 '14 at 19:04
  • Can you explain how I can do it? – Forin Oct 15 '14 at 19:09
  • I'll add a response in a minute. – Opal Oct 15 '14 at 19:12
  • Ok, once again. It seems that there's a jar file missing. How You provide that jar? Do You run gradle on heroku or commit the built spring-boot app (jar) to heroku with source control? – Opal Oct 15 '14 at 19:26
  • I'm using this buildpack: [https://devcenter.heroku.com/articles/buildpacks], that's it. It's my first gradle app on heroku, so maybe I missed something. – Forin Oct 15 '14 at 19:38
  • Have You done everything according to these instructions: https://github.com/heroku/heroku-buildpack-gradle ? – Opal Oct 15 '14 at 19:40
  • And also, can You share You build.gradle please? – Opal Oct 15 '14 at 19:43
  • I think so, I've edited question and added build.gradle – Forin Oct 15 '14 at 19:49

2 Answers2

20

After a short discussion in comments it seems (according to this instructions) that You need add the following task to build.gradle file:

task stage(type: Copy, dependsOn: [clean, build]) {
    from jar.archivePath
    into project.rootDir 
    rename {
        'app.jar'
    }
}
stage.mustRunAfter(clean)

clean << {
    project.file('app.jar').delete()
}

And the content of Procfile will be:

web: java $JAVA_OPTS -jar app.jar

Now it should work fine.

Explanation:

Task stage prepares jar file to be run. After it's finished the output jar is copied into project.rootDir and renamed to app.jar. It guarantees that it will have always the same name and can be easily run with the command from Procfile. stage task also depends on clean (which has an additional action to remove app.jar) and build (which builds the app). It's important to set stage.mustRunAfter(clean) because otherwise the order in which tasks are run is not determined (this probably happens now - check it locally). What I mean is if just dependsOn is specified build may be run, then clean and finally stage - and nothing is created. I hope it's clear.

Opal
  • 81,889
  • 28
  • 189
  • 210
  • This paste bin has been removed. – Opal Oct 15 '14 at 20:14
  • 1
    This is a different problem. What You were asking about has been solved. See this question for port configuration for spring boot: http://stackoverflow.com/questions/21083170/spring-boot-how-to-configure-port. Basically You need the app to port number from $PORT environment variable. – Opal Oct 15 '14 at 20:18
  • Ok, thanks for your help. So I should create application.properties in resources folder and write there this: `server.port = 8080`? Or should I do something else? Because adding this still doesn't solve my problem. – Forin Oct 15 '14 at 20:31
  • 1
    Unfortunately You can't specify the port in application.properties for heroku, You need to take the one defined under $PORT. Maybe try adding `-Dserver.port=$PORT` to Procfile? – Opal Oct 15 '14 at 20:39
  • 1
    Ok, it's working now. If anyone will need solution, here it is. Procfile should look like this: `web: java $JAVA_OPTS -Dserver.port=$PORT -jar app.jar` – Forin Oct 15 '14 at 20:58
5

I've made an example so noobies can really check out and understand every line of code. Because I really know how frustrating this can be to figure out.

This is what your Procfile should look like

web: java $JAVA_OPTS -Dserver.port=$PORT -jar app.jar

This is what your Gradle file should look like

group 'com.springtest.api'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

//Path to the Main Web Class
mainClassName = "hello.Application"

jar {
    baseName = 'spring-test-api'
    version = '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8

dependencies {
    testCompile 'junit:junit:4.11'

    // Spring Framework
    compile 'org.springframework.boot:spring-boot-starter-web'
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.6'
}

task stage(type: Copy, dependsOn: [clean, build]) {
    from jar.archivePath
    into project.rootDir
    rename {
        'app.jar'
    }
}
stage.mustRunAfter(clean)

clean << {
    project.file('app.jar').delete()
}

If the gradlew and gradlew.bat aren't in your main project directory or is not up-to-date then in cmd run the command gradle wrapper.

If you don't have Gradle actually installed on your computer install it from the main gradle website.

My example on github is below. https://github.com/arose13/Heroku-Spring-Gradle_Example

SARose
  • 3,558
  • 5
  • 39
  • 49
  • 1
    This should be the official gradle springboot heroku example, not some vague tutorial on their official website: https://devcenter.heroku.com/articles/deploying-gradle-apps-on-heroku +1 – Simon Dec 11 '15 at 17:22