Search code examples
javagradleherokudeploymentweb-deployment

Heroku deploys locally but crashes on web with gradle


Ive been trying to deploy a java gradle app on heroku, I can get it to deploy locally with heroku local but when using heroku open it says application error.

Logs say

2022-10-10T03:22:06.151325+00:00 heroku[web.1]: Starting process with command `java -jar app/build/libs/app.jar`
2022-10-10T03:22:07.027867+00:00 app[web.1]: Setting JAVA_TOOL_OPTIONS defaults based on dyno size. Custom settings will override them.
2022-10-10T03:22:07.031763+00:00 app[web.1]: Picked up JAVA_TOOL_OPTIONS: -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8
2022-10-10T03:22:07.339805+00:00 app[web.1]: Exception in thread "main" java.lang.NoClassDefFoundError: com/github/benmanes/caffeine/cache/Caffeine
2022-10-10T03:22:07.339946+00:00 app[web.1]: at org.jdbi.v3.core.statement.CachingSqlParser.<init>(CachingSqlParser.java:25)
2022-10-10T03:22:07.339987+00:00 app[web.1]: at org.jdbi.v3.core.statement.ColonPrefixSqlParser.<init>(ColonPrefixSqlParser.java:41)
2022-10-10T03:22:07.340028+00:00 app[web.1]: at org.jdbi.v3.core.statement.SqlStatements.<init>(SqlStatements.java:53)
2022-10-10T03:22:07.340075+00:00 app[web.1]: at org.jdbi.v3.core.config.ConfigRegistry.lambda$configFactory$3(ConfigRegistry.java:100)
2022-10-10T03:22:07.340116+00:00 app[web.1]: at org.jdbi.v3.core.internal.exceptions.Unchecked.lambda$function$4(Unchecked.java:76)
2022-10-10T03:22:07.340156+00:00 app[web.1]: at org.jdbi.v3.core.config.ConfigRegistry.get(ConfigRegistry.java:78)
2022-10-10T03:22:07.340210+00:00 app[web.1]: at org.jdbi.v3.core.config.ConfigRegistry.<init>(ConfigRegistry.java:47)
2022-10-10T03:22:07.340213+00:00 app[web.1]: at org.jdbi.v3.core.Jdbi.<init>(Jdbi.java:58)
2022-10-10T03:22:07.340233+00:00 app[web.1]: at org.jdbi.v3.core.Jdbi.create(Jdbi.java:104)
2022-10-10T03:22:07.340258+00:00 app[web.1]: at org.jdbi.v3.core.Jdbi.create(Jdbi.java:88)
2022-10-10T03:22:07.340289+00:00 app[web.1]: at dao.JDBIDaoFactory.initialisePool(JDBIDaoFactory.java:39)
2022-10-10T03:22:07.340315+00:00 app[web.1]: at dao.JDBIDaoFactory.getPersonDAO(JDBIDaoFactory.java:45)
2022-10-10T03:22:07.340359+00:00 app[web.1]: at group5MentorMatcher.Main.<init>(Main.java:32)
2022-10-10T03:22:07.340391+00:00 app[web.1]: at group5MentorMatcher.Main.main(Main.java:68)
2022-10-10T03:22:07.340479+00:00 app[web.1]: Caused by: java.lang.ClassNotFoundException: com.github.benmanes.caffeine.cache.Caffeine
2022-10-10T03:22:07.340510+00:00 app[web.1]: at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
2022-10-10T03:22:07.340543+00:00 app[web.1]: at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
2022-10-10T03:22:07.340573+00:00 app[web.1]: at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
2022-10-10T03:22:07.341430+00:00 app[web.1]: at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
2022-10-10T03:22:07.341432+00:00 app[web.1]: ... 14 more
2022-10-10T03:22:07.473893+00:00 heroku[web.1]: Process exited with status 1
2022-10-10T03:22:07.584112+00:00 heroku[web.1]: State changed from starting to crashed
2022-10-10T03:22:07.587213+00:00 heroku[web.1]: State changed from crashed to starting
2022-10-10T03:22:10.727576+00:00 heroku[web.1]: Starting process with command `java -jar app/build/libs/app.jar`
2022-10-10T03:22:11.754717+00:00 app[web.1]: Setting JAVA_TOOL_OPTIONS defaults based on dyno size. Custom settings will override them.
2022-10-10T03:22:11.759021+00:00 app[web.1]: Picked up JAVA_TOOL_OPTIONS: -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8
2022-10-10T03:22:12.078014+00:00 app[web.1]: Exception in thread "main" java.lang.NoClassDefFoundError: com/github/benmanes/caffeine/cache/Caffeine
2022-10-10T03:22:12.078115+00:00 app[web.1]: at org.jdbi.v3.core.statement.CachingSqlParser.<init>(CachingSqlParser.java:25)
2022-10-10T03:22:12.078141+00:00 app[web.1]: at org.jdbi.v3.core.statement.ColonPrefixSqlParser.<init>(ColonPrefixSqlParser.java:41)
2022-10-10T03:22:12.078165+00:00 app[web.1]: at org.jdbi.v3.core.statement.SqlStatements.<init>(SqlStatements.java:53)
2022-10-10T03:22:12.078193+00:00 app[web.1]: at org.jdbi.v3.core.config.ConfigRegistry.lambda$configFactory$3(ConfigRegistry.java:100)
2022-10-10T03:22:12.078219+00:00 app[web.1]: at org.jdbi.v3.core.internal.exceptions.Unchecked.lambda$function$4(Unchecked.java:76)
2022-10-10T03:22:12.078256+00:00 app[web.1]: at org.jdbi.v3.core.config.ConfigRegistry.get(ConfigRegistry.java:78)
2022-10-10T03:22:12.078281+00:00 app[web.1]: at org.jdbi.v3.core.config.ConfigRegistry.<init>(ConfigRegistry.java:47)
2022-10-10T03:22:12.078305+00:00 app[web.1]: at org.jdbi.v3.core.Jdbi.<init>(Jdbi.java:58)
2022-10-10T03:22:12.078327+00:00 app[web.1]: at org.jdbi.v3.core.Jdbi.create(Jdbi.java:104)
2022-10-10T03:22:12.078377+00:00 app[web.1]: at org.jdbi.v3.core.Jdbi.create(Jdbi.java:88)
2022-10-10T03:22:12.078377+00:00 app[web.1]: at dao.JDBIDaoFactory.initialisePool(JDBIDaoFactory.java:39)
2022-10-10T03:22:12.078395+00:00 app[web.1]: at dao.JDBIDaoFactory.getPersonDAO(JDBIDaoFactory.java:45)
2022-10-10T03:22:12.078453+00:00 app[web.1]: at group5MentorMatcher.Main.<init>(Main.java:32)
2022-10-10T03:22:12.078467+00:00 app[web.1]: at group5MentorMatcher.Main.main(Main.java:68)
2022-10-10T03:22:12.078587+00:00 app[web.1]: Caused by: java.lang.ClassNotFoundException: com.github.benmanes.caffeine.cache.Caffeine
2022-10-10T03:22:12.078628+00:00 app[web.1]: at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
2022-10-10T03:22:12.078667+00:00 app[web.1]: at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
2022-10-10T03:22:12.078694+00:00 app[web.1]: at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
2022-10-10T03:22:12.078722+00:00 app[web.1]: at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
2022-10-10T03:22:12.078775+00:00 app[web.1]: ... 14 more
2022-10-10T03:22:12.237958+00:00 heroku[web.1]: Process exited with status 1
2022-10-10T03:22:12.297708+00:00 heroku[web.1]: State changed from starting to crashed
2022-10-10T03:22:12.719118+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=intense-bastion-46272.herokuapp.com request_id=3042533f-c6d7-48a2-b5d8-d80384ee3514 fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:22:13.179675+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=intense-bastion-46272.herokuapp.com request_id=f78a3a9f-f2ea-442d-97b0-7bc441f360fc fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:22:14.000000+00:00 app[api]: Build succeeded
2022-10-10T03:22:58.344804+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=intense-bastion-46272.herokuapp.com request_id=e40e294d-f979-43cb-9954-262d0add0f65 fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:22:59.145356+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=intense-bastion-46272.herokuapp.com request_id=1fd76e2f-ba11-4564-b5c6-0c49927b0bd9 fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:22:59.918467+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=intense-bastion-46272.herokuapp.com request_id=1152492a-56a6-4336-a05b-313bf27db344 fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:23:00.694990+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=intense-bastion-46272.herokuapp.com request_id=ff8267ca-e4bf-4eba-a663-eed2b01631de fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:23:10.435273+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=intense-bastion-46272.herokuapp.com request_id=b3027c0c-41f4-4b21-afcb-887de8f10530 fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:23:11.257817+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=intense-bastion-46272.herokuapp.com request_id=39dfd85c-4ba2-4a77-a87a-b433276f72e0 fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:31:19.036836+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=intense-bastion-46272.herokuapp.com request_id=74c91344-577b-4f84-9cba-718f0bd3ad21 fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https
2022-10-10T03:31:19.461871+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=intense-bastion-46272.herokuapp.com request_id=459792e2-1462-4ef7-a1d5-a5699d345fb6 fwd="122.62.121.70" dyno= connect= service= status=503 bytes= protocol=https

The error seems to be NoClassDefFound wtth caffeine , but looking at my files locally the Caffeine jar is there.

My build.gradle looks like

plugins {
    // Apply the application plugin to add support for building a CLI application in Java.
    id 'application'  
}

jar {
    manifest {
        attributes(
                'Main-Class': 'group5MentorMatcher.Main',
                'Class-Path': 'jooby-2.13.0.jar javax.inject-1.jar config-1.4.1.jar \n\
                jdbi3-core-3.21.0.jar HikariCP-4.0.3.jar slf4j-api-1.7.36.jar antlr4-runtime-4.9.2.jar \n\
                caffeine-3.0.3.jar checker-qual-3.8.0.jar error_prone_annotations-2.5.1.jar \n\
                failureaccess-1.0.1.jar geantyref-1.3.11.jar gson-2.8.6.jar guava-30.1.1-jre.jar\n\
                j2objc-annotations-1.3.jar jdbi3-sqlobject-3.21.0.jar jooby-gson-2.13.0.jar\n\
                jooby-netty-2.13.0.jar jooby-swagger-ui-2.13.0.jar jsr305-3.0.2.jar\n\
                listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar logback-classic-1.2.10.jar\n\
                logback-core-1.2.10.jar netty-buffer-4.1.73.Final.jar netty-codec-4.1.73.Final.jar\n\
                netty-codec-http-4.1.73.Final.jar netty-common-4.1.73.Final.jar netty-handler-4.1.73.Final.jar\n\
                netty-resolver-4.1.73.Final.jar netty-tcnative-classes-2.0.46.Final.jar netty-transport-4.1.73.Final.jar\n\
                postgresql-42.4.0.jar'
        );
    }
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    //Dependencies for testing
    def junitVer = "5.8.2";
    testImplementation group: "org.junit.jupiter", name: "junit-jupiter-api", version: junitVer;
    testRuntimeOnly group: "org.junit.jupiter", name: "junit-jupiter-engine", version: junitVer;
    testImplementation group: "org.hamcrest", name: "hamcrest", version: "2.2";

    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'

    // This dependency is used by the application.
    implementation 'com.google.guava:guava:30.1.1-jre'
    
    // Use postgres to connect to the database
    implementation 'org.postgresql:postgresql:42.4.0'

    // guava
        implementation group: 'com.google.guava', name: 'guava', version: '30.1.1-jre'

    // jooby
    def joobyVer =  '2.13.0'
    implementation group: 'io.jooby', name: 'jooby-netty', version: joobyVer
    implementation group: 'io.jooby', name: 'jooby-gson', version: joobyVer
    implementation group: 'io.jooby', name: 'jooby-swagger-ui', version: joobyVer

    //logging
        implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.36'
        implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.10'

        implementation group: 'com.zaxxer', name: 'HikariCP', version: '4.0.3'
        implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.5'

        def jdbiVer = '3.21.0'
        implementation group: 'org.jdbi', name: 'jdbi3-core', version: jdbiVer
        implementation group: 'org.jdbi', name: 'jdbi3-sqlobject', version: jdbiVer
}

application {
    // Define the main class for the application.
    mainClass = 'group5MentorMatcher.Main'
}

//test {
//    useJUnitPlatform();
//    onlyIf { project.gradle.startParameter.taskNames.contains("test") }
//}

//tasks.named('test') {
    // Use JUnit Platform for unit tests.
 //   useJUnitPlatform()
//}

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

task copyToLib(type: Copy) {
    from configurations.compileClasspath
    into 'build/libs'
}

stage.dependsOn(copyToLib)

gradle.taskGraph.whenReady {
  taskGraph ->
    if (taskGraph.hasTask(stage)) {
      test.enabled = false
    }
}

sourceSets {
    'static' {
        resources {
            srcDirs = ['static']
        }
        java{
            srcDirs = []
        }
    }
}

and my procfile looks like

web: java -jar app/build/libs/app.jar

I have been on this for so long and I cant figure out the issue, any help would be greatly appreciated


Solution

  • This happens when there is a class file that your code depends on and it is present at compile time(it works locally) but not found at runtime(on heroku open). You can look for differences in your build time and runtime classpaths.

    You can get classpath using simple program.

    You can try and build a fat jar and start your java program with fat jar with all the dependencies.

    Further Reference to build Uber/Fat Jar : https://stackoverflow.com/a/4894308/8017666