DEV Community

loading...
Cover image for Properties in Spring Boot 2 Tutorial

Properties in Spring Boot 2 Tutorial

scottshipp profile image scottshipp Originally published at code.scottshipp.com ・5 min read

Who this post is for

If you are just getting started with Spring Boot 2, then this post is for you.

As a prerequisite, you have installed Java, Maven, and an IDE like IntelliJ, and you followed along with the Build A Next-Level RESTful Web Service with Spring Boot 2 post. You currently have a running RESTful web service.

Let’s get started

Let’s use the greeting application from the Building a next-level RESTful web service article to add and use a property.

The first thing you will notice is that in the /src/main/resources directory of this application, there is an application.properties file. This file is empty right now. This file was generated by Spring Initializr when we created the application. Remember that I mentioned that the Spring team recommends starting every Spring Boot application with Spring Initializr.

What is this file? application.properties is one of the default “property sources” meaning it is one place that Spring Boot is going to look for properties when the application starts up. Actually, Spring Boot looks for a file named application.properties in several places. You can read about that in the Spring Boot documentation.

Add a property

You can store properties for your Spring Boot 2 applications and services in the application.properties file in a key-value format.

Open up application.properties and add the line:

defaultGreeting=Hello

Once that’s done, you can use the @Value annotation anywhere within your application to refer to this property. The @Value annotation can refer to property variables with placeholders, which use the ${myVariableName} syntax. You can read more about placeholders in the Spring Boot documentation.

Use the property

Open GreetingController.java (found somewhere in /src/main/java/), and let’s now change the template variable from a static variable to a member variable, and annotate it with @Value("${defaultGreeting}"). I also changed the variable name from template to greeting, because “template” isn’t accurate anymore.

The result is this:

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/greeting")
public class GreetingController {
    private final AtomicLong counter = new AtomicLong();

    @Value("${defaultGreeting}")
    private String greeting;

    @GetMapping
    public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
        return customizeGreeting(name);
    }

    @PutMapping
    public ResponseEntity<Greeting> update(String greeting) {
        this.greeting = greeting;
        return ResponseEntity.ok(customizeGreeting("World"));
    }

    private Greeting customizeGreeting(String name) {
        return new Greeting(counter.incrementAndGet(), greeting + ", " + name);
    }
}

Be sure to build (mvn package), run (java -jar target/yourjar.jar), and test this before continuing, just like you did before using curl or Postman. Remember that you will send a GET request to http://localhost:8080/greeting.

Also try updating the value of defaultGreeting in application.properties. You will notice that when you change it while the application is running, nothing happens. You have to stop the application, rebuild it, and rerun it in order for the application to pick up the change.

Properties from Arguments

You currently have a defaultGreeting property in application.properties and you know how to change it.

The rebuild and rerun part of changing a property is fine for some things, but it may not quite be what you want.

What if you could set this property any time you start the application, without changing the application.properties file and rebuilding?

Luckily, you can. Currently, you run the application like this:

java -jar target/greeting-0.0.1-SNAPSHOT.jar

(Note that you may have named your application something else besides “greeting” so that would appear in the jar file name instead.)

You can actually pass properties, as arguments, to that run command. Try this, and see what happens:

java -DdefaultGreeting="Hey" -jar target/greeting-0.0.1-SNAPSHOT.jar

If you test that, you’ll notice that the default greeting changed to “Hey” as expected.

Environment variables

One of the main reasons to use properties is so that your application can run on different machines, but be customized in some ways for the machine it’s running on. Maybe you distinguish between a dev or test machine and a production machine. Or maybe the difference is simply about who is running the application.

In this greeting application, what if we could use the username from the environment to set the default person that the greeting is for?

This is actually rather easy with Spring Boot! Assuming you are using BASH shell, you should have a $USER environment variable. Open a terminal and try typing echo $USER and you should see your username. If you do not have a BASH shell on your machine, go find out how to set an environment variable named USER for your OS before proceeding, and set it to your username.

Update the code to use an environment variable property

So we know that we want to refer to an environment variable named $USER. Can you think of how you might change the code to do that? (Hint: using the @Value annotation.)

As silly as it sounds, you can directly refer to environment variables in @Value annotations in Spring Boot, because it automatically loads them. Environment variables are a default property source that the application populates when it loads up.

So you essentially just add @Value("${USER}"). Go ahead and add a member of the class named user that is a String.

Now, you’ll want to make it so that by default the name variable is set to this value. You may think that we can just set the defaultValue attribute of the @RequestParam to our new user variable, but that won’t be allowed because it requires the use of a constant. So, instead, let’s just remove that. The next thing that we run into is that, by default, query parameters are required, but you can set a required = false attribute, so I’m going to do that. Now, I’m going to go ahead and just check if name is null when we receive it, and in that case set it to the value of user. My final code looks like this:

@RestController
@RequestMapping("/greeting")
public class GreetingController {
    private final AtomicLong counter = new AtomicLong();

    @Value("${defaultGreeting}")
    private String greeting;

    @Value("${USER}")
    private String user = "World";

    @GetMapping
    public Greeting greeting(@RequestParam(value = "name", required = false) String name) {
        if(name == null) {
            name = user;
        }
        return customizeGreeting(name);
    }

    @PutMapping
    public ResponseEntity<Greeting> update(String greeting) {
        this.greeting = greeting;
        return ResponseEntity.ok(customizeGreeting("World"));
    }

    private Greeting customizeGreeting(String name) {
        return new Greeting(counter.incrementAndGet(), greeting + ", " + name);
    }
}

With those changes in place, I rebuild and rerun the application, and now by default the response to my GET request is, “Hello, scottshi” because “scottshi” happens to be the username I chose on this computer. When you run it, you should see your username instead.

What you learned

In this post, you learned how to provide configuration (properties) to a Spring Boot application via:

  • environment variables

  • command-line arguments

  • application.properties

. . . and consume them with the @Value annotation.

In a future post, I will cover more ways to consume properties.

Where to learn more

If you are ready to learn more, right now, check out the Spring Boot reference manual where you can learn:

  • additional default property sources

  • the order of evaluation that Spring Boot follows to determine which properties win

Discussion

pic
Editor guide