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 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
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
Partner Zones AWS Cloud
by AWS Developer Relations
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
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • Why You Should Consider Using React Router V6: An Overview of Changes
  • Top 10 Engineering KPIs Technical Leaders Should Know
  • What Is mTLS? How To Implement It With Istio
  • 13 Impressive Ways To Improve the Developer’s Experience by Using AI

Trending

  • Why You Should Consider Using React Router V6: An Overview of Changes
  • Top 10 Engineering KPIs Technical Leaders Should Know
  • What Is mTLS? How To Implement It With Istio
  • 13 Impressive Ways To Improve the Developer’s Experience by Using AI
  1. DZone
  2. Coding
  3. Frameworks
  4. Understanding Spring Reactive: Servlet 3.1/Spring MVC Non-Blocking IO

Understanding Spring Reactive: Servlet 3.1/Spring MVC Non-Blocking IO

Want to learn more about using Spring Reactive? Check out this post to learn more about using the non-blocking IO in Spring Reactive and Spring MVC.

Naveen Katiyar user avatar by
Naveen Katiyar
·
Updated Oct. 03, 18 · Presentation
Like (11)
Save
Tweet
Share
29.17K Views

Join the DZone community and get the full member experience.

Join For Free

Servlet 3.0 was released as part of Java EE 6 and made huge changes focused at ease-of-use. The idea was to leverage the latest language features, such as annotations and generics, and modernize how Servlets can be written. One of the major changes was Async Servlets. The web.xml was also made as optional as possible. Servlet 3.1, released as part of Java EE 7, was an incremental release, focusing on a couple of key features like non-blocking IO.

Non-blocking I/O with Servlet 3.0 (Async Servlets as discussed in the previous article) allowed asynchronous request processing, but only the traditional I/O was permitted, which is blocking. This can restrict that scalability of your applications. Non-blocking I/O allows you to build scalable applications.

Let’s discuss what I mean by the above. We have learned, in the previous article, that in the case of an async servlet, we must use non-blocking code. So, let’s modify our earlier MyServlet code and replace runnable logic as below:

Let’s revisit the code snippet that we discussed in the previous article:

@WebServlet(name="myServlet", urlPatterns={"/asyncprocess"}, asyncSupported=true)
public class MyServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
OutputStream out = response.getOutputStream();
            AsyncContext aCtx = request.startAsync(request, response); 
            doAsyncREST(request).thenAccept(json -> {
out.write(json);  ---> BLOCKING!
ctx.complete();
          });
}


In the above code, the container request thread is released and work is done in another thread. So, for the Async Servlet to actually work as expected, we have the following requirements:

  •  doAsyncREST() must use the Async library to call REST and return CompletableFuture.This is possible using AsyncHttpClient, which we have already used in the previous article.
  •  thenAccept() should use Async libraries.

But, in Servlet 3.0, IO was traditional for blocking, and hence, the thread calling out.write() will block.

Let’s say that we have to write a large JSON file back to the client. As we are using the NIO connector, OutputStream will first write to buffers and those buffers need to be emptied by clients, using the selector/channel mechanism of NIO. Now, if clients are on a slow network, then out.write() will have to wait until buffers are empty again, as  InputStream/OutputStream is blocking.

The above problem of blocking was removed by the Servlet 3.1 release by introducing Async IO.

Servlet 3.1 Async IO

Let’s discuss this with the help of the code snippet shown below:

 void doGet(request, response) {
        ServletOutputStream out = response.getOutputStream();
        AsyncContext ctx = request.startAsync();
        out.setWriteListener(new WriteListener() {
            void onWritePossible() {
                while (out.isReady()) {
                    byte[] buffer = readFromSomeSource();
                    if (buffer != null)
                        out.write(buffer); ---> Async Write!
                    else{
                        ctx.complete(); break;
                    }
                  }
                }
            });
        }


In the above code, we are making use of the Write/Read Listener, which were introduced in 3.1. WriteListener is an interface that has an onWritePossible() method, which gets called by the Servlet Container. ServletOutputStreamt.isReady()is used to check if it is possible to write in NIO channel buffers. In case it returns false, then it schedules a call on the Servlet container for the  onWritePossible() method, and at some later point, onWritePossible() is called on another thread. So, in this way, out.write() never blocks for the slow client to empty the channel buffers.

Non-Blocking IO in Spring?

To use this feature of non-blocking IO in the Spring application, we would need Spring 5, which has Java EE 7 as its baseline version. So, our earlier example, which is also mentioned below, will execute in full non-blocking mode if we run this code on Spring 5 MVC, Tomcat 8.5+:

@GetMapping(value = "/asyncNonBlockingRequestProcessing")
    public CompletableFuture<String> asyncNonBlockingRequestProcessing(){
            ListenableFuture<String> listenableFuture = getRequest.execute(new AsyncCompletionHandler<String>() {
                @Override
                public String onCompleted(Response response) throws Exception {
                    logger.debug("Async Non Blocking Request processing completed");
                    return "Async Non blocking...";
                 }
            });
            return listenableFuture.toCompletableFuture();
    }


By now, we have discussed how Servlet has evolved, along with Spring, to provide complete non-blocking support. This means that we can scale our application with a smaller number of threads. In our next article, we will be discussing the Spring Reactive stack (i.e. Spring Webflux). One might think that, if Spring MVC is capable of handling request in a non-blocking way, then why use Spring Webflux because it was released as a separate stack?

Stay tuned! We will answer this question in our next article.

Spring Framework

Published at DZone with permission of Naveen Katiyar, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Why You Should Consider Using React Router V6: An Overview of Changes
  • Top 10 Engineering KPIs Technical Leaders Should Know
  • What Is mTLS? How To Implement It With Istio
  • 13 Impressive Ways To Improve the Developer’s Experience by Using AI

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

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: