Skip to content

Commit 3ebb6cb

Browse files
committed
Fix getCustomMappings API for resolvers
This fixes the DefaultTopicResolver.getCustomTopicMappings and DefaultSchemaResolver.getCustomSchemaMappings APIs to actually return the mappings and also use ClassUtils.forName instead of Class.forName to safely load the class from string key.
1 parent a91dd81 commit 3ebb6cb

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultSchemaResolver.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
import java.util.HashMap;
2828
import java.util.LinkedHashMap;
2929
import java.util.Map;
30+
import java.util.Map.Entry;
3031
import java.util.Objects;
3132
import java.util.Optional;
33+
import java.util.stream.Collectors;
3234

3335
import org.apache.pulsar.client.api.Schema;
3436
import org.apache.pulsar.client.impl.schema.AvroSchema;
@@ -38,11 +40,13 @@
3840
import org.apache.pulsar.common.schema.KeyValueEncodingType;
3941
import org.apache.pulsar.common.schema.SchemaType;
4042

43+
import org.springframework.beans.factory.BeanClassLoaderAware;
4144
import org.springframework.core.ResolvableType;
4245
import org.springframework.core.log.LogAccessor;
4346
import org.springframework.lang.Nullable;
4447
import org.springframework.pulsar.annotation.PulsarMessage;
4548
import org.springframework.util.Assert;
49+
import org.springframework.util.ClassUtils;
4650

4751
import com.fasterxml.jackson.databind.ObjectMapper;
4852

@@ -58,7 +62,7 @@
5862
* @author Chris Bono
5963
* @author Aleksei Arsenev
6064
*/
61-
public class DefaultSchemaResolver implements SchemaResolver {
65+
public class DefaultSchemaResolver implements SchemaResolver, BeanClassLoaderAware {
6266

6367
private final LogAccessor logger = new LogAccessor(this.getClass());
6468

@@ -100,6 +104,9 @@ public class DefaultSchemaResolver implements SchemaResolver {
100104

101105
private ObjectMapper objectMapper;
102106

107+
@Nullable
108+
private ClassLoader classLoader;
109+
103110
public void setObjectMapper(ObjectMapper objectMapper) {
104111
this.objectMapper = objectMapper;
105112
}
@@ -143,11 +150,9 @@ public Schema<?> removeCustomMapping(Class<?> messageType) {
143150
*/
144151
@Deprecated(since = "1.2.5", forRemoval = true)
145152
public Map<Class<?>, Schema<?>> getCustomSchemaMappings() {
146-
Map<Class<?>, Schema<?>> copyOfMappings = new HashMap<>();
147-
this.customSchemaMappings.entrySet()
153+
return this.customSchemaMappings.entrySet()
148154
.stream()
149-
.map((e) -> copyOfMappings.put(this.fromMessageTypeMapKey(e.getKey()), e.getValue()));
150-
return copyOfMappings;
155+
.collect(Collectors.toMap((e) -> this.fromMessageTypeMapKey(e.getKey()), Entry::getValue));
151156
}
152157

153158
/**
@@ -306,7 +311,7 @@ private <X> Schema<X> castToType(Schema<?> rawSchema) {
306311

307312
private Class<?> fromMessageTypeMapKey(String messageTypeKey) {
308313
try {
309-
return Class.forName(messageTypeKey);
314+
return ClassUtils.forName(messageTypeKey, this.classLoader);
310315
}
311316
catch (ClassNotFoundException e) {
312317
throw new RuntimeException(e);
@@ -317,4 +322,9 @@ private String toMessageTypeMapKey(Class<?> messageType) {
317322
return messageType.getName();
318323
}
319324

325+
@Override
326+
public void setBeanClassLoader(ClassLoader classLoader) {
327+
this.classLoader = classLoader;
328+
}
329+
320330
}

spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultTopicResolver.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,22 @@
1616

1717
package org.springframework.pulsar.core;
1818

19-
import java.util.HashMap;
2019
import java.util.LinkedHashMap;
2120
import java.util.Map;
21+
import java.util.Map.Entry;
2222
import java.util.Optional;
2323
import java.util.function.Supplier;
24+
import java.util.stream.Collectors;
2425

2526
import org.springframework.beans.BeansException;
27+
import org.springframework.beans.factory.BeanClassLoaderAware;
2628
import org.springframework.beans.factory.BeanFactory;
2729
import org.springframework.beans.factory.BeanFactoryAware;
2830
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
2931
import org.springframework.core.log.LogAccessor;
3032
import org.springframework.lang.Nullable;
3133
import org.springframework.pulsar.annotation.PulsarMessage;
34+
import org.springframework.util.ClassUtils;
3235
import org.springframework.util.StringUtils;
3336

3437
/**
@@ -42,7 +45,7 @@
4245
* @author Aleksei Arsenev
4346
* @author Jonas Geiregat
4447
*/
45-
public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware {
48+
public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware, BeanClassLoaderAware {
4649

4750
private final LogAccessor logger = new LogAccessor(this.getClass());
4851

@@ -55,6 +58,9 @@ public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware {
5558
@Nullable
5659
private ExpressionResolver expressionResolver;
5760

61+
@Nullable
62+
private ClassLoader classLoader;
63+
5864
/**
5965
* Constructs a new DefaultTopicResolver with the given expression resolver.
6066
* @param expressionResolver the expression resolver to use for resolving topic
@@ -109,11 +115,9 @@ public String removeCustomMapping(Class<?> messageType) {
109115
*/
110116
@Deprecated(since = "1.2.5", forRemoval = true)
111117
public Map<Class<?>, String> getCustomTopicMappings() {
112-
Map<Class<?>, String> copyOfMappings = new HashMap<>();
113-
this.customTopicMappings.entrySet()
118+
return this.customTopicMappings.entrySet()
114119
.stream()
115-
.map((e) -> copyOfMappings.put(this.fromMessageTypeMapKey(e.getKey()), e.getValue()));
116-
return copyOfMappings;
120+
.collect(Collectors.toMap((e) -> this.fromMessageTypeMapKey(e.getKey()), Entry::getValue));
117121
}
118122

119123
/**
@@ -193,7 +197,7 @@ private String resolveExpression(String v) {
193197

194198
private Class<?> fromMessageTypeMapKey(String messageTypeKey) {
195199
try {
196-
return Class.forName(messageTypeKey);
200+
return ClassUtils.forName(messageTypeKey, this.classLoader);
197201
}
198202
catch (ClassNotFoundException e) {
199203
throw new RuntimeException(e);
@@ -217,4 +221,9 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
217221
}
218222
}
219223

224+
@Override
225+
public void setBeanClassLoader(ClassLoader classLoader) {
226+
this.classLoader = classLoader;
227+
}
228+
220229
}

spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultSchemaResolverTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.pulsar.core;
1818

19+
import static java.util.Map.entry;
1920
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
2021
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
2122
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@@ -106,6 +107,15 @@ void removeMappings() {
106107
assertThat(resolver.getCustomSchemaMappings()).asInstanceOf(InstanceOfAssertFactories.MAP).isEmpty();
107108
}
108109

110+
@SuppressWarnings("removal")
111+
@Test
112+
void getCustomMappingsReturnsMapping() {
113+
assertThat(resolver.getCustomSchemaMappings()).asInstanceOf(InstanceOfAssertFactories.MAP).isEmpty();
114+
resolver.addCustomSchemaMapping(Foo.class, Schema.STRING);
115+
assertThat(resolver.getCustomSchemaMappings()).asInstanceOf(InstanceOfAssertFactories.MAP)
116+
.containsExactly(entry(Foo.class, Schema.STRING));
117+
}
118+
109119
}
110120

111121
@Nested

spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultTopicResolverTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.pulsar.core;
1818

19+
import static java.util.Map.entry;
1920
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
2021
import static org.junit.jupiter.params.provider.Arguments.arguments;
2122
import static org.mockito.Mockito.spy;
@@ -272,6 +273,15 @@ void removeMappings() {
272273
assertThat(resolver.getCustomTopicMappings()).asInstanceOf(InstanceOfAssertFactories.MAP).isEmpty();
273274
}
274275

276+
@SuppressWarnings("removal")
277+
@Test
278+
void getCustomMappingsReturnsMapping() {
279+
assertThat(resolver.getCustomTopicMappings()).asInstanceOf(InstanceOfAssertFactories.MAP).isEmpty();
280+
resolver.addCustomTopicMapping(Foo.class, "fooTopic");
281+
assertThat(resolver.getCustomTopicMappings()).asInstanceOf(InstanceOfAssertFactories.MAP)
282+
.containsExactly(entry(Foo.class, "fooTopic"));
283+
}
284+
275285
}
276286

277287
record Foo(String value) {

0 commit comments

Comments
 (0)