Search code examples
javaspring-bootherokuworkerdyno

Heroku Java Spring Boot web app project -> extend it to include one-off processes within it


We've an up and running Spring Boot java project working in Heroku using web dynos.

Business requirement is to include background processes to sync some master data grabbed from external system by invoking their REST API.

We've built a java class including public "static void main(String[] args)" method within it

package com.whatever.externalsystem.business;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
...

public class BrandNewClass {

    private static Logger logger = LogManager.getLogger(BrandNewClass .class);
    
    public static void main(String[] args) throws Exception {
        
        logger.info("Executing background task");

        }


    }

And edited the existing Procfile to add a new line containing the worker definition

web: java -jar target/myjar-1.0.jar
worker: java -cp target/myjar-1.0.jar com.whatever.externalsystem.business.BrandNewClass

The new process seems to be correctly identified in heroku control panel resources that because it appears there available to assign worker dynos.

However, when we increase the number of worker dynos from 0 to 1 it crashes

2024-06-11T17:10:21.691158+00:00 heroku[worker.1]: Starting process with command `java -cp target/myjar-1.0.jar com.whatever.externalsystem.business.BrandNewClass`
2024-06-11T17:10:22.303063+00:00 heroku[worker.1]: State changed from starting to up
2024-06-11T17:10:23.511665+00:00 app[worker.1]: [heroku-exec] Starting
2024-06-11T17:10:23.540932+00:00 app[worker.1]: Picked up JAVA_TOOL_OPTIONS: -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -javaagent:/app/.heroku/bin/heroku-metrics-agent.jar  -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1098 -Dcom.sun.management.jmxremote.rmi.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.hostname=172.18.90.38 -Djava.rmi.server.port=1099
2024-06-11T17:10:23.729462+00:00 app[worker.1]: Error: Could not find or load main class com.whatever.externalsystem.business.BrandNewClass
2024-06-11T17:10:24.111341+00:00 heroku[worker.1]: Process exited with status 1
2024-06-11T17:10:24.132665+00:00 heroku[worker.1]: State changed from up to crashed

Regarding the pom.xml file, it hasn't been modified so far

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://maven.apache.org/POM/4.0.0"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.whatever</groupId>
  <artifactId>myjar</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
    <relativePath/>
  </parent>

  <properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  </properties>

  <dependencies>

    ...

  </dependencies>

  <build>

    <plugins>

      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <includeSystemScope>true</includeSystemScope>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>build-info</goal>
            </goals>
            <configuration>
              <additionalProperties>
                <encoding.source>${project.build.sourceEncoding}</encoding.source>
                <encoding.reporting>${project.reporting.outputEncoding}</encoding.reporting>
                <java.source>${maven.compiler.source}</java.source>
                <java.target>${maven.compiler.target}</java.target>
              </additionalProperties>
            </configuration>
          </execution>
        </executions>
      </plugin>

 ...

Can you please advise on how to solve this issue?

Kind regards,

We've reviewed the following references:


Solution

  • That won't work for various reason but the largest being you cannot use a Spring Boot application like that due to its structure. You would need to launch the jar differently.

    Some hints can be found in this GitHub ticket. But it boilsdown to change your run command to the following.

    java -cp target/myjar-1.0.jar -Dloader.main=com.whatever.externalsystem.business.BrandNewClass org.springframework.boot.loader.PropertiesLauncher
    

    But maybe you can have some more inspiration from the ticket linked in this answer.