Skip to content

Commit 675a68c

Browse files
artembilangaryrussell
authored andcommitted
GH-2140: Improve generics for DelegatingByTypeSer
Fixes #2140 Improve some internal code around generics in the `DelegatingByTypeSerializer`. This allows us to use a dedicated external `Map` variable for the delegates
1 parent 24d7cad commit 675a68c

File tree

2 files changed

+45
-48
lines changed

2 files changed

+45
-48
lines changed
Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021 the original author or authors.
2+
* Copyright 2021-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.kafka.support.serializer;
1818

19-
import java.util.Iterator;
2019
import java.util.LinkedHashMap;
2120
import java.util.Map;
2221
import java.util.Map.Entry;
@@ -32,24 +31,22 @@
3231
* Delegates to a serializer based on type.
3332
*
3433
* @author Gary Russell
34+
* @author Artem Bilan
35+
*
3536
* @since 2.7.9
3637
*
3738
*/
3839
public class DelegatingByTypeSerializer implements Serializer<Object> {
3940

40-
private static final String RAWTYPES = "rawtypes";
41-
42-
@SuppressWarnings(RAWTYPES)
43-
private final Map<Class<?>, Serializer> delegates = new LinkedHashMap<>();
41+
private final Map<Class<?>, Serializer<?>> delegates = new LinkedHashMap<>();
4442

4543
private final boolean assignable;
4644

4745
/**
4846
* Construct an instance with the map of delegates; keys matched exactly.
4947
* @param delegates the delegates.
5048
*/
51-
@SuppressWarnings(RAWTYPES)
52-
public DelegatingByTypeSerializer(Map<Class<?>, Serializer> delegates) {
49+
public DelegatingByTypeSerializer(Map<Class<?>, Serializer<?>> delegates) {
5350
this(delegates, false);
5451
}
5552

@@ -62,8 +59,7 @@ public DelegatingByTypeSerializer(Map<Class<?>, Serializer> delegates) {
6259
* @param assignable whether the target is assignable to the key.
6360
* @since 2.8.3
6461
*/
65-
@SuppressWarnings(RAWTYPES)
66-
public DelegatingByTypeSerializer(Map<Class<?>, Serializer> delegates, boolean assignable) {
62+
public DelegatingByTypeSerializer(Map<Class<?>, Serializer<?>> delegates, boolean assignable) {
6763
Assert.notNull(delegates, "'delegates' cannot be null");
6864
Assert.noNullElements(delegates.values(), "Serializers in delegates map cannot be null");
6965
this.delegates.putAll(delegates);
@@ -73,67 +69,62 @@ public DelegatingByTypeSerializer(Map<Class<?>, Serializer> delegates, boolean a
7369
/**
7470
* Returns true if {@link #findDelegate(Object, Map)} should consider assignability to
7571
* the key rather than an exact match.
76-
* @return true if assigable.
72+
* @return true if assignable.
7773
* @since 2.8.3
7874
*/
7975
protected boolean isAssignable() {
8076
return this.assignable;
8177
}
8278

83-
@SuppressWarnings("unchecked")
8479
@Override
8580
public void configure(Map<String, ?> configs, boolean isKey) {
8681
this.delegates.values().forEach(del -> del.configure(configs, isKey));
8782
}
8883

89-
@SuppressWarnings({ RAWTYPES, "unchecked" })
9084
@Override
9185
public byte[] serialize(String topic, Object data) {
92-
Serializer delegate = findDelegate(data, this.delegates);
86+
Serializer<Object> delegate = findDelegate(data, this.delegates);
9387
return delegate.serialize(topic, data);
9488
}
9589

96-
@SuppressWarnings({ "unchecked", RAWTYPES })
9790
@Override
9891
public byte[] serialize(String topic, Headers headers, Object data) {
99-
Serializer delegate = findDelegate(data, this.delegates);
92+
Serializer<Object> delegate = findDelegate(data, this.delegates);
10093
return delegate.serialize(topic, headers, data);
10194
}
10295

10396
/**
10497
* Determine the serializer for the data type.
10598
* @param data the data.
10699
* @param delegates the available delegates.
107-
* @return the delgate.
100+
* @param <T> the data type
101+
* @return the delegate.
108102
* @throws SerializationException when there is no match.
109103
* @since 2.8.3
110104
*/
111-
@SuppressWarnings(RAWTYPES)
112-
protected Serializer findDelegate(Object data, Map<Class<?>, Serializer> delegates) {
105+
@SuppressWarnings("unchecked")
106+
protected <T> Serializer<T> findDelegate(T data, Map<Class<?>, Serializer<?>> delegates) {
113107
if (!this.assignable) {
114-
Serializer delegate = delegates.get(data.getClass());
108+
Serializer<?> delegate = delegates.get(data.getClass());
115109
if (delegate == null) {
116110
throw new SerializationException("No matching delegate for type: " + data.getClass().getName()
117111
+ "; supported types: " + this.delegates.keySet().stream()
118-
.map(clazz -> clazz.getName())
119-
.collect(Collectors.toList()));
112+
.map(Class::getName)
113+
.collect(Collectors.toList()));
120114
}
121-
return delegate;
115+
return (Serializer<T>) delegate;
122116
}
123117
else {
124-
Iterator<Entry<Class<?>, Serializer>> iterator = this.delegates.entrySet().iterator();
125-
while (iterator.hasNext()) {
126-
Entry<Class<?>, Serializer> entry = iterator.next();
118+
for (Entry<Class<?>, Serializer<?>> entry : this.delegates.entrySet()) {
127119
if (entry.getKey().isAssignableFrom(data.getClass())) {
128-
return entry.getValue();
120+
return (Serializer<T>) entry.getValue();
129121
}
130122
}
131123
throw new SerializationException("No matching delegate for type: " + data.getClass().getName()
132124
+ "; supported types: " + this.delegates.keySet().stream()
133-
.map(clazz -> clazz.getName())
134-
.collect(Collectors.toList()));
125+
.map(Class::getName)
126+
.collect(Collectors.toList()));
135127
}
136128
}
137129

138-
139130
}

spring-kafka/src/test/java/org/springframework/kafka/support/serializer/DelegatingSerializationTests.java

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2021 the original author or authors.
2+
* Copyright 2019-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
3535
import org.apache.kafka.common.serialization.BytesSerializer;
3636
import org.apache.kafka.common.serialization.IntegerDeserializer;
3737
import org.apache.kafka.common.serialization.IntegerSerializer;
38+
import org.apache.kafka.common.serialization.Serializer;
3839
import org.apache.kafka.common.serialization.StringDeserializer;
3940
import org.apache.kafka.common.serialization.StringSerializer;
4041
import org.apache.kafka.common.utils.Bytes;
@@ -45,6 +46,8 @@
4546

4647
/**
4748
* @author Gary Russell
49+
* @author Artem Bilan
50+
*
4851
* @since 2.3
4952
*
5053
*/
@@ -121,16 +124,16 @@ void testWithPropertyConfigKeys() {
121124
private void doTest(DelegatingSerializer serializer, DelegatingDeserializer deserializer) {
122125
Headers headers = new RecordHeaders();
123126
headers.add(new RecordHeader(DelegatingSerializer.VALUE_SERIALIZATION_SELECTOR, "bytes".getBytes()));
124-
byte[] bytes = new byte[] { 1, 2, 3, 4 };
127+
byte[] bytes = new byte[]{ 1, 2, 3, 4 };
125128
byte[] serialized = serializer.serialize("foo", headers, new Bytes(bytes));
126129
assertThat(serialized).isSameAs(bytes);
127130
headers.add(new RecordHeader(DelegatingSerializer.VALUE_SERIALIZATION_SELECTOR, "int".getBytes()));
128131
serialized = serializer.serialize("foo", headers, 42);
129-
assertThat(serialized).isEqualTo(new byte[] { 0, 0, 0, 42 });
132+
assertThat(serialized).isEqualTo(new byte[]{ 0, 0, 0, 42 });
130133
assertThat(deserializer.deserialize("foo", headers, serialized)).isEqualTo(42);
131134
headers.add(new RecordHeader(DelegatingSerializer.VALUE_SERIALIZATION_SELECTOR, "string".getBytes()));
132135
serialized = serializer.serialize("foo", headers, "bar");
133-
assertThat(serialized).isEqualTo(new byte[] { 'b', 'a', 'r' });
136+
assertThat(serialized).isEqualTo(new byte[]{ 'b', 'a', 'r' });
134137
assertThat(deserializer.deserialize("foo", headers, serialized)).isEqualTo("bar");
135138

136139
// implicit Serdes
@@ -151,25 +154,25 @@ private void doTest(DelegatingSerializer serializer, DelegatingDeserializer dese
151154
Collections.singletonMap(DelegatingSerializer.VALUE_SERIALIZATION_SELECTOR, "string"));
152155
new DefaultKafkaHeaderMapper().fromHeaders(messageHeaders, headers);
153156
assertThat(headers.lastHeader(DelegatingSerializer.VALUE_SERIALIZATION_SELECTOR).value())
154-
.isEqualTo(new byte[] { 's', 't', 'r', 'i', 'n', 'g' });
157+
.isEqualTo(new byte[]{ 's', 't', 'r', 'i', 'n', 'g' });
155158
serialized = serializer.serialize("foo", headers, "bar");
156-
assertThat(serialized).isEqualTo(new byte[] { 'b', 'a', 'r' });
159+
assertThat(serialized).isEqualTo(new byte[]{ 'b', 'a', 'r' });
157160
assertThat(deserializer.deserialize("foo", headers, serialized)).isEqualTo("bar");
158161
}
159162

160163
private void doTestKeys(DelegatingSerializer serializer, DelegatingDeserializer deserializer) {
161164
Headers headers = new RecordHeaders();
162165
headers.add(new RecordHeader(DelegatingSerializer.KEY_SERIALIZATION_SELECTOR, "bytes".getBytes()));
163-
byte[] bytes = new byte[] { 1, 2, 3, 4 };
166+
byte[] bytes = new byte[]{ 1, 2, 3, 4 };
164167
byte[] serialized = serializer.serialize("foo", headers, new Bytes(bytes));
165168
assertThat(serialized).isSameAs(bytes);
166169
headers.add(new RecordHeader(DelegatingSerializer.KEY_SERIALIZATION_SELECTOR, "int".getBytes()));
167170
serialized = serializer.serialize("foo", headers, 42);
168-
assertThat(serialized).isEqualTo(new byte[] { 0, 0, 0, 42 });
171+
assertThat(serialized).isEqualTo(new byte[]{ 0, 0, 0, 42 });
169172
assertThat(deserializer.deserialize("foo", headers, serialized)).isEqualTo(42);
170173
headers.add(new RecordHeader(DelegatingSerializer.KEY_SERIALIZATION_SELECTOR, "string".getBytes()));
171174
serialized = serializer.serialize("foo", headers, "bar");
172-
assertThat(serialized).isEqualTo(new byte[] { 'b', 'a', 'r' });
175+
assertThat(serialized).isEqualTo(new byte[]{ 'b', 'a', 'r' });
173176
assertThat(deserializer.deserialize("foo", headers, serialized)).isEqualTo("bar");
174177

175178
// implicit Serdes
@@ -190,9 +193,9 @@ private void doTestKeys(DelegatingSerializer serializer, DelegatingDeserializer
190193
Collections.singletonMap(DelegatingSerializer.KEY_SERIALIZATION_SELECTOR, "string"));
191194
new DefaultKafkaHeaderMapper().fromHeaders(messageHeaders, headers);
192195
assertThat(headers.lastHeader(DelegatingSerializer.KEY_SERIALIZATION_SELECTOR).value())
193-
.isEqualTo(new byte[] { 's', 't', 'r', 'i', 'n', 'g' });
196+
.isEqualTo(new byte[]{ 's', 't', 'r', 'i', 'n', 'g' });
194197
serialized = serializer.serialize("foo", headers, "bar");
195-
assertThat(serialized).isEqualTo(new byte[] { 'b', 'a', 'r' });
198+
assertThat(serialized).isEqualTo(new byte[]{ 'b', 'a', 'r' });
196199
assertThat(deserializer.deserialize("foo", headers, serialized)).isEqualTo("bar");
197200
}
198201

@@ -218,21 +221,24 @@ void byTypeBadType() {
218221
assertThatExceptionOfType(SerializationException.class).isThrownBy(
219222
() -> serializer.serialize("foo", new Bytes(foo)))
220223
.withMessageMatching("No matching delegate for type: " + Bytes.class.getName()
221-
+ "; supported types: \\[(java.lang.String, \\[B|\\[B, java.lang.String)\\]");
224+
+ "; supported types: \\[(java.lang.String, \\[B|\\[B, java.lang.String)]");
222225
}
223226

224227
@Test
225228
void assignable() {
226-
DelegatingByTypeSerializer serializer = new DelegatingByTypeSerializer(Map.of(Number.class,
227-
new IntegerSerializer(), byte[].class, new ByteArraySerializer()), true);
229+
var delegates = new HashMap<Class<?>, Serializer<?>>();
230+
delegates.put(Number.class, new IntegerSerializer());
231+
delegates.put(byte[].class, new ByteArraySerializer());
232+
DelegatingByTypeSerializer serializer = new DelegatingByTypeSerializer(delegates, true);
233+
228234
Integer i = 42;
229-
assertThat(serializer.serialize("foo", i)).isEqualTo(new byte[] {0, 0, 0, 42});
235+
assertThat(serializer.serialize("foo", i)).isEqualTo(new byte[]{ 0, 0, 0, 42 });
230236
byte[] foo = "foo".getBytes();
231237
assertThat(serializer.serialize("foo", foo)).isSameAs(foo);
232238
assertThatExceptionOfType(SerializationException.class).isThrownBy(
233-
() -> serializer.serialize("foo", new Bytes(foo)))
234-
.withMessageMatching("No matching delegate for type: " + Bytes.class.getName()
235-
+ "; supported types: \\[(java.lang.Number, \\[B|\\[B, java.lang.Number)\\]");
239+
() -> serializer.serialize("foo", new Bytes(foo)))
240+
.withMessageMatching("No matching delegate for type: " + Bytes.class.getName()
241+
+ "; supported types: \\[(java.lang.Number, \\[B|\\[B, java.lang.Number)]");
236242
}
237243

238244
}

0 commit comments

Comments
 (0)