Zip Support

This Spring Integration module provides Zip (un-)compression support. A zipping algorithm implementation is based on a ZeroTurnaround ZIP Library. The following components are provided:

You need to include this dependency into your project:

Maven
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-zip</artifactId>
    <version>6.1.9</version>
</dependency>
Gradle
compile "org.springframework.integration:spring-integration-zip:6.1.9"

Namespace Support

All components within the Spring Integration Zip module provide namespace support. In order to enable namespace support, you need to import the schema for the Spring Integration Zip Module. The following example shows a typical setup:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"
  xmlns:int-zip="http://www.springframework.org/schema/integration/zip"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration
    https://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/zip
    https://www.springframework.org/schema/integration/zip/spring-integration-zip.xsd">
</beans>

(Un)Zip Transformer

The ZipTransformer implements a zipping functionality for these types of input payload: File, String, byte[] and Iterable. In input data types can be mixed as part of an Iterable. For example, it should be easily to compress a collection containing Strings, byte arrays and Files. It is important to note that nested Iterables are NOT SUPPORTED at present time.

The ZipTransformer can be customized by setting several properties:

  • compressionLevel - sets the compression level. Default is Deflater#DEFAULT_COMPRESSION.

  • useFileAttributes - specifies whether the name of the file shall be used for the zip entry.

For example to zip a simple test.txt file into a test.txt.zip, only this configuration is enough:

Java DSL
@Bean
public IntegrationFlow zipFlow() {
    return IntegrationFlow
             .from("zipChannel")
             .transform(new ZipTransformer())
             .get();
}
Kotlin DSL
@Bean
fun zipFlow() =
    integrationFlow("zipChannel") {
        transform(ZipTransformer())
    }
Groovy DSL
@Bean
zipFlow() {
    integrationFlow 'zipChannel',
            {
                transform new ZipTransformer()
            }
}
Java
@Transfomer(inputChannel = "zipChannel")
@Bean
ZipTransformer zipTransformer() {
    return new ZipTransformer();
}
XML
<int-zip:zip-transformer input-channel="zipChannel"/>

See ZipTransformer Javadocs for more information.

An UnZipTransformer supports these of input payload: File, byte[] and InputStream. When unzipping data, an expectSingleResult property can be specified. If set to true and more than 1 zip entry were detected, a MessagingException will be raised. This property also influences the return type of the payload. If set to false (default), then the payload will be of type SortedMap, if true, however, the actual zip entry will be returned.

Other properties that can be set on the UnZipTransformer:

  • deleteFiles - if the payload is an instance of File, this property specifies whether to delete the File after transformation. Default is false.

  • ZipResultType - defines the format of the data returned after transformation. Available options are: File, byte[].

  • workDirectory - the work directory is used when a ZipResultType is set to ZipResultType.FILE. By default, this property is set to the System temporary directory containing a subdirectory ziptransformer.

For example to zip a simple test.zip file into a map of its entries, only this configuration is enough:

Java DSL
@Bean
public IntegrationFlow unzipFlow() {
    return IntegrationFlow
             .from("unzipChannel")
             .transform(new UnZipTransformer())
             .get();
}
Kotlin DSL
@Bean
fun unzipFlow() =
    integrationFlow("unzipChannel") {
        transform(UnZipTransformer())
    }
Groovy DSL
@Bean
unzipFlow() {
    integrationFlow 'unzipChannel',
            {
                transform new UnZipTransformer()
            }
}
Java
@Transfomer(inputChannel = "unzipChannel")
@Bean
UnZipTransformer unzipTransformer() {
    return new UnZipTransformer();
}
XML
<int-zip:unzip-transformer input-channel="unzipChannel"/>

Unzipped Splitter

The UnZipResultSplitter is useful in cases where zip files contain more than 1 entry. Essentially it has to be used as the next step in the integration flow after the mentioned above UnZipTransformer. It supports only a Map as an input data and emits every entry into an outputChannel with FileHeaders.FILENAME and ZipHeaders.ZIP_ENTRY_PATH headers.

The following example demonstrates a simple configuration for splitting unzipped result:

Java DSL
@Bean
public IntegrationFlow unzipSplitFlow(Executor executor) {
    return IntegrationFlow
             .from("unzipChannel")
             .transform(new UnZipTransformer())
             .split(new UnZipResultSplitter())
             .channel(c -> c.executor("entriesChannel", executor))
             .get();
}
Kotlin DSL
@Bean
fun unzipFlow(executor: Executor) =
    integrationFlow("unzipChannel") {
        transform(UnZipTransformer())
        split(UnZipResultSplitter())
        channel { executor("entriesChannel", executor) }
    }
Groovy DSL
@Bean
unzipFlow(Executor executor) {
    integrationFlow 'unzipChannel',
            {
                transform new UnZipTransformer()
                split new UnZipResultSplitter()
                channel { executor 'entriesChannel', executor }
            }
}
Java
@Transfomer(inputChannel = "unzipChannel", outputChannel = "splitChannel")
@Bean
UnZipTransformer unzipTransformer() {
    return new UnZipTransformer();
}

@Spitter(inputChannel = "splitChannel", outputChannel = "entriesChannel")
@Bean
UnZipResultSplitter unZipSplitter() {
    return new UnZipResultSplitter();
}

@Bean
ExecutorChannel entriesChannel(Executor executor) {
    return new ExecutorChannel(executor);
}
XML
<int:chain input-channel="unzipChannel" output-channel="entriesChannel">
    <int-zip:unzip-transformer/>
    <int:splitter>
        <bean class="org.springframework.integration.zip.splitter.UnZipResultSplitter"/>
    </int:splitter>
</int:chain>

<int:channel id="entriesChannel">
    <int:dispatcher task-executor="executor"/>
</int:channel>