Home  >  Spring Boot

Spring Boot + HikariCP

By Arvind Rai, June 17, 2018
This page will walk through Spring Boot and HikariCP example. HikariCP is fast, simple, reliable and production ready JDBC connection pool. In Spring Boot 2.0 release, default database pooling technology has been switched from Tomcat Pool to HikariCP. This is because HikariCP offers superior performance. Now since Spring Boot 2.0 release, spring-boot-starter-jdbc and spring-boot-starter-data-jpa resolve HikariCP dependency by default and spring.datasource.type property has HikariDataSource as default value. Spring boot prefers HikariCP on first place then Tomcat pooling and then Commons DBCP2 on the basis of availability. Here on this page we will provide complete example of HikariCP with Spring Boot Data and MySQL. We will create a demo application in which we will perform create and read operation in database. We will configure HikariCP properties for example connectionTimeout, minimumIdle, maximumPoolSize, idleTimeout, maxLifetime and autoCommit in application.properties file.

Technologies Used

Find the technologies being used in our example.
1. Java 9
2. Spring 5.0.7.RELEASE
3. Spring Boot 2.0.3.RELEASE
4. Maven 3.5.2
5. MySQL 5.5
6. Eclipse Oxygen

HikariCP Dependency

Before using HikariCP, we need to make sure that we have resolved the HikariCP dependency. If we are using Maven we can use following dependency.
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>3.1.0</version>
</dependency> 
In case we are using Spring Boot 2.0 and onwards, we need not to include HikariCP dependency in pom.xml or build.gradle ourselves because spring-boot-starter-jdbc and spring-boot-starter-data-jpa resolve it by default. It means if we are using dependencies either
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>2.0.3.RELEASE</version>
</dependency> 
Or
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.0.3.RELEASE</version>
</dependency> 
Then we need not to include HikariCP dependency in our pom.xml or build.gradle.

HikariCP Configurations

For the Hikari connection pool configuration, we enable it by using spring.datasource.type and assigning it fully qualified name of the connection pool implementation in application.properties file as following.
spring.datasource.type = com.zaxxer.hikari.HikariDataSource 
If we are using Spring Boot 2.0 and onwards, Spring Boot selects HikariDataSource by default and we need not to configure above line.
Now to configure Hikari specific connection pool settings, Spring Boot provides spring.datasource.hikari.* prefix to be used in application.properties file. We will discuss here some frequently used configurations.
1. connectionTimeout
connectionTimeout is the maximum number of milliseconds that a client will wait for a connection from connection pool. We need to configure it as following.
spring.datasource.hikari.connection-timeout=20000 
2. minimumIdle
minimumIdle is the minimum number of idle connections that is maintained by HikariCP in connection pool. It is configured as following.
spring.datasource.hikari.minimum-idle=5 
3. maximumPoolSize
maximumPoolSize configures the maximum pool size. It is configured as following.
spring.datasource.hikari.maximum-pool-size=12 
4. idleTimeout
idleTimeout is the maximum amount of time in milliseconds that a connection is allowed to sit idle in connection pool. It is configured as following.
spring.datasource.hikari.idle-timeout=300000 
5. maxLifetime
maxLifetime is the maximum life time in milliseconds of a connection in pool after it is closed. It is configured as following.
spring.datasource.hikari.max-lifetime=1200000 
An in-use connection will never be retired, only when it is closed will it then be removed after maximum lifetime.
6. autoCommit
autoCommit configures the default auto-commit behavior of connections returned from pool. Default value is true.
spring.datasource.hikari.auto-commit=true 

Spring Boot Data + HikariCP + MySQL Example

We will create a Spring Boot REST web service with Spring Boot Data, HikariCP and MySQL. We will use CrudRepository to query database. We will also create a REST client using RestTemplate to test our application. First find the project structure of the demo application.
Spring Boot + HikariCP
Find the MySQL table structure used in our example.
MySQL Table: articles
CREATE TABLE `articles` (
	`article_id` INT(5) NOT NULL AUTO_INCREMENT,
	`title` VARCHAR(200) NOT NULL,
	`category` VARCHAR(100) NOT NULL,
	PRIMARY KEY (`article_id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB; 
Find the Maven file to resolve dependencies.
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-app</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<name>spring-boot-app</name>
	<description>Spring Boot Application</description>
	<parent>
	    <groupId>org.springframework.boot</groupId>
  	    <artifactId>spring-boot-starter-parent</artifactId>
	    <version>2.0.3.RELEASE</version>
 	    <relativePath/>
	</parent>
	<properties>
	    <java.version>9</java.version>
	</properties>
	<dependencies>
	  <dependency>
		 <groupId>org.springframework.boot</groupId>
		 <artifactId>spring-boot-starter-web</artifactId>
	  </dependency>
	  <dependency>
		 <groupId>org.springframework.boot</groupId>
		 <artifactId>spring-boot-starter-data-jpa</artifactId>
	  </dependency>
	  <dependency>
		 <groupId>mysql</groupId>
		 <artifactId>mysql-connector-java</artifactId>
		 <version>6.0.5</version>
	  </dependency>	  
	  <!-- Spring Boot Data 2.0 includes HikariCP by default -->
          <!-- dependency>
                 <groupId>com.zaxxer</groupId>
                 <artifactId>HikariCP</artifactId>
                 <version>3.1.0</version>
          </dependency -->	  	  	  
	  <dependency>
		 <groupId>javax.xml.bind</groupId>
		 <artifactId>jaxb-api</artifactId>
		 <version>2.3.0</version>
	  </dependency>  	
          <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-devtools</artifactId>
                 <optional>true</optional>
          </dependency> 
	</dependencies>
	<build>
	  <plugins>
		 <plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		 </plugin>
	  </plugins>
	</build>
</project> 
If we are using Spring Boot version below Spring Boot 2.0 then we need to include HikariCP dependency as following.
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>3.1.0</version>
</dependency> 
HikariCP 3.1.0 is suitable for Java 8 and Java 9.
Now find the property file to configure datasource and other properties. Connection pool will be configured using HikariCP.
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/concretepage
spring.datasource.username=root
spring.datasource.password=cp

#Spring Boot 2.0 includes HikariDataSource by default
#spring.datasource.type = com.zaxxer.hikari.HikariDataSource

spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=12
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=1200000
spring.datasource.hikari.auto-commit=true

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 
If we are using Spring Boot version below Spring Boot 2.0 then we need to include spring.datasource.type property for HikariCP as following.
spring.datasource.type = com.zaxxer.hikari.HikariDataSource 
Now find the other files used in the demo application.
ArticleRepository.java
package com.concretepage.repository;
import org.springframework.data.repository.CrudRepository;
import com.concretepage.entity.Article;

public interface ArticleRepository extends CrudRepository<Article, Long>  {
} 
Article.java
package com.concretepage.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="articles")
public class Article implements Serializable { 
	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="article_id")
        private long articleId;  
	@Column(name="title")
        private String title;
	@Column(name="category")	
	private String category;
	public long getArticleId() {
		return articleId;
	}
	public void setArticleId(long articleId) {
		this.articleId = articleId;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getCategory() {
		return category;
	}
	public void setCategory(String category) {
		this.category = category;
	}
} 
IArticleService.java
package com.concretepage.service;
import java.util.List;
import com.concretepage.entity.Article;

public interface IArticleService {
     List<Article> getAllArticles();
     void addArticle(Article article);
} 
ArticleService.java
package com.concretepage.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.concretepage.entity.Article;
import com.concretepage.repository.ArticleRepository;

@Service
public class ArticleService implements IArticleService {
	@Autowired
	private ArticleRepository articleRepository;

	@Override
	public List<Article> getAllArticles(){
		List<Article> list = new ArrayList<>();
		articleRepository.findAll().forEach(e -> list.add(e));
		return list;
	}
	@Override
	public void addArticle(Article article){
    	articleRepository.save(article);
	}
} 
ArticleInfo.java
package com.concretepage.controller;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

public class ArticleInfo {
	@JsonInclude(Include.NON_NULL)
        private long articleId;
	@JsonInclude(Include.NON_NULL)
        private String title;
	@JsonInclude(Include.NON_NULL)
        private String category;
	public long getArticleId() {
		return articleId;
	}
	public void setArticleId(long articleId) {
		this.articleId = articleId;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getCategory() {
		return category;
	}
	public void setCategory(String category) {
		this.category = category;
	} 
} 
ArticleController.java
package com.concretepage.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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 org.springframework.web.util.UriComponentsBuilder;
import com.concretepage.entity.Article;
import com.concretepage.service.IArticleService;

@RestController
@RequestMapping("user")
public class ArticleController {
	@Autowired
	private IArticleService articleService;

	//Fetches all articles 
	@GetMapping(value= "articles")
	public ResponseEntity<List<ArticleInfo>> getAllArticles() {
		List<ArticleInfo> responseArticleList = new ArrayList<>();
		List<Article> articleList = articleService.getAllArticles();
		for (int i = 0; i < articleList.size(); i++) {
		    ArticleInfo ob = new ArticleInfo();
		    BeanUtils.copyProperties(articleList.get(i), ob);
		    responseArticleList.add(ob);    
		}
		return new ResponseEntity<List<ArticleInfo>>(responseArticleList, HttpStatus.OK);
	}
	
	//Creates a new article
	@PostMapping(value= "article")
	public ResponseEntity<Void> addArticle(@RequestBody ArticleInfo articleInfo, UriComponentsBuilder builder) {
		Article article = new Article();
		BeanUtils.copyProperties(articleInfo, article);
                articleService.addArticle(article);
                HttpHeaders headers = new HttpHeaders();
                headers.setLocation(builder.path("/article/{id}").buildAndExpand(article.getArticleId()).toUri());
                return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
	}
} 
Now find the Main Java class to run the application. To ensure that we are using HikariCP, we are printing datasource name.
SpringBootAppStarter.java
package com.concretepage;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootAppStarter implements CommandLineRunner {
    @Autowired
    DataSource dataSource;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootAppStarter.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        System.out.println("DataSource = " + dataSource);
    }
} 
When we start our application, we can see following message in console at the end of server log.
Output
DataSource = HikariDataSource (HikariPool-1) 
Now find the REST client to test the application.
RestClientUtil.java
package com.concretepage.client;
import java.net.URI;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import com.concretepage.entity.Article;

public class RestClientUtil {
    public void getAllArticlesDemo() {
	HttpHeaders headers = new HttpHeaders();
	headers.setContentType(MediaType.APPLICATION_JSON);
        RestTemplate restTemplate = new RestTemplate();
	String url = "http://localhost:8080/user/articles";
        HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
        ResponseEntity<Article[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article[].class);
        Article[] articles = responseEntity.getBody();
        for(Article article : articles) {
              System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle()
                      +", Category: "+article.getCategory());
        }
    }
    public void addArticleDemo() {
    	HttpHeaders headers = new HttpHeaders();
    	headers.setContentType(MediaType.APPLICATION_JSON);
        RestTemplate restTemplate = new RestTemplate();
	String url = "http://localhost:8080/user/article";
	Article objArticle = new Article();
	objArticle.setTitle("Spring REST Security using Hibernate");
	objArticle.setCategory("Spring");
        HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers);
        URI uri = restTemplate.postForLocation(url, requestEntity);
        System.out.println(uri.getPath());    	
    }
    public static void main(String args[]) {
    	RestClientUtil util = new RestClientUtil();
    	util.addArticleDemo();
    	util.getAllArticlesDemo();    	
    }    
} 
When we run the client we will get following output.
Output
Id:1, Title:Spring REST Security using Hibernate, Category: Spring 

Test Application

To test the application, first create table in MySQL as given in the article and configure your database credentials in application.properties file. Then we can run REST web service in following ways.
1. Using Maven Command: Download the project source code. Go to the root folder of the project using command prompt and run the command.
mvn spring-boot:run 
Tomcat server will be started.

2. Using Eclipse: Download the project source code using the download link given at the end of article. Import the project into eclipse. Using command prompt, go to the root folder of the project and run.
mvn clean eclipse:eclipse 
and then refresh the project in eclipse. Run Main class SpringBootAppStarter by clicking Run as -> Java Application. Tomcat server will be started.

3. Using Executable JAR: Using command prompt, go to the root folder of the project and run the command.
mvn clean package 
We will get executable JAR spring-boot-app-0.0.1-SNAPSHOT.jar in target folder. Run this JAR as
java -jar target/spring-boot-app-0.0.1-SNAPSHOT.jar 
Tomcat server will be started.

Now we are ready to test the application. To run web service client, go to the RestClientUtil class in eclipse and click on Run as -> Java Application.

References

1. Spring Boot Reference Guide
2. HikariCP
3. Spring Boot 2.0 Release Notes

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS


©2019 concretepage.com | Privacy Policy | Contact Us