[Guide] Building a simple REST API with Spring Boot

Simple getting started blog post on how to create a Spring Boot application from Scratch!

This guide will show how to setup a simple REST API with Spring Boot. The Spring Boot guys have been so pleasent to create a page for easy configuration of your project dependencies. Go to Spring Initializer at start.spring.io. If you use IntelliJ or Spring Tool Suite, you get the same options within these environments as well - hell, they even added a possibility to configure your project via curl (if you are interested, have a look at it here here!).

For now we just use the online version of Spring Initializer.

As you can see in the screendump above, you need to enter some metadata like the name of project, the package name, type of packaging and so on. You also have to choose which build system you want to use, either Maven og Gradle. We use Maven and it seems that this is still the most used build system for Java projects. However, if you prefer Gradle have a look at the official guide provided by spring.io.

When all the project metadata is filled out, we need to add the dependencies we wish to use in our application. Since we are building a simple REST Repository, we for now only add the Web-dependency, which will provide the tools we need to get started.

Great, we are all set now and ready to go! Click the generate project and download the project.

So what do we get with Spring Initializer? As you can see in the screendump above, Spring Initializer creates the project structure, provides you with an example of setting up test cases and configures the main entry of the application.

Let's try to run the default configuration and application that Spring Initializer provided us. If using IntelliJ, you should simply be able to press the Run button. If using the commandline, use the following command to run your application mvn spring-boot:run You should see the following output:

As you can see in the output, Spring provides you with some beautiful created ASCII art for you pleasure every time you run an application. Moreover the output also provides you with the information on which port the application is running. As its printed in the output above, the Tomcat server was started in is running on port: 8080

To verify that this is actually true, grab your favorite browser and type the following:

http://localhost:8080  

You should see the following page, which tells us that the server is running, however we haven't setup any endpoints, yet!
If you want to run your Spring application on another port simply add the following configuration to your application.properties file.

server.port=8081  

Try to rerun the application, and the Tomcat server should now be started on the newly specified port instead of the default :8080.

Great everything works so far! Let's take a closer look at the files provided by Spring Initializer. Firstly, let's explore the src/main/java/com.rpicloud/SpringBootRestExampleApplication.java file. The content of the file is shown below.

@SpringBootApplication
public class SpringBootRestExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootRestExampleApplication.class, args);
    }
}

This file is the entry-point of our application, our main-method and this is where our Spring application get's started. The annotation @SpringBootApplication is a convenience method instead of annotating the main class with @Configuration, @EnableAutoConfiguration and @ComponentScan. Using these three annotations with default values instead of @SpringBootApplication would result in the same thing.

Secondly, let's have a look at our test-class which are located at src/test/java/com.rpicloud/SpringBootRestExampleApplicationTests.java. Spring Initializer provides you with this out of the box, and thereby helps you to get started writing test-cases from the beginning of your project. The content of the file is shown below.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringBootRestExampleApplication.class)
@WebAppConfiguration
public class SpringBootRestExampleApplicationTests {

    @Test
    public void contextLoads() {
    }

}

The last file, i'm gonna mention are our pom.xml file, which is project object model file. This is where we configure our maven builds, and managing our dependencies. The content of the file are as shown below

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

    <groupId>com.rpicloud</groupId>
    <artifactId>spring-boot-rest-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-boot-rest-example</name>
    <description>Demo project created by Kasper Nissen, rpi-cloud.com</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

As you can se above, we have the a dependency called spring-boot-starter-web which is of course the one we selected in the Spring Initializer in the beginning of this tutorial.

FINALY its time for some coding!

We will be creating a REST API that will respond with a list of 10 random pies whenever hitting the endpoint /pies or a specified number provided with a query parameter. Be aware that this is a simple getting started guide, and that we will be blogging about more advanced stuff you can do in your spring APIs later on.

Before getting completely started, I forgot that we would like to actually store our Pies somewhere. Luckily adding dependencies to a Spring Boot application is really easy. We are going to need the following dependencies:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

Add the two dependencies above to your pom.xml file between

<dependencies>  
...
</dependencies>  

We are going to use an in-memory database and Java Persistence API to access the database. Now we are ready to add a model to our project. Since we are going to return pies, lets create a Pie model: Pie.java. I prefer to create a package for models, controllers, etc. So create the Pie.java in src/main/java/com.rpicloud/models/. Paste the following into your Pie.java file and tweak if you want a Pie with more properties.

@Entity
public class Pie {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
    private String description;

    public Pie(String name, String description) {
        this.name = name;
        this.description = description;
    }

    //for JPA
    public Pie() {}

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }
}

Awesome, now we have a model! Next item on the list to implement, is a way to access our data. Let's create a new package called repositories in /src/main/java/com.rpicloud/repositories and create a file called PieRepository.java. This repository will be our access point to all of our data in our in-memory database. Paste the following code into your newly created file:

public interface PieRepository extends CrudRepository<Pie, Long> {  
    List<Pie> findByName(String name);
}

The PieRepository is an interface that extends CrudRepository which provides you with functionality such as findAll() or findOne(). We extended this interface with a method for finding a specific Pie by its name. This is all we have to do to implement this functionality! Easy! Like Magic! Spring will look at your model and see that this contains a property named name and will then use this for filtering. Awesome!

Next up is the controller, our gateway for accessing our data. Let's add a new package called controllers /src/main/java/com.rpicloud/controllers and add a new file called PieRestController.java. Paste the following into your newly created controller and soon you will be able to see the magic happens.

@RestController
@RequestMapping("/pies")
public class PieRestController {

        @Autowired
        private PieRepository repository;

        @RequestMapping(method = RequestMethod.GET)
        public ResponseEntity<Collection<Pie>> getAllPies(){
            return new ResponseEntity<>((Collection<Pie>) repository.findAll(), HttpStatus.OK);
        }

        @RequestMapping(method = RequestMethod.GET, value = "/{id}")
        public ResponseEntity<Pie> getPieWithId(@PathVariable Long id) {
            return new ResponseEntity<>(repository.findOne(id),HttpStatus.OK);
        }

        @RequestMapping(method = RequestMethod.GET, params = {"name"})
        public ResponseEntity<Collection<Pie>> findPieWithName(@RequestParam(value="name") String name) {
            return new ResponseEntity<>(repository.findByName(name), HttpStatus.OK);
        }

        @RequestMapping(method = RequestMethod.POST)
        public ResponseEntity<?> addPie(@RequestBody Pie input) {
            return new ResponseEntity<>(repository.save(input), HttpStatus.CREATED);
        }
}

Cool, so what's going on here? Well, first we need to annotate our class with @RestController for it to be a REST-endpoint. Next i specify that this restcontroller will respond to calls made on the /pies endpoint. To access our database, we create a private instance of our PieRepository we created before and annotate it with @Autowired. This will inject our repository into your controller. This RestController contains 4 ways of interacting with the API, add more if you like to! The 4 endpoints are as follows:

  • GET: /pies //Returns all Pies in the database
  • GET: /pies/{id} //Returns a specific Pie by its ID
  • GET: /pies?name={name} //Returns a list of pies that matches the name
  • POST: /pies //Create a new Pie and add it to the database

One last thing we need to hook up before trying our awesome new REST API is some lovely Pies to return. For this, we add a @Bean to our application SpringBootRestExampleApplication.java as a CommandLineRunner that will initialize our database whenever we fire up our application. Add the following:

@SpringBootApplication
public class SpringBootRestExampleApplication {

    private final Faker faker = new Faker();

    public static void main(String[] args) {
        SpringApplication.run(SpringBootRestExampleApplication.class, args);
    }

    @Bean
    public CommandLineRunner initializeDb(PieRepository repository){
        return (args) -> {
            repository.deleteAll();
            //Insert some random pies
            for(int i = 0; i < 20; i++) {
                repository.save(new Pie(faker.lorem().word(), faker.lorem().sentence()));
            }
        };
    }

}

For this example I'm using a Faker object, that will provide me with some Fake data to return. I know, this will probably result in some weird Pies, however this is an easy way to get up and running. To add the Faker library add the following to your pom.xml file and check out their page for more information:

<dependency>  
    <groupId>com.github.javafaker</groupId>
    <artifactId>javafaker</artifactId>
    <version>0.7</version>
</dependency>  

Finaly, we are ready to fire up our brand new API. Start your application either via commandline mvn spring-boot:run or via your IDE and visit the endpoint http://localhost:8080/pies and watch a list of Pies come to life! Play around with the other endpoints as well, and try to post an object to verify that this item will be added to the database. You POST an object by embedding the JSON-object into the body of the request as follows:

{
    "name": "Raspberry",
    "description": "Pie"
}

The server will respond with the newly created object and with a 201 Created status.

All of the above code can be found at GitHub - LINK HERE

Be aware, that this is a simple getting started application, and there are many unhandled issues left to the reader to solve, e.g. security.

Stay tuned for more blog post on Spring and how you can deploy your Spring Boot applications on a Raspberry Pi cluster!

Happy Hacking - Over and Out!