Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implement JacksonSerializer to allow serialization to JSON

Issue #AXON-228 Fixed
  • Loading branch information...
commit 98804a5a392b310e33c54f7da1a47d14eb49c86d 1 parent 1d471a8
@abuijze abuijze authored
View
11 core/pom.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- ~ Copyright (c) 2010-2012. Axon Framework
+ ~ Copyright (c) 2010-2014. Axon Framework
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -15,7 +15,8 @@
~ limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.axonframework</groupId>
<artifactId>axon</artifactId>
@@ -139,6 +140,12 @@
<optional>true</optional>
</dependency>
<dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.2.2</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
View
63 core/src/main/java/org/axonframework/serializer/json/ByteArrayToJsonNodeConverter.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010-2014. Axon Framework
+ *
+ * Licensed 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.axonframework.serializer.json;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.axonframework.serializer.AbstractContentTypeConverter;
+import org.axonframework.serializer.CannotConvertBetweenTypesException;
+
+import java.io.IOException;
+
+/**
+ * ContentTypeConverter implementation that converts byte[] containing UTF8 encoded JSON string to a Jackson JsonNode.
+ *
+ * @author Allard Buijze
+ * @since 2.2
+ */
+public class ByteArrayToJsonNodeConverter extends AbstractContentTypeConverter<byte[], JsonNode> {
+
+ private final ObjectMapper objectMapper;
+
+ /**
+ * Initialize the Converter, using given <code>objectMapper</code> to parse the binary contents
+ *
+ * @param objectMapper the Jackson ObjectMapper to parse the byte array with
+ */
+ public ByteArrayToJsonNodeConverter(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public Class<byte[]> expectedSourceType() {
+ return byte[].class;
+ }
+
+ @Override
+ public Class<JsonNode> targetType() {
+ return JsonNode.class;
+ }
+
+ @Override
+ public JsonNode convert(byte[] original) {
+ try {
+ return objectMapper.readTree(original);
+ } catch (IOException e) {
+ throw new CannotConvertBetweenTypesException("An error occurred while converting a JsonNode to byte[]", e);
+ }
+ }
+}
View
269 core/src/main/java/org/axonframework/serializer/json/JacksonSerializer.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2010-2014. Axon Framework
+ *
+ * Licensed 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.axonframework.serializer.json;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import org.axonframework.serializer.AnnotationRevisionResolver;
+import org.axonframework.serializer.ChainingConverterFactory;
+import org.axonframework.serializer.ConverterFactory;
+import org.axonframework.serializer.RevisionResolver;
+import org.axonframework.serializer.SerializationException;
+import org.axonframework.serializer.SerializedObject;
+import org.axonframework.serializer.SerializedType;
+import org.axonframework.serializer.Serializer;
+import org.axonframework.serializer.SimpleSerializedObject;
+import org.axonframework.serializer.SimpleSerializedType;
+import org.axonframework.serializer.UnknownSerializedTypeException;
+import org.joda.time.DateTime;
+import org.joda.time.Instant;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.joda.time.LocalTime;
+import org.joda.time.MonthDay;
+import org.joda.time.MutableDateTime;
+import org.joda.time.ReadableInstant;
+import org.joda.time.YearMonth;
+
+import java.io.IOException;
+
+/**
+ * Serializer implementation that uses Jackson to serialize objects into a JSON format. Although the Jackson serializer
+ * requires classes to be compatible with this specific serializer, it providers much more compact serialization, while
+ * still being human readable.
+ *
+ * @author Allard Buijze
+ * @since 2.2
+ */
+public class JacksonSerializer implements Serializer {
+
+ private final RevisionResolver revisionResolver;
+ private final ConverterFactory converterFactory;
+ private final ObjectMapper objectMapper;
+ private final ClassLoader classLoader;
+
+ /**
+ * Initialize the serializer with a default ObjectMapper instance. Revisions are resolved using {@link
+ * org.axonframework.serializer.Revision @Revision} annotations on the serialized classes.
+ */
+ public JacksonSerializer() {
+ this(new AnnotationRevisionResolver(), new ChainingConverterFactory());
+ }
+
+ /**
+ * Initialize the serializer with the given <code>objectMapper</code> to serialize and parse the objects to JSON.
+ * This objectMapper allows for customization of the serialized form.
+ *
+ * @param objectMapper The objectMapper to serialize objects and parse JSON with
+ */
+ public JacksonSerializer(ObjectMapper objectMapper) {
+ this(objectMapper, new AnnotationRevisionResolver(), new ChainingConverterFactory());
+ }
+
+ /**
+ * Initialize the serializer using a default ObjectMapper instance, using the given <code>revisionResolver</code>
+ * to define revision for each object to serialize, and given <code>converterFactory</code> to be used by
+ * upcasters.
+ *
+ * @param revisionResolver The strategy to use to resolve the revision of an object
+ * @param converterFactory The factory providing the converter instances for upcasters
+ */
+ public JacksonSerializer(RevisionResolver revisionResolver, ConverterFactory converterFactory) {
+ this(new ObjectMapper(), revisionResolver, converterFactory);
+ }
+
+ /**
+ * Initialize the serializer with the given <code>objectMapper</code> to serialize and parse the objects to JSON.
+ * This objectMapper allows for customization of the serialized form. The given <code>revisionResolver</code> is
+ * used to resolve the revision from an object to be serialized.
+ *
+ * @param objectMapper The objectMapper to serialize objects and parse JSON with
+ * @param revisionResolver The strategy to use to resolve the revision of an object
+ */
+ public JacksonSerializer(ObjectMapper objectMapper, RevisionResolver revisionResolver) {
+ this(objectMapper, revisionResolver, new ChainingConverterFactory());
+ }
+
+ /**
+ * Initialize the serializer with the given <code>objectMapper</code> to serialize and parse the objects to JSON.
+ * This objectMapper allows for customization of the serialized form. The given <code>revisionResolver</code> is
+ * used to resolve the revision from an object to be serialized. The given <code>converterFactory</code> is the
+ * converter factory used by upcasters to convert between content types.
+ *
+ * @param objectMapper The objectMapper to serialize objects and parse JSON with
+ * @param revisionResolver The strategy to use to resolve the revision of an object
+ * @param converterFactory The factory providing the converter instances for upcasters
+ */
+ public JacksonSerializer(ObjectMapper objectMapper, RevisionResolver revisionResolver,
+ ConverterFactory converterFactory) {
+ this(objectMapper, revisionResolver, converterFactory, null);
+ }
+
+ /**
+ * Initialize the serializer with the given <code>objectMapper</code> to serialize and parse the objects to JSON.
+ * This objectMapper allows for customization of the serialized form. The given <code>revisionResolver</code> is
+ * used to resolve the revision from an object to be serialized. The given <code>converterFactory</code> is the
+ * converter factory used by upcasters to convert between content types.
+ *
+ * @param objectMapper The objectMapper to serialize objects and parse JSON with
+ * @param revisionResolver The strategy to use to resolve the revision of an object
+ * @param converterFactory The factory providing the converter instances for upcasters
+ * @param classLoader The class loader to load classes with when deserializing
+ */
+ public JacksonSerializer(ObjectMapper objectMapper, RevisionResolver revisionResolver,
+ ConverterFactory converterFactory, ClassLoader classLoader) {
+ this.revisionResolver = revisionResolver;
+ this.converterFactory = converterFactory;
+ this.objectMapper = objectMapper;
+ this.classLoader = classLoader == null ? getClass().getClassLoader() : classLoader;
+ this.objectMapper.registerModule(
+ new SimpleModule("Axon-Jackson Module")
+ .addSerializer(ReadableInstant.class, new ToStringSerializer())
+ .addDeserializer(DateTime.class, new JodaDeserializer<DateTime>(DateTime.class))
+ .addDeserializer(Instant.class, new JodaDeserializer<Instant>(Instant.class))
+ .addDeserializer(MutableDateTime.class,
+ new JodaDeserializer<MutableDateTime>(MutableDateTime.class))
+ .addDeserializer(YearMonth.class, new JodaDeserializer<YearMonth>(YearMonth.class))
+ .addDeserializer(MonthDay.class, new JodaDeserializer<MonthDay>(MonthDay.class))
+ .addDeserializer(LocalDate.class, new JodaDeserializer<LocalDate>(LocalDate.class))
+ .addDeserializer(LocalTime.class, new JodaDeserializer<LocalTime>(LocalTime.class))
+ .addDeserializer(LocalDateTime.class, new JodaDeserializer<LocalDateTime>(LocalDateTime.class))
+ );
+ if (converterFactory instanceof ChainingConverterFactory) {
+ registerConverters((ChainingConverterFactory) converterFactory);
+ }
+ }
+
+ /**
+ * Registers converters with the given <code>converterFactory</code> which depend on the actual contents of the
+ * serialized for to represent a JSON format.
+ *
+ * @param converterFactory The ChainingConverterFactory instance to register the converters with.
+ */
+ protected void registerConverters(ChainingConverterFactory converterFactory) {
+ converterFactory.registerConverter(new JsonNodeToByteArrayConverter(objectMapper));
+ converterFactory.registerConverter(new ByteArrayToJsonNodeConverter(objectMapper));
+ }
+
+ @Override
+ public <T> SerializedObject<T> serialize(Object object, Class<T> expectedRepresentation) {
+
+ try {
+ if (String.class.equals(expectedRepresentation)) {
+ //noinspection unchecked
+ return new SimpleSerializedObject<T>((T) getWriter().writeValueAsString(object),
+ expectedRepresentation, typeForClass(object.getClass()));
+ }
+
+ byte[] serializedBytes = getWriter().writeValueAsBytes(object);
+ T serializedContent = converterFactory.getConverter(byte[].class, expectedRepresentation)
+ .convert(serializedBytes);
+ return new SimpleSerializedObject<T>(serializedContent, expectedRepresentation,
+ typeForClass(object.getClass()));
+ } catch (JsonProcessingException e) {
+ throw new SerializationException("Unable to serialize object", e);
+ }
+ }
+
+ /**
+ * Returns the ObjectMapper used by this serializer, allowing for configuration of the serialization settings.
+ *
+ * @return the ObjectMapper instance used by his serializer
+ */
+ public final ObjectMapper getObjectMapper() {
+ return objectMapper;
+ }
+
+ /**
+ * Provides the ObjectWriter, with which objects are serialized to JSON form. This method may be overridden to
+ * change the configuration of the writer to use.
+ *
+ * @return The writer to serialize objects with
+ */
+ protected ObjectWriter getWriter() {
+ return objectMapper.writer();
+ }
+
+ /**
+ * Provides the ObjectReader, with which objects are read from the JSON form. This method may be overridden to
+ * change the configuration of the reader to use.
+ *
+ * @param type The type of object to create a reader for
+ * @return The writer to serialize objects with
+ */
+ protected ObjectReader getReader(Class<?> type) {
+ return objectMapper.reader(type);
+ }
+
+ @Override
+ public <T> boolean canSerializeTo(Class<T> expectedRepresentation) {
+ return JsonNode.class.equals(expectedRepresentation)
+ || String.class.equals(expectedRepresentation)
+ || converterFactory.hasConverter(byte[].class, expectedRepresentation);
+ }
+
+ @Override
+ public <S, T> T deserialize(SerializedObject<S> serializedObject) {
+ try {
+ if (JsonNode.class.equals(serializedObject.getContentType())) {
+ return getReader(classForType(serializedObject.getType()))
+ .readValue((JsonNode) serializedObject.getData());
+ }
+ SerializedObject<byte[]> byteSerialized = converterFactory.getConverter(serializedObject.getContentType(),
+ byte[].class)
+ .convert(serializedObject);
+ return getReader(classForType(serializedObject.getType())).readValue(byteSerialized.getData());
+ } catch (IOException e) {
+ throw new SerializationException("Error while deserializing object", e);
+ }
+ }
+
+ @Override
+ public Class classForType(SerializedType type) throws UnknownSerializedTypeException {
+ try {
+ return classLoader.loadClass(resolveClassName(type));
+ } catch (ClassNotFoundException e) {
+ throw new UnknownSerializedTypeException(type, e);
+ }
+ }
+
+ /**
+ * Resolve the class name from the given <code>serializedType</code>. This method may be overridden to customize
+ * the names used to denote certain classes, for example, by leaving out a certain base package for brevity.
+ *
+ * @param serializedType The serialized type to resolve the class name for
+ * @return The fully qualified name of the class to load
+ */
+ protected String resolveClassName(SerializedType serializedType) {
+ return serializedType.getName();
+ }
+
+ @Override
+ public SerializedType typeForClass(Class type) {
+ return new SimpleSerializedType(type.getName(), revisionResolver.revisionOf(type));
+ }
+
+ @Override
+ public ConverterFactory getConverterFactory() {
+ return converterFactory;
+ }
+}
View
63 core/src/main/java/org/axonframework/serializer/json/JodaDeserializer.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010-2014. Axon Framework
+ *
+ * Licensed 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.axonframework.serializer.json;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import org.axonframework.common.AxonConfigurationException;
+import org.axonframework.serializer.SerializationException;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+
+/**
+ * Jackson Serializer used to serialize and deserialize Joda DateTime classes. These classes use the convention that
+ * the toString() method returns an ISO8601 formatted string, while a constructor accepting an Object will allow
+ * one to reconstruct the instant from this String.
+ *
+ * @param <T> The type of Joda object to serialize
+ * @author Allard Buijze
+ * @since 2.2
+ */
+public class JodaDeserializer<T> extends JsonDeserializer<T> {
+
+ private final Constructor<T> constructor;
+
+ /**
+ * @param instantType The type of object to serialize into
+ * @throws org.axonframework.common.AxonConfigurationException if the given <code>instantType</code> is
+ * incompatible with this serializer
+ */
+ public JodaDeserializer(Class<T> instantType) {
+ try {
+ this.constructor = instantType.getConstructor(Object.class);
+ } catch (NoSuchMethodException e) {
+ throw new AxonConfigurationException(
+ "The type " + instantType.getName() + " isn't compatible with the JodaDeserializer", e);
+ }
+ }
+
+ @Override
+ public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
+ try {
+ return constructor.newInstance(jp.readValueAs(String.class));
+ } catch (Exception e) {
+ throw new SerializationException("Unable to read instant from JSON document", e);
+ }
+ }
+}
View
64 core/src/main/java/org/axonframework/serializer/json/JsonNodeToByteArrayConverter.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010-2014. Axon Framework
+ *
+ * Licensed 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.axonframework.serializer.json;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.axonframework.serializer.AbstractContentTypeConverter;
+import org.axonframework.serializer.CannotConvertBetweenTypesException;
+
+/**
+ * ContentTypeConverter implementation that converts a JsonNode object into a byte[]. The byte[] will contain the UTF8
+ * encoded JSON string.
+ *
+ * @author Allard Buijze
+ * @since 2.2
+ */
+public class JsonNodeToByteArrayConverter extends AbstractContentTypeConverter<JsonNode, byte[]> {
+
+ private final ObjectMapper objectMapper;
+
+ /**
+ * Initialize the converter, using given <code>objectMapper</code> to convert the JSonNode into bytes. Typically,
+ * this would be the objectMapper used by the Serializer that serializes objects into JsonNode.
+ *
+ * @param objectMapper The objectMapper to serialize the JsonNode with.
+ */
+ public JsonNodeToByteArrayConverter(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public Class<JsonNode> expectedSourceType() {
+ return JsonNode.class;
+ }
+
+ @Override
+ public Class<byte[]> targetType() {
+ return byte[].class;
+ }
+
+ @Override
+ public byte[] convert(JsonNode original) {
+ try {
+ return objectMapper.writeValueAsBytes(original);
+ } catch (JsonProcessingException e) {
+ throw new CannotConvertBetweenTypesException("An error occurred while converting a JsonNode to byte[]", e);
+ }
+ }
+}
View
46 core/src/test/java/org/axonframework/serializer/json/ByteArrayToJsonNodeConverterTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010-2014. Axon Framework
+ *
+ * Licensed 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.axonframework.serializer.json;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.axonframework.common.io.IOUtils;
+import org.junit.*;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Allard Buijze
+ */
+public class ByteArrayToJsonNodeConverterTest {
+
+ private ByteArrayToJsonNodeConverter testSubject;
+ private ObjectMapper objectMapper;
+
+ @Before
+ public void setUp() throws Exception {
+ objectMapper = new ObjectMapper();
+ testSubject = new ByteArrayToJsonNodeConverter(objectMapper);
+ }
+
+ @Test
+ public void testConvertNodeToBytes() throws Exception {
+ final String content = "{\"someKey\":\"someValue\",\"someOther\":true}";
+ JsonNode expected = objectMapper.readTree(content);
+ assertEquals(expected, testSubject.convert(content.getBytes(IOUtils.UTF8)));
+ }
+}
View
181 core/src/test/java/org/axonframework/serializer/json/JacksonSerializerTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2010-2014. Axon Framework
+ *
+ * Licensed 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.axonframework.serializer.json;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.axonframework.serializer.AnnotationRevisionResolver;
+import org.axonframework.serializer.ChainingConverterFactory;
+import org.axonframework.serializer.ContentTypeConverter;
+import org.axonframework.serializer.RevisionResolver;
+import org.axonframework.serializer.SerializedObject;
+import org.joda.time.DateTime;
+import org.junit.*;
+
+import java.io.InputStream;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.*;
+
+/**
+ * @author Allard Buijze
+ */
+public class JacksonSerializerTest {
+
+ private JacksonSerializer testSubject;
+ private DateTime time;
+
+ @Before
+ public void setUp() throws Exception {
+ testSubject = new JacksonSerializer();
+ time = new DateTime();
+ }
+
+ @Test
+ public void testCanSerializeToStringByteArrayAndInputStream() {
+ assertTrue(testSubject.canSerializeTo(byte[].class));
+ assertTrue(testSubject.canSerializeTo(String.class));
+ assertTrue(testSubject.canSerializeTo(InputStream.class));
+ }
+
+ @Test
+ public void testSerializeAndDeserializeObject_StringFormat() throws Exception {
+ SimpleSerializableType toSerialize = new SimpleSerializableType("first", time,
+ new SimpleSerializableType("nested"));
+
+ SerializedObject<String> serialized = testSubject.serialize(toSerialize, String.class);
+
+ System.out.println(serialized.getData());
+ SimpleSerializableType actual = testSubject.deserialize(serialized);
+ assertEquals(toSerialize.getValue(), actual.getValue());
+ assertEquals(toSerialize.getNested().getValue(), actual.getNested().getValue());
+ }
+
+ @Test
+ public void testSerializeAndDeserializeObject_ByteArrayFormat() throws Exception {
+ SimpleSerializableType toSerialize = new SimpleSerializableType("first", time,
+ new SimpleSerializableType("nested"));
+
+ SerializedObject<byte[]> serialized = testSubject.serialize(toSerialize, byte[].class);
+
+ SimpleSerializableType actual = testSubject.deserialize(serialized);
+
+ assertEquals(toSerialize.getValue(), actual.getValue());
+ assertEquals(toSerialize.getNested().getValue(), actual.getNested().getValue());
+ }
+
+ @Test
+ public void testSerializeAndDeserializeObject_JsonNodeFormat() throws Exception {
+ SimpleSerializableType toSerialize = new SimpleSerializableType("first", time,
+ new SimpleSerializableType("nested"));
+
+ SerializedObject<JsonNode> serialized = testSubject.serialize(toSerialize, JsonNode.class);
+ SimpleSerializableType actual = testSubject.deserialize(serialized);
+
+ assertEquals(toSerialize.getValue(), actual.getValue());
+ assertEquals(toSerialize.getNested().getValue(), actual.getNested().getValue());
+ }
+
+ @Test
+ public void testCustomObjectMapperRevisionResolverAndConverterFactory() {
+ ObjectMapper objectMapper = spy(new ObjectMapper());
+ RevisionResolver revisionResolver = spy(new AnnotationRevisionResolver());
+ ChainingConverterFactory converterFactory = spy(new ChainingConverterFactory());
+
+ testSubject = new JacksonSerializer(objectMapper, revisionResolver, converterFactory);
+
+ SerializedObject<byte[]> serialized = testSubject.serialize(new SimpleSerializableType("test"),
+ byte[].class);
+ SimpleSerializableType actual = testSubject.deserialize(serialized);
+
+ assertNotNull(actual);
+ verify(objectMapper).reader(SimpleSerializableType.class);
+ verify(objectMapper).writer();
+ verify(revisionResolver).revisionOf(SimpleSerializableType.class);
+ verify(converterFactory, times(2)).registerConverter(isA(ContentTypeConverter.class));
+ assertSame(objectMapper, testSubject.getObjectMapper());
+ }
+
+ @Test
+ public void testCustomObjectMapperAndRevisionResolver() {
+ ObjectMapper objectMapper = spy(new ObjectMapper());
+ RevisionResolver revisionResolver = spy(new AnnotationRevisionResolver());
+
+ testSubject = new JacksonSerializer(objectMapper, revisionResolver);
+
+ SerializedObject<byte[]> serialized = testSubject.serialize(new SimpleSerializableType("test"),
+ byte[].class);
+ SimpleSerializableType actual = testSubject.deserialize(serialized);
+
+ assertNotNull(actual);
+ assertTrue(testSubject.getConverterFactory() instanceof ChainingConverterFactory);
+ verify(objectMapper).reader(SimpleSerializableType.class);
+ verify(objectMapper).writer();
+ verify(revisionResolver).revisionOf(SimpleSerializableType.class);
+ }
+
+ @Test
+ public void testCustomObjectMapper() {
+ ObjectMapper objectMapper = spy(new ObjectMapper());
+
+ testSubject = new JacksonSerializer(objectMapper);
+
+ SerializedObject<byte[]> serialized = testSubject.serialize(new SimpleSerializableType("test"),
+ byte[].class);
+ SimpleSerializableType actual = testSubject.deserialize(serialized);
+
+ assertNotNull(actual);
+ assertTrue(testSubject.getConverterFactory() instanceof ChainingConverterFactory);
+ verify(objectMapper).reader(SimpleSerializableType.class);
+ verify(objectMapper).writer();
+ }
+
+ public static class SimpleSerializableType {
+
+ private final String value;
+ private final DateTime time;
+ private final SimpleSerializableType nested;
+
+ public SimpleSerializableType(String value) {
+ this(value, new DateTime(), null);
+ }
+
+ @JsonCreator
+ public SimpleSerializableType(@JsonProperty("value") String value,
+ @JsonProperty("time") DateTime time,
+ @JsonProperty("nested") SimpleSerializableType nested) {
+ this.value = value;
+ this.time = time;
+ this.nested = nested;
+ }
+
+ public SimpleSerializableType getNested() {
+ return nested;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public DateTime getTime() {
+ return time;
+ }
+ }
+}
View
46 core/src/test/java/org/axonframework/serializer/json/JsonNodeToByteArrayConverterTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010-2014. Axon Framework
+ *
+ * Licensed 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.axonframework.serializer.json;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.axonframework.common.io.IOUtils;
+import org.junit.*;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Allard Buijze
+ */
+public class JsonNodeToByteArrayConverterTest {
+
+ private JsonNodeToByteArrayConverter testSubject;
+ private ObjectMapper objectMapper;
+
+ @Before
+ public void setUp() throws Exception {
+ objectMapper = new ObjectMapper();
+ testSubject = new JsonNodeToByteArrayConverter(objectMapper);
+ }
+
+ @Test
+ public void testConvertNodeToBytes() throws Exception {
+ final String content = "{\"someKey\":\"someValue\",\"someOther\":true}";
+ JsonNode node = objectMapper.readTree(content);
+ assertArrayEquals(content.getBytes(IOUtils.UTF8), testSubject.convert(node));
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.