Category: Spring boot complete tutorial with example

Home / Category: Spring boot complete tutorial with example

As we know we can use many database with spring boot application like MySQL, MongoDB, SQL Server etc. But if we don’t have any database installed in our machine then we can use this embedded database of spring boot. Spring boot provide us this embedded database for performing task. But it is not a good choice for production because this database is accessible only when our application is running if we stop our application it will automatically off the H2 database. To see how to configure h2 database in spring boot we have to follow the below steps:

  1. Add the required dependency in your pom.xml file
  2. Enable the H2 database by defining property in your application.properties file.
  3. Create an Entity using JPA named as student.
  4. Run your application and hit the H2 console URL, Change the JDBC URL in H2 UI to jdbc:h2:mem:testdb and connect to database.

Follow above Steps:

1- Add the required dependency in your pom.xml file

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <scope>runtime</scope>
 <optional>true</optional>
</dependency>

<dependency>
 <groupId>com.h2database</groupId>
 <artifactId>h2</artifactId>
</dependency>

2- Enable the H2 database by defining property in your application.properties file.

server.port=8081
   
spring.h2.console.path=/h2-console
Spring.h2.console.enabled=true

Spring.jpa.show-sql=true
spring.datasource.url=jdbc:h2:mem:testdb


3- Create an Entity using JPA named as student.

package com.example.demo.model;

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 = "student")
public class Student {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "studentId")
	private long id;

	private String name;

	private String emailId;

	public Student() {
		super();
	}

	public Student(long id, String name, String emailId) {
		super();
		this.id = id;
		this.name = name;
		this.emailId = emailId;
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

}

4- Run your application and hit the H2 console URL, Change the JDBC URL in H2 UI to jdbc:h2:mem:testdb and connect to database.

As we define port as 8081 and h2 console path as /h2-console in application.properties file. So you have to hit the below URL:

http://localhost:8081/h2-console

Now when you hit the above URL you will get a UI like below, change the JDBC URL to jdbc:h2:mem:testdb and click on connect you will get the table named as Student at we create using JPA.

h2 database spring boot
h2 database spring boot

Complete code on GitHub: Spring Boot H2 Database

You may also like:

Profiles in Spring boot application

Swagger2 in Spring Boot

Spring Boot Security With MySql

Spring boot security using JWT ( JSON WEB TOKENS ).

File Upload in Spring Boot

Help Others, Please Share

We always need some tool that is used for monitoring our application. Spring boot provides Actuator for monitoring the application. It tells us the complete status of our application like status of our application, Information about our application, Beans detail of application and many more. We can see the actuator endPoint using hit the below URL

http://localhost:8080/actuator

For using this actuator endPoint you have to add the below dependency in your pom.xml file.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Now run your application and hit the above given URL you will get the response like below:

By default only health and info end point are available using HTTP if you want to show all the endPoint using HTTP, you have to add below property in your application.properties file.

management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=health,info,metrics,env,mappings,beans,shutdown

No hit the URL again now you will get the response like below:

By default if you hit the health or info URL it will give only specific information like below:

But if you want to see the complete health status and give information about your application using info endPoint you have to add the below property in your application.properties file.

management.endpoint.health.show-details=always

info.appInformation.name=Spring Actuator Example
info.appInformation.description=This is First Spring Boot Actuator Application Example
info.appInformation.version=1.1.1

Now hit the /health and /info URL again you will get the response like below:

Spring boot Actuator provide /shutdown endPoint using which we can shutdown our application. This is a post request if you hit the /shutdown URL with POST method your application will shutdown and you will get the response like below:

We know by default all the actuator endPoints are available on /actuator endPoint but if we want to change this URL and port we have to add the below property in application.properties file:

management.endpoints.web.base-path=/vasu
management.server.port=9009

Now our actuator endPoints are available on below URL:

http://localhost:9009/vasu/

Complete Code on GitHub: Actuator SpringBoot

Help Others, Please Share

we know database connectivity is the most interesting part of any web application. As we already know how to use Mysql Database in Spring Boot application ( CLICK ME ), but sometime we need more than one database to interact with in our single application. So it is very easy to use multiple database in a single application. In this blog we see how to connect two different MySql database in Spring boot application. For that we have to follow the below steps:

  1. Add required dependency in your pom.xml file.
  2. Create Two Database named database1, database2 and create a table named testing in both the databases.
  3. Define MySql property for both the database in your application.properties file.
  4. Define a configuration class and initialise jdbctemplate for both the databases.
  5. Create a Service class and Autowired both the initialize jdbctemplate in that class and perform query to save data in different databases tables.
  6. Create a controller class that is used to declare an rest endPoint .

Follow Above steps:

1- Add required dependency in your pom.xml file.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <scope>runtime</scope>
 <optional>true</optional>
</dependency>

<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <scope>runtime</scope>
</dependency>

2- Create Two Database named database1, database2 and create a table names testing in both the databases.

create database1;

use database1;

CREATE TABLE `testing` (
  `id` int(2) NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

create database2;

use database2;

CREATE TABLE `testing` (
  `id` int(2) NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
)


3- Define MySql property for both the database in your application.properties file.

#Configuration for First Database
database1.datasource.jdbc-url=jdbc:mysql://localhost:3306/database1
database1.datasource.username=vasu
database1.datasource.password=12345@
database1.datasource.driver-class-name=com.mysql.jdbc.Driver


#Configuration For Second Database
database2.datasource.jdbc-url=jdbc:mysql://localhost:3306/database2
database2.datasource.username=vasu
database2.datasource.password=12345@
database2.datasource.driver-class-name=com.mysql.jdbc.Driver

4- Define a configuration class and initialise jdbctemplate for both the databases.

package com.example.demo.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;

@org.springframework.context.annotation.Configuration
public class Configuration {

	/* ********* For Database 1 *********** */
	@Bean(name = "datasource1")
	@ConfigurationProperties(prefix = "database1.datasource")
	@Primary
	public DataSource dataSource1() {
		return DataSourceBuilder.create().build();
	}

	@Bean(name = "db1_template")
	public JdbcTemplate database_1_template(@Qualifier("datasource1") DataSource db1) {
		return new JdbcTemplate(db1);
	}
	
	
	/* ********* For Database 2 *********** */
	@Bean(name = "datasource2")
	@ConfigurationProperties(prefix = "database2.datasource")
	public DataSource dataSource2() {
		return DataSourceBuilder.create().build();
	}
	
	@Bean(name = "db2_template")
	public JdbcTemplate database_2_template(@Qualifier("datasource2") DataSource db2) {
		return new JdbcTemplate(db2);
	}
}

5- Create a Service class and Autowired both the initialize jdbctemplate in that class and perform query to save data in different databases tables.

package com.example.demo.service;

import javax.transaction.Transactional;

import org.hibernate.annotations.common.util.impl.LoggerFactory;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class MainService {
	
	private static final Logger logger = org.slf4j.LoggerFactory.getLogger(MainService.class);
	
	private static final String query = "insert into testing(id,name) values(?,?)";

	@Autowired
	@Qualifier("db1_template")
	private JdbcTemplate template_database_1;
	
	@Autowired
	@Qualifier("db2_template")
	private JdbcTemplate template_database_2;
	
	@Transactional
	public int save() {
		try {
			int insertDB1Status = template_database_1.update(query, new Object[] {1,"vasu rajput"});
			logger.info("insertDB1Status= "+insertDB1Status);
			
			int insertDB2Status = template_database_2.update(query, new Object[] {2,"vishu rajput"});
			logger.info("insertDB1Status= "+insertDB1Status);
			
			return 1;
		} catch (Exception e) {
			logger.error("Exception: "+e);
			return 0;
		}
	}
}

6- Create a controller class that is used to declare an rest endPoint .

package com.example.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.service.MainService;

@RestController
public class MainController {

	private static final Logger logger = LoggerFactory.getLogger(MainController.class);

	@Autowired
	private MainService service;

	@GetMapping("/")
	public String test() {
		try {
			int saveStatus = service.save();
			logger.info("saveStatus= " + saveStatus);
			if (saveStatus == 1) {
				return "Nice Try Champ !!";
			} else {
				return "Some Technical Error Please Try again";
			}
		} catch (Exception e) {
			logger.error("Exception: " + e);
			return "Some Technical Error Please Try again";
		}
	}
}

Complete Code on Github: Multiple Database SpringBoot

Help Others, Please Share

As we know in microservice architecture we have many application and every application have some end points. But it is difficult if we integrate our application with any front end technology. For that we have to define many end point and at some point it becomes hard to maintain the endpoints. So we have to give a common API address to other front end technology and that is also secure because now our Zuul API gateway address is open to others and our rest of application end Points are secured on private IP server . So spring cloud provide Netflix zuul Server for this that is used for routing the other application end Points. To use Netflix Zuul API gateway we have to follow below steps:

  1. Add required dependency in your pom.xml file.
  2. Use @EnableZuulProxy annotation in your main class.
  3. Register this Zuul API gateway application With Eureka Server.
  4. Provide routing endPoints property in your application.properties file.
  5. Run Eureka Server and all other application and use your zuul gateway url to access all other application end Points.

Summary of Project: In this Project we have created Four Application.

  1. An Eureka Server application that is used to monitor other application.
  2. An Student application that is registered with Eureka Server and have a GET end Point name /student.
  3. An Teacher application that is registered with Eureka Server and have a GET end Point name /teacher
  4. An Zuul API Gateway that is also register with Eureka Server and provide URL using which we can access Teacher and Student end points.

First Three Steps of Project Summary we have already know how to create if not than see my blogs on Microservices ( CLICK ME ). In this we focus on Fourth point how to create zuul API gateway. So now flow above given steps:

1- Add required dependency in your pom.xml file.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

2- Use @EnableZuulProxy annotation in your main class.

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableEurekaClient
@EnableZuulProxy
@SpringBootApplication
public class AccountServiceApplication {

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

}

3- Now in this steps we have to register our Zuul API gateway with Eureka Server and also provide routing to others endPoint. So this use below properties in your application.properties file.

server.port=8082
spring.application.name=gateway-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka

zuul.routes.student-service.path=/studentGateway/**
zuul.routes.teacher-service.path=/teacherGateway/**

In the above properties zuul.routes.student-service.path

zuul.routes is fixed student-service is the name of application that you have defined for Student application in your Student application.properties file after that append path and in value you can give any prefix that you want here we give /studentGateway/** Now our property become

zuul.routes.student-service.path=/studentGateway/**

Same is For teacher property Now you have to hit the below URL for access Student and Teacher end point response.

To Access Student URL hit below URL

http://localhost:8082/studentGateway/student

To Access teacher URL hit below URL

http://localhost:8082/teacherGateway/teacher/

If You want to give any prefix also you can add that in your Zuul API gateway application.properties file.

zuul.prefix=/gatewayAPI

Now your application.properties look like

server.port=8082
spring.application.name=gateway-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka

zuul.prefix=/gatewayAPI
zuul.routes.student-service.path=/studentGateway/**
zuul.routes.teacher-service.path=/teacherGateway/**




Now your Student and Teacher URL become.

http://localhost:8082/gatewayAPI/studentGateway/student
http://localhost:8082/gatewayAPI/teacherGateway/teacher/

Complete Code On GitHub : Zull Gateway Routing

Help Others, Please Share

As we know we use Eureka server to monitor the status of our microservices. Eureka server provides a dashboard on which we can see every microservice status and other details like port no on which microservice running and how many instance of microservice are running. But if you see we can easily see dashbord by hitting the URL of Eureak and it is open to all if anybody get your Eureka server URL, they will see all the details about your project.

So to protect our Eureka server we have to define some sort of security so only authorized person can see the server details. In this post we will see how to use HTTP basic security in Eureka Server. so to do this we have to follow below steps:

  1. Add required dependency in your pom.xml file of Eureka Server.
  2. Allow basic security property in your application.properties file with username and password.
  3. Enable security using @EnableWebSecurity annotation in your main class.
  4. Define a configuration class that extends WebSecurityConfigurerAdapter class and overrides configure methos.

Follow below steps:

  1. Add required dependency in your pom.xml file of Eureka Server.
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2- Allow basic security in your application.properties file.

spring.security.basic.enabled=true
spring.security.user.name=vasu
spring.security.user.password=rajput


spring.application.name=netflix-eureka-server
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false



3- Enable security using @EnableWebSecurity annotation in your main class.

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@EnableEurekaServer
@EnableWebSecurity
@SpringBootApplication
public class SecureEurekaServerApplication {

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

}

4- Define a configuration class that extends WebSecurityConfigurerAdapter class and overrides configure methos.

package com.example.demo;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();
	}

}

Now Run your application and Hit the Eurka Server URL you will get a popup, Now enter username and password if credentials are valid you will be login otherwise you are not able to login on Eureka server.

Now we have to register our Eureka Client to Eureka server. We know how to connect Eureka client with Eureka Server we use

eureka.client.service-url.default-zone=http://localhost:8761/eureka

in application.properties file of our Eureka client. Now if you use the same configuration you will get error that no server found to connect with so you have to change the above property as

eureka.client.serviceUrl.defaultZone=http://vasu:rajput@localhost:8761/eureka

Now your Eureka client application.properties file look like below

spring.application.name=secureEurekaClient
server.port=9091
eureka.client.serviceUrl.defaultZone=http://vasu:rajput@localhost:8761/eureka



In the above URL http://vasu:rajput@localhost:8761/eureka vasu is username and rajput is password.

Now run your Eureka client and it will successfully register to Eureka Server.

Complete Code on GitHub : Eureka Server Security

Help Others, Please Share

In this article we see about Spring Cloud Security. As we know security is the first concern when we work on any project, we don’t want to compromise with user credentials so we have to more concern about security.

JWT ( Json Web Token ) is one of the feature Spring Cloud Security. Any API can be accessed only if user has valid signed token otherwise he will not able to access that APIs.

JWT ( Json Web Token ) consist of three parts. And Structure will be like ( Header.Payload.Secret ). For More Go to ( visit jwt.io )

  1. Header ( Consist of typ that always be JWT and a Hashing algo )
  2. Payload ( Consist of claims or Information )
  3. Signature ( Secret Key that you provide to signed token )

We can use JWT in Spring Boot using below steps:

  1. Add required dependency in your pom.xml file.
  2. Add MySQL configuration in your application.properties file.
  3. Create a class where you define some constatnts like JWT Secret and expire time for JWT token.
  4. Create a utility Class where we can define claim, generate or validate JWT tokens for user.
  5. Create a DAO class where you can perform MySQL activity.
  6. Create a class that implements UserDetailsService and perform user authentication by getting userName and password of user.
  7. create a controller class where we can provide endPoint for getting our Token if authentication successful.
  8. Create Two Model class one is for getting userName and password and other is for JWT Response.
  9. Create a Filter class that perform JWT validation on each request.
  10. create a class that implements AuthenticationEntryPoint for reject every unauthenticated request and Send 401 Error Code for unauthorised user.
  11. Create a class that extends WebSecurityConfigurerAdapter and provide security configuration for endPoint that we want to secure.
  12. After This we will run our application and make a Post request with username and password to authenticate API that we define in controller to get JWT Token.
  13. Now add this Token to your Header with Bearer keyword to get response from Secured APIs. You will get response only if you pass a valid Token.

Follow below steps:

1- Add required dependency in your pom.xml file.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</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-web</artifactId>
</dependency>

<dependency>
 <groupId>io.jsonwebtoken</groupId>
 <artifactId>jjwt</artifactId>
 <version>0.9.1</version>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <scope>runtime</scope>
 <optional>true</optional>
</dependency>

<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <scope>runtime</scope>
</dependency>

2- Add MySQL configuration in your application.properties file.

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/springBootSecurityMySQL
spring.datasource.username=vasu
spring.datasource.password=12345@
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

3- Create a class where you define some constatnts like JWT Secret and expire time for JWT token.

package com.javadream.constant;

public class JwtConstatnt {

	public static final String JWT_SECRET = "123@@#&amp;javadream.in#$%";
	public static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;
}

4- Create a utility Class where we can define claim, generate or validate JWT tokens for user.

package com.javadream.utility;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.UserDetails;

import com.javadream.constant.JwtConstatnt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Configuration
public class JwtTokenUtility implements Serializable{

	private static final long serialVersionUID = -9172337479697036292L;
	private static final Logger logger = LoggerFactory.getLogger(JwtTokenUtility.class);
	
	private static final String JWT_SECRET = JwtConstatnt.JWT_SECRET;
	private static final long JWT_TOKEN_VALIDITY = JwtConstatnt.JWT_TOKEN_VALIDITY;
	
	     //get username from jwt token
		public String getUsernameFromToken(String token) {
			return getClaimFromToken(token, Claims::getSubject);
		}

		public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
			final Claims claims = getAllClaimsFromToken(token);
			return claimsResolver.apply(claims);
		}
		
		//for get any information from token we will need the secret key
		private Claims getAllClaimsFromToken(String token) {
			return Jwts.parser().setSigningKey(JWT_SECRET).parseClaimsJws(token).getBody();
		}
		
		//check if the token has expired
		private Boolean isTokenExpired(String token) {
			final Date expiration = getExpirationDateFromToken(token);
			return expiration.before(new Date());
		}
		
		//retrieve expiration date from jwt token
		public Date getExpirationDateFromToken(String token) {
			return getClaimFromToken(token, Claims::getExpiration);
		}
		
		//generate token for user
		public String generateToken(UserDetails userDetails) {
			Map<String, Object> claims = new HashMap<>();
			return doGenerateToken(claims, userDetails.getUsername());
		}
		

		private String doGenerateToken(Map<String, Object> claims, String subject) {
			return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
					.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
					.signWith(SignatureAlgorithm.HS512, JWT_SECRET).compact();
		}
		
		//validate token
		public Boolean validateToken(String token, UserDetails userDetails) {
			final String username = getUsernameFromToken(token);
			return (username.equals(userDetails.getUsername()) &amp;&amp; !isTokenExpired(token));
		}
}

5- Create a DAO class where you can perform MySQL activity.

package com.javadream.dao;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;

import com.javadream.model.UserBean;

@Repository
public class UserDAO {
	
	private static final Logger logger = LoggerFactory.getLogger(UserDAO.class);
	
	@Autowired
    private PasswordEncoder encoder;

	@Autowired
	private JdbcTemplate template;
	
	public UserBean getUserInfo(String userName) {
		try {
			String query = "select * from userDetail where userName=?";
			List<Map<String, Object>> userResponse = template.queryForList(query, new Object[] {userName});
			logger.info("vvv::  userResponse= "+userResponse);
			if(userName !=null) {
				UserBean userBean = new UserBean(userResponse.get(0).get("username").toString(),
						userResponse.get(0).get("password").toString());
				return userBean;
			}
		} catch (Exception e) {
			logger.error(e.getStackTrace().toString());
		}
		return null;
	}
	
	   public int insertUser(UserBean user) {
	        try {
	            String userName = user.getUserName();
	            String pass = user.getPassword();

	            logger.info("vvv::  userName= "+userName + " ,pass= "+pass );
	            int updateStatus = template.update("insert into userDetail(username,password) values(?,?)", new Object[] {userName,encoder.encode(pass)});
	            logger.info("vvv::  updateStatus= "+updateStatus);
	            if(updateStatus == 1) {
	             return 1;
	            }
	            return 0;
	        } catch (Exception e) {
	            e.printStackTrace();
	            return 0;
	        }
	    }
}

6- Create a class that implements UserDetailsService and perform user authentication by getting userName and password of user.

package com.javadream.service;

import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.javadream.dao.UserDAO;
import com.javadream.model.UserBean;

@Service
public class JwtUserDetailService implements UserDetailsService {

	private static final Logger logger = LoggerFactory.getLogger(JwtUserDetailService.class);

	@Autowired
	private UserDAO dao;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		try {
			UserBean userInfo = dao.getUserInfo(username);
			logger.info("vvv::  userInfo= " + userInfo);
			if (userInfo != null) {
				UserDetails userDetails = (UserDetails) new org.springframework.security.core.userdetails.User(
						userInfo.getUserName(), userInfo.getPassword(), new ArrayList<>());
				return userDetails;
			} else {
				throw new UsernameNotFoundException("User not found with username: " + username);
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return null;
	}

}

7- create a controller class where we can provide endPoint for getting our Token if authentication successful.

package com.javadream.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.javadream.dao.UserDAO;
import com.javadream.model.JwtResponse;
import com.javadream.model.UserBean;
import com.javadream.service.JwtUserDetailService;
import com.javadream.utility.JwtTokenUtility;

@RestController
public class JwtAuthenticationController {

	private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationController.class);

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private JwtTokenUtility jwtTokenUtil;

	@Autowired
	private JwtUserDetailService userDetailService;
	
	@Autowired
	private UserDAO dao;

	@PostMapping("/authenticateAPI")
	public ResponseEntity<?> createAuthenticationToken(@RequestBody UserBean authenticationRequest) {
		try {
			logger.info("vvv::  Loading createAuthenticationToken for UserBean= " + authenticationRequest);
			authenticateUser(authenticationRequest.getUserName(), authenticationRequest.getPassword());
			final UserDetails userDetails = userDetailService.loadUserByUsername(authenticationRequest.getUserName());

			final String token = jwtTokenUtil.generateToken(userDetails);

			return ResponseEntity.ok(new JwtResponse(token));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
	}
	
	@PostMapping("/insert")
    public String insert(@RequestBody UserBean user) {
        try {
            logger.info("vvv::  user= "+user);
            if(user == null) {
                return "Some technical error try again";
            }
            int insertUser = dao.insertUser(user);
            return "Insert Status= "+insertUser;
        } catch (Exception e) {
            e.printStackTrace();
            return "Some Technical Error Try Again";
        }
         
    }

	private void authenticateUser(String username, String password) throws Exception {
		try {
			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
		} catch (DisabledException e) {
			throw new Exception("USER_DISABLED", e);
		} catch (BadCredentialsException e) {
			throw new Exception("INVALID_CREDENTIALS", e);
		}
	}
}

Create Another Controller Whose APIs are secured.

package com.javadream.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SecureController {

	
	@GetMapping("/SecureAPI")
	public String getSecureEndPoint() {
		return "Nice try! You have learned Spring Boot JWT Security";
	}
}

8- Create Two Model class one is for getting userName and password and other is for JWT Response.

package com.javadream.model;

public class UserBean {

	private String userName;
	private String password;

	public UserBean() {
		super();
	}

	public UserBean(String userName, String password) {
		super();
		this.userName = userName;
		this.password = password;
	}

	@Override
	public String toString() {
		return "UserBean [userName=" + userName + ", password=" + password + "]";
	}

	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;
	}

}

package com.javadream.model;

import java.io.Serializable;

public class JwtResponse implements Serializable {

	private static final long serialVersionUID = 2624374270511956111L;

	private final String jwttoken;

	public JwtResponse(String jwttoken) {
		this.jwttoken = jwttoken;
	}

	public String getToken() {
		return this.jwttoken;
	}
}

9- Create a Filter class that perform JWT validation on each request.

package com.javadream.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.javadream.service.JwtUserDetailService;

import com.javadream.utility.JwtTokenUtility;

import io.jsonwebtoken.ExpiredJwtException;

@Component
public class JwtFilter extends OncePerRequestFilter {
	private static final Logger logger = LoggerFactory.getLogger(JwtFilter.class);

	@Autowired
	private JwtTokenUtility jwtTokenUtil;

	@Autowired
	private JwtUserDetailService jwtUserDetailsService;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		final String requestTokenHeader = request.getHeader("Authorization");

		String username = null;
		String jwtToken = null;

		if (requestTokenHeader != null &amp;&amp; requestTokenHeader.startsWith("Bearer ")) {
			jwtToken = requestTokenHeader.substring(7);
			try {
				username = jwtTokenUtil.getUsernameFromToken(jwtToken);
			} catch (IllegalArgumentException e) {
				System.out.println("Unable to get JWT Token for this user");
			} catch (ExpiredJwtException e) {
				System.out.println("JWT Token has been expired");
			}
		} else {
			logger.warn("JWT Token do not start with Bearer keyword");
		}

		// Once we get the token validate it.
		if (username != null &amp;&amp; SecurityContextHolder.getContext().getAuthentication() == null) {

			UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);

			if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {

				UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
						userDetails, null, userDetails.getAuthorities());
				usernamePasswordAuthenticationToken
						.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

				SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
			}
		}
		filterChain.doFilter(request, response);

	}

}

10- create a class that implements AuthenticationEntryPoint for reject every unauthenticated request and Send 401 Error Code for unauthorised user.

package com.javadream.service;

import java.io.IOException;
import java.io.Serializable;

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.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {

	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException authException) throws IOException, ServletException {
		response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");

	}

}

11- Create a class that extends WebSecurityConfigurerAdapter and provide security configuration for endPoint that we want to secure.

package com.javadream.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.javadream.filter.JwtFilter;
import com.javadream.service.JwtAuthenticationEntryPoint;

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter{

	@Autowired
	private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

	@Autowired
	private UserDetailsService jwtUserDetailsService;

	@Autowired
	private JwtFilter jwtRequestFilter;

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
	}

	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {

		httpSecurity.csrf().disable()
				.authorizeRequests().antMatchers("/authenticateAPI","/insert").permitAll().
				
				anyRequest().authenticated().and().
				exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
				.and().sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.STATELESS);

		httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
	}
}

Now our application has been ready to run, Just run your application and first create a user ( SignUp ). we do not define any security on signup API because everybody allow to do SignUp but rest endPoint are secured. So now make a SignUp request using Postman.

Complete Code on GitHub : SpringBoot Security JWT

Spring Cloud Security

12- After This we will run our application and make a Post request with username and password to authenticate API that we define in controller to get JWT Token.

Spring Cloud Security

13- Now add this Token to your Header with Bearer keyword to get response from Secured APIs. You will get response only if you pass a valid Token.

Spring Cloud Security

You may also like

Spring Boot Security With MySql

spring batch example

Spring Boot with Apache kafka.

File Upload in Spring Boot

HTTPS in Spring Boot

Help Others, Please Share

As we know security is the first concern when we working on any web application. Spring Boot also provide this feature to prevent our user from unauthorised access. Some time we also want Role wise authentication in our application means we want a user to access API only if he will authorised to use that. In this post we will see how we can manage a complete role wise authentication using MySQL in Spring boot, So to do that we have to follow below steps:

  1. Add required dependency in your pom.xml file.
  2. Add MySQL configuration in your application.properties file
  3. create user and authorities table in your MySQL.
  4. Enable security in your main class using @EnableWebSecurity annotaion.
  5. Create a Model class User.
  6. Create a configuration class that extends WebSecurityConfigurerAdapter and specify security config in this class.
  7. Create a DAO Class that Perform MySQL activity.
  8. Create a class that implements UserDetailsService and perform Spring Boot Security validation.
  9. Create Controller class for Rest Endpoint .

Follow above steps:

1- Add below dependency in your pom.xml file.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</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-web</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <scope>runtime</scope>
 <optional>true</optional>
</dependency>

<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <scope>runtime</scope>
</dependency>

2- Add MySQL configuration in your application.properties file.

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/springBootSecurityMySQL
spring.datasource.username=vasu
spring.datasource.password=12345@
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

3- Create user and authorities table in MySQL.

CREATE TABLE IF NOT EXISTS `user` (
  `username` varchar(50) NOT NULL,
  `password` varchar(150) NOT NULL,
  `enabled` tinyint(1) NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;



CREATE TABLE IF NOT EXISTS `authorities` (
  `username` varchar(50) NOT NULL,
  `authority` varchar(50) NOT NULL,
  UNIQUE KEY `ix_auth_username` (`username`,`authority`),
  CONSTRAINT `fk_authorities_users` FOREIGN KEY (`username`) REFERENCES `user` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

4- Enable security in your main class using @EnableWebSecurity annotaion.

package com.javadream;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@EnableWebSecurity
@SpringBootApplication
public class SpringBootSecurityMySqlApplication {

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

}

5- Create a Model class User.

package com.javadream.model;

public class User {

	private String userName;
	private String password;
	private String role;

	public User() {
		super();
	}

	public User(String userName, String password, String role) {
		super();
		this.userName = userName;
		this.password = password;
		this.role = role;
	}

	@Override
	public String toString() {
		return "User [userName=" + userName + ", password=" + password + ", role=" + role + "]";
	}

	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;
	}

}

6- Create a configuration class that extends WebSecurityConfigurerAdapter

package com.javadream.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.javadream.service.UserAuthenticationService;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Autowired
	UserAuthenticationService authenticationService;

	@Autowired
	private PasswordEncoder encoder;

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		auth.userDetailsService(authenticationService).passwordEncoder(encoder);
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
		.antMatchers("/signUp/**").permitAll()
		.antMatchers("/userRoleAPIs/**")
		.hasAnyRole("USER")
		.antMatchers("/adminRoleAPIs/**")
		.hasAnyRole("ADMIN")
		.antMatchers("/anyRoleAPIs/**")
		.hasAnyRole("USER","ADMIN")
		.and().csrf().disable().formLogin();
	}

}

In above class we override configure method of WebSecurityConfigurerAdapter class. Inside this function we define the APIs end point and the role that can access that APIs. We do not define any type of security on SignUp endPoint because anybody can do Sign Up and we don’t required any authentication for Sing Up process.

7- Create a DAO Class that Perform MySQL activity .

package com.javadream.dao;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import org.springframework.security.authentication.*;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.javadream.model.User;

@Repository
public class UserDao {
	private static final Logger logger = LoggerFactory.getLogger(UserDao.class);

	@Autowired
	private JdbcTemplate template;
	
	@Autowired
	private PasswordEncoder encoder;

	public User getUserInfo(String userName) {
		try {
			String sql = "SELECT u.username name, u.password pass, a.authority role FROM "
					+ "user u INNER JOIN authorities a on u.username=a.username WHERE "
					+ "u.enabled =1 and u.username = ?";
			List<Map<String, Object>> userResponse = template.queryForList(sql, new Object[] { userName });
			logger.info("vvv::  userResponse= " + userResponse);
			
			if (userResponse != null) {
				User user = new User(userResponse.get(0).get("name").toString(),
						userResponse.get(0).get("pass").toString(),
						userResponse.get(0).get("role").toString());
				
				logger.info("vvv:: user= " + user);
				return user;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;

	}
	
	
	public int insertUser(User user) {
		try {
			String userName = user.getUserName();
			String pass = user.getPassword();
			String role = user.getRole();
			logger.info("vvv::  userName= "+userName + " ,pass= "+pass + ", role= "+role);
			int updateStatus = template.update("insert into user(username,password,enabled) values(?,?,?)", new Object[] {userName,encoder.encode(pass),"1"});
			logger.info("vvv::  updateStatus= "+updateStatus);
			if(updateStatus == 1) {
				int insertIntoAuthTable = template.update("insert into authorities(username,authority) values(?,?)", new Object[] {userName,role});
                logger.info("vvv::  insertIntoAuthTable = "+insertIntoAuthTable);
                if(insertIntoAuthTable == 1) {
                	return 1;
                }
			}
			return 0;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

}

In above class we define a bean PasswordEncoder , because we don’t want to save our user password in Plain Text in MySQL table so we use PasswordEncoder to encrypt our password before save it to MySQL.

8- Create a class that implements UserDetailsService and perform Spring Boot Security validation.

package com.javadream.service;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import com.javadream.dao.UserDao;
import com.javadream.model.User;

@Service
public class UserAuthenticationService implements UserDetailsService {

	private static final Logger logger = LoggerFactory.getLogger(UserAuthenticationService.class);

	@Autowired
	private UserDao dao;

	@Autowired
	private BCryptPasswordEncoder encoder;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		try {
			logger.info("vvv::  calling loadUserByUsername for username= " + username);
			User userInfo = dao.getUserInfo(username);
			GrantedAuthority authority = new SimpleGrantedAuthority(userInfo.getRole());
			UserDetails userDetails = (UserDetails) new org.springframework.security.core.userdetails.User(
					userInfo.getUserName(), userInfo.getPassword(), Arrays.asList(authority));

			return userDetails;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
	}

}

9- Create Controller Class for Rest EndPoint.

Here we define three controller to demonstrate how APIs will be access with valid role.

First We create a SignUp controller to Sign Up. APIs for Sign up is open to all any body can access that.

package com.javadream.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.javadream.dao.UserDao;
import com.javadream.model.User;

@RestController
@RequestMapping("signUp")
public class InsertController {
	private static final Logger logger = LoggerFactory.getLogger(InsertController.class);
	private static final String GLOBAL_ERROR = "Some technical Error try again!";

	@Autowired
	private UserDao dao;
	
	
	@PostMapping("/insert")
	public String insert(@RequestBody User user) {
		try {
			logger.info("vvv::  user= "+user);
			if(user == null) {
				return GLOBAL_ERROR;
			}
			int insertUser = dao.insertUser(user);
			return "Insert Status= "+insertUser;
		} catch (Exception e) {
			e.printStackTrace();
			return "Some Technical Error Try Again";
		}
		
	}
}

Second We create a UserController. APIs for this controller is accessed by those who have USER role.

package com.javadream.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.javadream.dao.UserDao;
import com.javadream.model.User;

@RestController
@RequestMapping("userRoleAPIs")
public class UserController {

	private static final Logger logger = LoggerFactory.getLogger(UserController.class);

	
	@GetMapping("/testAPI")
	public String demo() {
		return "Nice Try! You have learned Spring Boot Security With MySql";
	}
}

Third we create a AdminController. APIs for this controller is accessed by those who have ADMIN role.

package com.javadream.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/adminRoleAPIs")
public class AdminController {

	@GetMapping("/testAPI")
	public String demo() {
		return "Nice Try! You have learned Spring Boot Security With MySql";
	}
}

Fourth we create a AnyRoleController. APIs for this controller is accessed by those who any role ADMIN role or USER role.

package com.javadream.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/anyRoleAPIs")
public class AnyRoleController {

	
	@GetMapping("/testAPI")
	public String demo() {
		return "Nice Try! You have learned Spring Boot Security With MySql";
	}
}

Now Run this application and use below steps to test your application functionality.

  1. Make a Post Request to Sign Up URL using postman .
  2. Define role parameter accordingly for Admin role use parameter ROLE_ADMIN and for user role use parameter ROLE_USER
  3. Now try to access any API from any controller ( UserController, AdminController, AnyRoleController).
  4. when you hit API a default SignUp Page will open now enter your credentials if your user has valid credential and valid role then you will get the response otherwise 403 error will display.

Complete Code On GitHub: SpringBoot Role Wise authentication with MySQL

Help Others, Please Share

We know that Spring boot micro services application is divided into modules or separate application. And in many cases it is necessary that we have to call the one application end point from another application. So to Call one application end point from another application Spring boot provided two choices.

  1. RestTemplae
  2. Feign Client

In this example we are using Feign Client to communicate between two applications.

So to working with Feign Client we have to create two applications with some end Point. You can follow my Create Application in Spring boot microservice Blog to see how to create application in Spring boot Microservices.

Suppose we have two differnet application hosted on Eureka Server with name CLIENT1 , CLIENT2.

Note: CLIENT1 and CLIENT2 are the name that you give to your application inside application.properties using.

spring.application.name=client1

Now Suppose we are Calling end point of CLIENT2 application from CLIENT1

So we will perform some steps in CLIENT1 application

1- Add below dependency in your pom.xml file

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2- Enable Feign Client using @EnableFeignClients annotation in your main class.

@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class EurekaClient1Application {

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

3- Create an Interface with @FeignClient and @RibbonClient annotation and give the name of application that display on your Eureka Server.

@FeignClient(name = "CLIENT2")
@RibbonClient(name = "CLIENT2")
public interface Client2proxy {

	@GetMapping("client2")
	public String proxyResponse();
}

In above Interface we are given name of CLIENT2 application and create a end point with same that we created in CLIENT2 application.

Note: In CLIENT2 application you must have an end point /client2 that return some string.

4- Now create a Controller class in CLIENT1 application and Auto-wired your proxy interface in that application

@RestController
public class ClientController1 {
	
	@Autowired
	private Client2proxy proxy;

	@GetMapping("/client1")
	public String client1() {
		return "I am client 1";
	}
	
	@GetMapping("/testProxy")
	public String testP() {
		String proxyResponse = proxy.proxyResponse();
		return proxyResponse;
	}
}

Now Hit below URL in your browser you will get the response from CLIENT2 application end point

http://localhost:8081/testProxy

Help Others, Please Share

As we know in microservice architecture we have many independent application and some time it is needed that one application communicates with other application to do some operation. So if we want to communicate between two microservice then spring cloud provide us two useful Component

  1. RestTemplate
  2. Feign Client

In This Post we will discuss how two microservice communicate between them using RestTemplate. Make Sure you have your Eureka Server Running and both the application is registered on that. To use RestTemplate in our application we have to follow below steps:

  1. Add required dependeny in your pom.xml file.
  2. Create Two MicroService project. In this we create two project one is MicroService-1 and another is MicroService-2.
  3. Give ApplicationName , Port and Eureka server path in your application.properties file.
  4. Create a Bean for RestTemplate because we can’t auto-wired RestTemlate directly. So we create a configuration class and initialize a Bean for RestTemplate.
  5. Autowired RestTemplate in your Service class to call Rest End Point of another application.

Follow above Steps:

1- Add below dependency in your pom.xml file.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
 <groupId>com.googlecode.json-simple</groupId>
 <artifactId>json-simple</artifactId>
 <version>1.1.1</version>
</dependency>

2- Now we are creating a project Name MicroService-1 and from here we call RestEndPoint of MicroService-2 application.

3- Add below property in your application.properties file.

spring.application.name=microservice-1
server.port=8081
eureka.client.service-url.default-zone=http://localhost:8761/eureka

4- Create a Bean for RestTemplate.

package com.javadream.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class Config {

	@Bean
	public RestTemplate template() {
		HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
		httpRequestFactory.setConnectionRequestTimeout(4000);
		httpRequestFactory.setConnectTimeout(4000);
		httpRequestFactory.setReadTimeout(4000);
		return new RestTemplate(httpRequestFactory);
	}
}

5- Now create a Controller class autowired RestTemplate inside that and call RestEndPoint of MicroService-2 application.

For Calling a Get Request of MicroService-2 we use below syntax:

String responseFromMS2 = restTemplate.getForObject("http://localhost:8082/student/showAllStudent",
					String.class);

For Calling a Post Request of MicroService-2 we use below syntax:

HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		JSONObject studentObj = new JSONObject();
		studentObj.put("rollNo", 199);
		studentObj.put("name", "New_Student");
		studentObj.put("email", "new.student@gmail.com");
		org.springframework.http.HttpEntity<String> s = new org.springframework.http.HttpEntity<String>(studentObj.toString(),headers);
		String postForObject = restTemplate.postForObject("http://localhost:8082/student/addStudent", s, String.class);

Complete Code For Calling Get and Post EndPoint of MicroService-2 application:

package com.javadream.controller;

import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/restTemplateDemo")
public class RestTemplateDemoController {

	private static final Logger logger = LoggerFactory.getLogger(RestTemplateDemoController.class);
	private final String GLOBAL_ERROR = "Some technical Error Please try again after some time";

	@Autowired
	private RestTemplate restTemplate;

	@GetMapping("call_MS2_showAllStudent_endPoint")
	public String callMicroservice_2_ShowAllStudent() {
		try {
			String responseFromMS2 = restTemplate.getForObject("http://localhost:8082/student/showAllStudent",
					String.class);
			logger.info("vvv::  responseFromMS2= " + responseFromMS2);
			return responseFromMS2;
		} catch (Exception e) {
			e.printStackTrace();
			return GLOBAL_ERROR;
		}
	}
	
	@GetMapping("call_MS2_addStudent_endPoint")
	public String call_MS_2_addStudent_endPoint() {
		HttpHeaders headers = new HttpHeaders();
	      headers.setContentType(MediaType.APPLICATION_JSON);
		JSONObject studentObj = new JSONObject();
		studentObj.put("rollNo", 199);
		studentObj.put("name", "New_Student");
		studentObj.put("email", "new.student@gmail.com");
		org.springframework.http.HttpEntity<String> s = new org.springframework.http.HttpEntity<String>(studentObj.toString(),headers);
		String postForObject = restTemplate.postForObject("http://localhost:8082/student/addStudent", s, String.class);
		return postForObject;
	}
	
	
}

Complete Code on GitHub : RestTemplate in Spring Cloud

You may also like:

Spring boot security using JWT ( JSON WEB TOKENS ).

How to deploy spring boot application on docker 

Spring Boot with Apache kafka.

Swagger2 in Spring Boot

Create WAR of Spring Boot Project

Help Others, Please Share

In Last Post ( Eureka Server ) we have seen that how to create a Eureka Server. Now we learn how to register our microservices on Eureka Server, We register our microservice on Eureka because of we need a dashboard where we can check status of our all microservices. So for registering them on eureka we have to follow below steps.

  1. Create a project and add required dependency in your pom.xml file
  2. Enable your main class as a client using @EnableEurekaClient annotation.
  3. Define Eureka Server path in your application.properties file.

Follow above steps:

1- Add Below dependency in pom.xml

<dependency>			 
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>			 
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2- Enable Eureka Client using @EnableEurekaClient

package com.javadream;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableEurekaClient
@SpringBootApplication
public class MicroService1Application {

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

}

3- Define below lines in your application.properties file

spring.application.name=microservice-1
server.port=8081
eureka.client.service-url.default-zone=http://localhost:8761/eureka

Now run this application and check your Eureka Server You will get a instance of MICROSERVICE-1 on port 8081.

NOTE: Make Sure before running your microservice-1 application your eureka server is already running otherwise it will throw exception that no server found.

Complete Code On GitHub : Register MicroService Source Code

Help Others, Please Share

x