How to create RESTFul Webservices using Spring Boot

In this part of Spring Boot series, we will learn How to create RESTFul Webservices using Spring Boot. We will also look into Actuator and it’s usefulness in an Application. Spring boot has made bootstrapping Java application incredibly simple. You probably already know about RESTful webservice, however we will see how easily we can create them using Spring Boot annotations.

We have already added the Web as a dependency in our project. You can see the following being added in the pom file. In case you want to add any additional features, you can add in the pom file directly and IntelliJ IDEA or Eclipse will automatically add the dependent jars.

pom.xml

XHTML

1

2

3

4

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

The @SpringBootApplication annotation is the starting point of Spring Boot application. We will initialize the application by calling the following line from our main method.

Java

1

2

3

4

5

6

@SpringBootApplication

publicclassApplication{

publicstaticvoidmain(String[]args){

SpringApplication.run(Application.class,args);

}

}

Let’s create a Student Application where we can add/delete/view student data. We will use static variable to hold the data for our application. We will start by creating a Student class, then we will create a StudentService class and expose the methods there as REST service.

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

packagecom.adeveloperdiary;

importjava.util.Date;

publicclassStudent{

privatelongid;

privateStringname;

publicStudent(){

}

publicStudent(Stringname,Stringsubject){

this.id=(newDate()).getTime();

this.name=name;

this.subject=subject;

}

privateStringsubject;

publiclonggetId(){

returnid;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicStringgetSubject(){

returnsubject;

}

publicvoidsetSubject(Stringsubject){

this.subject=subject;

}

@Override

publicStringtoString(){

return"Student{"+

"id="+id+

", name='"+name+'\''+

", subject='"+subject+'\''+

'}';

}

}

We will create a static hash map to keep the student data. We will initialize that with some static values at the beginning. Let’s add two new Students in our hmStudent map.

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@SpringBootApplication

publicclassApplication{

publicstaticHashMap<Long,Student>hmStudent;

publicstaticvoidmain(String[]args){

hmStudent=newHashMap<Long,Student>();

Student one=newStudent("John","math");

hmStudent.put(newLong(one.getId()),one);

SpringApplication.run(Application.class,args);

Student two=newStudent("Jane","history");

hmStudent.put(newLong(two.getId()),two);

}

}

@RequestMapping

Create a StudentService class, annotate that using @RestController and @RequestMapping. Set the value for @RequestMapping to /rest/student, this will enforce to have all the services under StudentService class to have this as parent path. Next create a function named getAllStudents() and set the value for the @RequestMapping to /.

Java

1

2

3

4

5

6

7

8

9

@RestController

@RequestMapping(value="/rest/student")

classStudentService{

@RequestMapping(value="/",method=RequestMethod.GET)

publicHashMap<Long,Student>getAllStudents(){

returnApplication.hmStudent;

}

}

Now start the application and access the http://localhost:8080/rest/student/ URL. You should be able to see the following JSON.

1

2

3

4

5

6

7

8

9

10

11

12

13

{

{

"id":1459658467056,

"name":"John",

"subject":"math"

}

,

{

"id":1459658467056,

"name":"Jane",

"subject":"history"

}

}

@RequestParam

We will try out different ways of sending data from the Browser to the Server. We will first use request parameter to send the data. Our URL would look like this.

http://localhost:8080/rest/student/add?name=Joe&subject=english

We are using @RequestParam annotation here, if you set a defaultValue it will also make the parameter optional. By default everything is mandatory. You can also set the required=false if needed.

Java

1

2

3

4

5

6

7

8

9

@RequestMapping(value="/add",method=RequestMethod.POST)

publicStudent addStudent(@RequestParam(value="name")Stringname

,@RequestParam(value="subject",defaultValue="unknown")Stringsubject){

Student student=newStudent(name,subject);

Application.hmStudent.put(newLong(student.getId()),student);

returnstudent;

}

In order to test the POST service we created we would need a REST Client. I am using a plugin in Chrome itself, its called Advanced REST Client. Submit the URL using POST and you should see the below response.

1

2

3

4

5

{

"id":1459661501207

"name":"Joe"

"subject":"english"

}

Now if you invoke http://localhost:8080/rest/student/ you will get total 3 students.

@RequestBody

Now lets update the Students. This time we will pass the JSON Student object, Spring will use Jackson to map that to our Student class automatically. We need to use @RequestBody for this.

We need to set the Content-Type to application/json and send the JSON as the request body. See below :

We should get the following response back with the updated object.

1

2

3

4

5

6

{

"id":1459663189412

"name":"New Name"

"subject":"New Subject"

}

Notice, in case the id is not available our code would throw an exception. Spring will automatically covert that to JSON response. Let’s use an invalid id as 1234. Our service will return the following response. Our custom error has been embedded in the error here.

1

2

3

4

5

6

7

8

{

"timestamp":1459663812487

"status":500

"error":"Internal Server Error"

"exception":"java.lang.Exception"

"message":"Student 1234 does not exists"

"path":"/rest/student/update"

}

@PathVariable

Now its time to delete our Student data. This time we will use Path Variable to send the data as part of the URL itself. Spring provides @PathVariable annotation for this. The URL would look like:

http://localhost:8080/rest/student/delete/1459664087939

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

@RequestMapping(value="/delete/{id}",method=RequestMethod.DELETE)

publicStudent deleteStudent(@PathVariablelongid)throwsException{

Student student;

if(Application.hmStudent.containsKey(newLong(id))){

student=Application.hmStudent.get(newLong(id));

Application.hmStudent.remove(newLong(id));

}else{

thrownewException("Student "+id+" does not exists");

}

returnstudent;

}

Also lets add a getStudent() by id method.

Java

1

2

3

4

@RequestMapping(value="/{id}",method=RequestMethod.GET)

publicStudent getStudent(@PathVariablelongid){

returnApplication.hmStudent.get(newLong(id));

}

So we have used @RequestParam, @RequestBody and @PathVariable annotation to send the data from client to server. Use them as needed in your project.

Spring Boot Actuator

I want to quickly introduce Actuator here. Actuator is a very helpful library which provides runtime details of our application. To start with, we can find whether our App and all of its components (Like DB, Cache, MQ etc) are up or down. It also shows all the services available for an application. Additionally all properties, including server details, dump and many other details are easily available is your browser using Actuator.

In case you missed, here is the dependency details to be included in the pom.xml file.

XHTML

1

2

3

4

5

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-actuator</artifactId>

<version>1.3.3.RELEASE</version>

</dependency>

Application Health

We have already added actuator in out spring boot application, so just access http://localhost:8080/health

1

2

3

4

5

6

7

8

9

{

"status":"UP",

"diskSpace":{

"status":"UP",

"total":249779191808,

"free":183181832192,

"threshold":10485760

}

}

List of Services

Access the URL to get all the Request Mappings. http://localhost:8080/mappings. This is very useful and when multiple teams working together it can really be very helpful.

You can customize actuator to display or restrict information that should/shouldn’t be available. For getting the full list, check this URL.

URL

Desc

env

Exposes properties from Spring’s ConfigurableEnvironment.

beans

Displays a complete list of all the Spring beans in your application.

configprops

Displays a collated list of all @ConfigurationProperties.

dump

Performs a thread dump.

health

Shows application health information (when the application is secure, a simple ‘status’ when accessed over an unauthenticated connection or full message details when authenticated).

logfile

Returns the contents of the logfile (if logging.file or logging.path properties have been set). Only available via MVC. Supports the use of the HTTP Range header to retrieve part of the log file’s content.

metrics

Shows ‘metrics’ information for the current application.

mappings

Displays a collated list of all @RequestMapping paths.

trace

Displays trace information (by default the last few HTTP requests).

Consuming a RESTful Web Service

We may have to consume a RESTful service from our backend itself. So integration of REST Service from backend server is also very important and useful. Lets learn how Spring Boot can help there. We create another Spring Boot app to consume our StudentService.

In order to have both the server up and running we need to use another port other than 8080. Once you have created another Spring Boot App, open the application.properties and add the following line there.

server.port=8081

We will create a simple Service named, SchoolService. Before we add any method there, lets create our Student Class here so that the data can be mapped to the attributes automatically. Everything will be as is, however just add one annotation to the top of the class. This will help us to ignore any unused variables.

Java

1

2

3

4

@JsonIgnoreProperties(ignoreUnknown=true)

publicclassStudent{

...

}

Now we will create a service named getStudents(). Spring Boot provides RestTemplates for consuming REST Services. The Student object will be automatically mapped. Here is a very simple basic implementation.

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

@RestController

@RequestMapping(value="/rest/school")

classSchoolService{

@RequestMapping(value="/students/{id}")

publicStudent getStudent(@PathVariableStringid){

StringURL="http://localhost:8080/rest/student/"+id;

RestTemplate template=newRestTemplate();

Student student=template.getForObject(URL,Student.class);

returnstudent;

}

}

Our URL would look like the following.

http://localhost:8081/rest/school/students/1459668282416

Here is the response.

1

2

3

4

5

{

id:1459668282416,

name:"Jane",

subject:"history"

}

Consuming a RESTful Web Service in Java is a much larger topic than we can discuss here. I hope you have got the initial idea of it. I will have detailed post on this topic later.

Conclusion

There are few topics I have not discussed here, like uploading/downloading a file using REST service. However this tutorial should get you started. Next we will learn how to deploy our service in IBM Application Servers.

This is the 3rd part of Getting Started with Spring Boot Series. Find all the parts here.

Hey A Developer Diary,
Great Job man!! Your approach of explaining things is good.
Correction- In Application health field, I guess the URL should be “http://localhost:8080/health” instead of “http://localhost:8080/heath”, I guess. I was confused thinking it to be a new command.