[go: up one dir, main page]

DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux
  • Graceful Shutdown: Spring Framework vs Golang Web Services
  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4

Trending

  • Simplify Authorization in Ruby on Rails With the Power of Pundit Gem
  • Scalability 101: How to Build, Measure, and Improve It
  • Setting Up Data Pipelines With Snowflake Dynamic Tables
  • Start Coding With Google Cloud Workstations
  1. DZone
  2. Coding
  3. Frameworks
  4. Spring 5 WebFlux and JDBC: To Block or Not to Block

Spring 5 WebFlux and JDBC: To Block or Not to Block

With Spring 5's awaited promise of more reactive support, let's examine both how we can make JDBC more asynchronous and the problems that brings.

By 
Grygoriy Gonchar user avatar
Grygoriy Gonchar
·
Updated Jun. 02, 17 · Tutorial
Likes (27)
Comment
Save
Tweet
Share
97.0K Views

Join the DZone community and get the full member experience.

Join For Free

The 5th version of the Spring Framework brings a huge step forward in Functional and Reactive Programming support. You don’t need ApplicationContext or dozens of annotations to have the simplest REST API up and running. Spring 5 will offer lightweight Web Functions and reactive Web Flux support that can help this transition happen. Those new features make Java and Spring 5 good candidates for building reactive web applications

To be reactive, according to The Reactive Manifesto, you have to be Responsive, Resilient, Elastic, and Message Driven. The last criteria in this list caused big movement into the asynchronous way of communications. This includes asynchronous RPC and messaging libraries, database drivers, and more. RDBMSs are quite powerful and useful. The official instruments for database access on JVM provided by database vendors are drivers implementing JDBC API. But JDBC is designed to be blocking and consumes threads per database call. You will not find in the API itself methods or interfaces allowing you to get query results in another thread. There is also an opinion that a transactional database is not a fit for the reactive concept:

The concept of a transaction doesn’t naturally fit the reactive world, as it’s about blocking a resource, which is exactly what you want to avoid here

I would partially agree. However, it depends on how exactly you will be using your relational database. Moreover, in the new era of highly scalable SQL databases (such as Amazon’s Aurora or Google’s Cloud Spanner) reactivity is a fit to achieve high throughput by using them together. The question is what shall we do when we are building applications on top of a SQL database with reactivity in mind. One option would be to use alternative SQL clients that are fully non-blocking. Some examples include here and here.

Of course, none of these drivers is officially supported by database vendors yet. Also, functionality is way much less attractive when compared to mature JDBC-based abstractions such as Hibernate or jOOQ.

An alternative idea came to me from the Scala world. We can dispatch blocking calls into an isolated Thread Pool to avoid mixing blocking and non-blocking calls together. This will allow us to control the overall number of threads and will let the CPU serve non-blocking tasks in the main execution context, applying various optimisations.

Assuming that we have a JDBC-based implementation, such as Spring Data JPA, which is indeed blocking.

import org.springframework.data.repository.CrudRepository;

public interface AddressRepository extends CrudRepository<Address, Long> {}


We can make its execution asynchronous and dispatch it to a dedicated thread pool.

@Service
public class AddressService {

    private final AddressRepository repository;

    private final Scheduler scheduler;

    public AddressRouter(AddressRepository repository, @Qualifier("jdbcScheduler") Scheduler scheduler) {
        this.repository = repository;
        this.scheduler = scheduler;
    }

    public Mono<Iterable<Address>> findAll() {
        return async(() -> repository.findAll());
    }

    private <T> Mono<T> async(Callable<T> callable) {
        return Mono.fromCallable(callable).publishOn(scheduler);
    }
}


Our Scheduler for JDBC should be configured by using a dedicated Thread Pool with a size count equal to the number of connections.

@Configuration
public class SchedulerConfiguration {
    private final Integer connectionPoolSize;

    public SchedulerConfiguration(@Value("${spring.datasource.maximum-pool-size}") Integer connectionPoolSize) {
        this.connectionPoolSize = connectionPoolSize;
    }

    @Bean
    public Scheduler jdbcScheduler() {
        return Schedulers.fromExecutor(Executors.newFixedThreadPool(connectionPoolSize));
    }

}


However, there are difficulties with this approach. The main one is transaction management. In JDBC, transactions are possible only within a single java.sql.Connection. To make several operations in one transaction, they have to share a connection. If we want to make some calculations in between them, we have to keep the connection. This is not very effective, as we keep a limited number of connections idle while doing calculations in between.

This idea of an asynchronous JDBC wrapper is not new and is already implemented in the Scala library Slick 3. Finally, non-blocking JDBC may come along on the Java roadmap. As it was announced at JavaOne in September 2016, and it is possible that we will see it in Java 10.

Spring Framework

Published at DZone with permission of Grygoriy Gonchar, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux
  • Graceful Shutdown: Spring Framework vs Golang Web Services
  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: