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.
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.
1 2 3 4 5 6 |
@SpringBootApplication public class Application { public static void main(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.
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 |
package com.adeveloperdiary; import java.util.Date; public class Student { private long id; private String name; public Student() { } public Student(String name, String subject) { this.id = (new Date()).getTime(); this.name = name; this.subject = subject; } private String subject; public long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } @Override public String toString() { 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@SpringBootApplication public class Application { public static HashMap<Long,Student> hmStudent; public static void main(String[] args) { hmStudent=new HashMap<Long,Student>(); Student one=new Student("John","math"); hmStudent.put(new Long(one.getId()),one); SpringApplication.run(Application.class, args); Student two=new Student("Jane","history"); hmStudent.put(new Long(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 /
.
1 2 3 4 5 6 7 8 9 |
@RestController @RequestMapping(value="/rest/student") class StudentService{ @RequestMapping(value="/",method = RequestMethod.GET) public HashMap<Long,Student> getAllStudents(){ return Application.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.
1 2 3 4 5 6 7 8 9 |
@RequestMapping(value="/add",method = RequestMethod.POST) public Student addStudent(@RequestParam(value="name") String name ,@RequestParam(value="subject",defaultValue = "unknown") String subject){ Student student=new Student(name,subject); Application.hmStudent.put(new Long(student.getId()),student); return student; } |
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.
1 2 3 4 5 6 7 8 9 10 11 |
@RequestMapping(value="/update",method = RequestMethod.PUT) public Student updateStudent(@RequestBody Student student) throws Exception { if(Application.hmStudent.containsKey(new Long(student.getId()))){ Application.hmStudent.put(new Long(student.getId()),student); }else{ throw new Exception("Student "+student.getId()+" does not exists"); } return student; } |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@RequestMapping(value="/delete/{id}",method = RequestMethod.DELETE) public Student deleteStudent(@PathVariable long id) throws Exception { Student student; if(Application.hmStudent.containsKey(new Long(id))){ student=Application.hmStudent.get(new Long(id)); Application.hmStudent.remove(new Long(id)); }else{ throw new Exception("Student "+id+" does not exists"); } return student; } |
Also lets add a getStudent()
by id method.
1 2 3 4 |
@RequestMapping(value="/{id}",method = RequestMethod.GET) public Student getStudent(@PathVariable long id){ return Application.hmStudent.get(new Long(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.
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.
1 2 3 4 |
@JsonIgnoreProperties(ignoreUnknown = true) public class Student { . . . } |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@RestController @RequestMapping(value="/rest/school") class SchoolService { @RequestMapping(value="/students/{id}") public Student getStudent(@PathVariable String id){ String URL="http://localhost:8080/rest/student/"+id; RestTemplate template=new RestTemplate(); Student student =template.getForObject(URL,Student.class); return student; } } |
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.
- An Introduction to Spring Boot
- How to Create Spring Boot Application Step by Step
- How to create RESTFul Webservices using Spring Boot
- How to deploy Spring Boot application in IBM Liberty and WAS 8.5
Ala says
Thanks a lot – you absolutely helped me to start with SpringBoot.
A Developer Diary says
You are most welcome Ala, glad to hear that this tutorial was helpful to you.
Thanks for your feedback !
Iron says
Where can I get complete reference of Spring Boot??,Since am new to it!!
Thank you
Sumit says
Thanks for providing so simple example for starting spring boot.
A Developer Diary says
Hi Sumit,
Appreciate your feedback on this !
Thanks,
A Developer Diary
Anonymous says
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.
adeveloperdiary says
Appreciate your feedback… I have corrected the typo. Thank you very much.
Pradipta Maitra says
Awesome A Developer Diary!
Any example of end-to-end examples using JavaScript/SpringBoot (with JPA)/Mongo (or any DB) will be of great help.
adeveloperdiary says
Hi Pradipta,
Thank you for your feedback !
Sure, I will have end-to-end example posted soon.
Thanks,
A Developer Diary
Yolpo says
Hi,
Thanks for all, very usefull post. I can’t wait for the end-to-end examples :).
Best regards
Siva Prakash says
when i specify server.port=8081 port in application.properties file my application is not started. if i change to 8083 it is started but it says
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for “http://localhost:8080/rest/student/1476824007402”: Connection refused; nested exception is java.net.ConnectException: Connection refused] with root cause
java.net.ConnectException: Connection refused
adeveloperdiary says
Hi Siva,
If the server.port is defined as 8083 then you need to connect to 8083 and not 8080, unless you have a different service in 8080.
Let me know if this helps.
Thanks,
A Developer Diary
artegento says
very good article, i find out that, in order to use hasMap, you need to redefine hasCode, other way, in my case, at least, i was seeing just only record.
Samer Najjar says
Thanks alot
Usman Haider says
Great tutorial for a start to SpringBoot
Matt says
This tutorial is a jem, thank you sir!
Yu says
Thanks for your material, this is really helpful for a guy who needs to study spring boot. Is it possible to get some tutorial about how to use JDBC in spring boot?Appreciated.
arsa says
Hi Thanks a lot for working example.
Anyway my JSON output has additional element ID as below.
{
1486465076953: {
“id”: 1486465076953,
“name”: “Jane”,
“subject”: “history”
}
}
How to hide it so I could have output as yours.
{
“id”: 1486465076953,
“name”: “Jane”,
“subject”: “history”
}
Gireesh Bhat says
No worries, its just a HashMap data, first ID is the key of HashMap..
Anyways a very good example for newbiess(like me)..
Thank you 🙂
Zubin says
Thanks for the article. It helped me a lot.
Just to add one point for usage of Actuator.
We need to add below line in application.properties file.
management.security.enabled=false
vivek says
Wow!!! Excellent tutorial!!! Great job!! Gave me a headstart to SpringBoot
Midza says
Thanx a lot
solomon says
i was glad when start the tutorial but get stacked when “404 page not found” to i try the code on browser
Raj says
Awesome !! Great job.Implementing this was a breeze