http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobModule.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobModule.java
 
b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobModule.java
new file mode 100644
index 0000000..234988a
--- /dev/null
+++ 
b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobModule.java
@@ -0,0 +1,68 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+import java.util.List;
+
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.components.CassandraTable;
+import org.apache.james.backends.cassandra.components.CassandraType;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
+import com.google.common.collect.ImmutableList;
+
+public class CassandraBlobModule implements CassandraModule {
+
+    private final List<CassandraTable> tables;
+    private final List<CassandraType> types;
+
+    public CassandraBlobModule() {
+        tables = ImmutableList.of(
+            new CassandraTable(BlobTable.TABLE_NAME,
+                SchemaBuilder.createTable(BlobTable.TABLE_NAME)
+                    .ifNotExists()
+                    .addPartitionKey(BlobTable.ID, DataType.text())
+                    .addClusteringColumn(BlobTable.NUMBER_OF_CHUNK, 
DataType.cint())
+                    .withOptions()
+                    .comment("Holds information for retrieving all blob parts 
composing this blob. " +
+                        "Messages` headers and bodies are stored as 
blobparts.")),
+            new CassandraTable(BlobTable.BlobParts.TABLE_NAME,
+                SchemaBuilder.createTable(BlobTable.BlobParts.TABLE_NAME)
+                    .ifNotExists()
+                    .addPartitionKey(BlobTable.ID, DataType.text())
+                    .addClusteringColumn(BlobTable.BlobParts.CHUNK_NUMBER, 
DataType.cint())
+                    .addColumn(BlobTable.BlobParts.DATA, DataType.blob())
+                    .withOptions()
+                    .comment("Holds blob parts composing blobs ." +
+                        "Messages` headers and bodies are stored, chunked in 
blobparts.")));
+        types = ImmutableList.of();
+    }
+
+    @Override
+    public List<CassandraTable> moduleTables() {
+        return tables;
+    }
+
+    @Override
+    public List<CassandraType> moduleTypes() {
+        return types;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
 
b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
new file mode 100644
index 0000000..97965ec
--- /dev/null
+++ 
b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
@@ -0,0 +1,210 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.james.backends.cassandra.init.CassandraConfiguration;
+import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.api.ObjectStore;
+import org.apache.james.blob.cassandra.BlobTable.BlobParts;
+import org.apache.james.blob.cassandra.utils.DataChunker;
+import org.apache.james.util.FluentFutureStream;
+import org.apache.james.util.OptionalUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Bytes;
+
+public class CassandraBlobsDAO implements ObjectStore {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(CassandraBlobsDAO.class);
+    private final CassandraAsyncExecutor cassandraAsyncExecutor;
+    private final PreparedStatement insert;
+    private final PreparedStatement insertPart;
+    private final PreparedStatement select;
+    private final PreparedStatement selectPart;
+    private final DataChunker dataChunker;
+    private final CassandraConfiguration configuration;
+
+    @Inject
+    public CassandraBlobsDAO(Session session, CassandraConfiguration 
cassandraConfiguration) {
+        this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
+        this.configuration = cassandraConfiguration;
+        this.dataChunker = new DataChunker();
+        this.insert = prepareInsert(session);
+        this.select = prepareSelect(session);
+
+        this.insertPart = prepareInsertPart(session);
+        this.selectPart = prepareSelectPart(session);
+    }
+
+    @VisibleForTesting
+    public CassandraBlobsDAO(Session session) {
+        this(session, CassandraConfiguration.DEFAULT_CONFIGURATION);
+    }
+
+    private PreparedStatement prepareSelect(Session session) {
+        return session.prepare(select()
+            .from(BlobTable.TABLE_NAME)
+            .where(eq(BlobTable.ID, bindMarker(BlobTable.ID))));
+    }
+
+    private PreparedStatement prepareSelectPart(Session session) {
+        return session.prepare(select()
+            .from(BlobParts.TABLE_NAME)
+            .where(eq(BlobTable.ID, bindMarker(BlobTable.ID)))
+            .and(eq(BlobParts.CHUNK_NUMBER, 
bindMarker(BlobParts.CHUNK_NUMBER))));
+    }
+
+    private PreparedStatement prepareInsert(Session session) {
+        return session.prepare(insertInto(BlobTable.TABLE_NAME)
+            .value(BlobTable.ID, bindMarker(BlobTable.ID))
+            .value(BlobTable.NUMBER_OF_CHUNK, 
bindMarker(BlobTable.NUMBER_OF_CHUNK)));
+    }
+
+    private PreparedStatement prepareInsertPart(Session session) {
+        return session.prepare(insertInto(BlobParts.TABLE_NAME)
+            .value(BlobTable.ID, bindMarker(BlobTable.ID))
+            .value(BlobParts.CHUNK_NUMBER, bindMarker(BlobParts.CHUNK_NUMBER))
+            .value(BlobParts.DATA, bindMarker(BlobParts.DATA)));
+    }
+
+    @Override
+    public CompletableFuture<BlobId> save(byte[] data) {
+        Preconditions.checkNotNull(data);
+
+        CassandraBlobId blobId = CassandraBlobId.forPayload(data);
+        return saveBlobParts(data, blobId)
+            .thenCompose(numberOfChunk -> saveBlobPartsReferences(blobId, 
numberOfChunk))
+            .thenApply(any -> blobId);
+    }
+
+    private CompletableFuture<Integer> saveBlobParts(byte[] data, 
CassandraBlobId blobId) {
+        return FluentFutureStream.of(
+            dataChunker.chunk(data, configuration.getBlobPartSize())
+                .map(pair -> writePart(pair.getRight(), blobId, pair.getKey())
+                    .thenApply(partId -> Pair.of(pair.getKey(), partId))))
+            .completableFuture()
+            .thenApply(stream ->
+                getLastOfStream(stream)
+                    .map(numOfChunkAndPartId -> numOfChunkAndPartId.getLeft() 
+ 1)
+                    .orElse(0));
+    }
+
+    private static <T> Optional<T> getLastOfStream(Stream<T> stream) {
+        return stream.reduce((first, second) -> second);
+    }
+
+    private CompletableFuture<Void> writePart(ByteBuffer data, CassandraBlobId 
blobId, int position) {
+        return cassandraAsyncExecutor.executeVoid(
+            insertPart.bind()
+                .setString(BlobTable.ID, blobId.asString())
+                .setInt(BlobParts.CHUNK_NUMBER, position)
+                .setBytes(BlobParts.DATA, data));
+    }
+
+    private CompletableFuture<Void> saveBlobPartsReferences(CassandraBlobId 
blobId, int numberOfChunk) {
+        return cassandraAsyncExecutor.executeVoid(insert.bind()
+            .setString(BlobTable.ID, blobId.asString())
+            .setInt(BlobTable.NUMBER_OF_CHUNK, numberOfChunk));
+    }
+
+    @Override
+    public CompletableFuture<byte[]> read(BlobId blobId) {
+        return cassandraAsyncExecutor.executeSingleRow(
+            select.bind()
+                .setString(BlobTable.ID, blobId.asString()))
+            .thenCompose(row -> toDataParts(row, blobId))
+            .thenApply(this::concatenateDataParts);
+    }
+
+    private CompletableFuture<Stream<BlobPart>> toDataParts(Optional<Row> 
blobRowOptional, BlobId blobId) {
+        return blobRowOptional.map(blobRow -> {
+            int numOfChunk = blobRow.getInt(BlobTable.NUMBER_OF_CHUNK);
+            return FluentFutureStream.of(
+                IntStream.range(0, numOfChunk)
+                    .mapToObj(position -> readPart(blobId, position)))
+                .completableFuture();
+        }).orElseGet(() -> {
+            LOGGER.warn("Could not retrieve blob metadata for {}", blobId);
+            return CompletableFuture.completedFuture(Stream.empty());
+        });
+    }
+
+    private byte[] concatenateDataParts(Stream<BlobPart> blobParts) {
+        ImmutableList<byte[]> parts = blobParts
+            .map(blobPart -> OptionalUtils.executeIfEmpty(
+                blobPart.row,
+                () -> LOGGER.warn("Missing blob part for blobId {} and 
position {}", blobPart.blobId, blobPart.position)))
+            .flatMap(OptionalUtils::toStream)
+            .map(this::rowToData)
+            .collect(Guavate.toImmutableList());
+
+        return Bytes.concat(parts.toArray(new byte[parts.size()][]));
+    }
+
+    private byte[] rowToData(Row row) {
+        byte[] data = new byte[row.getBytes(BlobParts.DATA).remaining()];
+        row.getBytes(BlobParts.DATA).get(data);
+        return data;
+    }
+
+    private CompletableFuture<BlobPart> readPart(BlobId blobId, int position) {
+        return cassandraAsyncExecutor.executeSingleRow(
+            selectPart.bind()
+                .setString(BlobTable.ID, blobId.asString())
+                .setInt(BlobParts.CHUNK_NUMBER, position))
+            .thenApply(row -> new BlobPart(blobId, position, row));
+    }
+
+    private static class BlobPart {
+        private final BlobId blobId;
+        private final int position;
+        private final Optional<Row> row;
+
+        public BlobPart(BlobId blobId, int position, Optional<Row> row) {
+            Preconditions.checkNotNull(blobId);
+            Preconditions.checkArgument(position >= 0, "position need to be 
positive");
+            this.blobId = blobId;
+            this.position = position;
+            this.row = row;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/utils/DataChunker.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/utils/DataChunker.java
 
b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/utils/DataChunker.java
new file mode 100644
index 0000000..aad71dc
--- /dev/null
+++ 
b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/utils/DataChunker.java
@@ -0,0 +1,52 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra.utils;
+
+import java.nio.ByteBuffer;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.google.common.base.Preconditions;
+
+public class DataChunker {
+
+    public Stream<Pair<Integer, ByteBuffer>> chunk(byte[] data, int chunkSize) 
{
+        Preconditions.checkNotNull(data);
+        Preconditions.checkArgument(chunkSize > 0, "ChunkSize can not be 
negative");
+
+        int size = data.length;
+        int fullChunkCount = size / chunkSize;
+
+        return Stream.concat(
+            IntStream.range(0, fullChunkCount)
+                .mapToObj(i -> Pair.of(i, ByteBuffer.wrap(data, i * chunkSize, 
chunkSize))),
+            lastChunk(data, chunkSize * fullChunkCount, fullChunkCount));
+    }
+
+    private Stream<Pair<Integer, ByteBuffer>> lastChunk(byte[] data, int 
offset, int index) {
+        if (offset == data.length && index > 0) {
+            return Stream.empty();
+        }
+        return Stream.of(Pair.of(index, ByteBuffer.wrap(data, offset, 
data.length - offset)));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
 
b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
new file mode 100644
index 0000000..62e73cd
--- /dev/null
+++ 
b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
@@ -0,0 +1,86 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.james.backends.cassandra.CassandraCluster;
+import org.apache.james.backends.cassandra.DockerCassandraExtension;
+import 
org.apache.james.backends.cassandra.DockerCassandraExtension.DockerCassandra;
+import org.apache.james.backends.cassandra.init.CassandraConfiguration;
+import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.api.ObjectStore;
+import org.apache.james.blob.api.ObjectStoreContract;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import com.google.common.base.Strings;
+
+@ExtendWith(DockerCassandraExtension.class)
+public class CassandraBlobsDAOTest implements ObjectStoreContract {
+
+    private static final int CHUNK_SIZE = 10240;
+    private static final int MULTIPLE_CHUNK_SIZE = 3;
+
+    private CassandraCluster cassandra;
+    private CassandraBlobsDAO testee;
+
+    @BeforeEach
+    public void setUp(DockerCassandra dockerCassandra) {
+        cassandra = CassandraCluster.create(
+                new CassandraBlobModule(), dockerCassandra.getIp(), 
dockerCassandra.getBindingPort());
+        
+        testee = new CassandraBlobsDAO(cassandra.getConf(),
+            CassandraConfiguration.builder()
+                .blobPartSize(CHUNK_SIZE)
+                .build());
+    }
+
+    @AfterEach
+    public void tearDown() {
+        cassandra.close();
+    }
+
+    @Override
+    public ObjectStore testee() {
+        return testee;
+    }
+
+    @Override
+    public BlobId from(String blodIdAsString) {
+        return CassandraBlobId.from(blodIdAsString);
+    }
+
+    @Test
+    public void readShouldReturnSplitSavedDataByChunk() throws IOException {
+        String longString = Strings.repeat("0123456789\n", 
MULTIPLE_CHUNK_SIZE);
+        BlobId blobId = 
testee.save(longString.getBytes(StandardCharsets.UTF_8)).join();
+
+        byte[] bytes = testee.read(blobId).join();
+
+        assertThat(new String(bytes, 
StandardCharsets.UTF_8)).isEqualTo(longString);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/utils/DataChunkerTest.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/utils/DataChunkerTest.java
 
b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/utils/DataChunkerTest.java
new file mode 100644
index 0000000..0f97a0d
--- /dev/null
+++ 
b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/utils/DataChunkerTest.java
@@ -0,0 +1,110 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Bytes;
+
+public class DataChunkerTest {
+
+    public static final int CHUNK_SIZE = 10;
+
+    private DataChunker testee;
+
+    @BeforeEach
+    public void setUp() {
+        testee = new DataChunker();
+    }
+
+    @Test
+    public void chunkShouldThrowOnNullData() {
+        assertThatThrownBy(() -> testee.chunk(null, CHUNK_SIZE))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void chunkShouldThrowOnNegativeChunkSize() {
+        int chunkSize = -1;
+        assertThatThrownBy(() -> testee.chunk(new byte[0], chunkSize))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void chunkShouldThrowOnZeroChunkSize() {
+        int chunkSize = 0;
+        assertThatThrownBy(() -> testee.chunk(new byte[0], chunkSize))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void chunkShouldReturnOneEmptyArrayWhenInputEmpty() {
+        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(new byte[0], 
CHUNK_SIZE);
+        ByteBuffer emptyBuffer = ByteBuffer.wrap(new byte[0]);
+        assertThat(chunks)
+            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, emptyBuffer)));
+    }
+
+    @Test
+    public void chunkShouldReturnOneArrayWhenInputLessThanChunkSize() {
+        byte[] data = "12345".getBytes(StandardCharsets.UTF_8);
+
+        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, 
CHUNK_SIZE);
+
+        assertThat(chunks)
+            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, 
ByteBuffer.wrap(data))));
+    }
+
+    @Test
+    public void chunkShouldReturnOneArrayWhenInputEqualsChunkSize() {
+        byte[] data = "1234567890".getBytes(StandardCharsets.UTF_8);
+        assertThat(data.length).isEqualTo(CHUNK_SIZE);
+
+        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, 
CHUNK_SIZE);
+
+        assertThat(chunks)
+            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, 
ByteBuffer.wrap(data))));
+    }
+
+    @Test
+    public void chunkShouldReturnSeveralArrayWhenInputBiggerThanChunkSize() {
+        byte[] part1 = "1234567890".getBytes(StandardCharsets.UTF_8);
+        byte[] part2 = "12345".getBytes(StandardCharsets.UTF_8);
+        byte[] data = Bytes.concat(part1, part2);
+
+        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, 
CHUNK_SIZE);
+
+        assertThat(chunks)
+        .containsOnlyElementsOf(ImmutableList.of(
+                Pair.of(0, ByteBuffer.wrap(part1)),
+                Pair.of(1, ByteBuffer.wrap(part2))));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
 
b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
index b233920..3d1c404 100644
--- 
a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
+++ 
b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
@@ -23,6 +23,7 @@ import javax.inject.Singleton;
 import org.apache.james.adapter.mailbox.store.UserRepositoryAuthenticator;
 import org.apache.james.adapter.mailbox.store.UserRepositoryAuthorizator;
 import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.AttachmentManager;
 import org.apache.james.mailbox.BlobManager;
 import org.apache.james.mailbox.MailboxListener;
@@ -43,7 +44,6 @@ import 
org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO;
-import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO;
@@ -159,7 +159,7 @@ public class CassandraMailboxModule extends AbstractModule {
         
cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule.class);
         
cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule.class);
         
cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule.class);
-        
cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraBlobModule.class);
+        
cassandraDataDefinitions.addBinding().to(org.apache.james.blob.cassandra.CassandraBlobModule.class);
         
cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule.class);
         
cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule.class);
         
cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule.class);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to