[java] Using GZIP compression with Spring Boot/MVC/JavaConfig with RESTful

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.

This question is related to java spring rest spring-mvc gzip

The answer is


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

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.


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


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!


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/


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;
}

On recents versions in application.yml config:

---

spring:
  profiles: dev

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

---

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);
                        }
                    }
            );
        }
    };
}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to spring

Are all Spring Framework Java Configuration injection examples buggy? Two Page Login with Spring Security 3.2.x Access blocked by CORS policy: Response to preflight request doesn't pass access control check Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified Spring Data JPA findOne() change to Optional how to use this? After Spring Boot 2.0 migration: jdbcUrl is required with driverClassName The type WebMvcConfigurerAdapter is deprecated No converter found capable of converting from type to type

Examples related to rest

Access blocked by CORS policy: Response to preflight request doesn't pass access control check Returning data from Axios API Access Control Origin Header error using Axios in React Web throwing error in Chrome JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value How to send json data in POST request using C# How to enable CORS in ASP.net Core WebAPI RestClientException: Could not extract response. no suitable HttpMessageConverter found REST API - Use the "Accept: application/json" HTTP Header 'Field required a bean of type that could not be found.' error spring restful API using mongodb MultipartException: Current request is not a multipart request

Examples related to spring-mvc

Two Page Login with Spring Security 3.2.x ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Spring 5.0.3 RequestRejectedException: The request was rejected because the URL was not normalized The type WebMvcConfigurerAdapter is deprecated RestClientException: Could not extract response. no suitable HttpMessageConverter found Spring boot: Unable to start embedded Tomcat servlet container UnsatisfiedDependencyException: Error creating bean with name 8080 port already taken issue when trying to redeploy project from Spring Tool Suite IDE Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed Difference between the annotations @GetMapping and @RequestMapping(method = RequestMethod.GET)

Examples related to gzip

gzip: stdin: not in gzip format tar: Child returned status 1 tar: Error is not recoverable: exiting now How to unzip gz file using Python How to enable GZIP compression in IIS 7.5 Using GZIP compression with Spring Boot/MVC/JavaConfig with RESTful How are zlib, gzip and zip related? What do they have in common and how are they different? How to uncompress a tar.gz in another directory compression and decompression of string data in java Extract and delete all .gz in a directory- Linux How to extract filename.tar.gz file Read from a gzip file in python