123

We use Spring Boot/MVC with annotation-based java-config for series of RESTful services and we want to selectively enable HTTP GZIP stream compression on some API responses.

I know I can do this manually in my controller and a byte[] @ResponseBody, however we'd prefer to rely on the Spring MVC infrastructure (filters/etc) and have it automatically do the JSON conversion and compression (i.e. the method returns a POJO).

How can I enable GZIP compression in the ResponseBody or embedded Tomcat instance, and in a way we can selectively compress only some responses?

We don't currently have any XML based configuration.

3
  • You should check out GzipFilter. Commented Jul 29, 2014 at 20:13
  • 2
    don't use HTTP compression with HTTPS unless you know what you're doing Commented Jan 23, 2016 at 2:00
  • 1
    The gzip compression is disabled by default. Check this to enable gzip compression Commented Jan 12, 2024 at 10:11

10 Answers 10

234

The rest of these answers are out of date and/or over the top complicated for something that should be simple IMO (how long has gzip been around for now? longer than Java...) From the docs:

In application.properties 1.3+

# 🗜️🗜️🗜️
server.compression.enabled=true
# opt in to content types
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
# not worth the CPU cycles at some point, probably
server.compression.min-response-size=10240 

In application.properties 1.2.2 - <1.3

server.tomcat.compression=on
server.tomcat.compressableMimeTypes=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css

Older than 1.2.2:

@Component
public class TomcatCustomizer implements TomcatConnectorCustomizer {

  @Override
  public void customize(Connector connector) {
    connector.setProperty("compression", "on");
    // Add json and xml mime types, as they're not in the mimetype list by default
    connector.setProperty("compressableMimeType", "text/html,text/xml,text/plain,application/json,application/xml");
  }
}

Also note this will ONLY work if you are running embedded tomcat:

If you plan to deploy to a non embedded tomcat you will have to enable it in server.xml http://tomcat.apache.org/tomcat-9.0-doc/config/http.html#Standard_Implementation

IRL Production Note:

Also to avoid all of this consider using a proxy/load balancer setup in front of Tomcat with nginx and/or haproxy or similar since it will handle static assets and gzip MUCH more efficiently and easily than Java/Tomcat's threading model.

You don't want to throw 'cat in the bath because it's busy compressing stuff instead of serving up requests (or more likely spinning up threads/eating CPU/heap sitting around waiting for database IO to occur while running up your AWS bill which is why traditional Java/Tomcat might not be a good idea to begin with depending on what you are doing but I digress...)

refs: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/howto.html#how-to-enable-http-response-compression

https://github.com/spring-projects/spring-boot/issues/2031

Sign up to request clarification or add additional context in comments.

15 Comments

Your approach for versions old than 1.2.2 won't work as Spring Boot doesn't look for TomcatConnectorCustomizer instances in the application context; they have to be programatically registered with TomcatEmbeddedServletContainerFactory
Thanks for the heads up. I ended up giving up on this since it seems static/dynamic/tomcat/vs boot was still an issue. This is way harder than it should be... Nginx reverse proxy FTW!
In SpringBoot, the new properties are server.compression.enabled=true and server.compression.mime-types=XXX,YYY github.com/spring-projects/spring-boot/wiki/…
If for spring boot we have multiple rest controllers all returning JSON responses. Can we selectively apply the zip on some controllers?
You should also mention the minimum response size for compression (ex: 10KB) otherwise it becomes overhead for the server to compress every (ex: 0.5KB) request. server.compression.min-response-size=10240
|
17

On recents versions in application.yml config:

---

spring:
  profiles: dev

server:
  compression:
    enabled: true
    mime-types: text/html,text/css,application/javascript,application/json

---

2 Comments

The corresponding bug report and fix where this was changed is github.com/spring-projects/spring-boot/issues/2737
Can you use wildcard mime types? i.e image/*? It does not seem to work
14

This is basically the same solution as @andy-wilkinson provided, but as of Spring Boot 1.0 the customize(...) method has a ConfigurableEmbeddedServletContainer parameter.

Another thing that is worth mentioning is that Tomcat only compresses content types of text/html, text/xml and text/plain by default. Below is an example that supports compression of application/json as well:

@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer servletContainer) {
            ((TomcatEmbeddedServletContainerFactory) servletContainer).addConnectorCustomizers(
                    new TomcatConnectorCustomizer() {
                        @Override
                        public void customize(Connector connector) {
                            AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
                            httpProtocol.setCompression("on");
                            httpProtocol.setCompressionMinSize(256);
                            String mimeTypes = httpProtocol.getCompressableMimeTypes();
                            String mimeTypesWithJson = mimeTypes + "," + MediaType.APPLICATION_JSON_VALUE;
                            httpProtocol.setCompressableMimeTypes(mimeTypesWithJson);
                        }
                    }
            );
        }
    };
}

2 Comments

I tried adding this into my Java Configuration and found that the compression didn't seem to be operating at all. I am using Spring Boot with Tomcat as the embedded container, and wondered if there were any additional things I needed to set other than this configuration?
Try verifying by specifying the Accept-Encoding: gzip,deflate header, if you are using curl: curl -i -H 'Accept-Encoding: gzip,deflate' http://url.to.your.server
12

I have added for this:

Server compression

server.compression.enabled=true
server.compression.min-response-size=2048
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain

taken from http://bisaga.com/blog/programming/web-compression-on-spring-boot-application/

Comments

10

Spring Boot 1.4 Use this for Javascript HTML Json all compressions.

server.compression.enabled: true
server.compression.mime-types: application/json,application/xml,text/html,text/xml,text/plain,text/css,application/javascript

2 Comments

How do we verify this compression?
@Bhargav See the response header of your api response. It should contain the header:Content-Encoding : gzip
7

Enabeling GZip in Tomcat doesn't worked in my Spring Boot Project. I used CompressingFilter found here.

@Bean
public Filter compressingFilter() {
    CompressingFilter compressingFilter = new CompressingFilter();
    return compressingFilter;
}

1 Comment

@user1127860 tnx this works but anyway to configure this Filter further? I use spring boot and cant seem to add init params as manual says in web.xml
5

To enable GZIP compression, you need to modify the configuration of the embedded Tomcat instance. To do so, you declare a EmbeddedServletContainerCustomizer bean in your Java configuration and then register a TomcatConnectorCustomizer with it.

For example:

@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
            ((TomcatEmbeddedServletContainerFactory) factory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
                @Override
                public void customize(Connector connector) {
                    AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
                    httpProtocol.setCompression("on");
                    httpProtocol.setCompressionMinSize(64);
                }
            });
        }
    };
}

See the Tomcat documentation for more details on the various compression configuration options that are available.

You say that you want to selectively enable compression. Depending on your selection criteria, then the above approach may be sufficient. It enables you to control compression by the request's user-agent, the response's size, and the response's mime type.

If this doesn't meet your needs then I believe you will have to perform the compression in your controller and return a byte[] response with a gzip content-encoding header.

5 Comments

what is the diffrent between your answer to the option to put the setting on application.properties ? server.compression.enabled=true server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
This answer was written before properties-based compression configuration was available. They are equivalent, but the properties-based approach is easier so I would recommend using that.
just want to share that in my case tomcat is behind a load balancer that get https and forword the request to tomcat as http ., when I use application.properties solution response is not gzip but when I use the programmatic config solution on connector i get gzip response with https request LB
another question in case I use application.properties solution .. and define more 2 connectors on 8081 and 8082 ports .. does compresion applay to all conectors or just to the 8080 connector ?
i verfiy this , compersion is only apply on port 8080 , even if you open more connectors .. , i think bug should be open on this to spring boot ??.. , so only work solution for me was programmatic config for each connector , not application.properties
3

I had the same problem into my Spring Boot+Spring Data project when invoking to a @RepositoryRestResource.

The problem is the MIME type returned; which is application/hal+json. Adding it to the server.compression.mime-types property solved this problem for me.

Hope this helps to someone else!

Comments

0

Add following dependency in pom.xml

<dependency>
    <groupId>net.sourceforge.pjl-comp-filter</groupId>
    <artifactId>pjl-comp-filter</artifactId>
    <version>1.6.4</version>
</dependency>

Add following bean configuration into your configuration file.

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.DispatcherServlet;
import com.planetj.servlet.filter.compression.CompressingFilter;

@Bean
public FilterRegistrationBean<CompressingFilter> dispatcherRegistration(DispatcherServlet dispatcherServlet) {
    FilterRegistrationBean<CompressingFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new CompressingFilter());
    registrationBean.setEnabled(true);
    registrationBean.addUrlPatterns("/*");
    return registrationBean;
}

CompressingFilter helps to compress the response.

You can set GZIP compression of selective endpoints using addUrlPatterns(String) method in FilterRegistrationBean. Use setUrlPatterns(Collection<String>) method in case you have multiple endpoints.

If no URL pattern is set, filter compresses all responses.

Note: this won't even need to add any properties in application.properties file.

Comments

-1

Get the latest documentation from the below spring-docs url :

Spring-docs Embedded Server Configuration

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.