Spring Boot REST Example
December 15, 2019
This page will walk through Spring Boot RESTful web service CRUD example. REST is REpresentational State Transfer. REST or RESTful web services provide communication medium between software applications on the Internet. REST uses uniform and predefined set of stateless operations. RESTful web service can produce and consume JSON, XML and other media types. To create a Spring RESTful web service endpoint, we need to create a Spring controller annotated with
@RestController
. Spring provides @RequestMapping
, @GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
and @PatchMapping
annotations to bind the request path with Spring controller methods. For CORS support, spring provides @CrossOrigin
annotation that can be annotated at class level as well as method level. In Spring Boot application, to enable RESTful web service we need to include spring-boot-starter-web
in our build files. It configures Jackson JSON library i.e. jackson-databind
by default. Spring Boot RESTful web service produces JSON response when it detects Jackson JSON library in classpath and if it detects Jackson XML library then it produces XML response. For Jackson XML library we need to include jackson-dataformat-xml
in our build files. Spring provides RestTemplate
class to create RESTful web service client application. Here on this page we will create Spring RESTful web service CRUD example using CrudRepository
and MySQL with complete detail step by step.
Contents
- 1. Technologies Used
- 2. Maven Dependency
- 3. RESTful Web Service URLs and Response Status Code for CRUD Operation
- 4. RESTful Web Service Endpoint
- 5. RESTful Web Service Client with RestTemplate
- 6. @GetMapping
- 7. @PostMapping
- 8. @PutMapping
- 9. @DeleteMapping
- 10. Configure Producible and Consumable Media Types
- 11. RESTful Web Service JSON Response
- 12. RESTful Web Service XML Response
- 13. CORS Support
- 14. Spring REST CRUD + CrudRepository + MySQL Complete Example
- 15. Client Code using RestTemplate
- 16. Test Application
- 17. References
- 18. Download Source Code
1. Technologies Used
Find the technologies being used in our example.1. Java 9
2. Spring 5.0.5.RELEASE
3. Spring Boot 2.0.1.RELEASE
4. Maven 3.5.2
5. MySQL 5.5
6. Eclipse Oxygen
2. Maven Dependency
To work with Spring Boot RESTful web service, we need to providespring-boot-starter-web
Maven dependency as following.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
jackson-databind
. Spring Boot REST gives JSON response by default because it detects jackson-databind
in its classpath.
To support XML response in Spring Boot REST, we need to provide
jackson-dataformat-xml
library with spring-boot-starter-web
. Find the Maven dependency.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.9.4</version> </dependency>
pom.xml
and we are all set to get XML response.
3. RESTful Web Service URLs and Response Status Code for CRUD Operation
We will use following HTTP URLs, HTTP methods and response status code in our RESTful web service CRUD example.1. Create :
HTTP Method: POST, URL: /user/article
HTTP Response Status Code: 201 CREATED and 409 CONFLICT
2. Read :
HTTP Method: GET, URL: /user/article/{id} (Fetches article by id)
HTTP Method: GET, URL: /user/articles (Fetches all articles)
HTTP Response Status Code: 200 OK
3. Update :
HTTP Method: PUT, URL: /user/article
HTTP Response Status Code: 200 OK
4. Delete :
HTTP Method: DELETE, URL: /user/article/{id}
HTTP Response Status Code: 204 NO CONTENT
Find the print screen of the JSON response of our RESTful web service example.

4. RESTful Web Service Endpoint
To create a RESTful web service endpoint, we need to create a Spring controller annotated with@RestController
. Here we have created endpoints for CRUD operations. We have created different web service methods to handle create, read, update and delete operations as given below.
ArticleController.java
@RestController @RequestMapping("user") @CrossOrigin(origins = {"http://localhost:4200"}) public class ArticleController { @Autowired private IArticleService articleService; //Fetches article by id @GetMapping("article/{id}") public ResponseEntity<ArticleInfo> getArticleById(@PathVariable("id") Integer id) { ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(articleService.getArticleById(id), ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); } //Fetches all articles @GetMapping(value="articles") public ResponseEntity<List<ArticleInfo>> getAllArticles() { List<ArticleInfo> responseArticleList = new ArrayList<>(); List<Article> articleList = articleService.getAllArticles(); for (int i = 0; i < articleList.size(); i++) { ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(articleList.get(i), ob); responseArticleList.add(ob); } return new ResponseEntity<List<ArticleInfo>>(responseArticleList, HttpStatus.OK); } //Creates a new article @PostMapping("article") public ResponseEntity<Void> addArticle(@RequestBody ArticleInfo articleInfo, UriComponentsBuilder builder) { Article article = new Article(); BeanUtils.copyProperties(articleInfo, article); boolean flag = articleService.addArticle(article); if (flag == false) { return new ResponseEntity<Void>(HttpStatus.CONFLICT); } HttpHeaders headers = new HttpHeaders(); headers.setLocation(builder.path("/article/{id}").buildAndExpand(article.getArticleId()).toUri()); return new ResponseEntity<Void>(headers, HttpStatus.CREATED); } //Updates article @PutMapping("article") public ResponseEntity<ArticleInfo> updateArticle(@RequestBody ArticleInfo articleInfo) { Article article = new Article(); BeanUtils.copyProperties(articleInfo, article); articleService.updateArticle(article); ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(article, ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); } //Deletes article by id @DeleteMapping("article/{id}") public ResponseEntity<Void> deleteArticle(@PathVariable("id") Integer id) { articleService.deleteArticle(id); return new ResponseEntity<Void>(HttpStatus.NO_CONTENT); } }
@RestController
is combination of @Controller
and @ResponseBody
.
@CrossOrigin: It is used for CORS support that permits cross-origin requests on class level as well as method level.
@RequestMapping: It maps web requests onto methods in REST web service endpoints to provide flexible method signature.
@GetMapping: It is
@RequestMapping
with HTTP GET method.
@PostMapping: It is
@RequestMapping
with HTTP POST method.
@PutMapping: It is
@RequestMapping
with HTTP PUT method.
@DeleteMapping: It is
@RequestMapping
with HTTP DELETE method.
@PatchMapping: It is
@RequestMapping
with HTTP PATCH method.
@PathVariable: It indicates that a method parameter should be bound to a URI template variable.
@RequestBody: It is used with the method parameter to bind the body of the web request.
@RequestParam: It is used with method parameter to bind the web request parameter.
ResponseEntity: It is the extension of
HttpEntity
that represents HTTP request or response entity, consisting of headers and body.
UriComponentsBuilder: It is the builder for
UriComponents
that represents an immutable collection of URI components.
The annotations
@RequestMapping
, @GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
and @PatchMapping
are having optional elements as following.
consumes: It defines an array of consumable media types of mapped request.
produces: It defines an array of producible media types of mapped request.
headers: It defines the acceptable headers of mapped request.
params: It defines the parameters of the mapped request, narrowing the primary mapping.
path: It defines path mapping URIs in servlet environment.
name: It assigns a name to this mapping.
value: It defines primary mapping expressed by this annotation.
5. RESTful Web Service Client with RestTemplate
RestTemplate
is the central class for synchronous client side HTTP access. RestTemplate
communicates to RESTful web services using HTTP methods. Find some of RestTemplate
methods.
getForObject: Retrieves data by using HTTP GET on specified URL.
postForLocation: Creates a new resource using given object to the URI template with HTTP POST method.
put: Creates or updates resource using given object to the URI template with HTTP PUT method.
delete: Deletes the resources at the specified URI.
exchange: It can execute any HTTP method to the given URI template. It returns
ResponseEntity
.
Find the sample example to execute
RestTemplate.exchange
method.
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); String url = "http://localhost:8080/user/articles"; RestTemplate restTemplate = new RestTemplate(); HttpEntity<String> requestEntity = new HttpEntity<String>(headers); ResponseEntity<Article[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article[].class);
Article
type using exchange
with HTTP GET method. In our demo application, RestClientUtil.java
contains client code.
6. @GetMapping
In RESTful web service@GetMapping
is used to create endpoint that fetchs resources. @GetMapping
is @RequestMapping
with HTTP GET method. We have created a web service method to fetch data by id using @GetMapping
.
@GetMapping("article/{id}") public ResponseEntity<ArticleInfo> getArticleById(@PathVariable("id") Integer id) { ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(articleService.getArticleById(id), ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); }
/user/article/101
and it will listen on HTTP GET method. Above web service method will return data for that id with HTTP status 200 (Ok).
Client Code: To create client code for the above RESTful web service, we will use
exchange
method of RestTemplate
with HTTP GET method.
public void getArticleByIdDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article/{id}"; HttpEntity<String> requestEntity = new HttpEntity<String>(headers); ResponseEntity<Article> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article.class, 101); Article article = responseEntity.getBody(); System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle() +", Category:"+article.getCategory()); }
7. @PostMapping
In RESTful web service@PostMapping
is used to create a web service endpoint that creates resource. @PostMapping
is the @RequestMapping
with HTTP POST method. We have created a web service method to create resource using @PostMapping
as following.
@PostMapping("article") public ResponseEntity<Void> addArticle(@RequestBody ArticleInfo articleInfo, UriComponentsBuilder builder) { Article article = new Article(); BeanUtils.copyProperties(articleInfo, article); boolean flag = articleService.addArticle(article); if (flag == false) { return new ResponseEntity<Void>(HttpStatus.CONFLICT); } HttpHeaders headers = new HttpHeaders(); headers.setLocation(builder.path("/article/{id}").buildAndExpand(article.getArticleId()).toUri()); return new ResponseEntity<Void>(headers, HttpStatus.CREATED); }
/user/article
that will listen on HTTP POST method. In the above code, we are creating the resource and returning the location of created data with HTTP status 201 (Created). If the resource is already available, we are returning HTTP status 409 (Conflict).
Client Code: To create client code, for above RESTful web service, we are using
postForLocation
method of RestTemplate
.
public void addArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article"; Article objArticle = new Article(); objArticle.setTitle("Spring REST Security using Hibernate"); objArticle.setCategory("Spring"); HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers); URI uri = restTemplate.postForLocation(url, requestEntity); System.out.println(uri.getPath()); }
8. @PutMapping
In RESTful web service@PutMapping
is used to create a web service endpoint that creates or updates resource. @PutMapping
is @RequestMapping
with HTTP PUT method. We have created a web service method to update resource using @PutMapping
as following.
@PutMapping("article") public ResponseEntity<ArticleInfo> updateArticle(@RequestBody ArticleInfo articleInfo) { Article article = new Article(); BeanUtils.copyProperties(articleInfo, article); articleService.updateArticle(article); ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(article, ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); }
/user/article
that will listen on HTTP PUT method. In the above code we are updating a resource and returning the updated resource with HTTP status 200 (Ok).
Client Code: To create client code, for above RESTful web service, we are using
put
method of RestTemplate
.
public void updateArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article"; Article objArticle = new Article(); objArticle.setArticleId(1); objArticle.setTitle("Update:Java Concurrency"); objArticle.setCategory("Java"); HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers); restTemplate.put(url, requestEntity); }
9. @DeleteMapping
In RESTful web service@DeleteMapping
is used to create a web service endpoint that deletes a resource. @DeleteMapping
is @RequestMapping
with HTTP DELETE method. We have created a web service method to delete a resource using @DeleteMapping
as following.
@DeleteMapping("article/{id}") public ResponseEntity<Void> deleteArticle(@PathVariable("id") Integer id) { articleService.deleteArticle(id); return new ResponseEntity<Void>(HttpStatus.NO_CONTENT); }
/user/article/101
that will listen on HTTP DELETE method. In the above code we are deleting a resource for the given id and returning the HTTP status 204 (No Content).
Client Code: To create client code, for above RESTful web service, we are using
exchange
method of RestTemplate
with HTTP DELETE method.
public void deleteArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article/{id}"; HttpEntity<Article> requestEntity = new HttpEntity<Article>(headers); restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Void.class, 101); }
10. Configure Producible and Consumable Media Types
A web service method can produce and consume primary media types by default. We can restrict to only configured media types to consume and produce. The annotations@RequestMapping
, @GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
and @PatchMapping
are having optional elements as produces
and consumes
that is configured with required media types. Find the sample code.
@GetMapping(value= "article/{id}", produces= { MediaType.APPLICATION_XML_VALUE }, consumes= { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<ArticleInfo> getArticleById(@PathVariable("id") Integer id) { ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(articleService.getArticleById(id), ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); }
application/xml
and consume application/json
media types.
If we want to configure media types at class level that will be applicable for all its web service methods, we can do it using
@RequestMapping
as following.
@RestController @RequestMapping(value= "user", produces= { MediaType.APPLICATION_XML_VALUE }, consumes= { MediaType.APPLICATION_JSON_VALUE }) public class ArticleController { ------ }
11. RESTful Web Service JSON Response
Spring uses the Jackson JSON library to automatically marshal instances of type resource into JSON. Our Spring RESTful web service application will produce JSON response by default if there is Jackson JSON library i.e.jackson-databind
in the classpath. In Spring Boot application, the spring-boot-starter-web
library by default includes jackson-databind
library. To ignore null values in JSON response using Jackson JSON, we need to use @JsonInclude
in our resource class.
ArticleInfo.java
public class ArticleInfo { @JsonInclude(Include.NON_NULL) private long articleId; @JsonInclude(Include.NON_NULL) private String title; @JsonInclude(Include.NON_NULL) private String category; //Getters and Setters }
produces
element of mapping annotations such as @GetMapping
.
@GetMapping(value= "article/{id}", produces= { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<ArticleInfo> getArticleById(@PathVariable("id") Integer id) { ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(articleService.getArticleById(id), ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); }
HttpMessageConverter
for JSON, we can create JavaConfig as following.
AppConfig.java
@Configuration @ComponentScan("com.concretepage") @EnableWebMvc public class AppConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.indentOutput(true); converters.add(new MappingJackson2HttpMessageConverter(builder.build())); } }
12. RESTful Web Service XML Response
To get XML response by our Spring RESTful web service, we need to include Jackson XML library i.e.jackson-dataformat-xml
library in our application classpath. Find the maven dependency for jackson-dataformat-xml
library.
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.9.4</version> </dependency>
pom.xml
and we are all set to get XML response. We can use @JacksonXmlProperty
annotation in our resource class to change local name etc.
ArticleInfo.java
@JacksonXmlRootElement(localName="article", namespace="com.concretepage") public class ArticleInfo { @JacksonXmlProperty(localName="articleId") private long articleId; @JacksonXmlProperty(localName="title") private String title; @JacksonXmlProperty(localName="category") private String category; //Getters and Setters }
produces
element of mapping annotations such as @GetMapping
.
@GetMapping(value= "article/{id}", produces= { MediaType.APPLICATION_XML_VALUE }) public ResponseEntity<ArticleInfo> getArticleById(@PathVariable("id") Integer id) { ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(articleService.getArticleById(id), ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); }
HttpMessageConverter
for XML, we can create JavaConfig as following.
AppConfig.java
@Configuration @ComponentScan("com.concretepage") @EnableWebMvc public class AppConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml(); builder.indentOutput(true); converters.add(new MappingJackson2XmlHttpMessageConverter(builder.build())); } }
13. CORS Support
For CORS support, Spring provides@CrossOrigin
annotation. This annotation can be used at class level as well as method level in RESTful Web service controller. Find the sample code to use it at class level.
@RestController @RequestMapping("user") @CrossOrigin(origins = {"http://localhost:4200"}) public class ArticleController { ------ }
http://localhost:4200
. It means a web application running at URL http://localhost:4200
can only access our RESTful web service application.
14. Spring REST CRUD + CrudRepository + MySQL Complete Example
Now we will provide here complete code of our demo application. We will perform here Spring REST operation. We are using MySQL database and for database query we are usingCrudRepository
. We have created two demo applications, one for JSON response and another for XML response. Here we are providing code for JSON response application and has given the changes required for XML response. At the end of the article we have provided source code download link for both the applications.
14.1 Project Structure in Eclipse
Find the project structure in Eclipse.
14.2 Maven Dependencies used in Project
Find the Maven file used in the project.pom.xml
<?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.concretepage</groupId> <artifactId>spring-boot-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-demo</name> <description>Spring Boot Application</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> <relativePath/> </parent> <properties> <java.version>9</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-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.5</version> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring-boot-starter-parent: Parent POM for dependency management.
spring-boot-starter-web: Starter for building web, REST applications. It uses tomcat server as default embedded server.
spring-boot-starter-data-jpa: Starter for spring data JPA with hibernate.
spring-boot-devtools: It provides developer tools. These tools are helpful in application development mode. One of the features of developer tool is automatic restart of the server for any change in code.
spring-boot-maven-plugin: It is used to create executable JAR of the application.
The above Maven file will give JSON response. To get XML response, we need to add following dependency.
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.9.4</version> </dependency>
14.3 MySQL Database used in Project
CREATE DATABASE IF NOT EXISTS `concretepage`; USE `concretepage`; CREATE TABLE IF NOT EXISTS `articles` ( `article_id` bigint(5) NOT NULL AUTO_INCREMENT, `title` varchar(200) NOT NULL, `category` varchar(100) NOT NULL, PRIMARY KEY (`article_id`) ) ENGINE=InnoDB; INSERT INTO `articles` (`article_id`, `title`, `category`) VALUES (1, 'Java Concurrency', 'Java'), (2, 'Spring Boot Getting Started', 'Spring Boot'), (3, 'Lambda Expressions Java 8 Example', 'Java 8');
14.4 Repository and Service
ArticleRepository.javapackage com.concretepage.repository; import java.util.List; import org.springframework.data.repository.CrudRepository; import com.concretepage.entity.Article; public interface ArticleRepository extends CrudRepository<Article, Long> { List<Article> findByTitle(String title); List<Article> findDistinctByCategory(String category); List<Article> findByTitleAndCategory(String title, String category); }
package com.concretepage.entity; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="articles") public class Article implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="article_id") private long articleId; @Column(name="title") private String title; @Column(name="category") private String category; public long getArticleId() { return articleId; } public void setArticleId(long articleId) { this.articleId = articleId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } }
package com.concretepage.service; import java.util.List; import com.concretepage.entity.Article; public interface IArticleService { List<Article> getAllArticles(); Article getArticleById(long articleId); boolean addArticle(Article article); void updateArticle(Article article); void deleteArticle(int articleId); }
package com.concretepage.service; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.concretepage.entity.Article; import com.concretepage.repository.ArticleRepository; @Service public class ArticleService implements IArticleService { @Autowired private ArticleRepository articleRepository; @Override public Article getArticleById(long articleId) { Article obj = articleRepository.findById(articleId).get(); return obj; } @Override public List<Article> getAllArticles(){ List<Article> list = new ArrayList<>(); articleRepository.findAll().forEach(e -> list.add(e)); return list; } @Override public synchronized boolean addArticle(Article article){ List<Article> list = articleRepository.findByTitleAndCategory(article.getTitle(), article.getCategory()); if (list.size() > 0) { return false; } else { articleRepository.save(article); return true; } } @Override public void updateArticle(Article article) { articleRepository.save(article); } @Override public void deleteArticle(int articleId) { articleRepository.delete(getArticleById(articleId)); } }
14.5 Application Property File
Datasource, JPA properties and logging etc need to be configured inapplication.properties
file located in the classpath of Spring boot application. These properties will automatically be read by Spring boot.
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/concretepage spring.datasource.username=root spring.datasource.password=cp spring.datasource.hikari.connection-timeout=20000 spring.datasource.hikari.minimum-idle=5 spring.datasource.hikari.maximum-pool-size=12 spring.datasource.hikari.idle-timeout=300000 spring.datasource.hikari.max-lifetime=1200000 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect spring.jpa.properties.hibernate.id.new_generator_mappings=false spring.jpa.properties.hibernate.format_sql=true logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
spring-boot-starter-jdbc
and spring-boot-starter-data-jpa
resolve HikariCP dependency by default and spring.datasource.type
property has HikariDataSource
as default value. The datasource properties starting with spring.datasource.*
will automatically be read by Spring boot JPA. To change the Hibernate properties we will use prefix spring.jpa.properties.*
with Hibernate property names. On the basis of given data source URL, Spring Boot can automatically identify data source driver class. So we need not to configure diver class.
14.6 Create Controller
ArticleController.javapackage com.concretepage.controller; import java.util.ArrayList; import java.util.List; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.util.UriComponentsBuilder; import com.concretepage.entity.Article; import com.concretepage.service.IArticleService; @RestController @RequestMapping("user") @CrossOrigin(origins = {"http://localhost:4200"}) public class ArticleController { @Autowired private IArticleService articleService; //Fetches article by id @GetMapping(value= "article/{id}", produces= { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<ArticleInfo> getArticleById(@PathVariable("id") Integer id) { ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(articleService.getArticleById(id), ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); } //Fetches all articles @GetMapping(value= "articles", produces= { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<List<ArticleInfo>> getAllArticles() { List<ArticleInfo> responseArticleList = new ArrayList<>(); List<Article> articleList = articleService.getAllArticles(); for (int i = 0; i < articleList.size(); i++) { ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(articleList.get(i), ob); responseArticleList.add(ob); } return new ResponseEntity<List<ArticleInfo>>(responseArticleList, HttpStatus.OK); } //Creates a new article @PostMapping(value= "article", produces= { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<Void> addArticle(@RequestBody ArticleInfo articleInfo, UriComponentsBuilder builder) { Article article = new Article(); BeanUtils.copyProperties(articleInfo, article); boolean flag = articleService.addArticle(article); if (flag == false) { return new ResponseEntity<Void>(HttpStatus.CONFLICT); } HttpHeaders headers = new HttpHeaders(); headers.setLocation(builder.path("/article/{id}").buildAndExpand(article.getArticleId()).toUri()); return new ResponseEntity<Void>(headers, HttpStatus.CREATED); } //Updates article @PutMapping(value= "article", produces= { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<ArticleInfo> updateArticle(@RequestBody ArticleInfo articleInfo) { Article article = new Article(); BeanUtils.copyProperties(articleInfo, article); articleService.updateArticle(article); ArticleInfo ob = new ArticleInfo(); BeanUtils.copyProperties(article, ob); return new ResponseEntity<ArticleInfo>(ob, HttpStatus.OK); } //Deletes article by id @DeleteMapping(value= "article/{id}", produces= { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<Void> deleteArticle(@PathVariable("id") Integer id) { articleService.deleteArticle(id); return new ResponseEntity<Void>(HttpStatus.NO_CONTENT); } }
MediaType.APPLICATION_JSON_VALUE
in our JSON response demo application. In our XML response demo application, we are using producible media type as MediaType.APPLICATION_XML_VALUE
.
Find the
ArticleInfo.java
for JSON.
ArticleInfo.java
package com.concretepage.controller; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; public class ArticleInfo { @JsonInclude(Include.NON_NULL) private long articleId; @JsonInclude(Include.NON_NULL) private String title; @JsonInclude(Include.NON_NULL) private String category; public long getArticleId() { return articleId; } public void setArticleId(long articleId) { this.articleId = articleId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } }
ArticleInfo.java
for XML.
ArticleInfo.java
package com.concretepage.controller; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @JacksonXmlRootElement(localName="article", namespace="com.concretepage") public class ArticleInfo { @JacksonXmlProperty(localName="articleId") private long articleId; @JacksonXmlProperty(localName="title") private String title; @JacksonXmlProperty(localName="category") private String category; public long getArticleId() { return articleId; } public void setArticleId(long articleId) { this.articleId = articleId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } }
14.7 Class with Main Method using SpringApplication
To run Spring Boot application, we need to create a class withmain
method using SpringApplication
and annotated with @SpringBootApplication
as following.
MyApplication.java
package com.concretepage; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
@SpringBootApplication
annotation is the combination of @Configuration
, @EnableAutoConfiguration
and @ComponentScan
annotations.
15. Client Code using RestTemplate
Find the client code usingRestTemplate
to test the REST application.
RestClientUtil.java
package com.concretepage.client; import java.net.URI; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import com.concretepage.entity.Article; public class RestClientUtil { public void getArticleByIdDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article/{id}"; HttpEntity<String> requestEntity = new HttpEntity<String>(headers); ResponseEntity<Article> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article.class, 1); Article article = responseEntity.getBody(); System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle() +", Category:"+article.getCategory()); } public void getAllArticlesDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/articles"; HttpEntity<String> requestEntity = new HttpEntity<String>(headers); ResponseEntity<Article[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article[].class); Article[] articles = responseEntity.getBody(); for(Article article : articles) { System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle() +", Category: "+article.getCategory()); } } public void addArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article"; Article objArticle = new Article(); objArticle.setTitle("Spring REST Security using Hibernate"); objArticle.setCategory("Spring"); HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers); URI uri = restTemplate.postForLocation(url, requestEntity); System.out.println(uri.getPath()); } public void updateArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article"; Article objArticle = new Article(); objArticle.setArticleId(1); objArticle.setTitle("Update:Java Concurrency"); objArticle.setCategory("Java"); HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers); restTemplate.put(url, requestEntity); } public void deleteArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article/{id}"; HttpEntity<Article> requestEntity = new HttpEntity<Article>(headers); restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Void.class, 4); } public static void main(String args[]) { RestClientUtil util = new RestClientUtil(); //util.getArticleByIdDemo(); //util.addArticleDemo(); //util.updateArticleDemo(); //util.deleteArticleDemo(); util.getAllArticlesDemo(); } }
16. Test Application
To test the application, first create table in MySQL as given in the example. Then we can run REST web service in following ways.1. Using Maven Command: Download the project source code. Go to the root folder of the project using command prompt and run the command.
mvn spring-boot:run
2. Using Eclipse: Download the project source code using the download link given at the end of article. Import the project into eclipse. Using command prompt, go to the root folder of the project and run.
mvn clean eclipse:eclipse
MyApplication
by clicking Run as -> Java Application. Tomcat server will be started.
3. Using Executable JAR: Using command prompt, go to the root folder of the project and run the command.
mvn clean package
java -jar target/spring-boot-demo-0.0.1-SNAPSHOT.jar
Now we are ready to test the application. To run web service client, go to the
RestClientUtil
class in eclipse and click on Run as -> Java Application. We can also use Postman to test the application. Find the print screen for XML response.

17. References
Spring Boot Reference GuideSpring Boot CrudRepository Example