Getting Started with Gradle on Heroku
Introduction
Complete this tutorial to deploy a sample Java app to Cedar, the legacy generation of the Heroku platform. To deploy the app to the Fir generation, only available to Heroku Private Spaces, follow this guide instead.
The tutorial assumes that you have:
- A verified Heroku Account
- OpenJDK 17 (or newer) installed
- Postgres installed
- An Eco dynos plan subscription (recommended)
If you’d prefer to use Maven instead of Gradle, see the Getting Started with Java guide.
We recommend using our low-cost plans to complete this tutorial. Eligible students can apply for platform credits through our new Heroku for GitHub Students program.
Set Up
The Heroku CLI requires Git, the popular version control system. If you don’t already have Git installed, complete the following before proceeding:
In this step, you install the Heroku Command Line Interface (CLI). You use the CLI to manage and scale your applications, provision add-ons, view your recent application logs, and run your application locally.
Download and run the installer for your platform:
$ brew tap heroku/brew && brew install heroku
Download the appropriate installer for your Windows installation:
After installation completes, you can use the heroku
command from your terminal.
Use the heroku login
command to log in to the Heroku CLI:
$ heroku login
heroku: Press any key to open up the browser to login or q to exit
› Warning: If browser does not open, visit
› https://cli-auth.heroku.com/auth/browser/***
heroku: Waiting for login...
Logging in... done
Logged in as me@example.com
This command opens your web browser to the Heroku login page to complete authentication. If your browser is already logged in to Heroku, click the Log in
button displayed on the page.
Both the heroku
and git
commands require this authentication to work correctly.
If you’re behind a firewall that requires a proxy to connect with external HTTP/HTTPS services, set the HTTP_PROXY
or HTTPS_PROXY
environment variables in your local development environment before running the heroku
command.
Prepare the App
In this step, you clone a sample application and prepare to deploy it to Heroku.
If you’re new to Heroku, it’s recommended to complete this tutorial using the Heroku-provided sample application.
If you have your own application that you want to deploy instead, see Preparing a Codebase for Heroku Deployment.
Create a local copy of the sample app by executing the following commands in your local command shell or terminal:
$ git clone https://github.com/heroku/gradle-getting-started
$ cd gradle-getting-started
This functioning Git repository contains a simple Java application. The application includes a Procfile
, a special plaintext file used by Heroku apps. You explicitly declare the processes and commands used to start your app in this file.
The Procfile
in the example app source code looks like this:
web: java -jar build/libs/java-getting-started-gradle-1.0.0-SNAPSHOT.jar
This file declares a single process type, web
, and the command needed to run it. The name web
is important. It declares that this process type attaches to Heroku’s HTTP routing stack, and is able to receive web traffic.
Procfiles can contain additional process types. For example, you can declare a background worker that processes items off a queue. This tutorial doesn’t cover other processes but you can refer to The Procfile and The Process Model for more info.
The example app also includes a build.gradle.kts
file which is used by Gradle, a Java build tool. The next step covers how to use this file to declare dependencies.
Declare App Dependencies
Heroku automatically identifies an app as a Gradle app if it contains a build.gradle.kts
file in the root directory. When a Gradle app is detected, Heroku adds the official Gradle buildpack to your app, which installs the dependencies for your application.
The example app you deployed already has a build.gradle.kts
(see it here).
When deploying an app, Heroku reads this file and installs the dependencies. Take a look at the dependencies listed in your build.gradle.kts
.
Another file, system.properties
, indicates the version of Java to use. The contents of this optional file look like:
java.runtime.version=17
Heroku supports many different versions. You can push your own apps using a different version of Java.
Deploy the App
In this step you will deploy the app to Heroku.
Using a dyno and a database to complete this tutorial counts towards your usage. Delete your app and database as soon as you are done experimenting to control costs.
By default, apps use Eco dynos if you are subscribed to Eco. Otherwise, it defaults to Basic dynos. The Eco dynos plan is shared across all Eco dynos in your account and is recommended if you plan on deploying many small apps to Heroku. Learn more here. Eligible students can apply for platform credits through our Heroku for GitHub Students program.
Create an app on Heroku to prepare it to receive your source code for deployment:
$ heroku create
Creating app... done, ⬢ peaceful-inlet-84135
https://peaceful-inlet-84135.herokuapp.com/ | https://git.heroku.com/peaceful-inlet-84135.git
This command both creates an app and a Git remote (named heroku
) associated with your local Git repository.
By default, Heroku generates a random name for your app. You can pass a parameter to specify your own app name.
If you create your app via the Heroku Dashboard instead of using the CLI command, add a remote to your local repo with heroku git:remote --app example-app
.
Now deploy your code:
$ git push heroku main
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-22 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Gradle app detected
remote: -----> Spring Boot detected
remote: -----> Installing OpenJDK 17... done
remote: -----> Building Gradle app...
remote: -----> executing ./gradlew build -x check
remote: Downloading https://services.gradle.org/distributions/gradle-7.6.1-bin.zip
remote: ...........10%............20%...........30%............40%............50%...........60%............70%............80%...........90%............100%
remote: To honour the JVM settings for this build a single-use Daemon process will be forked. See https://docs.gradle.org/7.6.1/userguide/gradle_daemon.html#sec:disabling_the_daemon.
remote: Daemon will be stopped at the end of the build
remote: > Task :compileJava
remote: > Task :processResources
remote: > Task :classes
remote: > Task :resolveMainClassName
remote: > Task :bootJar
remote: > Task :jar
remote: > Task :assemble
remote: > Task :build
remote:
remote: BUILD SUCCESSFUL in 1m 9s
remote: 5 actionable tasks: 5 executed
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 85.6M
remote: -----> Launching...
remote: Released v5
remote: https://peaceful-inlet-84135.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/peaceful-inlet-84135.git
* [new branch] main -> main
By default, your app deploys on a eco dyno. A dyno is a lightweight Linux container that runs the command specified in your Procfile
. After deployment, ensure that you have one web
dyno running the app. You can check how many dynos are running using the heroku ps
command:
$ heroku ps
Eco dyno hours quota remaining this month: 1000h 0m (100%)
Eco dyno usage for this app: 0h 0m (0%)
For more information on Eco dyno hours, see:
https://devcenter.heroku.com/articles/eco-dyno-hours
=== web (Eco): java -jar build/libs/java-getting-started-gradle-1.0.0-SNAPSHOT.jar (1)
web.1: up 2023/03/09 17:00:28 +0100 (~ 1m ago)
The running web
dynos serve requests. Visit the app at the URL generated by its app name. As a handy shortcut, you can open the website with:
$ heroku open
Eco dynos sleep after thirty minutes of inactivity (for example, if they don’t receive any traffic). This behavior causes a delay of a few seconds for the first request upon waking. Subsequent requests perform normally. Eco dynos consume from a monthly, account-level quota of eco dyno hours. As long as you haven’t exhausted the quota, your apps can continue to run.
To avoid dyno sleeping, upgrade to a Basic or Professional dyno type as described in Dyno Types.
Scale the App
Horizontal scaling an application on Heroku is equivalent to changing the number of running dynos.
Scale the number of web dynos to zero:
$ heroku ps:scale web=0
Access the app again by refreshing your browser or running heroku open
. You get an error message because your app no longer has any web dynos available to serve requests.
Scale it up again:
$ heroku ps:scale web=1
You can also vertically scale your app by upgrading to larger dynos. See Dyno Types and Scaling Your Dyno Formation for more info.
View Logs
Heroku aggregates all output streams from both your app and the platform’s components into a single channel of time-ordered logs.
View information about your running app using the heroku logs --tail
command:
$ heroku logs --tail
2023-03-09T16:03:23.130513+00:00 app[web.1]: 2023-03-09T16:03:23.130Z INFO 2 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 41040 (http)
2023-03-09T16:03:23.141029+00:00 app[web.1]: 2023-03-09T16:03:23.140Z INFO 2 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-03-09T16:03:23.141265+00:00 app[web.1]: 2023-03-09T16:03:23.141Z INFO 2 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.5]
2023-03-09T16:03:23.218914+00:00 app[web.1]: 2023-03-09T16:03:23.218Z INFO 2 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-03-09T16:03:23.220624+00:00 app[web.1]: 2023-03-09T16:03:23.220Z INFO 2 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 976 ms
2023-03-09T16:03:23.469655+00:00 app[web.1]: 2023-03-09T16:03:23.469Z INFO 2 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
2023-03-09T16:03:23.692938+00:00 app[web.1]: 2023-03-09T16:03:23.692Z INFO 2 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 41040 (http) with context path ''
2023-03-09T16:03:23.707694+00:00 app[web.1]: 2023-03-09T16:03:23.707Z INFO 2 --- [ main] c.heroku.java.GettingStartedApplication : Started GettingStartedApplication in 1.927 seconds (process running for 2.33)
2023-03-09T16:03:23.940755+00:00 heroku[web.1]: State changed from starting to up
2023-03-09T16:03:24.673236+00:00 app[web.1]: 2023-03-09T16:03:24.672Z INFO 2 --- [io-41040-exec-3] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-03-09T16:03:24.673549+00:00 app[web.1]: 2023-03-09T16:03:24.673Z INFO 2 --- [io-41040-exec-3] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2023-03-09T16:03:24.674938+00:00 app[web.1]: 2023-03-09T16:03:24.674Z INFO 2 --- [io-41040-exec-3] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2023-03-09T16:03:24.948408+00:00 heroku[router]: at=info method=GET path="/" host=peaceful-inlet-84135.herokuapp.com request_id=e010a5e5-f212-4e0b-a624-c96f7421c98f fwd="85.222.134.1" dyno=web.1 connect=0ms service=304ms status=200 bytes=8917 protocol=https
2023-03-09T16:03:25.162539+00:00 heroku[router]: at=info method=GET path="/stylesheets/main.css" host=peaceful-inlet-84135.herokuapp.com request_id=dcbe440f-82c5-4442-80bc-be7be0b5cd61 fwd="85.222.134.1" dyno=web.1 connect=0ms service=10ms status=304 bytes=208 protocol=https
2023-03-09T16:03:25.335819+00:00 heroku[router]: at=info method=GET path="/lang-logo.png" host=peaceful-inlet-84135.herokuapp.com request_id=071b67a6-1e22-4cfe-b57b-c49db6b5af19 fwd="85.222.134.1" dyno=web.1 connect=0ms service=3ms status=304 bytes=208 protocol=https
2023-03-09T16:03:25.534061+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=peaceful-inlet-84135.herokuapp.com request_id=cc651ead-23ce-4c43-a3ce-4edc93450b14 fwd="85.222.134.1" dyno=web.1 connect=0ms service=82ms status=404 bytes=333 protocol=https
Visit your application in the browser again to generate another log message.
Press CTRL+C
to stop streaming logs.
By default, Heroku stores your app’s 1500 most recent log lines. You can provision a logging add-on or implement your own log drain for long-term storage. In the next step, you add a logging add-on to your app.
Provision Add-ons
Add-ons are cloud services that provide additional services for your application, such as databases, logging, and monitoring.
Several logging add-ons are available that provide features such as log persistence, search, and alerting. Papertrail is one such add-on with a free plan.
Provision the add-on like so:
$ heroku addons:create papertrail
Creating papertrail on ⬢ peaceful-inlet-84135... free
Welcome to Papertrail. Questions and ideas are welcome (technicalsupport@solarwinds.com). Happy logging!
Created papertrail-slippery-84785 as PAPERTRAIL_API_TOKEN
Use heroku addons:docs papertrail to view documentation
This command provisions the add-on and configures it for your application. To see this particular add-on in action, visit your application’s Heroku URL a few times. Each visit generates more log messages, which routes to the Papertrail add-on. Visit the Papertrail console to see the log messages:
$ heroku addons:open papertrail
Your browser opens up a Papertrail web console that shows the latest log events. The interface lets you search and set up alerts.
You can list all of your app’s active add-ons like so:
$ heroku addons
Running this command for your sample app lists its Papertrail add-on.
Use a Database
Adding a database to complete this tutorial counts towards your usage. Delete your database as soon as you’re done to control costs. Learn about our low-cost plans. Eligible students can apply for platform credits through our Heroku for GitHub Students program.
Heroku provides managed data services for Postgres and Redis, and the add-on marketplace provides additional data services, including MongoDB and MySQL.
Use the heroku addons:create
command to provision a Postgres database for your app:
$ heroku addons:create heroku-postgresql:essential-0
Creating heroku-postgresql:essential-0 on ⬢ peaceful-inlet-84135... ~$0.007/hour (max $5/month)
Database should be available soon
postgresql-fitted-70383 is being created in the background. The app will restart when complete...
Use heroku addons:info postgresql-fitted-70383 to check creation progress
Use heroku addons:docs heroku-postgresql to view documentation
Use the heroku addons
command for an overview of the database provisioned for your app:
$ heroku addons
Add-on Plan Price State
─────────────────────────────────────────── ─────────── ──────── ───────
heroku-postgresql (postgresql-fitted-70383) essential-0 $5/month created
└─ as DATABASE
papertrail (papertrail-slippery-84785) choklad free created
└─ as PAPERTRAIL
The table above shows add-ons and the attachments to the current app (peaceful-inlet-84135) or other apps.
Listing your app’s config vars displays the URL that your app uses to connect to the database (DATABASE_URL
):
$ heroku config
=== peaceful-inlet-84135 Config Vars
DATABASE_URL: postgres://avhrhofbiyvpct:3ab23026d0fc225bde4544cedabc356904980e6a02a2418ca44d7fd19dad8e03@ec2-23-21-4-7.compute-1.amazonaws.com:5432/d8e8ojni26668k
PAPERTRAIL_API_TOKEN: ChtIUu9fHbij1cBn7y6z
The heroku pg
command provides more in-depth information on your app’s Heroku Postgres databases:
$ heroku pg
=== DATABASE_URL
Plan: Essential 0
Status: Available
Connections: 0/20
PG Version: 15.5
Created: 2024-05-01 16:00 UTC
Data Size: 8.6 MB/1.00 GB (0.84%) (In compliance)
Tables: 0
Fork/Follow: Unsupported
Rollback: Unsupported
Continuous Protection: Off
Add-on: postgresql-fitted-70383
Running this command for your app indicates that the app has an essential-0
Postgres database with no tables.
The example app you deployed already has database functionality, which you can reach by visiting your app’s /database
path.
$ heroku open /database
You see something like this:
Database Output
* Read from DB: 2023-03-09 16:58:55.816605
* Read from DB: 2023-03-09 16:58:56.728701
* Read from DB: 2023-03-09 16:58:57.064755
Assuming that you have Postgres installed locally, use the heroku pg:psql
command to connect to the remote database and see all the rows:
$ heroku pg:psql
--> Connecting to postgresql-fitted-70383
psql (15.2, server 14.7 (Ubuntu 14.7-1.pgdg20.04+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
peaceful-inlet-84135::DATABASE=> SELECT * FROM ticks;
tick
----------------------------
2023-03-09 16:58:55.816605
2023-03-09 16:58:56.728701
2023-03-09 16:58:57.064755
(3 rows)
peaceful-inlet-84135::DATABASE=> \q
The following info illustrates how the example app implements its database functionality. Don’t make changes to your example app code in this step.
The code in the example app looks like this:
private final DataSource dataSource;
@Autowired
public GettingStartedApplication(DataSource dataSource) {
this.dataSource = dataSource;
}
@GetMapping("/database")
String database(Map<String, Object> model) {
try (Connection connection = dataSource.getConnection()) {
final var statement = connection.createStatement();
statement.executeUpdate("CREATE TABLE IF NOT EXISTS ticks (tick timestamp)");
statement.executeUpdate("INSERT INTO ticks VALUES (now())");
final var resultSet = statement.executeQuery("SELECT tick FROM ticks");
final var output = new ArrayList<>();
while (resultSet.next()) {
output.add("Read from DB: " + resultSet.getTimestamp("tick"));
}
model.put("records", output);
return "database";
} catch (Throwable t) {
model.put("message", t.getMessage());
return "error";
}
}
The database
method adds a new row to the tick
table when you access your app using the /database
route. It then returns all rows to render in the output.
The DataSource
shown in the example app code is automatically configured and injected by the Spring Boot framework. It refers to the values in the src/main/resources/application.properties
file for the database connection configuration.
The example app has spring.datasource.url
set to the value in the JDBC_DATABASE_URL
environment variable to establish a pool of connections to the database:
spring.datasource.url: ${JDBC_DATABASE_URL}
The official Heroku Gradle buildpack that’s automatically added to your app sets this JDBC_DATABASE_URL
environment variable. This variable is dynamic and doesn’t appear in your list of configuration variables when running heroku config
. You can view it by running the following command:
$ heroku run echo \$JDBC_DATABASE_URL
Read more about Heroku PostgreSQL. You can also install Redis or other data add-ons via heroku addons:create
.
Prepare the Local Environment
In the following steps, you learn how to work with your app locally and push changes to Heroku. Begin by installing your dependencies locally in this step.
Run ./gradlew build
in your local directory. This command installs the dependencies, preparing your system to run the app locally.
$ ./gradlew build
BUILD SUCCESSFUL in 800ms
5 actionable tasks: 5 executed
The Maven process compiles and builds a JAR, with dependencies, placing it into your application’s target
directory. The spring-boot-maven-plugin
in the pom.xml
provides this process.
After installing dependencies, you can run your app locally. However, the app requires a Postgres database. Create a local Postgres database and update your local .env
file. heroku local
, the command used to run apps locally, automatically sets up your environment based on the .env
file in your app’s root directory. Set the JDBC_DATABASE_URL
environment variable with your local Postgres database’s connection string:
JDBC_DATABASE_URL=jdbc:postgresql://localhost:5432/java_database_name
Your local environment is now ready to run your app and connect to the database.
Run the App Locally
Ensure you’ve already run ./gradlew build
before running your app locally.
Start your application locally with the heroku local
CLI command:
$ heroku local --port 5001
...
5:26:58 PM web.1 | 2023-03-09T17:26:58.009+01:00 INFO 39665 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 5001 (http)
5:26:58 PM web.1 | 2023-03-09T17:26:58.014+01:00 INFO 39665 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
5:26:58 PM web.1 | 2023-03-09T17:26:58.014+01:00 INFO 39665 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.5]
5:26:58 PM web.1 | 2023-03-09T17:26:58.055+01:00 INFO 39665 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
5:26:58 PM web.1 | 2023-03-09T17:26:58.056+01:00 INFO 39665 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 497 ms
5:26:58 PM web.1 | 2023-03-09T17:26:58.175+01:00 INFO 39665 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
5:26:58 PM web.1 | 2023-03-09T17:26:58.278+01:00 INFO 39665 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 5001 (http) with context path ''
5:26:58 PM web.1 | 2023-03-09T17:26:58.288+01:00 INFO 39665 --- [ main] c.heroku.java.GettingStartedApplication : Started GettingStartedApplication in 0.931 seconds (process running for 1.119)
Just like the Heroku platform, heroku local
examines your Procfile
to determine what command to run.
Open http://localhost:5001 with your web browser to see your app running locally.
If you want to access the app’s /database
route locally, ensure that your local Postgres database is running before you visit the URL.
To stop the app from running locally, go back to your terminal window and press CTRL+C
to exit.
Push Local Changes
In this step, you make local changes to your app and deploy them to Heroku. Add the following dependency and some code that uses it.
Modify build.gradle.kts
to include a dependency for jscience
by adding the following code inside the dependencies
element:
In file build.gradle.kts
, add the following dependency to the dependencies
element:
implementation("org.jscience:jscience:4.3.1")
In file src/main/java/com/heroku/java/GettingStartedApplication.java
, add the following import statements for the library:
import org.jscience.physics.amount.Amount;
import org.jscience.physics.model.RelativisticModel;
import javax.measure.unit.SI;
Add the following convert
method to GettingStartedApplication.java
:
@GetMapping("/convert")
String convert(Map<String, Object> model) {
RelativisticModel.select();
var energy = Amount.valueOf("12 GeV");
model.put("result", "E=mc^2: " + energy + " = " + energy.to(SI.KILOGRAM));
return "convert";
}
Finally, create a src/main/resources/templates/convert.html
file with these contents:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'hello')}">
<body>
<div class="container">
<p th:text="${result}"/>
</div>
</body>
</html>
Here’s the final source code for GettingStartedApplication.java
. Ensure that your changes look similar. Here’s a diff of all the local changes made.
Test your changes locally:
$ ./gradlew build
BUILD SUCCESSFUL in 734ms
6 actionable tasks: 6 executed
$ heroku local --port 5001
...
6:05:29 PM web.1 | 2023-03-09T18:05:29.514+01:00 INFO 69174 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 492 ms
6:05:29 PM web.1 | 2023-03-09T18:05:29.628+01:00 INFO 69174 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
6:05:29 PM web.1 | 2023-03-09T18:05:29.726+01:00 INFO 69174 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 5001 (http) with context path ''
6:05:29 PM web.1 | 2023-03-09T18:05:29.736+01:00 INFO 69174 --- [ main] c.heroku.java.GettingStartedApplication : Started GettingStartedApplication in 0.911 seconds (process running for 1.099)
Visiting your application’s /convert
path at http://localhost:5001/convert, which displays some scientific conversions:
E=mc^2: 12 GeV = (2.139194076302506E-26 ± 1.4E-42) kg
After testing, deploy your changes. Almost every Heroku deployment follows this same pattern. First, use the git add
command to stage your modified files for commit:
$ git add .
Next, commit the changes to the repository:
$ git commit -m "Add convert endpoint"
Now deploy, just as you did previously:
$ git push heroku main
Finally, check that your updated code successfully deployed by opening your browser to that route:
$ heroku open /convert
Define Config Vars
Heroku lets you externalize your app’s configuration by storing data such as encryption keys or external resource addresses in config vars.
At runtime, config vars are exposed to your app as environment variables. For example, modify GettingStartedApplication.java
so that the method obtains an energy value from the ENERGY
environment variable:
In file src/main/java/com/heroku/java/GettingStartedApplication.java
, change the convert
method:
@GetMapping("/convert")
String convert(Map<String, Object> model) {
RelativisticModel.select();
final var result = java.util.Optional
.ofNullable(System.getenv().get("ENERGY"))
.map(Amount::valueOf)
.map(energy -> "E=mc^2: " + energy + " = " + energy.to(SI.KILOGRAM))
.orElse("ENERGY environment variable is not set!");
model.put("result", result);
return "convert";
}
Recompile the app to integrate this change by running ./gradlew build
.
heroku local
automatically sets up your local environment based on the .env
file in your app’s root directory. Your sample app already includes a .env
file with the following contents:
ENERGY=20 GeV
Your local .env
file also includes the JDBC_DATABASE_URL
variable if you set it during the Run the App Locally step.
Don’t commit the .env
file to version control as it often includes secure credentials. Include .env
in your repo’s .gitignore
file. The sample app repo only includes a .env
file as an example for this tutorial step.
Run the app with heroku local --port 5001
and visit http://localhost:5001/convert to see the conversion value for 20 GeV.
Now that you know it works as expected locally, set this variable as a config var on your app running on Heroku. Execute the following:
$ heroku config:set ENERGY="20 GeV"
Setting ENERGY and restarting ⬢ peaceful-inlet-84135... done, v9
ENERGY: 20 GeV
View the app’s config vars using heroku config
to verify you’ve done it correctly:
$ heroku config
=== peaceful-inlet-84135 Config Vars
DATABASE_URL: postgres://avhrhofbiyvpct:3ab23026d0fc225bde4544cedabc356904980e6a02a2418ca44d7fd19dad8e03@ec2-23-21-4-7.compute-1.amazonaws.com:5432/d8e8ojni26668k
ENERGY: 20 GeV
PAPERTRAIL_API_TOKEN: ChtIUu9fHbij1cBn7y6z
Deploy your local changes to Heroku and visit the /convert
route to see your changes in action:
$ git add .
$ git commit -m "Use ENERGY environment variable"
$ git push heroku main
$ heroku open /convert
Start a One-off Dyno
The heroku run
command lets you run maintenance and administrative tasks on your app in a one-off dyno. It also lets you launch a REPL process attached to your local terminal for experimenting in your app’s environment or your deployed application code:
$ heroku run java -version
Running java -version on ⬢ peaceful-inlet-84135... up, run.4406 (Eco)
openjdk version "17.0.6" 2023-01-17 LTS
OpenJDK Runtime Environment Zulu17.40+19-CA (build 17.0.6+10-LTS)
OpenJDK 64-Bit Server VM Zulu17.40+19-CA (build 17.0.6+10-LTS, mixed mode, sharing)
If you receive an error, Error connecting to process
, configure your firewall.
Remember to type exit
to exit the shell and terminate the dyno.
Next Steps
Congratulations! You now know how to deploy an app, change its configuration, scale it, view logs, attach add-ons, and run it locally.
Here’s some recommended reading to continue your Heroku journey:
- How Heroku Works provides a technical overview of the concepts encountered while writing, configuring, deploying, and running apps.
- The Java category provides more in-depth information on developing and deploying Java apps.
- The Deployment category provides a variety of powerful integrations and features to help streamline and simplify your deployments.