From 75733141c215dbda9188bb612924409422356d7b Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 17 Oct 2017 10:07:47 +0200 Subject: [PATCH] DATAMONGO-1802 - Add Binary to byte array converter. We now provide and register a Binary to byte[] converter to provide conversion of binary data to a byte array. MongoDB deserializes binary data using the document API to its Binary type. With this converter, we reinstantiated the previous capability to use byte arrays for binary data within domain types. Original pull request: #505. --- .../mongodb/core/convert/MongoConverters.java | 26 ++++++- .../MongoConvertersIntegrationTests.java | 74 ++++++++++++++++--- 2 files changed, 87 insertions(+), 13 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java index 4fa794936..a2b352923 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core.convert; -import reactor.core.publisher.Flux; - import java.math.BigDecimal; import java.math.BigInteger; import java.net.MalformedURLException; @@ -29,9 +27,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.bson.Document; +import org.bson.types.Binary; import org.bson.types.Code; import org.bson.types.ObjectId; -import org.reactivestreams.Publisher; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalConverter; @@ -41,6 +39,7 @@ import org.springframework.data.convert.ReadingConverter; import org.springframework.data.convert.WritingConverter; import org.springframework.data.mongodb.core.query.Term; import org.springframework.data.mongodb.core.script.NamedMongoScript; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.NumberUtils; import org.springframework.util.StringUtils; @@ -68,7 +67,7 @@ abstract class MongoConverters { */ public static Collection getConvertersToRegister() { - List converters = new ArrayList(); + List converters = new ArrayList<>(); converters.add(BigDecimalToStringConverter.INSTANCE); converters.add(StringToBigDecimalConverter.INSTANCE); @@ -86,6 +85,7 @@ abstract class MongoConverters { converters.add(AtomicLongToLongConverter.INSTANCE); converters.add(LongToAtomicLongConverter.INSTANCE); converters.add(IntegerToAtomicIntegerConverter.INSTANCE); + converters.add(BinaryToByteArrayConverter.INSTANCE); return converters; } @@ -447,4 +447,22 @@ abstract class MongoConverters { return source != null ? new AtomicInteger(source) : null; } } + + /** + * {@link Converter} implementation capable of converting {@link Binary} to {@code byte[]}. + * + * @author Christoph Strobl + * @since 2.0.1 + */ + @ReadingConverter + public static enum BinaryToByteArrayConverter implements Converter { + + INSTANCE; + + @Nullable + @Override + public byte[] convert(Binary source) { + return source.getData(); + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java index d20d0a9b1..77dc9b94a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,16 +15,22 @@ */ package org.springframework.data.mongodb.core.convert; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; +import static org.springframework.data.mongodb.core.query.Query.*; + +import lombok.Data; import java.util.UUID; +import org.bson.types.Binary; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; @@ -34,37 +40,87 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * Integration tests for {@link MongoConverters}. * * @author Oliver Gierke + * @author Christoph Strobl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class MongoConvertersIntegrationTests { - static final String COLLECTION = "_sample"; + static final String COLLECTION = "converter-tests"; - @Autowired - MongoOperations template; + @Autowired MongoOperations template; @Before public void setUp() { template.dropCollection(COLLECTION); } - @Test + @Test // DATAMONGO-422 public void writesUUIDBinaryCorrectly() { Wrapper wrapper = new Wrapper(); wrapper.uuid = UUID.randomUUID(); template.save(wrapper); - assertThat(wrapper.id, is(notNullValue())); + assertThat(wrapper.id).isNotNull(); Wrapper result = template.findOne(Query.query(Criteria.where("id").is(wrapper.id)), Wrapper.class); - assertThat(result.uuid, is(wrapper.uuid)); + assertThat(result.uuid).isEqualTo(wrapper.uuid); } + @Test // DATAMONGO-1802 + public void shouldConvertBinaryDataOnRead() { + + WithBinaryDataInArray wbd = new WithBinaryDataInArray(); + wbd.data = "calliope-mini".getBytes(); + + template.save(wbd); + + assertThat(template.findOne(query(where("id").is(wbd.id)), WithBinaryDataInArray.class)).isEqualTo(wbd); + } + + @Test // DATAMONGO-1802 + public void shouldConvertEmptyBinaryDataOnRead() { + + WithBinaryDataInArray wbd = new WithBinaryDataInArray(); + wbd.data = new byte[] {}; + + template.save(wbd); + + assertThat(template.findOne(query(where("id").is(wbd.id)), WithBinaryDataInArray.class)).isEqualTo(wbd); + } + + @Test // DATAMONGO-1802 + public void shouldReadBinaryType() { + + WithBinaryDataType wbd = new WithBinaryDataType(); + wbd.data = new Binary("calliope-mini".getBytes()); + + template.save(wbd); + + assertThat(template.findOne(query(where("id").is(wbd.id)), WithBinaryDataType.class)).isEqualTo(wbd); + } + + @Document(collection = COLLECTION) static class Wrapper { String id; UUID uuid; } + + @Data + @Document(collection = COLLECTION) + static class WithBinaryDataInArray { + + @Id String id; + byte[] data; + } + + @Data + @Document(collection = COLLECTION) + static class WithBinaryDataType { + + @Id String id; + Binary data; + } }