In the world of high-performance APIs, speed is paramount. Delivering data quickly and efficiently significantly improves user experience and reduces server load. One of the most effective strategies for achieving this is GZIP compression. This post will guide you through enabling GZIP compression (Content Encoding) in your JAX-RS (RESTeasy) applications, ensuring your APIs are leaner and meaner.
GZIP works by compressing the data transferred between your server and the client. When a client requests data, the server can compress the response using GZIP before sending it. The client then decompresses the data, resulting in less data transmission over the network. This is particularly beneficial for large payloads like JSON or XML. Most modern browsers and HTTP clients automatically support GZIP decompression.
How to Enable GZIP Compression in RESTeasy
Enabling GZIP compression in RESTeasy is straightforward and primarily involves configuring your JAX-RS application. There are two main approaches:
1. Using the resteasy.providers Context Parameter (Recommended for Servlet Containers)
This is the most common and recommended way for applications deployed in traditional servlet containers like Tomcat, JBoss/WildFly, or Jetty. You’ll add a context parameter to your web.xml file.
First, ensure you have the necessary RESTeasy GZIP provider JAR in your classpath. If you’re using Maven, add the following dependency:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-gzip</artifactId>
<version>YOUR_RESTEASY_VERSION</version>
</dependency>
Replace YOUR_RESTEASY_VERSION with the version of RESTeasy you are using.
Next, modify your web.xml to include the resteasy.providers context parameter, pointing to the GZIP interceptor:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>RESTEasy GZIP Example</display-name>
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>org.jboss.resteasy.plugins.interceptors.GZIPEncodingInterceptor</param-value>
</context-param >
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.ankurm.rest.YourApplicationClass</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Remember to replace com.ankurm.rest.YourApplicationClass with the actual path to your JAX-RS Application subclass.
2. Registering the GZIP Interceptor Programmatically
If you prefer a programmatic approach, or if you’re not deploying in a traditional web.xml based servlet container (e.g., using an embedded server or JAX-RS in a non-servlet environment), you can register the GZIP interceptor directly in your JAX-RS Application subclass.
First, ensure the resteasy-gzip dependency is in your project.
Then, in your javax.ws.rs.core.Application subclass, override the getClasses() method to include the GZIPEncodingInterceptor:
package com.ankurm.rest;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import org.jboss.resteasy.plugins.interceptors.GZIPEncodingInterceptor;
public class YourApplicationClass extends Application {
private Set<Object> singletons = new HashSet<Object>();
public YourApplicationClass() {
singletons.add(new YourRestResource()); // Your actual REST resource
}
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
// Register GZIP Interceptor
classes.add(GZIPEncodingInterceptor.class);
// Add your resource classes here as needed
classes.add(YourRestResource.class);
return classes;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
Or, if you declare your resources as singletons:
package com.ankurm.rest;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import org.jboss.resteasy.plugins.interceptors.GZIPEncodingInterceptor;
@javax.ws.rs.ApplicationPath("/api") // Or wherever your base path is
public class YourApplicationClass extends Application {
@Override
public Set<Object> getSingletons() {
Set<Object> singletons = new HashSet<Object>();
// Register GZIP Interceptor
singletons.add(new GZIPEncodingInterceptor());
// Your actual REST resource instances
singletons.add(new YourRestResource());
return singletons;
}
}
The programmatic approach gives you more control and is often preferred in modern, configuration-as-code environments.
Testing GZIP Compression
To verify that GZIP compression is working, you can use tools like curl or your browser’s developer tools.
Using cURL:
When making a request with curl, ensure you include the Accept-Encoding: gzip header. The -I flag shows only headers, and –compressed tells curl to decompress if the server sends gzipped content (so you see the original size).
curl -I -H "Accept-Encoding: gzip" http://localhost:8080/yourapp/api/yourresource
Look for the Content-Encoding: gzip header in the response. If it’s present, GZIP is active.
To see the size difference:
# Without GZIP (if server supports it, it might still send uncompressed if no accept-encoding)
curl -s -o /dev/null -w "%{size_download}
" http://localhost:8080/yourapp/api/yourresource
# With GZIP
curl -s -H "Accept-Encoding: gzip" -o /dev/null -w "%{size_download}
" http://localhost:8080/yourapp/api/yourresource
You should see a significantly smaller size_download for the gzipped request.
Using Browser Developer Tools:
- Open your browser’s developer tools (usually by pressing F12).
- Navigate to the “Network” tab.
- Make a request to your API endpoint.
- Select the network request in the list.
- In the “Headers” or “Response Headers” section, look for Content-Encoding: gzip.
- You can also often see the original size vs. compressed size in the network tab summary for the request.
Important Considerations
- CPU Overhead: While GZIP saves network bandwidth, it introduces a small amount of CPU overhead on both the server (for compression) and the client (for decompression). For very small payloads, this overhead might negate the benefits. RESTeasy’s GZIP interceptor is generally smart enough not to compress very small responses.
- Already Compressed Content: Avoid GZIP compressing content that is already compressed (e.g., images like JPG/PNG, videos, or pre-compressed static files). This won’t yield significant size reductions and will only add unnecessary CPU cycles. The RESTeasy GZIP interceptor usually handles this by only compressing applicable media types.
- Client Support: Ensure your clients (browsers, mobile apps, other services) correctly send the Accept-Encoding: gzip header to indicate their capability to handle gzipped responses. Most modern clients do this by default.
- Proxy/Load Balancer: If you have proxies or load balancers in front of your application, ensure they are configured to pass through the Accept-Encoding header and do not strip Content-Encoding from the response. Some load balancers can also perform GZIP compression themselves, in which case you might disable it in RESTeasy to avoid double compression.
Conclusion
Enabling GZIP compression in your RESTeasy applications is a simple yet powerful optimization that can dramatically improve the performance of your APIs. By reducing the amount of data transferred over the network, you’ll deliver a faster, more responsive experience to your users and potentially reduce your bandwidth costs. Go ahead and implement it to make your RESTful services even more efficient!