Spring Boot Security REST + JPA + Hibernate + MySQL CRUD Example
May 12, 2017
This page will walk through Spring Boot Security REST + JPA + Hibernate + MySQL CRUD example. When we create application using Spring Boot, we have to write only few lines of code to include a feature such as web, security and database connectivity. If Spring Boot gets Spring Security in classpath, then it will automatically performs security related configurations. In the same way if Spring Boot gets Spring Web and Spring Data in its classpath then Spring Boot automatically performs Spring Web and database connectivity related configurations. In the case of Spring Security, Spring Boot configures in-memory authentication by default with a single user and random password which changes after every server restart. We can get default password printed in console. In our example we will save user authentication related data in database, so we have to override the Spring Boot default security configuration. We will create a security configuration file annotated with @Configuration
and @EnableWebSecurity
. To override the HttpSecurity
, our security configuration class needs to extend WebSecurityConfigurerAdapter
class and override the configure()
method. To enable method level security, annotate security configuration class with @EnableGlobalMethodSecurity
. To authenticate and authorize a user using database, we need to implement UserDetailsService
interface. We will handle CREATE, READ, UPDATE and DELETE (CRUD) operation in our REST web service example. Let us discuss the complete example step by step.
Contents
- Software Used
- Project Structure in Eclipse
- Spring Boot Default Authentication
- Maven File
- application.properties
- MySQL Database Schema and Java Entity
- Create DAO for User Authentication
- Implement UserDetailsService
- Implement BasicAuthenticationEntryPoint
- Spring Security REST JavaConfig
- Create DAO for CRUD Operation
- Create Service for CRUD Operation with Secured Methods
- Create Controller for CRUD Operation
- Create Main Class using SpringApplication
- Create Client using RestTemplate
- Run Application
- Reference
- Download Source Code
Software Used
Find the software used in the example.1. Java 8
2. Spring Boot 1.5.3.RELEASE
3. Maven 3.3
4. MySQL 5.5
Project Structure in Eclipse
Find the print screen of project structure in eclipse.Spring Boot Default Authentication
If spring security is in the classpath then our spring boot web applications are automatically secured by default using basic authentication. A default username as 'user' and random password that will be displayed in console when server starts, can be used for login authentication. The password is printed in console as follows.Using default security password: 7e9850aa-d985-471a-bae1-25d741d4da23
1. To enable spring security in spring boot application just use the following spring-boot in maven or gradle file.
spring-boot-starter-security
security.user.password
property that needs to be configured in application.properties
as given below.
security.user.password= concretepage
SecurityProperties
using the security.*
prefix in application.properties
as given below.
security.basic.enabled: It enables basic authentication. Default value is true.
security.basic.path: It configures paths to apply security. We need to provide comma separated paths.
security.enable-csrf: It enables CSRF. Default value is false.
security.require-ssl: It enables and disables SSL. Default value is false.
security.sessions: Default value is stateless. Values can be always, never, if_required, stateless.
security.user.name: It configures user name. Default user is user.
security.user.password: It configures password.
security.user.role: It configures role. Default role is USER.
3. If we have fine-tuned our logging configuration then to print default random password, we need to configure following property in
application.properties
with INFO
level.
logging.level.org.springframework.boot.autoconfigure.security= INFO
/css/**
, /js/**
, /images/**
, /webjars/**
and **/favicon.ico
.
5. The features such as HSTS, XSS, CSRF, caching are provided by default in spring security.
Above properties can be switched on and off using
security.*
but if we want to use username and password in database then we need to use UserDetailsService
. To control security related configuration, we can create a security configuration class that will extend WebSecurityConfigurerAdapter
then override configure()
method . This class will be annotated with @Configuration
and @EnableWebSecurity
. If we want to enable method level security, the class will be annotated with @EnableGlobalMethodSecurity
.
Maven File
Find the maven file used in the example.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-demo</name> <description>Spring Boot Demo Project</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> </parent> <properties> <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-security</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> </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-web: Configures web application settings automatically.
spring-boot-starter-security: Configures security related settings automatically.
spring-boot-starter-data-jpa: Configures database connectivity related settings automatically.
application.properties
In spring boot, to configure database related properties, hibernate and logging, we need to useapplication.properties
or application.yml
. These files are automatically read by Spring Boot.
application.properties
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/concretepage spring.datasource.username=root spring.datasource.password= spring.datasource.tomcat.max-wait=20000 spring.datasource.tomcat.max-active=50 spring.datasource.tomcat.max-idle=20 spring.datasource.tomcat.min-idle=15 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 #Security Configuration--- #security.user.password= concretepage #prints default password--- #logging.level.org.springframework.boot.autoconfigure.security= INFO
spring.datasource.*
to configure datasource related properties. Use spring.jpa.properties.*
to configure JPA related properties. Here in our example we are using JPA with hibernate.
MySQL Database Schema and Java Entity
Find the MySQL database schema.Database Schema
CREATE DATABASE IF NOT EXISTS `concretepage` ; USE `concretepage`; -- Dumping structure for table concretepage.articles CREATE TABLE IF NOT EXISTS `articles` ( `article_id` int(5) NOT NULL AUTO_INCREMENT, `title` varchar(200) NOT NULL, `category` varchar(100) NOT NULL, PRIMARY KEY (`article_id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; -- Dumping data for table concretepage.articles: ~3 rows (approximately) INSERT INTO `articles` (`article_id`, `title`, `category`) VALUES (1, 'Java Concurrency', 'Java'), (2, 'Hibernate HQL ', 'Hibernate'), (3, 'Spring MVC with Hibernate', 'Spring'); -- Dumping structure for table concretepage.users CREATE TABLE IF NOT EXISTS `users` ( `username` varchar(50) NOT NULL, `password` varchar(100) NOT NULL, `full_name` varchar(100) NOT NULL, `role` varchar(50) NOT NULL, `country` varchar(100) NOT NULL, `enabled` tinyint(1) NOT NULL, PRIMARY KEY (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- Dumping data for table concretepage.users: ~2 rows (approximately) INSERT INTO `users` (`username`, `password`, `full_name`, `role`, `country`, `enabled`) VALUES ('mukesh', '$2a$10$N0eqNiuikWCy9ETQ1rdau.XEELcyEO7kukkfoiNISk/9F7gw6eB0W', 'Mukesh Sharma', 'ROLE_ADMIN', 'India', 1), ('tarun', '$2a$10$QifQnP.XqXDW0Lc4hSqEg.GhTqZHoN2Y52/hoWr4I5ePxK7D2Pi8q', 'Tarun Singh', 'ROLE_USER', 'India', 1);
Main.java
package com.concretepage; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; public class Main { public static void main(String[] args) { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); System.out.println(encoder.encode("m123")); } }
UserInfo.java
package com.concretepage.entity; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="users") public class UserInfo implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name="username") private String userName; @Column(name="password") private String password; @Column(name="role") private String role; @Column(name="full_name") private String fullName; @Column(name="country") private String country; @Column(name="enabled") private short enabled; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public String getFullName() { return fullName; } public void setFullName(String fullName) { this.fullName = fullName; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public short getEnabled() { return enabled; } public void setEnabled(short enabled) { this.enabled = enabled; } }
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 int articleId; @Column(name="title") private String title; @Column(name="category") private String category; public int getArticleId() { return articleId; } public void setArticleId(int 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; } }
Create DAO for User Authentication
In our example, we are not using Spring Boot default in-memory authentication. We will store user authentication related information in MySQL database and access them using Hibernate. So we are creating a DAO method that return user information for a given user name.IUserInfoDAO.java
package com.concretepage.dao; import com.concretepage.entity.UserInfo; public interface IUserInfoDAO { UserInfo getActiveUser(String userName); }
package com.concretepage.dao; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.concretepage.entity.UserInfo; @Repository @Transactional public class UserInfoDAO implements IUserInfoDAO { @PersistenceContext private EntityManager entityManager; public UserInfo getActiveUser(String userName) { UserInfo activeUserInfo = new UserInfo(); short enabled = 1; List<?> list = entityManager.createQuery("SELECT u FROM UserInfo u WHERE userName=? and enabled=?") .setParameter(1, userName).setParameter(2, enabled).getResultList(); if(!list.isEmpty()) { activeUserInfo = (UserInfo)list.get(0); } return activeUserInfo; } }
@Transactional
annotation is to make DAO methods transactional. We are using JPA API for database transaction and hence we will instantiate EntityManager
using dependency injection. To achieve it create EntityManager
property annotated with @PersistenceContext
.
Implement UserDetailsService
Spring providesUserDetailsService
that authenticate and authorize user. It receives user related data from our DAO.
MyAppUserDetailsService.java
package com.concretepage.config; import java.util.Arrays; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import com.concretepage.dao.IUserInfoDAO; import com.concretepage.entity.UserInfo; @Service public class MyAppUserDetailsService implements UserDetailsService { @Autowired private IUserInfoDAO userInfoDAO; @Override public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { UserInfo activeUserInfo = userInfoDAO.getActiveUser(userName); GrantedAuthority authority = new SimpleGrantedAuthority(activeUserInfo.getRole()); UserDetails userDetails = (UserDetails)new User(activeUserInfo.getUserName(), activeUserInfo.getPassword(), Arrays.asList(authority)); return userDetails; } }
Implement BasicAuthenticationEntryPoint
In our example we are using header based authentication. When we are not using login page based authentication, then for any request to application, Spring needs to send an error with a proper status code. Spring providesBasicAuthenticationEntryPoint
that needs be implemented to achieve it. It has a method commence()
that we will override and return a status code (401) unauthorized with header containing authentication type required for authentication. In our example we are using basic authentication.
AppAuthenticationEntryPoint.java
package com.concretepage.config; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; import org.springframework.stereotype.Component; @Component public class AppAuthenticationEntryPoint extends BasicAuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\""); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); } @Override public void afterPropertiesSet() throws Exception { setRealmName("MY APP REALM"); } }
Spring Security REST JavaConfig
Now we will create security configuration file.SecurityConfig.java
package com.concretepage.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled=true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyAppUserDetailsService myAppUserDetailsService; @Autowired private AppAuthenticationEntryPoint appAuthenticationEntryPoint; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/user/**").hasAnyRole("ADMIN","USER") .and().httpBasic().realmName("MY APP REALM") .authenticationEntryPoint(appAuthenticationEntryPoint); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); auth.userDetailsService(myAppUserDetailsService).passwordEncoder(passwordEncoder); } }
@EnableWebSecurity
that configures spring security from the class WebSecurityConfigurer
. If we want to override any method of WebSecurityConfigurer
then we extend WebSecurityConfigurerAdapter
. In our example to configure HttpSecurity
we have overridden configure()
method. Here we have authorized a URL with /user/**
pattern. We will also configure implementation class of BasicAuthenticationEntryPoint
here.
Now autowire method
configureGlobal()
within which we configure implementation class of UserDetailsService
with BCryptPasswordEncoder
encoding scheme.
To secure service methods we need to use
@EnableGlobalMethodSecurity
annotation. To enable method level security with @Secured
annotation, configure securedEnabled
metadata with value true
. To enable @PreAuthorize
and @PostAuthorize
annotation, configure prePostEnabled
metadata with value true
.
Create DAO for CRUD Operation
Find the DAO class for CRUD operation using JPAEntityManager
.
IArticleDAO.java
package com.concretepage.dao; import java.util.List; import com.concretepage.entity.Article; public interface IArticleDAO { List<Article> getAllArticles(); Article getArticleById(int articleId); void addArticle(Article article); void updateArticle(Article article); void deleteArticle(int articleId); boolean articleExists(String title, String category); }
package com.concretepage.dao; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.concretepage.entity.Article; @Transactional @Repository public class ArticleDAO implements IArticleDAO { @PersistenceContext private EntityManager entityManager; @Override public Article getArticleById(int articleId) { return entityManager.find(Article.class, articleId); } @SuppressWarnings("unchecked") @Override public List<Article> getAllArticles() { String hql = "FROM Article as atcl ORDER BY atcl.articleId"; return (List<Article>) entityManager.createQuery(hql).getResultList(); } @Override public void addArticle(Article article) { entityManager.persist(article); } @Override public void updateArticle(Article article) { Article artcl = getArticleById(article.getArticleId()); artcl.setTitle(article.getTitle()); artcl.setCategory(article.getCategory()); entityManager.flush(); } @Override public void deleteArticle(int articleId) { entityManager.remove(getArticleById(articleId)); } @Override public boolean articleExists(String title, String category) { String hql = "FROM Article as atcl WHERE atcl.title = ? and atcl.category = ?"; int count = entityManager.createQuery(hql).setParameter(1, title) .setParameter(2, category).getResultList().size(); return count > 0 ? true : false; } }
Create Service for CRUD Operation with Secured Methods
Now we will create service methods for CRUD operation with secured methods.IArticleService.java
package com.concretepage.service; import java.util.List; import org.springframework.security.access.annotation.Secured; import com.concretepage.entity.Article; public interface IArticleService { @Secured ({"ROLE_ADMIN", "ROLE_USER"}) List<Article> getAllArticles(); @Secured ({"ROLE_ADMIN", "ROLE_USER"}) Article getArticleById(int articleId); @Secured ({"ROLE_ADMIN"}) boolean addArticle(Article article); @Secured ({"ROLE_ADMIN"}) void updateArticle(Article article); @Secured ({"ROLE_ADMIN"}) void deleteArticle(int articleId); }
getAllArticles()
and getArticleById()
service methods. Now find the implementation class.
ArticleService.java
package com.concretepage.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.concretepage.dao.IArticleDAO; import com.concretepage.entity.Article; @Service public class ArticleService implements IArticleService { @Autowired private IArticleDAO articleDAO; @Override public Article getArticleById(int articleId) { Article obj = articleDAO.getArticleById(articleId); return obj; } @Override public List<Article> getAllArticles(){ return articleDAO.getAllArticles(); } @Override public synchronized boolean addArticle(Article article){ if (articleDAO.articleExists(article.getTitle(), article.getCategory())) { return false; } else { articleDAO.addArticle(article); return true; } } @Override public void updateArticle(Article article) { articleDAO.updateArticle(article); } @Override public void deleteArticle(int articleId) { articleDAO.deleteArticle(articleId); } }
Create Controller for CRUD Operation
Find the controller class that has methods for CREATE, READ, UPDATE and DELETE (CRUD) operation.ArticleController.java
package com.concretepage.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; 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.util.UriComponentsBuilder; import com.concretepage.entity.Article; import com.concretepage.service.IArticleService; @Controller @RequestMapping("user") public class ArticleController { @Autowired private IArticleService articleService; @GetMapping("article/{id}") public ResponseEntity<Article> getArticleById(@PathVariable("id") Integer id) { Article article = articleService.getArticleById(id); return new ResponseEntity<Article>(article, HttpStatus.OK); } @GetMapping("articles") public ResponseEntity<List<Article>> getAllArticles() { List<Article> list = articleService.getAllArticles(); return new ResponseEntity<List<Article>>(list, HttpStatus.OK); } @PostMapping("article") public ResponseEntity<Void> addArticle(@RequestBody Article article, UriComponentsBuilder builder) { 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); } @PutMapping("article") public ResponseEntity<Article> updateArticle(@RequestBody Article article) { articleService.updateArticle(article); return new ResponseEntity<Article>(article, HttpStatus.OK); } @DeleteMapping("article/{id}") public ResponseEntity<Void> deleteArticle(@PathVariable("id") Integer id) { articleService.deleteArticle(id); return new ResponseEntity<Void>(HttpStatus.NO_CONTENT); } }
@GetMapping
for HTTP GET method
@PostMapping
for HTTP POST method
@PutMapping
for HTTP PUT method
@DeleteMapping
for HTTP DELETE method
We have created following URLS for CRUD operation.
1. Create :
HTTP Method: POST, URL: /user/article
2. Read :
HTTP Method: GET, URL: /user/article/{id}
HTTP Method: GET, URL: /user/articles
3. Update :
HTTP Method: PUT, URL: /user/article
4. Delete :
HTTP Method: DELETE, URL: /user/article/{id}
Create Main Class using SpringApplication
Create a class withmain()
method that will call SpringApplication.run()
to run the application. First all JAR dependencies are downloaded and then the project is compiled and then embedded tomcat server starts.
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 that is equivalent to @Configuration
, @EnableAutoConfiguration
and @ComponentScan
annotations.
Create Client using RestTemplate
To consume the REST web service, we are using RestTemplate. For authentication we will pass Base64 encoded credential as username:password token inHttpHeaders
with Basic authorization.
RestClientUtil.java
package com.concretepage.client; import java.net.URI; import org.apache.tomcat.util.codec.binary.Base64; 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 { private HttpHeaders getHeaders() { String credential="mukesh:m123"; //String credential="tarun:t123"; String encodedCredential = new String(Base64.encodeBase64(credential.getBytes())); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.add("Authorization", "Basic " + encodedCredential); return headers; } public void getArticleByIdDemo() { HttpHeaders headers = getHeaders(); 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 = getHeaders(); 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 = getHeaders(); 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 = getHeaders(); 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 = getHeaders(); 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.getAllArticlesDemo(); //util.addArticleDemo(); util.updateArticleDemo(); //util.deleteArticleDemo(); } }
Run Application
To run the application, first create table in MySQL as given in the example. Now we can run REST web service in following ways.1. Using Eclipse: Download the project source code using the download link given at the end of page. 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.
2. 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
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 client, go to the
RestClientUtil
class in eclipse and click on Run as -> Java Application.
We can also test application using Postman UI. Find the print screen.