Java Enterprise 101: Building a REST Server with Spring Boot
Tags: java, rest, spring, jee
Published: 2018-05-17 20:25:21

---
title: Java Enterprise 101: Building a REST Server with Spring Boot
published: true
description: A hands-on tutorial for building your first REST endpoint.
tags: java, rest, spring, jee
cover_image: https://thepracticaldev.s3.amazonaws.com/i/lr53fy1l2r3roqw4ajam.png
---


Following up [on the first part](https://dev.to/martinhaeusler/java-enterprise-101-3djl) of Java Enterprise 101, this time around we will get our hands dirty and implement the JEE stack with the help of [Spring](spring.io).

What you will need to follow along:

- A working installation of [JDK 10](http://www.oracle.com/technetwork/java/javase/downloads/jdk10-downloads-4416644.html) (or higher)
- A working internet connection
- Optionally, your favorite editor or IDE


# Setting up the project

We start... well, at the start. At [start.spring.io](start.spring.io) to be precise. This URL will lead you to the **Spring Initializr** - a handy little website where you can mix and match libraries and packages to suit your project. In our case, we want to have the **Web**, **JPA** and **H2** packages:

![Spring Initializr Setup](https://thepracticaldev.s3.amazonaws.com/i/4ws08d21qq4qpbcasawy.png)

I also changed the project name from "com.example" to "org.example" as well as the project type from **Maven** to **Gradle**. You can also use Maven perfectly fine, but for this guide I will be using Gradle. Once you hit the "generate project" button, you will end up with a *.zip file. Unpack it to a directory of your choice; this will become our project directory. Inside, you will find:

- **build.gradle**: this file contains your build configuration.
- **gradlew** / **gradlew.bat**: Gradle Wrapper. Always use these, never "gradle" itself.
- **settings.gradle**: basically your Gradle module structure. We won't touch this, at least for now.
- **.gitignore**: a very basic configuration to exclude binaries and generated files.
- **src**: the source directory for your code. Follows the maven project structure.

Let's have a look at the generated **build.gradle** script, shall we?


```gradle
buildscript {
	ext {
		springBootVersion = '2.0.2.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'org.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
	mavenCentral()
}


dependencies {
	compile('org.springframework.boot:spring-boot-starter-data-jpa')
	compile('org.springframework.boot:spring-boot-starter-web')
    runtime('com.h2database:h2')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}
```

As far as buildscripts go, this is actually quite readable. It first says that it uses the `spring-boot-gradle-plugin` and the [Maven Central](https://mvnrepository.com/repos/central) repository for fetching its dependencies. Not really surprising, is it?

In the next section we have a list of gradle plugins which are applied to our project. Feel free to replace the `eclipse` plugin with the plugin for your IDE instead (e.g. `idea` for IntelliJ users). If you stick to editor and command line, you don't need this at all.

In my version, I changed the `sourceCompatibility` to `1.10` so I can use the `var` keyword from Java 10. The build script also mentions the maven coordinates of our project. Be a good citizen and always stick to [semantic versioning](https://semver.org/) (SemVer)! In the final section, we see a list of our **dependencies**, both for *compiling* and for *testing* our project.

> **/!\ IMPORTANT:**
> In order to make this buildscript work properly with Java 9 and higher (modularized Java platform libs) you also need to add the following dependency:

> `compile('javax.xml.bind:jaxb-api')`

> We are not going to actually use JAXB, but you will get a `NoClassDefFoundError` if you are missing this dependency. Hopefully, the Spring Boot Team will add it to their starter packs in the near future.


The **Spring Boot Starter** packages are "meta-packages" which contain an opinionated selection of libraries for common tasks. For example:

 - `spring-boot-starter-web` contains an (embedded) `Tomcat` as an application container and `Jackson` for JSON handling
 - `spring-bot-stater-data-jpa` contains `Hibernate` as the JPA provider
 - `spring-boot-starter-test` contains `JUnit`

That's nice, but what if you don't *agree* with the choices of the Spring Boot team? Don't worry, they've got you covered. If Spring Boot detects the presence of another library, say TestNG, this library will automatically take precedence over the default. In many cases, you don't even have to configure anything manually to make this happen; just add the dependency in gradle and rebuild the project. If you want some more exotic alternatives that Spring doesn't recognize, you will have to do a little bit more work, but that's for another article. For now, let's make use of what we get out of the box.


# Getting to work!

First of all, you should verify that your setup is working as intended. The best way to do so is to open a command prompt (yes, even windows `cmd` will do...) and navigate to your project folder (where `build.gradle` is located). Run the following command:

```bash
gradlew build
```

Under windows `cmd`, you might need to use `gradlew.bat` instead. Anyways, this will:

- download all required dependencies from maven central
- compile your source files
- execute all your tests

"But we ain't got no tests!" you say? Well, Spring Initializr always includes one particular test case that may seem a little odd at first sight, but actually makes a lot of sense. Open up the file `DemoApplicationTests.java` (if you called your app something other than `Demo`, replace it accordingly).

```java
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

	@Test
	public void contextLoads() {
	}

}
```

This test does exactly what the name implies: it asserts that the Spring context loads up correctly. If this basic test fails, it means that you have a severe issue with your Spring / Spring Boot Setup that needs to be sorted out before continuing on. We should be okay with our setup now.

The other class that is generated by the Spring Initializr for you is the `DemoApplication.java` class:

```java
@SpringBootApplication
public class DemoApplication {

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

This is your main class, the entry point into your server-side application.

> **/!\ IMPORTANT:**
> The **package** in which this class resides is considered to be the **root package** by Spring Boot. Make sure that **all** of your source code either resides in the root package, or one of its (direct or indirect) child packages, otherwise Spring Boot will not be able to locate your classes.


# Our first Spring REST Endpoint

Ready to write some actual code? Create a Java file and place it in your root package (or a sub-package). I place mine in **org.example.demo.rest**:

```java
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloWorldRestController {

    @RequestMapping(method = RequestMethod.GET, path = "/api/hello-world")
    @ResponseBody
    public String sayHello(){
        return "Hello World!";
    }

}
```

There you go. That's **all** it takes to build a REST endpoint with Spring Boot. The `@RestController` annotation tells Spring Boot what to do with this class (later on in this tutorial series we wil see other examples as well). The method `sayHello` (the name does not matter in the slightest, as long as it is a valid Java identifier you can name it whatever you like) implements a REST endpoint. The `@RequestMapping` provides the information to Spring which incoming requests to route to this endpoint. In this case, we bind it to the resource path `/api/hello-world` and to the request method `GET`. With `@ResponseBody`, we tell Spring that this method produces a result that should be returned to the client as the body of the HTML response.

# Booting it up

Now for the really awesome part. Go to your command line interface again and navigate to your project folder (if you haven't done so already). Run the `gradlew build` command once more. Upon success, navigate to the **build/libs** sub-directory. In there, you will find a single **.jar** file. Run this file with `java` as you normally would:

```bash
java -jar demo-0.0.1-SNAPSHOT.jar
```

This will start up your application server for you. Wait, what? But we did not even install a Tomcat yet! The funny thing is: you don't need to. While you **can** deploy your Java Enterprise application now in the "traditional" way as a **war** file, you can also run it as a regular java application, because the application container is alreay **embedded** in your application. Once it has finished starting up, open up a web browser and navigate to:

```url
http://localhost:8080/api/hello-world
```

You should see our "Hello World!" message showing up.


# Testing

We wouldn't be much of a developer in 2018 if we didn't write proper tests, now would we? Luckily, Spring makes it relatively easy for us to test our REST endpoints. However, some setup is required. I will expand our existing test class for simplicities sake (and omit the existing test case in the following listings). Here's the setup code we need:

```java
package org.example.demo;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.junit.Assert.assertEquals;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    @Before
    public void setup(){
        this.mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .build();
    }

}
```

This helps us to set up the [MockMVC](https://docs.spring.io/spring-security/site/docs/current/reference/html/test-mockmvc.html) helper. There is a **lot** more to this class than it initially appears to be; we will explore in another tutorial why exactly this class is so awesome for testing Spring REST endpoints. For now, just consider it a nifty helper to formulate a REST request. Note that the set up code above can be moved to a testing base class; it's never going to change, and there is no need to repeat it in every test class. Let's have a look at the code in more detail.

`@Autowired` is the [dependency injection](https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/beans.html) annotation used by Spring, very similar to `@Inject` used by [JSR 330](https://www.jcp.org/en/jsr/detail?id=330) implementations (e.g. [Google Guice](https://github.com/google/guice)). With this, we basically tell Spring to pass in the single `WebApplicationContext` instance to our test. We then use JUnit's `@Before` method to set up our `MockMvc` instance using our web context. That is how the `MockMvc` instance "finds" your endpoints.

Now, let's write an actual test for our REST endpoint:

```java
@Test
public void testHelloWorldEndpoint() throws Exception {
    var response = this.mvc.perform(
            get("/api/hello-world")
    ).andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
    assertEquals("Hello World!", response);
}
```

This [internal DSL](https://en.wikipedia.org/wiki/Domain-specific_language) allows us to `perform` the `get` request and we `expect` the HTTP `status` code to be `ok`, and we `return` the `response` `content` as a String. This [reads like prose](http://wiki.c2.com/?ReadsLikeProse). Compiler-checked prose that reduces dozens of lines with assertions into a single line. If that isn't beautiful, I don't know what is.

Run this test and watch it pass! You can either do it in the command line with

```bash
gradlew test
```

... (this runs *all* tests) or directly in your IDE.


# Closing Thoughts

This has become quite a long article - a lot longer than I intended. However, if we consider how many lines of actual code we actually wrote (about 10?) it is hard to argue that Java is "such a verbose language", considering what we achieved in terms of functionality. We also have the foundations in place to extend our server with a data model and a database connection in the next article. We literally merely scratched the surface. Brevity aside, the true advantages of Spring Boot and the JEE architecture are not yet visible. Bear with me for now please ;)