Config
This guide describes how to create a sample MicroProfile (MP) project that can be used to run some basic examples using both default and custom configuration with Helidon MP.
What You Need
For this 20 minute tutorial, you will need the following:
| Requirement | Description |
|---|---|
| Java 21 (Open JDK 21) | Helidon requires Java 21+ (25+ recommended). |
| Maven 3.8+ | Helidon requires Maven 3.8+. |
| Docker 18.09+ | If you want to build and run Docker containers. |
| Kubectl 1.16.5+ | If you want to deploy to Kubernetes, you need kubectl and a Kubernetes cluster. |
Prerequisite product versions for Helidon 4.4.0-SNAPSHOT
Verify Prerequisites:
java -version
mvn --version
docker --version
kubectl version
Setting JAVA_HOME:
# On Mac
export JAVA_HOME=`/usr/libexec/java_home -v 21`
# On Linux
# Use the appropriate path to your JDK
export JAVA_HOME=/usr/lib/jvm/jdk-21
Getting Started with Configuration
Helidon provides a very flexible and comprehensive configuration system, offering you many application configuration choices. You can include configuration data from a variety of sources using different formats, like JSON and YAML. Furthermore, you can customize the precedence of sources and make them optional or mandatory. This guide introduces Helidon MP configuration and demonstrates the fundamental concepts using several examples. Refer to Helidon Config for the full configuration concepts documentation.
Create a Sample Helidon MP Project
Use the Helidon MP Maven archetype to create a simple project that can be used for the examples in this guide.
Run the Maven archetype:
mvn -U archetype:generate -DinteractiveMode=false \
-DarchetypeGroupId=io.helidon.archetypes \
-DarchetypeArtifactId=helidon-quickstart-mp \
-DarchetypeVersion=4.4.0-SNAPSHOT \
-DgroupId=io.helidon.examples \
-DartifactId=helidon-quickstart-mp \
-Dpackage=io.helidon.examples.quickstart.mp
The project will be built and run from the helidon-quickstart-mp directory:
cd helidon-quickstart-mp
Default Configuration
Helidon has an internal configuration, so you are not required to provide any
configuration data for your application, though in practice you most likely
would. By default, that configuration can be overridden from three sources:
system properties, environment variables, and the contents of
META-INF/microprofile-config.properties. For example, if you specify a custom
server port in META-INF/microprofile-config.properties then your server will
listen on that port.
A main class is also required to start up the server and run the application. By
default, the Quickstart sample project uses the built-in Helidon main class. In
this guide you want to use your own main class, so you have more control over
the server initialization. First define your own Main:
In this class, a main method is defined which starts the Helidon MP server and
prints out a message with the listen address.
<properties>
<mainClass>io.helidon.examples.quickstart.mp.Main</mainClass>
</properties>
This property will be used to set the Main-Class attribute in the application
jar’s MANIFEST.
In your application code, Helidon uses the default configuration when you create
a Server object without a custom Config object. See the following code from
the project you created.
View Main#startServer:
Source Precedence for Default Configuration
In order to properly configure your application using configuration sources, you need to understand the precedence rules that Helidon uses to merge your configuration data. By default, Helidon will use the following sources in precedence order:
- Java system properties
- Environment variables
- Properties specified in
META-INF/microprofile-config.properties
Each of these sources specify configuration properties in Java Property format
(key/value), like color=red. If any of the Helidon required properties are not
specified in one of these source, like server.port, then Helidon will use a
default value.
The following examples will demonstrate the default precedence order.
Default Configuration Resource
Change a configuration parameter in the default configuration resource file,
META-INF/microprofile-config.properties. There are no environment variable or
system property overrides defined.
Change app.greeting in the META-INF/microprofile-config.properties from Hello
to HelloFromMPConfig:
app.greeting=HelloFromMPConfig
Build the application, skipping unit tests, then run it:
mvn package -DskipTests=true
java -jar target/helidon-quickstart-mp.jar
Run the curl command in a new terminal window and check the response:
curl http://localhost:8080/greet
Environment Variable Override
An environment variable has a higher precedence than the configuration properties file.
Set the environment variable and restart the application:
export APP_GREETING=HelloFromEnvironment
java -jar target/helidon-quickstart-mp.jar
Invoke the endpoint:
curl http://localhost:8080/greet
System Property Override
A system property has a higher precedence than environment variables.
Restart the application with a system property. The app.greeting environment variable is still set:
java -Dapp.greeting="HelloFromSystemProperty" -jar target/helidon-quickstart-mp.jar
Invoke the endpoint:
curl http://localhost:8080/greet
Accessing Config within an Application
The examples in this section will demonstrate how to access that config data at
runtime. Your application uses the Config object to access the in-memory tree,
retrieving config data.
The generated project already accesses configuration data in the
GreetingProvider class as follows:
View the following code from GreetingProvider.java:
Injecting at Field Level
You can inject configuration at the field level as shown below. Use the
volatile keyword since you cannot use AtomicReference with field level
injection.
Update the meta configuration with the following content:
Update the following code from GreetingProvider.java:
Build and run the application, then invoke the endpoint:
curl http://localhost:8080/greet
{
"message": "HelloFromMPConfig World!"
}
Injecting the Config Object
You can inject the Config object into the class and access it directly as
shown below.
Replace the GreetingProvider class:
Build and run the application, then invoke the endpoint:
curl http://localhost:8080/greet
{
"message": "HelloFromMPConfig World!"
}
Navigating the Config Tree
Helidon offers a variety of methods to access in-memory configuration. These can
be categorized as key access or tree navigation. You have been using key
access for all the examples to this point. For example app.greeting is
accessing the greeting child node of the app parent node.
This simple example below demonstrates how to access a child node as a detached configuration subtree.
Create the following file:
app:
greeting:
sender: Joe
message: Hello-from-config-file.yaml
Update the meta configuration:
sources:
- type: "classpath"
properties:
resource: "META-INF/microprofile-config.properties"
- type: "file"
properties:
path: "./config-file.yaml"
Replace GreetingProvider class with the following code:
Build and run the application, then invoke the endpoint:
curl http://localhost:8080/greet
{
"message": "Joe says Hello-from-config-file.yaml World!"
}
Integration with Kubernetes
The following example uses a Kubernetes ConfigMap to pass the configuration data
to your Helidon application deployed to Kubernetes. When the pod is created,
Kubernetes will automatically create a local file within the container that has
the contents of the configuration file used for the ConfigMap. This example will
create the file at /etc/config/config-file.properties.
Update the Main class and replace the buildConfig method:
Update the following code from GreetingProvider.java:
@ApplicationScoped
public class GreetingProvider {
@Inject
@ConfigProperty(name = "app.greeting")
private volatile String message;
String getMessage() {
return message;
}
void setMessage(String message) {
this.message = message;
}
}
Build and run the application, then invoke the endpoint:
curl http://localhost:8080/greet
Stop the application and build the docker image:
docker build -t helidon-config-mp .
Generate a ConfigMap from config-file.properties:
kubectl create configmap helidon-configmap --from-file config-file.properties
View the contents of the ConfigMap:
kubectl get configmap helidon-configmap -o yaml
Create the Kubernetes YAML specification:
Create and deploy the application into Kubernetes:
kubectl apply -f ./k8s-config.yaml
Get the service information:
kubectl get service/helidon-config
Verify the configuration endpoint using port 31143, your port will likely be different:
curl http://localhost:31143/greet
You can now delete the Kubernetes resources that were just created during this example.
Delete the Kubernetes resources:
kubectl delete -f ./k8s-config.yaml
kubectl delete configmap helidon-configmap
Summary
This guide has demonstrated how to use basic Helidon configuration features. For more information about using the advanced Helidon configuration features, including mutability support and extensions, see Helidon Configuration.
Reference
Refer to the following references for additional information: