Providers, Filters & Interceptors
Quarkus 3.9+ Providers, Filters & Interceptors
Section titled “Quarkus 3.9+ Providers, Filters & Interceptors”The easiest way to understand these concepts is to think about an airport.
- Resource (
@Path) → The airplane that takes passengers to their destination. - Request Filter → Security check before boarding.
- Reader Interceptor → Staff inspecting your luggage before loading it.
- Resource Method → The flight itself.
- Writer Interceptor → Staff preparing luggage before unloading.
- Response Filter → Immigration/customs before you leave the airport.
- Providers → Airport services that help everything work.
Complete Request Flow
Section titled “Complete Request Flow”flowchart TD A[HTTP Request] A --> B[ContainerRequestFilter] B --> C[ParamConverterProvider] C --> D[MessageBodyReader] D --> E[ReaderInterceptor] E --> F["@GET / @POST Resource Method"] F --> G[WriterInterceptor] G --> H[MessageBodyWriter] H --> I[ContainerResponseFilter] I --> J[HTTP Response]
What is a Provider?
Section titled “What is a Provider?”A Provider is any class that extends or customizes the REST framework.
Think of it like installing a plugin in VS Code.
Instead of changing Quarkus itself, you provide additional behavior.
Examples:
| Provider | Purpose |
|---|---|
| ExceptionMapper | Handle exceptions |
| Request Filter | Inspect requests |
| Response Filter | Inspect responses |
| ReaderInterceptor | Read request body |
| WriterInterceptor | Write response body |
| MessageBodyReader | JSON → Java |
| MessageBodyWriter | Java → JSON |
| ParamConverterProvider | Convert URL parameters |
| ContextResolver | Configure Jackson |
| DynamicFeature | Register providers conditionally |
Most providers are annotated with
@Provider1. ContainerRequestFilter
Section titled “1. ContainerRequestFilter”What is it?
Section titled “What is it?”Runs before the REST endpoint executes.
Think of it as airport security.
Person arrives
↓
Security checks passport
↓
Allowed to boardRequest Flow
Section titled “Request Flow”flowchart LR A[HTTP Request] -->B[Request Filter] -->C[REST Endpoint]
Example
Section titled “Example”@Providerpublic class LoggingFilter implements ContainerRequestFilter {
@Override public void filter(ContainerRequestContext ctx) {
System.out.println( ctx.getMethod() + " " + ctx.getUriInfo().getPath()); }}Calling
GET /usersConsole
GET usersWhen should I use it?
Section titled “When should I use it?”✅ Authentication
Is user logged in?✅ Authorization
Can user access this API?✅ Logging
Who called this API?✅ Rate limiting
Has this client exceeded requests?✅ Correlation IDs
Generate request ID2. ContainerResponseFilter
Section titled “2. ContainerResponseFilter”Runs after the endpoint finishes but before the response is sent.
flowchart LR A[REST Endpoint] -->B[Response Filter] -->C[HTTP Response]
Example
Section titled “Example”@Providerpublic class HeaderFilterimplements ContainerResponseFilter {
@Override public void filter( ContainerRequestContext req, ContainerResponseContext res) {
res.getHeaders() .add("X-App", "Quarkus"); }}Client receives
HTTP 200
X-App: QuarkusWhen should I use it?
Section titled “When should I use it?”✅ Add security headers
X-Frame-Options
Strict-Transport-Security✅ Add CORS headers
Access-Control-Allow-Origin✅ Add custom headers
X-Request-ID✅ Log response status
200
404
5003. ReaderInterceptor
Section titled “3. ReaderInterceptor”Runs while reading the request body.
Imagine someone opens every package before it enters a warehouse.
flowchart LR A[JSON Request] -->B[ReaderInterceptor] -->C[Java Object]
Example
Section titled “Example”@Providerpublic class RequestLoggerimplements ReaderInterceptor {
@Override public Object aroundReadFrom( ReaderInterceptorContext ctx) throws IOException {
System.out.println("Reading request");
return ctx.proceed(); }}When should I use it?
Section titled “When should I use it?”✅ Decrypt request body
Encrypted JSON
↓
Decrypt
↓
Java Object✅ Scan uploads
Virus Scan✅ Validate payload
Reject invalid data✅ Log request body
4. WriterInterceptor
Section titled “4. WriterInterceptor”Runs while writing the response body.
Think of it as wrapping a gift before shipping.
flowchart LR A[Java Object] -->B[WriterInterceptor] -->C[JSON Response]
Example
Section titled “Example”@Providerpublic class ResponseLoggerimplements WriterInterceptor {
@Override public void aroundWriteTo( WriterInterceptorContext ctx) throws IOException {
System.out.println("Sending response");
ctx.proceed(); }}When should I use it?
Section titled “When should I use it?”✅ Encrypt response
Java Object
↓
Encrypt
↓
Client✅ Compress response
gzip✅ Digital signature
Sign response✅ Log response body
5. MessageBodyReader
Section titled “5. MessageBodyReader”Converts incoming data into Java objects.
JSON
↓
User classflowchart LR A[JSON] -->B[MessageBodyReader] -->C[User Object]
Example
Section titled “Example”Incoming JSON
{ "name":"Ali"}Automatically becomes
User user@POSTpublic void save(User user) {
}Normally Jackson handles this automatically.
When should I use it?
Section titled “When should I use it?”Almost never.
Create one only when supporting
- CSV
- XML
- Binary
- Protobuf
- Custom formats
6. MessageBodyWriter
Section titled “6. MessageBodyWriter”Opposite of MessageBodyReader.
Converts Java into JSON.
flowchart LR A[Java Object] -->B[MessageBodyWriter] -->C[JSON]
Example
Section titled “Example”return new User("Ali");Produces
{ "name":"Ali"}When should I use it?
Section titled “When should I use it?”Only when returning
- CSV
- XML
- Binary
- Custom formats
7. ExceptionMapper
Section titled “7. ExceptionMapper”Handles exceptions globally.
flowchart LR A[Exception] -->B[ExceptionMapper] -->C[HTTP Response]
Example
Section titled “Example”@Providerpublic class GlobalExceptionMapperimplements ExceptionMapper<Exception>{
@Override public Response toResponse(Exception ex){
return Response.status(500) .entity("Something went wrong") .build(); }}When should I use it?
Section titled “When should I use it?”Always.
Instead of
500 Internal Server ErrorReturn
{ "message":"User not found", "code":"USR-001"}This gives every API a consistent error format.
8. ParamConverterProvider
Section titled “8. ParamConverterProvider”Converts URL parameters into Java objects.
flowchart LR A["/users/HIGH"] -->B[ParamConverter] -->C[Priority.HIGH]
Example
Section titled “Example”/priority/HIGHAutomatically becomes
Priority.HIGHWhen should I use it?
Section titled “When should I use it?”Useful for custom types.
Examples
Money
Currency
UUID
OrderId
CustomerId
Email9. ContextResolver
Section titled “9. ContextResolver”Provides configuration to another provider.
Usually used with Jackson.
flowchart LR A[Jackson] -->B[ContextResolver] -->C[Custom ObjectMapper]
Example
Section titled “Example”@Providerpublic class ObjectMapperResolverimplements ContextResolver<ObjectMapper>{
@Override public ObjectMapper getContext(Class<?> type){
ObjectMapper mapper=new ObjectMapper(); mapper.findAndRegisterModules();
return mapper; }}When should I use it?
Section titled “When should I use it?”Customize JSON serialization.
Examples
Pretty JSON
Date formats
Ignore nulls
Custom serializers10. DynamicFeature
Section titled “10. DynamicFeature”Registers filters only where needed.
flowchart TD
A[Incoming Request]
A --> B{Admin API?}
B -->|Yes| C[Register Auth Filter]
B -->|No| D[Skip Filter]
When should I use it?
Section titled “When should I use it?”Instead of applying authentication to every endpoint,
Only apply it to
/admin
/privateNot
/health
/login
/publicFilter vs Interceptor
Section titled “Filter vs Interceptor”flowchart LR A[HTTP Request] A --> B[Request Filter] B --> C[Reader Interceptor] C --> D[REST Method] D --> E[Writer Interceptor] E --> F[Response Filter] F --> G[HTTP Response]
| Component | Works On | Main Purpose | Typical Uses |
|---|---|---|---|
| Request Filter | HTTP Request | Headers & request metadata | Authentication, logging, authorization, rate limiting |
| Reader Interceptor | Request Body | Request payload | Decryption, validation, body logging |
| Resource Method | Business Logic | Process the request | CRUD operations, service calls |
| Writer Interceptor | Response Body | Response payload | Encryption, compression, signing |
| Response Filter | HTTP Response | Headers & metadata | CORS, security headers, response logging |
Which One Should I Use?
Section titled “Which One Should I Use?”flowchart TD
A[Need to customize request/response?]
A --> B{What do you need?}
B -->|Authentication| C[ContainerRequestFilter]
B -->|Logging Headers| C
B -->|Modify Request Body| D[ReaderInterceptor]
B -->|Modify Response Body| E[WriterInterceptor]
B -->|Add Response Headers| F[ContainerResponseFilter]
B -->|Handle Exceptions| G[ExceptionMapper]
B -->|Custom JSON Format| H[ContextResolver]
B -->|Custom Request Format| I[MessageBodyReader]
B -->|Custom Response Format| J[MessageBodyWriter]
B -->|Convert URL Parameters| K[ParamConverterProvider]
B -->|Apply Only to Specific APIs| L[DynamicFeature]
Real-world usage frequency
Section titled “Real-world usage frequency”| Component | How Often? | Typical Real-world Scenario |
|---|---|---|
⭐⭐⭐⭐⭐ ExceptionMapper | Every project | Consistent API error responses |
⭐⭐⭐⭐⭐ ContainerRequestFilter | Every project | JWT authentication, authorization, request logging |
⭐⭐⭐⭐ ContainerResponseFilter | Very common | CORS, security headers, request IDs |
⭐⭐⭐ ReaderInterceptor | Sometimes | Decrypting or validating request bodies |
⭐⭐⭐ WriterInterceptor | Sometimes | Encrypting or compressing responses |
⭐⭐ ContextResolver | Occasionally | Global Jackson configuration |
⭐⭐ ParamConverterProvider | Occasionally | Domain-specific URL parameter conversion |
⭐ MessageBodyReader | Rare | Supporting CSV, XML, Protobuf, or other custom input formats |
⭐ MessageBodyWriter | Rare | Producing CSV, XML, PDF, or other custom output formats |
⭐ DynamicFeature | Rare | Conditionally applying filters or interceptors |
The One Diagram to Remember
Section titled “The One Diagram to Remember”flowchart TD A[HTTP Request] A --> B[ContainerRequestFilter] B --> C[ParamConverterProvider] C --> D[MessageBodyReader] D --> E[ReaderInterceptor] E --> F[Resource Method] F --> G[WriterInterceptor] G --> H[MessageBodyWriter] H --> I[ContainerResponseFilter] I --> J[HTTP Response] F -. Exception .-> K[ExceptionMapper] K --> I
Beginner learning order
Section titled “Beginner learning order”Don’t try to learn everything at once. A practical progression is:
ContainerRequestFilter– understand authentication, authorization, and request logging.ContainerResponseFilter– learn how to add headers and handle CORS.ExceptionMapper– create consistent error responses for your APIs.ReaderInterceptorandWriterInterceptor– understand request and response body processing.MessageBodyReaderandMessageBodyWriter– learn how Quarkus converts between Java objects and HTTP payloads.ParamConverterProvider,ContextResolver, andDynamicFeature– advanced customization you’ll encounter less frequently but should recognize when reading production code.
If you’re becoming a professional Quarkus developer, these are the provider-related concepts you’ll encounter most often in enterprise applications.