> For the complete documentation index, see [llms.txt](https://amartyushov.gitbook.io/tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://amartyushov.gitbook.io/tech/frameworks/spring/servlet-containers-clients.md).

# Servlet containers, clients

## Servlet containers

<table data-full-width="true"><thead><tr><th width="295">Servlet Container</th><th width="138">Blocking HTTP Requests</th><th>Non-Blocking HTTP Requests</th><th width="122">WebSockets Support</th><th>Works Well with Kotlin Coroutines</th></tr></thead><tbody><tr><td><strong>Jetty</strong></td><td>✅ Yes</td><td>✅ Yes (via async I/O)</td><td>✅ Yes</td><td>✅ Yes (with Coroutine-based APIs)</td></tr><tr><td><strong>Tomcat</strong></td><td>✅ Yes</td><td>✅ Yes (via async servlets)</td><td>✅ Yes</td><td>⚠️ Limited (needs adapters like <code>ktor-server-tomcat</code>)</td></tr><tr><td><strong>Undertow</strong></td><td>✅ Yes</td><td>✅ Yes (reactive streams)</td><td>✅ Yes</td><td>✅ Yes (used in <code>ktor-server-undertow</code>)</td></tr><tr><td><strong>Netty (is not a servlet container</strong>—it's an <strong>event-driven network application framework</strong> that can be used to build non-blocking servers and clients<strong>)</strong></td><td>⚠️ Not its primary model</td><td>✅ Yes (fully event-driven)</td><td>✅ Yes</td><td>✅ Yes (integrates well with Ktor and coroutines)</td></tr></tbody></table>

####

## Clients

<table data-full-width="true"><thead><tr><th width="171">HTTP Client</th><th width="148">Blocking Requests</th><th width="141">Non-Blocking Requests</th><th width="170">Coroutine Friendly</th><th>Additional Notes</th></tr></thead><tbody><tr><td><strong>RestTemplate</strong></td><td>✅ Yes</td><td>❌ No</td><td>⚠️ Limited</td><td>Synchronous API, designed for Spring MVC.</td></tr><tr><td><strong>WebClient (</strong>Reactor Netty (default in Spring Boot)<strong>)</strong></td><td>⚠️ Limited</td><td>✅ Yes</td><td>✅ Yes</td><td>Non-blocking, reactive web client from Spring WebFlux.</td></tr><tr><td><strong>Ktor</strong></td><td>✅ Yes</td><td>✅ Yes</td><td>✅ Yes</td><td>Designed for Kotlin; supports both blocking and non-blocking calls.</td></tr><tr><td><strong>OkHttp</strong></td><td>✅ Yes</td><td>✅ Yes</td><td>⚠️ Limited</td><td>Primarily synchronous but supports asynchronous requests; good for Kotlin coroutines.</td></tr><tr><td><strong>Apache HttpClient</strong></td><td>✅ Yes</td><td>⚠️ Limited</td><td>⚠️ Limited</td><td>Synchronous by default; can use <code>Future</code> for async.</td></tr><tr><td><strong>Retrofit</strong></td><td>✅ Yes</td><td>✅ Yes</td><td>✅ Yes</td><td>Works with OkHttp, designed for REST APIs; supports coroutines via extensions.</td></tr><tr><td><strong>Vert.x Web Client</strong></td><td>❌ No</td><td>✅ Yes</td><td>✅ Yes</td><td>Fully non-blocking and designed for asynchronous programming.</td></tr></tbody></table>

Spring’s `WebClient` is a **non-blocking** HTTP client, but it can use different underlying **engines** for handling HTTP requests.

#### **What determines WebClient's underlying engine?**

It depends on **which Spring Boot starter you include**:

1. **If using `spring-boot-starter-webflux` (Reactive)**
   * WebClient **defaults to Netty** (via `Reactor Netty`).
   * **Netty handles HTTP connections asynchronously**.
2. **If using `spring-boot-starter-web` (Blocking, Tomcat)**
   * WebClient **uses Apache HttpClient or Java’s `HttpURLConnection`**.
   * It can still be non-blocking at the application level, but the underlying client might not be fully asynchronous.
     * **If you’re making a few HTTP requests per second** → You can use a blocking client inside coroutines with `Dispatchers.IO`


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://amartyushov.gitbook.io/tech/frameworks/spring/servlet-containers-clients.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
