diff --git a/spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultSchemaResolver.java b/spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultSchemaResolver.java index 3ccc5a91..980cf69e 100644 --- a/spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultSchemaResolver.java +++ b/spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultSchemaResolver.java @@ -27,8 +27,10 @@ import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import org.apache.pulsar.client.api.Schema; import org.apache.pulsar.client.impl.schema.AvroSchema; @@ -38,11 +40,13 @@ import org.apache.pulsar.common.schema.KeyValue; import org.apache.pulsar.common.schema.KeyValueEncodingType; import org.apache.pulsar.common.schema.SchemaType; +import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.core.ResolvableType; import org.springframework.core.log.LogAccessor; import org.springframework.lang.Nullable; import org.springframework.pulsar.annotation.PulsarMessage; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import com.fasterxml.jackson.databind.ObjectMapper; @@ -58,7 +62,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Chris Bono * @author Aleksei Arsenev */ -public class DefaultSchemaResolver implements SchemaResolver { +public class DefaultSchemaResolver implements SchemaResolver, BeanClassLoaderAware { private final LogAccessor logger = new LogAccessor(this.getClass()); @@ -100,6 +104,9 @@ public class DefaultSchemaResolver implements SchemaResolver { private ObjectMapper objectMapper; + @Nullable + private ClassLoader classLoader; + public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @@ -143,11 +150,9 @@ public class DefaultSchemaResolver implements SchemaResolver { */ @Deprecated(since = "1.2.5", forRemoval = true) public Map, Schema> getCustomSchemaMappings() { - Map, Schema> copyOfMappings = new HashMap<>(); - this.customSchemaMappings.entrySet() + return this.customSchemaMappings.entrySet() .stream() - .map((e) -> copyOfMappings.put(this.fromMessageTypeMapKey(e.getKey()), e.getValue())); - return copyOfMappings; + .collect(Collectors.toMap((e) -> this.fromMessageTypeMapKey(e.getKey()), Entry::getValue)); } /** @@ -306,7 +311,7 @@ public class DefaultSchemaResolver implements SchemaResolver { private Class fromMessageTypeMapKey(String messageTypeKey) { try { - return Class.forName(messageTypeKey); + return ClassUtils.forName(messageTypeKey, this.classLoader); } catch (ClassNotFoundException e) { throw new RuntimeException(e); @@ -317,4 +322,9 @@ public class DefaultSchemaResolver implements SchemaResolver { return messageType.getName(); } + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + } diff --git a/spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultTopicResolver.java b/spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultTopicResolver.java index 3c7b35b2..db755cb1 100644 --- a/spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultTopicResolver.java +++ b/spring-pulsar/src/main/java/org/springframework/pulsar/core/DefaultTopicResolver.java @@ -16,19 +16,22 @@ package org.springframework.pulsar.core; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.function.Supplier; +import java.util.stream.Collectors; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.log.LogAccessor; import org.springframework.lang.Nullable; import org.springframework.pulsar.annotation.PulsarMessage; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** @@ -42,7 +45,7 @@ import org.springframework.util.StringUtils; * @author Aleksei Arsenev * @author Jonas Geiregat */ -public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware { +public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware, BeanClassLoaderAware { private final LogAccessor logger = new LogAccessor(this.getClass()); @@ -55,6 +58,9 @@ public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware { @Nullable private ExpressionResolver expressionResolver; + @Nullable + private ClassLoader classLoader; + /** * Constructs a new DefaultTopicResolver with the given expression resolver. * @param expressionResolver the expression resolver to use for resolving topic @@ -109,11 +115,9 @@ public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware { */ @Deprecated(since = "1.2.5", forRemoval = true) public Map, String> getCustomTopicMappings() { - Map, String> copyOfMappings = new HashMap<>(); - this.customTopicMappings.entrySet() + return this.customTopicMappings.entrySet() .stream() - .map((e) -> copyOfMappings.put(this.fromMessageTypeMapKey(e.getKey()), e.getValue())); - return copyOfMappings; + .collect(Collectors.toMap((e) -> this.fromMessageTypeMapKey(e.getKey()), Entry::getValue)); } /** @@ -193,7 +197,7 @@ public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware { private Class fromMessageTypeMapKey(String messageTypeKey) { try { - return Class.forName(messageTypeKey); + return ClassUtils.forName(messageTypeKey, this.classLoader); } catch (ClassNotFoundException e) { throw new RuntimeException(e); @@ -217,4 +221,9 @@ public class DefaultTopicResolver implements TopicResolver, BeanFactoryAware { } } + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + } diff --git a/spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultSchemaResolverTests.java b/spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultSchemaResolverTests.java index 794293b5..a2674e86 100644 --- a/spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultSchemaResolverTests.java +++ b/spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultSchemaResolverTests.java @@ -16,6 +16,7 @@ package org.springframework.pulsar.core; +import static java.util.Map.entry; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -106,6 +107,15 @@ class DefaultSchemaResolverTests { assertThat(resolver.getCustomSchemaMappings()).asInstanceOf(InstanceOfAssertFactories.MAP).isEmpty(); } + @SuppressWarnings("removal") + @Test + void getCustomMappingsReturnsMapping() { + assertThat(resolver.getCustomSchemaMappings()).asInstanceOf(InstanceOfAssertFactories.MAP).isEmpty(); + resolver.addCustomSchemaMapping(Foo.class, Schema.STRING); + assertThat(resolver.getCustomSchemaMappings()).asInstanceOf(InstanceOfAssertFactories.MAP) + .containsExactly(entry(Foo.class, Schema.STRING)); + } + } @Nested diff --git a/spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultTopicResolverTests.java b/spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultTopicResolverTests.java index 704204a9..77444484 100644 --- a/spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultTopicResolverTests.java +++ b/spring-pulsar/src/test/java/org/springframework/pulsar/core/DefaultTopicResolverTests.java @@ -16,6 +16,7 @@ package org.springframework.pulsar.core; +import static java.util.Map.entry; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.mockito.Mockito.spy; @@ -272,6 +273,15 @@ class DefaultTopicResolverTests { assertThat(resolver.getCustomTopicMappings()).asInstanceOf(InstanceOfAssertFactories.MAP).isEmpty(); } + @SuppressWarnings("removal") + @Test + void getCustomMappingsReturnsMapping() { + assertThat(resolver.getCustomTopicMappings()).asInstanceOf(InstanceOfAssertFactories.MAP).isEmpty(); + resolver.addCustomTopicMapping(Foo.class, "fooTopic"); + assertThat(resolver.getCustomTopicMappings()).asInstanceOf(InstanceOfAssertFactories.MAP) + .containsExactly(entry(Foo.class, "fooTopic")); + } + } record Foo(String value) {