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
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Embracing Reactive Programming With Spring WebFlux
  • Spring Boot Annotations: Behind the Scenes and the Self-Invocation Problem
  • Comparing ModelMapper and MapStruct in Java: The Power of Automatic Mappers
  • A Guide to Enhanced Debugging and Record-Keeping

Trending

  • Monkey-Patching in Java
  • Essential Complexity Is the Developer's Unique Selling Point
  • Top 7 Best Practices DevSecOps Team Must Implement in the CI/CD Process
  • Hugging Face Is the New GitHub for LLMs
  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.

Grygoriy Gonchar user avatar by
Grygoriy Gonchar
·
Updated Jun. 02, 17 · Tutorial
Like (27)
Save
Tweet
Share
95.41K 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

  • Embracing Reactive Programming With Spring WebFlux
  • Spring Boot Annotations: Behind the Scenes and the Self-Invocation Problem
  • Comparing ModelMapper and MapStruct in Java: The Power of Automatic Mappers
  • A Guide to Enhanced Debugging and Record-Keeping

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • 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: