Running Spring app built with gradle on Heroku

2020-04-02 06:43发布

问题:

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.

回答1:

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.



回答2:

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