1. Overview
Spring Boot is an opinionated β yet powerful β layer of abstraction placed on top of a plain Spring platform, which makes developing stand-alone and web applications a no-brainer. Spring Boot provides a few handy βstarterβ dependencies, aimed at running and testing Java applications with a minimal footprint.
One key component of these starter dependencies is spring-boot-starter-data-jpa. This allows us to use JPA and work with production databases by using some popular JDBC connection pooling implementations, such as HikariCP and Tomcat JDBC Connection Pool.
In this tutorial, weβll learn how to configure a Tomcat connection pool in Spring Boot.
2. The Maven Dependencies
Spring Boot uses HikariCP as the default connection pool, due to its remarkable performance and enterprise-ready features.
Hereβs how Spring Boot automatically configures a connection pool datasource:
- Spring Boot will look for HikariCP on the classpath and use it by default when present
- If HikariCP is not found on the classpath, then Spring Boot will pick up the Tomcat JDBC Connection Pool, if itβs available
- If neither of these options is available, Spring Boot will choose Apache Commons DBCP2, if that is available
To configure a Tomcat JDBC connection pool instead of the default HikariCP, weβll exclude HikariCP from the spring-boot-starter-data-jpa dependency and add the tomcat-jdbc Maven dependency to our pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>10.1.7</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
<scope>runtime</scope>
</dependency>
This simple approach allows us to get Spring Boot using a Tomcat connection pool without having to write a @Configuration class and programmatically define a DataSource bean.
Itβs also worth noting that in this case, weβre using the H2 in-memory database. Spring Boot will autoconfigure H2 for us, without having to specify a database URL, user, and password.
We just need to include the corresponding dependency in the βpom.xmlβ file and Spring Boot will do the rest for us.
Alternatively, itβs possible to skip the connection pool scanning algorithm that Spring Boot uses and explicitly specify a connection pooling datasource in the βapplication.propertiesβ file, using the βspring.datasource.typeβ property:
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
// other spring datasource properties
3. Tweaking the Connection Pool With the βapplication.propertiesβ File
Once weβve successfully configured a Tomcat connection pool in Spring Boot, itβs very likely that weβll want to set up some additional properties, for optimizing its performance and suiting some specific requirements.
We can do so in the βapplication.propertiesβ file:
spring.datasource.tomcat.initial-size=15
spring.datasource.tomcat.max-wait=20000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.max-idle=15
spring.datasource.tomcat.min-idle=8
spring.datasource.tomcat.default-auto-commit=true
Please notice that weβve configured a few additional connection pooling properties, such as the poolβs initial size, and the maximum and minimum number of idle connections.
We can also specify some Hibernate-specific properties:
# Hibernate specific properties
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.id.new_generator_mappings=false
4. Testing the Connection Pool
Letβs write a simple integration test to check that Spring Boot has correctly configured the connection pool:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootTomcatConnectionPoolIntegrationTest {
@Autowired
private DataSource dataSource;
@Test
public void givenTomcatConnectionPoolInstance_whenCheckedPoolClassName_thenCorrect() {
assertThat(dataSource.getClass().getName())
.isEqualTo("org.apache.tomcat.jdbc.pool.DataSource");
}
}
5. A Sample Command Line Application
With all the connection pooling plumbing already set, letβs build a simple command line application.
In doing so, we can see how to perform some CRUD operations on an H2 database using the powerful DAO layer that Spring Data JPA (and transitively, Spring Boot) provides out of the box.
For a detailed guide on how to get started using Spring Data JPA, please check this article.
5.1. The Customer Entity Class
Letβs first define a naive Customer entity class:
@Entity
@Table(name = "customers")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "first_name")
private String firstName;
// standard constructors / getters / setters / toString
}
5.2. The CustomerRepository Interface
In this case, we just want to perform CRUD operations on a few Customer entities. Additionally, we need to fetch all the customers that match a given last name.
So, all that we have to do is to extend Spring Data JPAβs CrudRepository interface and define a tailored method:
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
Now we can easily fetch a Customer entity by its last name.
5.3. The CommandLineRunner Implementation
Finally, we need at least to persist a few Customer entities in the database and verify that our Tomcat connection pool is actually working.
Letβs create an implementation of Spring Bootβs CommandLineRunner interface. Spring Boot will bootstrap the implementation before launching the application:
public class CommandLineCrudRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(CommandLineCrudRunner.class);
@Autowired
private final CustomerRepository repository;
public void run(String... args) throws Exception {
repository.save(new Customer("John", "Doe"));
repository.save(new Customer("Jennifer", "Wilson"));
logger.info("Customers found with findAll():");
repository.findAll().forEach(c -> logger.info(c.toString()));
logger.info("Customer found with findById(1L):");
Customer customer = repository.findById(1L)
.orElseGet(() -> new Customer("Non-existing customer", ""));
logger.info(customer.toString());
logger.info("Customer found with findByLastName('Wilson'):");
repository.findByLastName("Wilson").forEach(c -> {
logger.info(c.toString());
});
}
}
In a nutshell, the CommandLineCrudRunner class first saves a couple of Customer entities in the database. Next, it fetches the first one using the findById() method. Finally, it retrieves a customer with the findByLastName() method.
5.4. Running the Spring Boot Application
Of course, the last thing that we need to do is just run the sample application. Then we can see the Spring Boot/Tomcat connection pool tandem in action:
@SpringBootApplication
public class SpringBootConsoleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootConsoleApplication.class);
}
}
6. Conclusion
In this tutorial, we learned how to configure and use a Tomcat connection pool in Spring Boot. In addition, we developed a basic command line application to show how easy is to work with Spring Boot, a Tomcat connection pool, and the H2 database.
