Update library versions (formatter only)
- Updates 'io.spring.javaformat:spring-javaformat-gradle-plugin' from '0.0.34` to `0.0.38`
- This in turn formats many files (expectd)
`
This commit is contained in:
@@ -43,7 +43,7 @@ dependencies {
|
||||
implementation 'commons-codec:commons-codec:1.15'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.4'
|
||||
implementation 'io.github.gradle-nexus:publish-plugin:1.1.0'
|
||||
implementation("io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.34")
|
||||
implementation("io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.38")
|
||||
implementation 'io.spring.nohttp:nohttp-gradle:0.0.10'
|
||||
implementation "org.apache.maven:maven-embedder:3.6.3"
|
||||
implementation "org.asciidoctor:asciidoctor-gradle-jvm:3.3.2"
|
||||
|
||||
@@ -132,8 +132,9 @@ class PulsarFunctionAdministrationIntegrationTests {
|
||||
|
||||
// Send messages to rabbit and wait for them to come through the rabbit source
|
||||
RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);
|
||||
List<String> messages = LongStream.range(0, RECEIVED_MESSAGE_LATCH.getCount()).mapToObj((i) -> "bar" + i)
|
||||
.toList();
|
||||
List<String> messages = LongStream.range(0, RECEIVED_MESSAGE_LATCH.getCount())
|
||||
.mapToObj((i) -> "bar" + i)
|
||||
.toList();
|
||||
messages.forEach(msg -> rabbitTemplate.convertAndSend(RABBIT_QUEUE, msg));
|
||||
|
||||
assertThat(RECEIVED_MESSAGE_LATCH.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
@@ -180,20 +181,23 @@ class PulsarFunctionAdministrationIntegrationTests {
|
||||
private void assertSourceExistsWithStatus(String name, boolean isRunning, PulsarAdmin admin)
|
||||
throws PulsarAdminException {
|
||||
assertThat(admin.sources().getSourceStatus("public", "default", name)).isNotNull()
|
||||
.extracting(SourceStatus::getNumRunning).isEqualTo(isRunning ? 1 : 0);
|
||||
.extracting(SourceStatus::getNumRunning)
|
||||
.isEqualTo(isRunning ? 1 : 0);
|
||||
}
|
||||
|
||||
private void assertSourceDoesNotExist(String name, PulsarAdmin admin) {
|
||||
assertThatThrownBy(() -> admin.sources().getSourceStatus("public", "default", name))
|
||||
.isInstanceOf(NotFoundException.class);
|
||||
.isInstanceOf(NotFoundException.class);
|
||||
}
|
||||
|
||||
static boolean rabbitConnectorExists() {
|
||||
try {
|
||||
Resource[] connectors = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader())
|
||||
.getResources("classpath:/connectors/**");
|
||||
boolean available = Arrays.stream(connectors).map(Resource::getFilename).filter(Objects::nonNull)
|
||||
.anyMatch((name) -> name.contains("pulsar-io-rabbitmq"));
|
||||
.getResources("classpath:/connectors/**");
|
||||
boolean available = Arrays.stream(connectors)
|
||||
.map(Resource::getFilename)
|
||||
.filter(Objects::nonNull)
|
||||
.anyMatch((name) -> name.contains("pulsar-io-rabbitmq"));
|
||||
if (!available) {
|
||||
logTestDisabledReason();
|
||||
return false;
|
||||
@@ -226,9 +230,14 @@ class PulsarFunctionAdministrationIntegrationTests {
|
||||
configs.put("password", "guest");
|
||||
configs.put("queueName", RABBIT_QUEUE + suffix);
|
||||
configs.put("connectionName", "pft_foo_connection" + suffix);
|
||||
SourceConfig sourceConfig = SourceConfig.builder().tenant("public").namespace("default")
|
||||
.name("rabbit-test-source" + suffix).archive("builtin://rabbitmq").topicName(PULSAR_TOPIC + suffix)
|
||||
.configs(configs).build();
|
||||
SourceConfig sourceConfig = SourceConfig.builder()
|
||||
.tenant("public")
|
||||
.namespace("default")
|
||||
.name("rabbit-test-source" + suffix)
|
||||
.archive("builtin://rabbitmq")
|
||||
.topicName(PULSAR_TOPIC + suffix)
|
||||
.configs(configs)
|
||||
.build();
|
||||
return new PulsarSource(sourceConfig, stopPolicy != null ? stopPolicy : FunctionStopPolicy.DELETE, null);
|
||||
}
|
||||
|
||||
@@ -276,7 +285,7 @@ class PulsarFunctionAdministrationIntegrationTests {
|
||||
@Override
|
||||
public void testFailed(ExtensionContext context, Throwable cause) {
|
||||
this.logger.error(() -> "Test %s failed due to: %s - inspect container logs below:%n%n%s"
|
||||
.formatted(context.getDisplayName(), cause.getMessage(), getPulsarContainerLogs()));
|
||||
.formatted(context.getDisplayName(), cause.getMessage(), getPulsarContainerLogs()));
|
||||
}
|
||||
|
||||
private String getPulsarContainerLogs() {
|
||||
|
||||
@@ -64,7 +64,7 @@ class PulsarListenerIntegrationTests implements PulsarTestContainerSupport {
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
PulsarTemplate<String> pulsarTemplate = context.getBean(PulsarTemplate.class);
|
||||
pulsarTemplate.send("plt-basic-topic", "John Doe");
|
||||
@@ -78,7 +78,7 @@ class PulsarListenerIntegrationTests implements PulsarTestContainerSupport {
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
PulsarTemplate<Foo> pulsarTemplate = context.getBean(PulsarTemplate.class);
|
||||
pulsarTemplate.send("plt-foo-topic1", new Foo("John Doe"), Schema.JSON(Foo.class));
|
||||
@@ -92,7 +92,7 @@ class PulsarListenerIntegrationTests implements PulsarTestContainerSupport {
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
PulsarTemplate<Foo> pulsarTemplate = context.getBean(PulsarTemplate.class);
|
||||
pulsarTemplate.send("plt-foo-topic2", new Foo("John Doe"));
|
||||
@@ -106,7 +106,7 @@ class PulsarListenerIntegrationTests implements PulsarTestContainerSupport {
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
PulsarTemplate<Foo> pulsarTemplate = context.getBean(PulsarTemplate.class);
|
||||
pulsarTemplate.send("plt-topicMapping-topic", new Foo("Crazy8z"), Schema.JSON(Foo.class));
|
||||
@@ -120,7 +120,7 @@ class PulsarListenerIntegrationTests implements PulsarTestContainerSupport {
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
PulsarTemplate<String> pulsarTemplate = context.getBean(PulsarTemplate.class);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
||||
@@ -72,7 +72,7 @@ class ReactivePulsarListenerIntegrationTests implements PulsarTestContainerSuppo
|
||||
SpringApplication app = new SpringApplication(BasicListenerConfig.class);
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ReactivePulsarTemplate<String> pulsarTemplate = context.getBean(ReactivePulsarTemplate.class);
|
||||
pulsarTemplate.send("rplt-topic1", "John Doe").block();
|
||||
@@ -85,7 +85,7 @@ class ReactivePulsarListenerIntegrationTests implements PulsarTestContainerSuppo
|
||||
SpringApplication app = new SpringApplication(BasicListenerCustomTypeConfig.class);
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ReactivePulsarTemplate<Foo> pulsarTemplate = context.getBean(ReactivePulsarTemplate.class);
|
||||
pulsarTemplate.send("rplt-custom-topic1", new Foo("John Doe"), Schema.JSON(Foo.class)).block();
|
||||
@@ -98,7 +98,7 @@ class ReactivePulsarListenerIntegrationTests implements PulsarTestContainerSuppo
|
||||
SpringApplication app = new SpringApplication(BasicListenerCustomTypeWithTypeMappingConfig.class);
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ReactivePulsarTemplate<Foo> pulsarTemplate = context.getBean(ReactivePulsarTemplate.class);
|
||||
pulsarTemplate.send("rplt-custom-topic2", new Foo("John Doe")).block();
|
||||
@@ -111,7 +111,7 @@ class ReactivePulsarListenerIntegrationTests implements PulsarTestContainerSuppo
|
||||
SpringApplication app = new SpringApplication(BasicListenerWithTopicMappingConfig.class);
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ReactivePulsarTemplate<Foo> pulsarTemplate = context.getBean(ReactivePulsarTemplate.class);
|
||||
pulsarTemplate.send("rplt-topicMapping-topic1", new Foo("Crazy8z"), Schema.JSON(Foo.class)).block();
|
||||
@@ -124,7 +124,7 @@ class ReactivePulsarListenerIntegrationTests implements PulsarTestContainerSuppo
|
||||
SpringApplication app = new SpringApplication(FluxListenerConfig.class);
|
||||
app.setWebApplicationType(WebApplicationType.NONE);
|
||||
try (ConfigurableApplicationContext context = app
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
.run("--spring.pulsar.client.serviceUrl=" + PulsarTestContainerSupport.getPulsarBrokerUrl())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
PulsarTemplate<String> pulsarTemplate = context.getBean(PulsarTemplate.class);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
||||
@@ -35,11 +35,14 @@ public class CaffeineCacheProviderFactory<K, V> implements CacheProviderFactory<
|
||||
@Override
|
||||
public CacheProvider<K, V> create(Duration cacheExpireAfterAccess, Long cacheMaximumSize,
|
||||
Integer cacheInitialCapacity, EvictionListener<K, V> evictionListener) {
|
||||
Cache<K, V> cache = Caffeine.newBuilder().expireAfterAccess(cacheExpireAfterAccess)
|
||||
.maximumSize(cacheMaximumSize).initialCapacity(cacheInitialCapacity)
|
||||
.scheduler(Scheduler.systemScheduler()).evictionListener((RemovalListener<K, V>) (key, value,
|
||||
cause) -> evictionListener.onEviction(key, value, cause.toString()))
|
||||
.build();
|
||||
Cache<K, V> cache = Caffeine.newBuilder()
|
||||
.expireAfterAccess(cacheExpireAfterAccess)
|
||||
.maximumSize(cacheMaximumSize)
|
||||
.initialCapacity(cacheInitialCapacity)
|
||||
.scheduler(Scheduler.systemScheduler())
|
||||
.evictionListener((RemovalListener<K, V>) (key, value, cause) -> evictionListener.onEviction(key, value,
|
||||
cause.toString()))
|
||||
.build();
|
||||
return new CaffeineCacheProvider<>(cache);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,9 @@ public interface CacheProviderFactory<K, V> {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <K, V> CacheProviderFactory<K, V> load() {
|
||||
return ServiceLoader.load(CacheProviderFactory.class).findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException("No ProducerCacheFactory available"));
|
||||
return ServiceLoader.load(CacheProviderFactory.class)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException("No ProducerCacheFactory available"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,22 +56,22 @@ public class ReactivePulsarRuntimeHints implements RuntimeHintsRegistrar {
|
||||
// and introspect all public methods. The components are a mix of JDK classes,
|
||||
// core Pulsar classes,
|
||||
// some other shaded components available through Pulsar client.
|
||||
Stream.of(HashSet.class, TreeMap.class, Authentication.class, AuthenticationDataProvider.class,
|
||||
SecretsSerializer.class, NioSocketChannel.class, AbstractByteBufAllocator.class,
|
||||
NioDatagramChannel.class, PulsarAdminBuilderImpl.class, OffloadProcessStatusImpl.class, Commands.class,
|
||||
ReferenceCountUtil.class).forEach(
|
||||
type -> reflectionHints.registerType(type,
|
||||
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INTROSPECT_PUBLIC_METHODS)));
|
||||
Stream
|
||||
.of(HashSet.class, TreeMap.class, Authentication.class, AuthenticationDataProvider.class,
|
||||
SecretsSerializer.class, NioSocketChannel.class, AbstractByteBufAllocator.class,
|
||||
NioDatagramChannel.class, PulsarAdminBuilderImpl.class, OffloadProcessStatusImpl.class,
|
||||
Commands.class, ReferenceCountUtil.class)
|
||||
.forEach(type -> reflectionHints.registerType(type,
|
||||
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS)));
|
||||
|
||||
// In addition to the above member category levels, these components need field
|
||||
// and declared class level access.
|
||||
Stream.of(ClientConfigurationData.class, ConsumerConfigurationData.class, ProducerConfigurationData.class)
|
||||
.forEach(type -> reflectionHints.registerType(type,
|
||||
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS,
|
||||
MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS)));
|
||||
.forEach(type -> reflectionHints.registerType(type,
|
||||
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS,
|
||||
MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS)));
|
||||
|
||||
// These are inaccessible interfaces/classes in a normal scenario, thus using the
|
||||
// String version,
|
||||
@@ -83,15 +83,16 @@ public class ReactivePulsarRuntimeHints implements RuntimeHintsRegistrar {
|
||||
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField",
|
||||
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField",
|
||||
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField")
|
||||
.forEach(typeName -> reflectionHints.registerTypeIfPresent(classLoader, typeName,
|
||||
MemberCategory.DECLARED_FIELDS));
|
||||
.forEach(typeName -> reflectionHints.registerTypeIfPresent(classLoader, typeName,
|
||||
MemberCategory.DECLARED_FIELDS));
|
||||
|
||||
Stream.of("reactor.core.publisher.Flux", "com.github.benmanes.caffeine.cache.SSMSA",
|
||||
"com.github.benmanes.caffeine.cache.PSAMS", "com.github.benmanes.caffeine.cache.SSLMSA",
|
||||
"com.github.benmanes.caffeine.cache.PSAMW")
|
||||
.forEach(typeName -> reflectionHints.registerTypeIfPresent(classLoader, typeName,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INTROSPECT_PUBLIC_METHODS));
|
||||
Stream
|
||||
.of("reactor.core.publisher.Flux", "com.github.benmanes.caffeine.cache.SSMSA",
|
||||
"com.github.benmanes.caffeine.cache.PSAMS", "com.github.benmanes.caffeine.cache.SSLMSA",
|
||||
"com.github.benmanes.caffeine.cache.PSAMW")
|
||||
.forEach(typeName -> reflectionHints.registerTypeIfPresent(classLoader, typeName,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INTROSPECT_PUBLIC_METHODS));
|
||||
|
||||
// Registering JDK dynamic proxies for these interfaces. Since the Connection
|
||||
// interface is protected,
|
||||
@@ -101,12 +102,13 @@ public class ReactivePulsarRuntimeHints implements RuntimeHintsRegistrar {
|
||||
// registered using the
|
||||
// string version of the API because all of them need to be registered through a
|
||||
// single call.
|
||||
hints.proxies().registerJdkProxy(TypeReference.of("org.apache.pulsar.shade.io.netty.util.TimerTask"),
|
||||
TypeReference.of("org.apache.pulsar.client.impl.ConnectionHandler$Connection"),
|
||||
TypeReference.of("org.apache.pulsar.client.api.Producer"),
|
||||
TypeReference.of("org.springframework.aop.SpringProxy"),
|
||||
TypeReference.of("org.springframework.aop.framework.Advised"),
|
||||
TypeReference.of("org.springframework.core.DecoratingProxy"));
|
||||
hints.proxies()
|
||||
.registerJdkProxy(TypeReference.of("org.apache.pulsar.shade.io.netty.util.TimerTask"),
|
||||
TypeReference.of("org.apache.pulsar.client.impl.ConnectionHandler$Connection"),
|
||||
TypeReference.of("org.apache.pulsar.client.api.Producer"),
|
||||
TypeReference.of("org.springframework.aop.SpringProxy"),
|
||||
TypeReference.of("org.springframework.aop.framework.Advised"),
|
||||
TypeReference.of("org.springframework.core.DecoratingProxy"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -120,15 +120,15 @@ public class MethodReactivePulsarListenerEndpoint<V> extends AbstractReactivePul
|
||||
MethodParameter[] methodParameters = handlerMethod.getInvokerHandlerMethod().getMethodParameters();
|
||||
MethodParameter messageParameter = null;
|
||||
Optional<MethodParameter> parameter = Arrays.stream(methodParameters)
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
|| !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
|| !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.findFirst();
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
|| !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
|| !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.findFirst();
|
||||
long count = Arrays.stream(methodParameters)
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
&& !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
&& !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.count();
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
&& !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
&& !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.count();
|
||||
Assert.isTrue(count == 1, "More than 1 expected payload types found");
|
||||
if (parameter.isPresent()) {
|
||||
messageParameter = parameter.get();
|
||||
@@ -140,7 +140,7 @@ public class MethodReactivePulsarListenerEndpoint<V> extends AbstractReactivePul
|
||||
SchemaType schemaType = pulsarContainerProperties.getSchemaType();
|
||||
ResolvableType messageType = resolvableType(messageParameter);
|
||||
schemaResolver.resolveSchema(schemaType, messageType)
|
||||
.ifResolved(schema -> pulsarContainerProperties.setSchema((Schema) schema));
|
||||
.ifResolved(schema -> pulsarContainerProperties.setSchema((Schema) schema));
|
||||
|
||||
// Make sure the schemaType is updated to match the current schema
|
||||
if (pulsarContainerProperties.getSchema() != null) {
|
||||
@@ -154,7 +154,7 @@ public class MethodReactivePulsarListenerEndpoint<V> extends AbstractReactivePul
|
||||
|| !ObjectUtils.isEmpty(pulsarContainerProperties.getTopics());
|
||||
if (!hasTopicInfo) {
|
||||
topicResolver.resolveTopic(null, messageType.getRawClass(), () -> null)
|
||||
.ifResolved((topic) -> pulsarContainerProperties.setTopics(Collections.singleton(topic)));
|
||||
.ifResolved((topic) -> pulsarContainerProperties.setTopics(Collections.singleton(topic)));
|
||||
}
|
||||
|
||||
ReactiveMessageConsumerBuilderCustomizer<V> customizer1 = b -> b.deadLetterPolicy(this.deadLetterPolicy);
|
||||
@@ -189,7 +189,7 @@ public class MethodReactivePulsarListenerEndpoint<V> extends AbstractReactivePul
|
||||
|
||||
protected HandlerAdapter configureListenerAdapter(AbstractPulsarMessageToSpringMessageAdapter<V> messageListener) {
|
||||
InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory
|
||||
.createInvocableHandlerMethod(getBean(), getMethod());
|
||||
.createInvocableHandlerMethod(getBean(), getMethod());
|
||||
return new HandlerAdapter(invocableHandlerMethod);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ public class ReactivePulsarListenerAnnotationBeanPostProcessor<V> extends Abstra
|
||||
this.registrar.setBeanFactory(this.beanFactory);
|
||||
|
||||
this.beanFactory.getBeanProvider(PulsarListenerConfigurer.class)
|
||||
.forEach(c -> c.configurePulsarListeners(this.registrar));
|
||||
.forEach(c -> c.configurePulsarListeners(this.registrar));
|
||||
|
||||
if (this.registrar.getEndpointRegistry() == null) {
|
||||
if (this.endpointRegistry == null) {
|
||||
@@ -271,8 +271,8 @@ public class ReactivePulsarListenerAnnotationBeanPostProcessor<V> extends Abstra
|
||||
String deadLetterPolicyBeanName = resolveExpressionAsString(reactivePulsarListener.deadLetterPolicy(),
|
||||
"deadLetterPolicy");
|
||||
if (StringUtils.hasText(deadLetterPolicyBeanName)) {
|
||||
endpoint.setDeadLetterPolicy(
|
||||
this.beanFactory.getBean(deadLetterPolicyBeanName, DeadLetterPolicy.class));
|
||||
endpoint
|
||||
.setDeadLetterPolicy(this.beanFactory.getBean(deadLetterPolicyBeanName, DeadLetterPolicy.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import java.lang.annotation.Target;
|
||||
* on the same method (or class), implicitly generating this container annotation.
|
||||
*
|
||||
* @author Christophe Bornet
|
||||
*
|
||||
* @see ReactivePulsarListener
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
|
||||
@@ -55,7 +55,7 @@ public class DefaultReactivePulsarReaderFactory<T> implements ReactivePulsarRead
|
||||
List<ReactiveMessageReaderBuilderCustomizer<T>> customizers) {
|
||||
|
||||
ReactiveMessageReaderBuilder<T> reader = this.reactivePulsarClient.messageReader(schema)
|
||||
.applySpec(this.readerSpec);
|
||||
.applySpec(this.readerSpec);
|
||||
if (!CollectionUtils.isEmpty(customizers)) {
|
||||
customizers.forEach((c) -> c.customize(reader));
|
||||
}
|
||||
|
||||
@@ -96,7 +96,8 @@ public class DefaultReactivePulsarSenderFactory<T> implements ReactivePulsarSend
|
||||
@Nullable List<ReactiveMessageSenderBuilderCustomizer<T>> customizers) {
|
||||
Objects.requireNonNull(schema, "Schema must be specified");
|
||||
String resolvedTopic = this.topicResolver
|
||||
.resolveTopic(topic, () -> getReactiveMessageSenderSpec().getTopicName()).orElseThrow();
|
||||
.resolveTopic(topic, () -> getReactiveMessageSenderSpec().getTopicName())
|
||||
.orElseThrow();
|
||||
this.logger.trace(() -> "Creating reactive message sender for '%s' topic".formatted(resolvedTopic));
|
||||
|
||||
ReactiveMessageSenderBuilder<T> sender = this.reactivePulsarClient.messageSender(schema);
|
||||
|
||||
@@ -146,9 +146,10 @@ public class ReactivePulsarTemplate<T> implements ReactivePulsarOperations<T> {
|
||||
String topicName = resolveTopic(topic, firstMessage.getValue());
|
||||
ReactiveMessageSender<T> sender = createMessageSender(topicName, firstMessage.getValue(), schema,
|
||||
customizer);
|
||||
return messageFlux.as(sender::sendMany).doOnError(
|
||||
ex -> this.logger.error(ex, () -> "Failed to send messages to '%s' topic".formatted(topicName)))
|
||||
.doOnNext(msgId -> this.logger.trace(() -> "Sent messages to '%s' topic".formatted(topicName)));
|
||||
return messageFlux.as(sender::sendMany)
|
||||
.doOnError(ex -> this.logger.error(ex,
|
||||
() -> "Failed to send messages to '%s' topic".formatted(topicName)))
|
||||
.doOnNext(msgId -> this.logger.trace(() -> "Sent messages to '%s' topic".formatted(topicName)));
|
||||
}
|
||||
// The flux has errored or is completed
|
||||
return messageFlux.thenMany(Flux.empty());
|
||||
|
||||
@@ -166,22 +166,23 @@ public non-sealed class DefaultReactivePulsarMessageListenerContainer<T>
|
||||
}
|
||||
|
||||
ReactiveMessageConsumer<T> consumer = getReactivePulsarConsumerFactory()
|
||||
.createConsumer(containerProperties.getSchema(), customizers);
|
||||
.createConsumer(containerProperties.getSchema(), customizers);
|
||||
ReactiveMessagePipelineBuilder<T> pipelineBuilder = ApiImplementationFactory
|
||||
.createReactiveMessageHandlerPipelineBuilder(consumer);
|
||||
.createReactiveMessageHandlerPipelineBuilder(consumer);
|
||||
Object messageHandler = containerProperties.getMessageHandler();
|
||||
ReactiveMessagePipeline pipeline;
|
||||
if (messageHandler instanceof ReactivePulsarStreamingHandler<?>) {
|
||||
pipeline = pipelineBuilder
|
||||
.streamingMessageHandler(((ReactivePulsarStreamingHandler<T>) messageHandler)::received).build();
|
||||
.streamingMessageHandler(((ReactivePulsarStreamingHandler<T>) messageHandler)::received)
|
||||
.build();
|
||||
}
|
||||
else {
|
||||
ReactiveMessagePipelineBuilder.OneByOneMessagePipelineBuilder<T> messagePipelineBuilder = pipelineBuilder
|
||||
.messageHandler(((ReactivePulsarOneByOneMessageHandler<T>) messageHandler)::received)
|
||||
.handlingTimeout(containerProperties.getHandlingTimeout());
|
||||
.messageHandler(((ReactivePulsarOneByOneMessageHandler<T>) messageHandler)::received)
|
||||
.handlingTimeout(containerProperties.getHandlingTimeout());
|
||||
if (containerProperties.getConcurrency() > 0) {
|
||||
ConcurrentOneByOneMessagePipelineBuilder<T> concurrentPipelineBuilder = messagePipelineBuilder
|
||||
.concurrency(containerProperties.getConcurrency());
|
||||
.concurrency(containerProperties.getConcurrency());
|
||||
if (containerProperties.isUseKeyOrderedProcessing()) {
|
||||
concurrentPipelineBuilder.useKeyOrderedProcessing();
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ class DefaultReactiveMessageConsumerFactoryTests {
|
||||
ReactiveMessageConsumer<String> consumer = consumerFactory.createConsumer(SCHEMA);
|
||||
|
||||
assertThat(consumer)
|
||||
.extracting("consumerSpec", InstanceOfAssertFactories.type(ReactiveMessageConsumerSpec.class))
|
||||
.isNotNull();
|
||||
.extracting("consumerSpec", InstanceOfAssertFactories.type(ReactiveMessageConsumerSpec.class))
|
||||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -62,8 +62,9 @@ class DefaultReactiveMessageConsumerFactoryTests {
|
||||
Collections.singletonList(builder -> builder.consumerName("new-test-consumer")));
|
||||
|
||||
assertThat(consumer)
|
||||
.extracting("consumerSpec", InstanceOfAssertFactories.type(ReactiveMessageConsumerSpec.class))
|
||||
.extracting(ReactiveMessageConsumerSpec::getConsumerName).isEqualTo("new-test-consumer");
|
||||
.extracting("consumerSpec", InstanceOfAssertFactories.type(ReactiveMessageConsumerSpec.class))
|
||||
.extracting(ReactiveMessageConsumerSpec::getConsumerName)
|
||||
.isEqualTo("new-test-consumer");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -86,8 +87,9 @@ class DefaultReactiveMessageConsumerFactoryTests {
|
||||
ReactiveMessageConsumer<String> consumer = consumerFactory.createConsumer(SCHEMA);
|
||||
|
||||
assertThat(consumer)
|
||||
.extracting("consumerSpec", InstanceOfAssertFactories.type(ReactiveMessageConsumerSpec.class))
|
||||
.extracting(ReactiveMessageConsumerSpec::getConsumerName).isEqualTo("test-consumer");
|
||||
.extracting("consumerSpec", InstanceOfAssertFactories.type(ReactiveMessageConsumerSpec.class))
|
||||
.extracting(ReactiveMessageConsumerSpec::getConsumerName)
|
||||
.isEqualTo("test-consumer");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,8 +98,9 @@ class DefaultReactiveMessageConsumerFactoryTests {
|
||||
Collections.singletonList(builder -> builder.consumerName("new-test-consumer")));
|
||||
|
||||
assertThat(consumer)
|
||||
.extracting("consumerSpec", InstanceOfAssertFactories.type(ReactiveMessageConsumerSpec.class))
|
||||
.extracting(ReactiveMessageConsumerSpec::getConsumerName).isEqualTo("new-test-consumer");
|
||||
.extracting("consumerSpec", InstanceOfAssertFactories.type(ReactiveMessageConsumerSpec.class))
|
||||
.extracting(ReactiveMessageConsumerSpec::getConsumerName)
|
||||
.isEqualTo("new-test-consumer");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ class DefaultReactiveMessageReaderFactoryTests {
|
||||
ReactiveMessageReader<String> reader = readerFactory.createReader(schema);
|
||||
|
||||
assertThat(reader).extracting("readerSpec", InstanceOfAssertFactories.type(ReactiveMessageReaderSpec.class))
|
||||
.extracting(ReactiveMessageReaderSpec::getReaderName).isEqualTo("test-reader");
|
||||
.extracting(ReactiveMessageReaderSpec::getReaderName)
|
||||
.isEqualTo("test-reader");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -62,7 +63,8 @@ class DefaultReactiveMessageReaderFactoryTests {
|
||||
Collections.singletonList(builder -> builder.readerName("new-test-reader")));
|
||||
|
||||
assertThat(reader).extracting("readerSpec", InstanceOfAssertFactories.type(ReactiveMessageReaderSpec.class))
|
||||
.extracting(ReactiveMessageReaderSpec::getReaderName).isEqualTo("new-test-reader");
|
||||
.extracting(ReactiveMessageReaderSpec::getReaderName)
|
||||
.isEqualTo("new-test-reader");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,14 +54,15 @@ class DefaultReactiveMessageSenderFactoryTests {
|
||||
}
|
||||
|
||||
private void assertThatSenderHasTopic(ReactiveMessageSender<String> sender, String expectedTopic) {
|
||||
assertThatSenderSpecSatisfies(sender, (senderSpec) -> assertThat(senderSpec)
|
||||
.extracting(ReactiveMessageSenderSpec::getTopicName).isEqualTo(expectedTopic));
|
||||
assertThatSenderSpecSatisfies(sender,
|
||||
(senderSpec) -> assertThat(senderSpec).extracting(ReactiveMessageSenderSpec::getTopicName)
|
||||
.isEqualTo(expectedTopic));
|
||||
}
|
||||
|
||||
private void assertThatSenderSpecSatisfies(ReactiveMessageSender<String> sender,
|
||||
ThrowingConsumer<ReactiveMessageSenderSpec> specConsumer) {
|
||||
assertThat(sender).extracting("senderSpec", InstanceOfAssertFactories.type(ReactiveMessageSenderSpec.class))
|
||||
.satisfies(specConsumer);
|
||||
.satisfies(specConsumer);
|
||||
}
|
||||
|
||||
private ReactivePulsarSenderFactory<String> newSenderFactory() {
|
||||
@@ -84,7 +85,7 @@ class DefaultReactiveMessageSenderFactoryTests {
|
||||
@Test
|
||||
void withoutSchema() {
|
||||
assertThatNullPointerException().isThrownBy(() -> newSenderFactory().createSender(null, "topic0"))
|
||||
.withMessageContaining("Schema must be specified");
|
||||
.withMessageContaining("Schema must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,7 +109,7 @@ class DefaultReactiveMessageSenderFactoryTests {
|
||||
@Test
|
||||
void noTopicSpecifiedWithoutDefaultTopic() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> newSenderFactory().createSender(schema, null))
|
||||
.withMessageContaining("Topic must be specified when no default topic is configured");
|
||||
.withMessageContaining("Topic must be specified when no default topic is configured");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,8 +71,10 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
void tearDown() throws PulsarClientException {
|
||||
// Make sure the producer was closed by the template (albeit indirectly as
|
||||
// client removes closed producers)
|
||||
await().atMost(Duration.ofSeconds(3)).untilAsserted(() -> assertThat(client).extracting("producers")
|
||||
.asInstanceOf(InstanceOfAssertFactories.COLLECTION).isEmpty());
|
||||
await().atMost(Duration.ofSeconds(3))
|
||||
.untilAsserted(() -> assertThat(client).extracting("producers")
|
||||
.asInstanceOf(InstanceOfAssertFactories.COLLECTION)
|
||||
.isEmpty());
|
||||
client.close();
|
||||
}
|
||||
|
||||
@@ -91,65 +93,71 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template.send(message).subscribe(),
|
||||
true, message),
|
||||
arguments("simpleSendWithTopic",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template
|
||||
.send("simpleSendWithTopic", message).subscribe(),
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (
|
||||
template) -> template.send("simpleSendWithTopic", message).subscribe(),
|
||||
false, message),
|
||||
arguments("simpleSendWithDefaultTopicAndSchema",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template.send(message, Schema.STRING)
|
||||
.subscribe(),
|
||||
.subscribe(),
|
||||
true, message),
|
||||
arguments("simpleSendWithTopicAndSchema",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template
|
||||
.send("simpleSendWithTopicAndSchema", message, Schema.STRING).subscribe(),
|
||||
.send("simpleSendWithTopicAndSchema", message, Schema.STRING)
|
||||
.subscribe(),
|
||||
false, message),
|
||||
arguments("simpleSendNullWithTopicAndSchema",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template
|
||||
.send("simpleSendNullWithTopicAndSchema", (String) null, Schema.STRING).subscribe(),
|
||||
.send("simpleSendNullWithTopicAndSchema", (String) null, Schema.STRING)
|
||||
.subscribe(),
|
||||
false, null),
|
||||
|
||||
arguments("simplePublisherSendWithDefaultTopic",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template.send(messagePublisher)
|
||||
.subscribe(),
|
||||
.subscribe(),
|
||||
true, message),
|
||||
arguments("simplePublisherSendWithTopic",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template
|
||||
.send("simplePublisherSendWithTopic", messagePublisher).subscribe(),
|
||||
.send("simplePublisherSendWithTopic", messagePublisher)
|
||||
.subscribe(),
|
||||
false, message),
|
||||
arguments("simplePublisherSendWithDefaultTopicAndSchema",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template
|
||||
.send(messagePublisher, Schema.STRING).subscribe(),
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (
|
||||
template) -> template.send(messagePublisher, Schema.STRING).subscribe(),
|
||||
true, message),
|
||||
arguments("simplePublisherSendWithTopicAndSchema",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template
|
||||
.send("simplePublisherSendWithTopicAndSchema", messagePublisher, Schema.STRING)
|
||||
.subscribe(),
|
||||
.send("simplePublisherSendWithTopicAndSchema", messagePublisher, Schema.STRING)
|
||||
.subscribe(),
|
||||
false, message),
|
||||
|
||||
arguments("fluentSendWithDefaultTopic",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template.newMessage(message).send()
|
||||
.subscribe(),
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (
|
||||
template) -> template.newMessage(message).send().subscribe(),
|
||||
true, message),
|
||||
arguments("fluentSendWithTopic",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template.newMessage(message)
|
||||
.withTopic("fluentSendWithTopic").send().subscribe(),
|
||||
arguments("fluentSendWithTopic", (Consumer<ReactivePulsarTemplate<String>>) (
|
||||
template) -> template.newMessage(message).withTopic("fluentSendWithTopic").send().subscribe(),
|
||||
false, message),
|
||||
arguments("fluentSendWithDefaultTopicAndSchema",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template.newMessage(message)
|
||||
.withSchema(Schema.STRING).send().subscribe(),
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (
|
||||
template) -> template.newMessage(message).withSchema(Schema.STRING).send().subscribe(),
|
||||
true, message),
|
||||
arguments("fluentSendNullWithTopicAndSchema",
|
||||
(Consumer<ReactivePulsarTemplate<String>>) (template) -> template.newMessage(null)
|
||||
.withSchema(Schema.STRING).withTopic("fluentSendNullWithTopicAndSchema").send()
|
||||
.subscribe(),
|
||||
.withSchema(Schema.STRING)
|
||||
.withTopic("fluentSendNullWithTopicAndSchema")
|
||||
.send()
|
||||
.subscribe(),
|
||||
false, null),
|
||||
arguments("fluentPublisherSend", (Consumer<ReactivePulsarTemplate<String>>) (template) -> template
|
||||
.newMessages(messagePublisher).send().subscribe(), true, message));
|
||||
arguments("fluentPublisherSend", (Consumer<ReactivePulsarTemplate<String>>) (
|
||||
template) -> template.newMessages(messagePublisher).send().subscribe(), true, message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendMessageWithMessageCustomizer() throws Exception {
|
||||
Consumer<ReactivePulsarTemplate<String>> sendFunction = (template) -> template.newMessage("test-message")
|
||||
.withMessageCustomizer((mb) -> mb.key("test-key")).send().subscribe();
|
||||
.withMessageCustomizer((mb) -> mb.key("test-key"))
|
||||
.send()
|
||||
.subscribe();
|
||||
Message<String> msg = sendAndConsume(sendFunction, "sendMessageWithMessageCustomizer", Schema.STRING,
|
||||
"test-message", true);
|
||||
assertThat(msg.getKey()).isEqualTo("test-key");
|
||||
@@ -158,7 +166,9 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void sendMessageWithSenderCustomizer() throws Exception {
|
||||
Consumer<ReactivePulsarTemplate<String>> sendFunction = (template) -> template.newMessage("test-message")
|
||||
.withSenderCustomizer((sb) -> sb.producerName("test-producer")).send().subscribe();
|
||||
.withSenderCustomizer((sb) -> sb.producerName("test-producer"))
|
||||
.send()
|
||||
.subscribe();
|
||||
Message<String> msg = sendAndConsume(sendFunction, "sendMessageWithSenderCustomizer", Schema.STRING,
|
||||
"test-message", true);
|
||||
assertThat(msg.getProducerName()).isEqualTo("test-producer");
|
||||
@@ -180,8 +190,8 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
ReactivePulsarTemplate<Foo> pulsarTemplate = new ReactivePulsarTemplate<>(producerFactory,
|
||||
new DefaultSchemaResolver(), topicResolver);
|
||||
Foo foo = new Foo("Foo-" + UUID.randomUUID(), "Bar-" + UUID.randomUUID());
|
||||
ThrowingConsumer<ReactivePulsarTemplate<Foo>> sendFunction = (template) -> template
|
||||
.send(foo, Schema.JSON(Foo.class)).subscribe();
|
||||
ThrowingConsumer<ReactivePulsarTemplate<Foo>> sendFunction = (
|
||||
template) -> template.send(foo, Schema.JSON(Foo.class)).subscribe();
|
||||
sendAndConsume(pulsarTemplate, sendFunction, topic, Schema.JSON(Foo.class), foo);
|
||||
}
|
||||
|
||||
@@ -191,7 +201,7 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
new MutableReactiveMessageSenderSpec(), null);
|
||||
ReactivePulsarTemplate<String> pulsarTemplate = new ReactivePulsarTemplate<>(senderFactory);
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> pulsarTemplate.send("test-message").subscribe())
|
||||
.withMessage("Topic must be specified when no default topic is configured");
|
||||
.withMessage("Topic must be specified when no default topic is configured");
|
||||
}
|
||||
|
||||
private <T> Message<T> sendAndConsume(Consumer<ReactivePulsarTemplate<T>> sendFunction, String topic,
|
||||
@@ -211,8 +221,10 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
private <T> Message<T> sendAndConsume(ReactivePulsarTemplate<T> template,
|
||||
Consumer<ReactivePulsarTemplate<T>> sendFunction, String topic, Schema<T> schema, @Nullable T expectedValue)
|
||||
throws Exception {
|
||||
try (org.apache.pulsar.client.api.Consumer<T> consumer = client.newConsumer(schema).topic(topic)
|
||||
.subscriptionName(topic + "-sub").subscribe()) {
|
||||
try (org.apache.pulsar.client.api.Consumer<T> consumer = client.newConsumer(schema)
|
||||
.topic(topic)
|
||||
.subscriptionName(topic + "-sub")
|
||||
.subscribe()) {
|
||||
sendFunction.accept(template);
|
||||
|
||||
Message<T> msg = consumer.receive(3, TimeUnit.SECONDS);
|
||||
@@ -229,8 +241,8 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
void withSpecifiedSchema() throws Exception {
|
||||
String topic = "ptt-specificSchema-topic";
|
||||
Foo foo = new Foo("Foo-" + UUID.randomUUID(), "Bar-" + UUID.randomUUID());
|
||||
ThrowingConsumer<ReactivePulsarTemplate<Foo>> sendFunction = (template) -> template
|
||||
.send(foo, Schema.AVRO(Foo.class)).subscribe();
|
||||
ThrowingConsumer<ReactivePulsarTemplate<Foo>> sendFunction = (
|
||||
template) -> template.send(foo, Schema.AVRO(Foo.class)).subscribe();
|
||||
sendAndConsume(sendFunction, topic, Schema.AVRO(Foo.class), foo, true);
|
||||
}
|
||||
|
||||
@@ -255,8 +267,8 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
ReactivePulsarTemplate<Foo> pulsarTemplate = new ReactivePulsarTemplate<>(producerFactory, schemaResolver,
|
||||
new DefaultTopicResolver());
|
||||
Foo foo = new Foo("Foo-" + UUID.randomUUID(), "Bar-" + UUID.randomUUID());
|
||||
ThrowingConsumer<ReactivePulsarTemplate<Foo>> sendFunction = (template) -> template.newMessage(foo).send()
|
||||
.subscribe();
|
||||
ThrowingConsumer<ReactivePulsarTemplate<Foo>> sendFunction = (
|
||||
template) -> template.newMessage(foo).send().subscribe();
|
||||
sendAndConsume(pulsarTemplate, sendFunction, topic, Schema.JSON(Foo.class), foo);
|
||||
}
|
||||
|
||||
@@ -273,8 +285,8 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
null);
|
||||
ReactivePulsarTemplate<String> pulsarTemplate = new ReactivePulsarTemplate<>(senderFactory);
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> pulsarTemplate.send((String) null, Schema.STRING).subscribe())
|
||||
.withMessage("Topic must be specified when the message is null");
|
||||
.isThrownBy(() -> pulsarTemplate.send((String) null, Schema.STRING).subscribe())
|
||||
.withMessage("Topic must be specified when the message is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -283,9 +295,8 @@ class ReactivePulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
new MutableReactiveMessageSenderSpec(), null);
|
||||
ReactivePulsarTemplate<String> pulsarTemplate = new ReactivePulsarTemplate<>(senderFactory);
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(
|
||||
() -> pulsarTemplate.send("sendNullWithoutSchemaFails", (String) null, null).subscribe())
|
||||
.withMessage("Schema must be specified when the message is null");
|
||||
.isThrownBy(() -> pulsarTemplate.send("sendNullWithoutSchemaFails", (String) null, null).subscribe())
|
||||
.withMessage("Schema must be specified when the message is null");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,8 +63,9 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
MutableReactiveMessageConsumerSpec config = new MutableReactiveMessageConsumerSpec();
|
||||
config.setTopicNames(Collections.singletonList(topic));
|
||||
config.setSubscriptionName("drpmlct-sb-012");
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
ReactivePulsarClient reactivePulsarClient = AdaptedReactivePulsarClientFactory.create(pulsarClient);
|
||||
DefaultReactivePulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultReactivePulsarConsumerFactory<>(
|
||||
reactivePulsarClient, config);
|
||||
@@ -95,8 +96,9 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
MutableReactiveMessageConsumerSpec config = new MutableReactiveMessageConsumerSpec();
|
||||
config.setTopicNames(Collections.singletonList(topic));
|
||||
config.setSubscriptionName("drpmlct-sb-013");
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
ReactivePulsarClient reactivePulsarClient = AdaptedReactivePulsarClientFactory.create(pulsarClient);
|
||||
DefaultReactivePulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultReactivePulsarConsumerFactory<>(
|
||||
reactivePulsarClient, config);
|
||||
@@ -104,8 +106,9 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
pulsarConsumerFactory.createConsumer(Schema.STRING).consumeNothing().block(Duration.ofSeconds(10));
|
||||
CountDownLatch latch = new CountDownLatch(5);
|
||||
ReactivePulsarContainerProperties<String> pulsarContainerProperties = new ReactivePulsarContainerProperties<>();
|
||||
pulsarContainerProperties.setMessageHandler((ReactivePulsarStreamingHandler<String>) (msg) -> msg
|
||||
.doOnNext((m) -> latch.countDown()).map(MessageResult::acknowledge));
|
||||
pulsarContainerProperties
|
||||
.setMessageHandler((ReactivePulsarStreamingHandler<String>) (msg) -> msg.doOnNext((m) -> latch.countDown())
|
||||
.map(MessageResult::acknowledge));
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
DefaultReactivePulsarMessageListenerContainer<String> container = new DefaultReactivePulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
@@ -125,17 +128,19 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
void containerProperties() throws Exception {
|
||||
String topic = "drpmlct-sb-014";
|
||||
String subscriptionName = "drpmlct-sb-014";
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
ReactivePulsarClient reactivePulsarClient = AdaptedReactivePulsarClientFactory.create(pulsarClient);
|
||||
DefaultReactivePulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultReactivePulsarConsumerFactory<>(
|
||||
reactivePulsarClient, null);
|
||||
// Ensure subscription is created
|
||||
pulsarConsumerFactory
|
||||
.createConsumer(Schema.STRING,
|
||||
Collections.singletonList(
|
||||
c -> c.topics(Collections.singletonList(topic)).subscriptionName(subscriptionName)))
|
||||
.consumeNothing().block(Duration.ofSeconds(10));
|
||||
.createConsumer(Schema.STRING,
|
||||
Collections.singletonList(
|
||||
c -> c.topics(Collections.singletonList(topic)).subscriptionName(subscriptionName)))
|
||||
.consumeNothing()
|
||||
.block(Duration.ofSeconds(10));
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
ReactivePulsarContainerProperties<String> pulsarContainerProperties = new ReactivePulsarContainerProperties<>();
|
||||
pulsarContainerProperties.setMessageHandler(
|
||||
@@ -158,9 +163,10 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
|
||||
assertThat(container).extracting("pipeline", InstanceOfAssertFactories.type(ReactiveMessagePipeline.class))
|
||||
.hasFieldOrPropertyWithValue("concurrency", 5)
|
||||
.hasFieldOrPropertyWithValue("handlingTimeout", Duration.ofMillis(7)).extracting("groupingFunction")
|
||||
.isInstanceOf(DefaultMessageGroupingFunction.class);
|
||||
.hasFieldOrPropertyWithValue("concurrency", 5)
|
||||
.hasFieldOrPropertyWithValue("handlingTimeout", Duration.ofMillis(7))
|
||||
.extracting("groupingFunction")
|
||||
.isInstanceOf(DefaultMessageGroupingFunction.class);
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -172,15 +178,16 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
MutableReactiveMessageConsumerSpec config = new MutableReactiveMessageConsumerSpec();
|
||||
config.setTopicNames(Collections.singletonList(topic));
|
||||
config.setSubscriptionName("drpmlct-sb-015");
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
ReactivePulsarClient reactivePulsarClient = AdaptedReactivePulsarClientFactory.create(pulsarClient);
|
||||
DefaultReactivePulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultReactivePulsarConsumerFactory<>(
|
||||
reactivePulsarClient, config);
|
||||
|
||||
ReactivePulsarContainerProperties<String> pulsarContainerProperties = new ReactivePulsarContainerProperties<>();
|
||||
pulsarContainerProperties
|
||||
.setMessageHandler((ReactivePulsarOneByOneMessageHandler<String>) (msg) -> Mono.empty());
|
||||
.setMessageHandler((ReactivePulsarOneByOneMessageHandler<String>) (msg) -> Mono.empty());
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
DefaultReactivePulsarMessageListenerContainer<String> container = new DefaultReactivePulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
@@ -189,11 +196,11 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
Thread.sleep(2_000);
|
||||
|
||||
StepVerifier
|
||||
.create(pulsarConsumerFactory
|
||||
.createConsumer(Schema.STRING,
|
||||
Collections.singletonList(c -> c.subscriptionType(SubscriptionType.Shared)))
|
||||
.consumeNothing())
|
||||
.expectError().verify(Duration.ofSeconds(10));
|
||||
.create(pulsarConsumerFactory.createConsumer(Schema.STRING,
|
||||
Collections.singletonList(c -> c.subscriptionType(SubscriptionType.Shared)))
|
||||
.consumeNothing())
|
||||
.expectError()
|
||||
.verify(Duration.ofSeconds(10));
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -205,15 +212,16 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
MutableReactiveMessageConsumerSpec config = new MutableReactiveMessageConsumerSpec();
|
||||
config.setTopicNames(Collections.singletonList(topic));
|
||||
config.setSubscriptionName("drpmlct-sb-016");
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
ReactivePulsarClient reactivePulsarClient = AdaptedReactivePulsarClientFactory.create(pulsarClient);
|
||||
DefaultReactivePulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultReactivePulsarConsumerFactory<>(
|
||||
reactivePulsarClient, config);
|
||||
|
||||
ReactivePulsarContainerProperties<String> pulsarContainerProperties = new ReactivePulsarContainerProperties<>();
|
||||
pulsarContainerProperties
|
||||
.setMessageHandler((ReactivePulsarOneByOneMessageHandler<String>) (msg) -> Mono.empty());
|
||||
.setMessageHandler((ReactivePulsarOneByOneMessageHandler<String>) (msg) -> Mono.empty());
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
pulsarContainerProperties.setSubscriptionType(SubscriptionType.Shared);
|
||||
DefaultReactivePulsarMessageListenerContainer<String> container = new DefaultReactivePulsarMessageListenerContainer<>(
|
||||
@@ -223,11 +231,11 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
Thread.sleep(2_000);
|
||||
|
||||
StepVerifier
|
||||
.create(pulsarConsumerFactory
|
||||
.createConsumer(Schema.STRING,
|
||||
Collections.singletonList(c -> c.subscriptionType(SubscriptionType.Shared)))
|
||||
.consumeNothing())
|
||||
.expectComplete().verify(Duration.ofSeconds(10));
|
||||
.create(pulsarConsumerFactory.createConsumer(Schema.STRING,
|
||||
Collections.singletonList(c -> c.subscriptionType(SubscriptionType.Shared)))
|
||||
.consumeNothing())
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(10));
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -237,17 +245,19 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
void containerTopicsPattern() throws Exception {
|
||||
String topic = "drpmlct-017-foo";
|
||||
String subscriptionName = "drpmlct-sb-017";
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
ReactivePulsarClient reactivePulsarClient = AdaptedReactivePulsarClientFactory.create(pulsarClient);
|
||||
DefaultReactivePulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultReactivePulsarConsumerFactory<>(
|
||||
reactivePulsarClient, null);
|
||||
// Ensure subscription is created
|
||||
pulsarConsumerFactory
|
||||
.createConsumer(Schema.STRING,
|
||||
Collections.singletonList(
|
||||
c -> c.topics(Collections.singletonList(topic)).subscriptionName(subscriptionName)))
|
||||
.consumeNothing().block(Duration.ofSeconds(10));
|
||||
.createConsumer(Schema.STRING,
|
||||
Collections.singletonList(
|
||||
c -> c.topics(Collections.singletonList(topic)).subscriptionName(subscriptionName)))
|
||||
.consumeNothing()
|
||||
.block(Duration.ofSeconds(10));
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
ReactivePulsarContainerProperties<String> pulsarContainerProperties = new ReactivePulsarContainerProperties<>();
|
||||
pulsarContainerProperties.setMessageHandler(
|
||||
@@ -278,8 +288,9 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
config.setTopicNames(Collections.singletonList(topic));
|
||||
config.setSubscriptionName("drpmlct-sb-018");
|
||||
config.setNegativeAckRedeliveryDelay(Duration.ZERO);
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
ReactivePulsarClient reactivePulsarClient = AdaptedReactivePulsarClientFactory.create(pulsarClient);
|
||||
DefaultReactivePulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultReactivePulsarConsumerFactory<>(
|
||||
reactivePulsarClient, config);
|
||||
@@ -292,15 +303,18 @@ class DefaultReactivePulsarMessageListenerContainerTests implements PulsarTestCo
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(6);
|
||||
ReactivePulsarContainerProperties<String> pulsarContainerProperties = new ReactivePulsarContainerProperties<>();
|
||||
pulsarContainerProperties.setMessageHandler((ReactivePulsarStreamingHandler<String>) (msg) -> msg
|
||||
.doOnNext((m) -> latch.countDown()).map((m) -> m.getValue().endsWith("4")
|
||||
? MessageResult.negativeAcknowledge(m) : MessageResult.acknowledge(m)));
|
||||
pulsarContainerProperties
|
||||
.setMessageHandler((ReactivePulsarStreamingHandler<String>) (msg) -> msg.doOnNext((m) -> latch.countDown())
|
||||
.map((m) -> m.getValue().endsWith("4") ? MessageResult.negativeAcknowledge(m)
|
||||
: MessageResult.acknowledge(m)));
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
pulsarContainerProperties.setSubscriptionType(SubscriptionType.Shared);
|
||||
DefaultReactivePulsarMessageListenerContainer<String> container = new DefaultReactivePulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
DeadLetterPolicy deadLetterPolicy = DeadLetterPolicy.builder().maxRedeliverCount(1)
|
||||
.deadLetterTopic(deadLetterTopic).build();
|
||||
DeadLetterPolicy deadLetterPolicy = DeadLetterPolicy.builder()
|
||||
.maxRedeliverCount(1)
|
||||
.deadLetterTopic(deadLetterTopic)
|
||||
.build();
|
||||
container.setConsumerCustomizer(b -> b.deadLetterPolicy(deadLetterPolicy));
|
||||
container.start();
|
||||
MutableReactiveMessageSenderSpec prodConfig = new MutableReactiveMessageSenderSpec();
|
||||
|
||||
@@ -89,7 +89,7 @@ public final class Proto {
|
||||
}
|
||||
int mutable_bitField0_ = 0;
|
||||
com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet
|
||||
.newBuilder();
|
||||
.newBuilder();
|
||||
try {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
@@ -402,7 +402,7 @@ public final class Proto {
|
||||
@Override
|
||||
protected FieldAccessorTable internalGetFieldAccessorTable() {
|
||||
return Proto.internal_static_proto_Person_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(Person.class, Builder.class);
|
||||
.ensureFieldAccessorsInitialized(Person.class, Builder.class);
|
||||
}
|
||||
|
||||
// Construct using
|
||||
|
||||
@@ -165,7 +165,7 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void testPulsarListener() throws Exception {
|
||||
ReactivePulsarContainerProperties<String> pulsarContainerProperties = registry.getListenerContainer("id-1")
|
||||
.getContainerProperties();
|
||||
.getContainerProperties();
|
||||
assertThat(pulsarContainerProperties.getTopics()).containsExactly("topic-1");
|
||||
assertThat(pulsarContainerProperties.getSubscriptionName()).isEqualTo("subscription-1");
|
||||
pulsarTemplate.send("topic-1", "hello foo");
|
||||
@@ -181,9 +181,9 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void testPulsarListenerWithTopicsPattern() throws Exception {
|
||||
ReactivePulsarContainerProperties<String> containerProperties = registry.getListenerContainer("id-3")
|
||||
.getContainerProperties();
|
||||
.getContainerProperties();
|
||||
assertThat(containerProperties.getTopicsPattern().toString())
|
||||
.isEqualTo("persistent://public/default/pattern.*");
|
||||
.isEqualTo("persistent://public/default/pattern.*");
|
||||
|
||||
pulsarTemplate.send("persistent://public/default/pattern-1", "hello baz");
|
||||
pulsarTemplate.send("persistent://public/default/pattern-2", "hello baz");
|
||||
@@ -212,7 +212,7 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Bean
|
||||
ReactiveMessageConsumerBuilderCustomizer<String> listen2Customizer() {
|
||||
return b -> b.topics(List.of("topic-2"))
|
||||
.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest);
|
||||
.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest);
|
||||
}
|
||||
|
||||
@ReactivePulsarListener(id = "id-3", topicPattern = "persistent://public/default/pattern.*",
|
||||
@@ -225,7 +225,7 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Bean
|
||||
ReactiveMessageConsumerBuilderCustomizer<String> consumerCustomizer() {
|
||||
return b -> b.topicsPatternAutoDiscoveryPeriod(Duration.ofSeconds(2))
|
||||
.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest);
|
||||
.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -325,7 +325,7 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Bean
|
||||
ReactiveMessageConsumerBuilderCustomizer<String> consumerCustomizer() {
|
||||
return b -> b.negativeAckRedeliveryDelay(Duration.ofSeconds(1))
|
||||
.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest);
|
||||
.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -729,9 +729,9 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void simpleListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-simple-listener")
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "simpleListenerWithHeaders"))
|
||||
.withTopic("simpleListenerWithHeaders").send();
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.property("foo", "simpleListenerWithHeaders"))
|
||||
.withTopic("simpleListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(simpleListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedData.get()).isEqualTo("hello-simple-listener");
|
||||
assertThat(PulsarHeadersTest.messageId.get()).isEqualTo(messageId);
|
||||
@@ -743,9 +743,10 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void pulsarMessageListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-pulsar-message-listener")
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "pulsarMessageListenerWithHeaders"))
|
||||
.withTopic("pulsarMessageListenerWithHeaders").send();
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "pulsarMessageListenerWithHeaders"))
|
||||
.withTopic("pulsarMessageListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(pulsarMessageListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedData.get()).isEqualTo("hello-pulsar-message-listener");
|
||||
assertThat(PulsarHeadersTest.messageId.get()).isEqualTo(messageId);
|
||||
@@ -757,17 +758,18 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void springMessagingMessageListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-spring-messaging-message-listener")
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.property("foo",
|
||||
"springMessagingMessageListenerWithHeaders"))
|
||||
.withTopic("springMessagingMessageListenerWithHeaders").send();
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "springMessagingMessageListenerWithHeaders"))
|
||||
.withTopic("springMessagingMessageListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(springMessagingMessageListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedData.get()).isEqualTo("hello-spring-messaging-message-listener");
|
||||
assertThat(PulsarHeadersTest.messageId.get()).isEqualTo(messageId);
|
||||
assertThat(topicName.get())
|
||||
.isEqualTo("persistent://public/default/springMessagingMessageListenerWithHeaders");
|
||||
.isEqualTo("persistent://public/default/springMessagingMessageListenerWithHeaders");
|
||||
assertThat(fooValue.get()).isEqualTo("springMessagingMessageListenerWithHeaders");
|
||||
assertThat(rawData.get())
|
||||
.isEqualTo("hello-spring-messaging-message-listener".getBytes(StandardCharsets.UTF_8));
|
||||
.isEqualTo("hello-spring-messaging-message-listener".getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@EnableReactivePulsar
|
||||
@@ -842,10 +844,14 @@ public class ReactivePulsarListenerTests implements PulsarTestContainerSupport {
|
||||
|
||||
@Test
|
||||
void pulsarListenerWithConcurrencyKeyOrdered() throws Exception {
|
||||
pulsarTemplate.newMessage("first").withTopic("pulsarListenerWithConcurrencyKeyOrdered")
|
||||
.withMessageCustomizer(m -> m.key("key")).send();
|
||||
pulsarTemplate.newMessage("second").withTopic("pulsarListenerWithConcurrencyKeyOrdered")
|
||||
.withMessageCustomizer(m -> m.key("key")).send();
|
||||
pulsarTemplate.newMessage("first")
|
||||
.withTopic("pulsarListenerWithConcurrencyKeyOrdered")
|
||||
.withMessageCustomizer(m -> m.key("key"))
|
||||
.send();
|
||||
pulsarTemplate.newMessage("second")
|
||||
.withTopic("pulsarListenerWithConcurrencyKeyOrdered")
|
||||
.withMessageCustomizer(m -> m.key("key"))
|
||||
.send();
|
||||
assertThat(queue.poll(5, TimeUnit.SECONDS)).isEqualTo("first");
|
||||
assertThat(queue.poll(5, TimeUnit.SECONDS)).isEqualTo("second");
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ public class AbstractPulsarAnnotationsBeanPostProcessor
|
||||
DefaultMessageHandlerMethodFactory defaultFactory = new DefaultMessageHandlerMethodFactory();
|
||||
defaultFactory.setBeanFactory(AbstractPulsarAnnotationsBeanPostProcessor.this.beanFactory);
|
||||
this.defaultFormattingConversionService
|
||||
.addConverter(new BytesToStringConverter(AbstractPulsarAnnotationsBeanPostProcessor.this.charset));
|
||||
.addConverter(new BytesToStringConverter(AbstractPulsarAnnotationsBeanPostProcessor.this.charset));
|
||||
this.defaultFormattingConversionService.addConverter(new BytesToNumberConverter());
|
||||
defaultFactory.setConversionService(this.defaultFormattingConversionService);
|
||||
GenericMessageConverter messageConverter = new GenericMessageConverter(
|
||||
|
||||
@@ -44,29 +44,29 @@ public class PulsarBootstrapConfiguration implements ImportBeanDefinitionRegistr
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(
|
||||
PulsarAnnotationSupportBeanNames.PULSAR_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)) {
|
||||
if (!registry
|
||||
.containsBeanDefinition(PulsarAnnotationSupportBeanNames.PULSAR_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(
|
||||
PulsarAnnotationSupportBeanNames.PULSAR_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME,
|
||||
new RootBeanDefinition(PulsarListenerAnnotationBeanPostProcessor.class));
|
||||
}
|
||||
|
||||
if (!registry
|
||||
.containsBeanDefinition(PulsarAnnotationSupportBeanNames.PULSAR_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME)) {
|
||||
.containsBeanDefinition(PulsarAnnotationSupportBeanNames.PULSAR_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(
|
||||
PulsarAnnotationSupportBeanNames.PULSAR_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME,
|
||||
new RootBeanDefinition(PulsarListenerEndpointRegistry.class));
|
||||
}
|
||||
|
||||
if (!registry.containsBeanDefinition(
|
||||
PulsarAnnotationSupportBeanNames.PULSAR_READER_ANNOTATION_PROCESSOR_BEAN_NAME)) {
|
||||
if (!registry
|
||||
.containsBeanDefinition(PulsarAnnotationSupportBeanNames.PULSAR_READER_ANNOTATION_PROCESSOR_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(
|
||||
PulsarAnnotationSupportBeanNames.PULSAR_READER_ANNOTATION_PROCESSOR_BEAN_NAME,
|
||||
new RootBeanDefinition(PulsarReaderAnnotationBeanPostProcessor.class));
|
||||
}
|
||||
|
||||
if (!registry
|
||||
.containsBeanDefinition(PulsarAnnotationSupportBeanNames.PULSAR_READER_ENDPOINT_REGISTRY_BEAN_NAME)) {
|
||||
.containsBeanDefinition(PulsarAnnotationSupportBeanNames.PULSAR_READER_ENDPOINT_REGISTRY_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(PulsarAnnotationSupportBeanNames.PULSAR_READER_ENDPOINT_REGISTRY_BEAN_NAME,
|
||||
new RootBeanDefinition(PulsarReaderEndpointRegistry.class));
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public class PulsarListenerAnnotationBeanPostProcessor<V> extends AbstractPulsar
|
||||
this.registrar.setBeanFactory(this.beanFactory);
|
||||
|
||||
this.beanFactory.getBeanProvider(PulsarListenerConfigurer.class)
|
||||
.forEach(c -> c.configurePulsarListeners(this.registrar));
|
||||
.forEach(c -> c.configurePulsarListeners(this.registrar));
|
||||
|
||||
if (this.registrar.getEndpointRegistry() == null) {
|
||||
if (this.endpointRegistry == null) {
|
||||
@@ -325,8 +325,8 @@ public class PulsarListenerAnnotationBeanPostProcessor<V> extends AbstractPulsar
|
||||
String deadLetterPolicyBeanName = resolveExpressionAsString(pulsarListener.deadLetterPolicy(),
|
||||
"deadLetterPolicy");
|
||||
if (StringUtils.hasText(deadLetterPolicyBeanName)) {
|
||||
endpoint.setDeadLetterPolicy(
|
||||
this.beanFactory.getBean(deadLetterPolicyBeanName, DeadLetterPolicy.class));
|
||||
endpoint
|
||||
.setDeadLetterPolicy(this.beanFactory.getBean(deadLetterPolicyBeanName, DeadLetterPolicy.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Soby Chacko
|
||||
* @author Chris Bono
|
||||
*
|
||||
* @see PulsarListener
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
|
||||
@@ -107,7 +107,7 @@ public class PulsarReaderAnnotationBeanPostProcessor<V> extends AbstractPulsarAn
|
||||
this.registrar.setBeanFactory(this.beanFactory);
|
||||
|
||||
this.beanFactory.getBeanProvider(PulsarReaderConfigurer.class)
|
||||
.forEach(c -> c.configurePulsarReaders(this.registrar));
|
||||
.forEach(c -> c.configurePulsarReaders(this.registrar));
|
||||
|
||||
if (this.registrar.getEndpointRegistry() == null) {
|
||||
if (this.endpointRegistry == null) {
|
||||
|
||||
@@ -54,22 +54,23 @@ public class PulsarRuntimeHints implements RuntimeHintsRegistrar {
|
||||
// methods and introspect all public methods. The components are a mix of JDK
|
||||
// classes, core Pulsar classes, and some other shaded components available
|
||||
// through Pulsar client.
|
||||
Stream.of(HashSet.class, LinkedHashMap.class, TreeMap.class, Authentication.class,
|
||||
AuthenticationDataProvider.class, SecretsSerializer.class, PulsarAdminBuilderImpl.class,
|
||||
OffloadProcessStatusImpl.class, Commands.class).forEach(
|
||||
type -> reflectionHints.registerType(type,
|
||||
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INTROSPECT_PUBLIC_METHODS)));
|
||||
Stream
|
||||
.of(HashSet.class, LinkedHashMap.class, TreeMap.class, Authentication.class,
|
||||
AuthenticationDataProvider.class, SecretsSerializer.class, PulsarAdminBuilderImpl.class,
|
||||
OffloadProcessStatusImpl.class, Commands.class)
|
||||
.forEach(type -> reflectionHints.registerType(type,
|
||||
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS)));
|
||||
|
||||
// In addition to the above member category levels, these components need field
|
||||
// and declared class level access.
|
||||
Stream.of(ClientConfigurationData.class, ConsumerConfigurationData.class, ProducerConfigurationData.class,
|
||||
ListTopicsOptions.class)
|
||||
.forEach(type -> reflectionHints.registerType(type,
|
||||
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS,
|
||||
MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS)));
|
||||
Stream
|
||||
.of(ClientConfigurationData.class, ConsumerConfigurationData.class, ProducerConfigurationData.class,
|
||||
ListTopicsOptions.class)
|
||||
.forEach(type -> reflectionHints.registerType(type,
|
||||
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS,
|
||||
MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS)));
|
||||
|
||||
// @formatter:off
|
||||
// These are shaded classes and other inaccessible interfaces/classes (thus using
|
||||
@@ -232,16 +233,18 @@ public class PulsarRuntimeHints implements RuntimeHintsRegistrar {
|
||||
// Although the other interfaces are public, due to ConnectionHandler$Connection
|
||||
// being protected forces all of them to be registered using the string version
|
||||
// of the API because all of them need to be registered through a single call.
|
||||
hints.proxies().registerJdkProxy(TypeReference.of("org.apache.pulsar.shade.io.netty.util.TimerTask"),
|
||||
TypeReference.of("org.apache.pulsar.client.impl.ConnectionHandler$Connection"),
|
||||
TypeReference.of("org.apache.pulsar.client.api.Producer"),
|
||||
TypeReference.of("org.springframework.aop.SpringProxy"),
|
||||
TypeReference.of("org.springframework.aop.framework.Advised"),
|
||||
TypeReference.of("org.springframework.core.DecoratingProxy"));
|
||||
hints.proxies()
|
||||
.registerJdkProxy(TypeReference.of("org.apache.pulsar.shade.io.netty.util.TimerTask"),
|
||||
TypeReference.of("org.apache.pulsar.client.impl.ConnectionHandler$Connection"),
|
||||
TypeReference.of("org.apache.pulsar.client.api.Producer"),
|
||||
TypeReference.of("org.springframework.aop.SpringProxy"),
|
||||
TypeReference.of("org.springframework.aop.framework.Advised"),
|
||||
TypeReference.of("org.springframework.core.DecoratingProxy"));
|
||||
|
||||
// Register required properties files
|
||||
hints.resources().registerPatternIfPresent(classLoader, "org/apache/pulsar/shade/org/asynchttpclient/config/",
|
||||
builder -> builder.includes("*.properties"));
|
||||
hints.resources()
|
||||
.registerPatternIfPresent(classLoader, "org/apache/pulsar/shade/org/asynchttpclient/config/",
|
||||
builder -> builder.includes("*.properties"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -164,10 +164,10 @@ public abstract class AbstractPulsarListenerContainerFactory<C extends AbstractP
|
||||
instanceProperties.setObservationEnabled(this.containerProperties.isObservationEnabled());
|
||||
|
||||
JavaUtils.INSTANCE.acceptIfNotNull(this.phase, instance::setPhase)
|
||||
.acceptIfNotNull(this.applicationContext, instance::setApplicationContext)
|
||||
.acceptIfNotNull(this.applicationEventPublisher, instance::setApplicationEventPublisher)
|
||||
.acceptIfNotNull(endpoint.getConsumerProperties(),
|
||||
instance.getContainerProperties()::setPulsarConsumerProperties);
|
||||
.acceptIfNotNull(this.applicationContext, instance::setApplicationContext)
|
||||
.acceptIfNotNull(this.applicationEventPublisher, instance::setApplicationEventPublisher)
|
||||
.acceptIfNotNull(endpoint.getConsumerProperties(),
|
||||
instance.getContainerProperties()::setPulsarConsumerProperties);
|
||||
// Update container properties if there are relevant direct consumer properties
|
||||
instanceProperties.updateContainerProperties();
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ public abstract class AbstractPulsarReaderContainerFactory<C extends AbstractPul
|
||||
}
|
||||
|
||||
JavaUtils.INSTANCE.acceptIfNotNull(this.phase, instance::setPhase)
|
||||
.acceptIfNotNull(this.applicationContext, instance::setApplicationContext)
|
||||
.acceptIfNotNull(this.applicationEventPublisher, instance::setApplicationEventPublisher);
|
||||
.acceptIfNotNull(this.applicationContext, instance::setApplicationContext)
|
||||
.acceptIfNotNull(this.applicationEventPublisher, instance::setApplicationEventPublisher);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -127,15 +127,15 @@ public class MethodPulsarListenerEndpoint<V> extends AbstractPulsarListenerEndpo
|
||||
MethodParameter[] methodParameters = handlerMethod.getInvokerHandlerMethod().getMethodParameters();
|
||||
MethodParameter messageParameter = null;
|
||||
Optional<MethodParameter> parameter = Arrays.stream(methodParameters)
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
|| !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
|| !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.findFirst();
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
|| !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
|| !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.findFirst();
|
||||
long count = Arrays.stream(methodParameters)
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
&& !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
&& !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.count();
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
&& !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
&& !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.count();
|
||||
Assert.isTrue(count == 1, "More than 1 expected payload types found");
|
||||
if (parameter.isPresent()) {
|
||||
messageParameter = parameter.get();
|
||||
@@ -160,7 +160,7 @@ public class MethodPulsarListenerEndpoint<V> extends AbstractPulsarListenerEndpo
|
||||
|| StringUtils.hasText(pulsarContainerProperties.getTopicsPattern());
|
||||
if (!hasTopicInfo) {
|
||||
topicResolver.resolveTopic(null, messageType.getRawClass(), () -> null)
|
||||
.ifResolved((topic) -> pulsarContainerProperties.setTopics(Set.of(topic)));
|
||||
.ifResolved((topic) -> pulsarContainerProperties.setTopics(Set.of(topic)));
|
||||
}
|
||||
|
||||
container.setNegativeAckRedeliveryBackoff(this.negativeAckRedeliveryBackoff);
|
||||
@@ -194,7 +194,7 @@ public class MethodPulsarListenerEndpoint<V> extends AbstractPulsarListenerEndpo
|
||||
|
||||
protected HandlerAdapter configureListenerAdapter(AbstractPulsarMessageToSpringMessageAdapter<V> messageListener) {
|
||||
InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory
|
||||
.createInvocableHandlerMethod(getBean(), getMethod());
|
||||
.createInvocableHandlerMethod(getBean(), getMethod());
|
||||
return new HandlerAdapter(invocableHandlerMethod);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,15 +101,15 @@ public class MethodPulsarReaderEndpoint<V> extends AbstractPulsarReaderEndpoint<
|
||||
MethodParameter[] methodParameters = handlerMethod.getInvokerHandlerMethod().getMethodParameters();
|
||||
MethodParameter messageParameter = null;
|
||||
Optional<MethodParameter> parameter = Arrays.stream(methodParameters)
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
|| !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
|| !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.findFirst();
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
|| !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
|| !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.findFirst();
|
||||
long count = Arrays.stream(methodParameters)
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
&& !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
&& !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.count();
|
||||
.filter(methodParameter1 -> !methodParameter1.getParameterType().equals(Consumer.class)
|
||||
&& !methodParameter1.getParameterType().equals(Acknowledgement.class)
|
||||
&& !methodParameter1.hasParameterAnnotation(Header.class))
|
||||
.count();
|
||||
Assert.isTrue(count == 1, "More than 1 expected payload types found");
|
||||
if (parameter.isPresent()) {
|
||||
messageParameter = parameter.get();
|
||||
@@ -165,7 +165,7 @@ public class MethodPulsarReaderEndpoint<V> extends AbstractPulsarReaderEndpoint<
|
||||
|
||||
protected HandlerAdapter configureListenerAdapter(AbstractPulsarMessageToSpringMessageAdapter<V> messageListener) {
|
||||
InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory
|
||||
.createInvocableHandlerMethod(getBean(), getMethod());
|
||||
.createInvocableHandlerMethod(getBean(), getMethod());
|
||||
return new HandlerAdapter(invocableHandlerMethod);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ public class CachingPulsarProducerFactory<T> extends DefaultPulsarProducerFactor
|
||||
this.producerCache = cacheFactory.create(cacheExpireAfterAccess, cacheMaximumSize, cacheInitialCapacity,
|
||||
(key, producer, cause) -> {
|
||||
this.logger.debug(() -> "Producer %s evicted from cache due to %s"
|
||||
.formatted(ProducerUtils.formatProducer(producer), cause));
|
||||
.formatted(ProducerUtils.formatProducer(producer), cause));
|
||||
closeProducer(producer);
|
||||
});
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class CachingPulsarProducerFactory<T> extends DefaultPulsarProducerFactor
|
||||
var producer = super.doCreateProducer(schema, topic, encryptionKeys, customizers);
|
||||
return new ProducerWithCloseCallback<>(producer,
|
||||
(p) -> this.logger.trace(() -> "Client closed producer %s but will skip actual closing"
|
||||
.formatted(ProducerUtils.formatProducer(producer))));
|
||||
.formatted(ProducerUtils.formatProducer(producer))));
|
||||
}
|
||||
catch (PulsarClientException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
@@ -122,7 +122,7 @@ public class CachingPulsarProducerFactory<T> extends DefaultPulsarProducerFactor
|
||||
}
|
||||
if (actualProducer == null) {
|
||||
this.logger.warn(() -> "Unable to get actual producer for %s - will skip closing it"
|
||||
.formatted(ProducerUtils.formatProducer(producer)));
|
||||
.formatted(ProducerUtils.formatProducer(producer)));
|
||||
return;
|
||||
}
|
||||
ProducerUtils.closeProducerAsync(actualProducer, this.logger);
|
||||
|
||||
@@ -206,7 +206,7 @@ public class DefaultSchemaResolver implements SchemaResolver {
|
||||
@Nullable
|
||||
private Class<?> requireNonNullMessageType(SchemaType schemaType, @Nullable ResolvableType messageType) {
|
||||
return Objects.requireNonNull(messageType, "messageType must be specified for " + schemaType.name())
|
||||
.getRawClass();
|
||||
.getRawClass();
|
||||
}
|
||||
|
||||
private Schema<?> getMessageKeyValueSchema(ResolvableType messageType) {
|
||||
|
||||
@@ -85,7 +85,8 @@ public class PulsarAdministration
|
||||
|
||||
private void initialize() {
|
||||
var topics = Objects.requireNonNull(this.applicationContext, "Application context was not set")
|
||||
.getBeansOfType(PulsarTopic.class, false, false).values();
|
||||
.getBeansOfType(PulsarTopic.class, false, false)
|
||||
.values();
|
||||
createOrModifyTopicsIfNeeded(topics);
|
||||
}
|
||||
|
||||
@@ -112,7 +113,8 @@ public class PulsarAdministration
|
||||
|
||||
private List<String> getMatchingTopicPartitions(PulsarTopic topic, List<String> existingTopics) {
|
||||
return existingTopics.stream()
|
||||
.filter(existing -> existing.startsWith(topic.getFullyQualifiedTopicName() + "-partition-")).toList();
|
||||
.filter(existing -> existing.startsWith(topic.getFullyQualifiedTopicName() + "-partition-"))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private void createOrModifyTopicsIfNeeded(Collection<PulsarTopic> topics) {
|
||||
@@ -144,7 +146,7 @@ public class PulsarAdministration
|
||||
if (existingTopicsInNamespace.contains(topicName)) {
|
||||
throw new IllegalStateException(
|
||||
"Topic '%s' already exists un-partitioned - needs to be deleted first"
|
||||
.formatted(topicName));
|
||||
.formatted(topicName));
|
||||
}
|
||||
var matchingPartitions = getMatchingTopicPartitions(topic, existingTopicsInNamespace);
|
||||
if (matchingPartitions.isEmpty()) {
|
||||
@@ -155,14 +157,14 @@ public class PulsarAdministration
|
||||
var numberOfExistingPartitions = matchingPartitions.size();
|
||||
if (numberOfExistingPartitions < topic.numberOfPartitions()) {
|
||||
this.logger.debug(() -> "Topic '%s' found with %d partitions - will update to %d"
|
||||
.formatted(topicName, numberOfExistingPartitions, topic.numberOfPartitions()));
|
||||
.formatted(topicName, numberOfExistingPartitions, topic.numberOfPartitions()));
|
||||
topicsToModify.add(topic);
|
||||
}
|
||||
else if (numberOfExistingPartitions > topic.numberOfPartitions()) {
|
||||
throw new IllegalStateException(
|
||||
"Topic '%s' found w/ %d partitions but can't shrink to %d - needs to be deleted first"
|
||||
.formatted(topicName, numberOfExistingPartitions,
|
||||
topic.numberOfPartitions()));
|
||||
.formatted(topicName, numberOfExistingPartitions,
|
||||
topic.numberOfPartitions()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,7 +173,7 @@ public class PulsarAdministration
|
||||
if (!matchingPartitions.isEmpty()) {
|
||||
throw new IllegalStateException(
|
||||
"Topic '%s' already exists partitioned - needs to be deleted first"
|
||||
.formatted(topicName));
|
||||
.formatted(topicName));
|
||||
}
|
||||
if (!existingTopicsInNamespace.contains(topicName)) {
|
||||
this.logger.debug(() -> "Topic '%s' does not yet exist - will add".formatted(topicName));
|
||||
@@ -191,7 +193,8 @@ public class PulsarAdministration
|
||||
|
||||
private void createTopics(PulsarAdmin admin, Set<PulsarTopic> topicsToCreate) throws PulsarAdminException {
|
||||
this.logger.debug(() -> "Creating topics: " + topicsToCreate.stream()
|
||||
.map(PulsarTopic::getFullyQualifiedTopicName).collect(Collectors.joining(",")));
|
||||
.map(PulsarTopic::getFullyQualifiedTopicName)
|
||||
.collect(Collectors.joining(",")));
|
||||
for (var topic : topicsToCreate) {
|
||||
if (topic.isPartitioned()) {
|
||||
admin.topics().createPartitionedTopic(topic.topicName(), topic.numberOfPartitions());
|
||||
@@ -204,7 +207,8 @@ public class PulsarAdministration
|
||||
|
||||
private void modifyTopics(PulsarAdmin admin, Set<PulsarTopic> topicsToModify) throws PulsarAdminException {
|
||||
this.logger.debug(() -> "Modifying topics: " + topicsToModify.stream()
|
||||
.map(PulsarTopic::getFullyQualifiedTopicName).collect(Collectors.joining(",")));
|
||||
.map(PulsarTopic::getFullyQualifiedTopicName)
|
||||
.collect(Collectors.joining(",")));
|
||||
for (var topic : topicsToModify) {
|
||||
admin.topics().updatePartitionedTopic(topic.topicName(), topic.numberOfPartitions());
|
||||
}
|
||||
|
||||
@@ -145,9 +145,9 @@ public class PulsarTemplate<T>
|
||||
return;
|
||||
}
|
||||
this.observationRegistry = this.applicationContext.getBeanProvider(ObservationRegistry.class)
|
||||
.getIfUnique(() -> this.observationRegistry);
|
||||
.getIfUnique(() -> this.observationRegistry);
|
||||
this.observationConvention = this.applicationContext.getBeanProvider(PulsarTemplateObservationConvention.class)
|
||||
.getIfUnique(() -> this.observationConvention);
|
||||
.getIfUnique(() -> this.observationConvention);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -210,7 +210,8 @@ public class PulsarTemplate<T>
|
||||
@Nullable ProducerBuilderCustomizer<T> producerCustomizer) throws PulsarClientException {
|
||||
try {
|
||||
return doSendAsync(topic, message, schema, encryptionKeys, typedMessageBuilderCustomizer,
|
||||
producerCustomizer).get();
|
||||
producerCustomizer)
|
||||
.get();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw PulsarClientException.unwrap(ex);
|
||||
|
||||
@@ -26,9 +26,9 @@ import org.apache.pulsar.common.naming.TopicDomain;
|
||||
* <pre>{@code
|
||||
* PulsarTopic topic = PulsarTopic.builder("topic-name").build();
|
||||
* }</pre>
|
||||
*
|
||||
* @param topicName the topic name
|
||||
* @param numberOfPartitions the number of partitions, or 0 for non-partitioned topics
|
||||
*
|
||||
* @author Alexander Preuß
|
||||
*/
|
||||
public record PulsarTopic(String topicName, int numberOfPartitions) {
|
||||
@@ -76,6 +76,7 @@ public record PulsarTopic(String topicName, int numberOfPartitions) {
|
||||
|
||||
/**
|
||||
* Model class for the individual identifying components of a Pulsar topic.
|
||||
*
|
||||
* @param domain the topic domain
|
||||
* @param tenant the topic tenant
|
||||
* @param namespace the topic namespace
|
||||
|
||||
@@ -27,10 +27,10 @@ import org.springframework.pulsar.PulsarException;
|
||||
|
||||
/**
|
||||
* Represents a user-defined Pulsar Function backed by a {@link FunctionConfig}.
|
||||
*
|
||||
* @param config the function details
|
||||
* @param stopPolicy the action to take on the function when the server is stopped
|
||||
* @param updateOptions the options to use during an update operation (optional)
|
||||
*
|
||||
* @author Chris Bono
|
||||
*/
|
||||
public record PulsarFunction(FunctionConfig config, FunctionStopPolicy stopPolicy,
|
||||
|
||||
@@ -27,10 +27,10 @@ import org.springframework.pulsar.PulsarException;
|
||||
|
||||
/**
|
||||
* Represents a Pulsar Sink backed by a {@link SinkConfig}.
|
||||
*
|
||||
* @param config the sink details
|
||||
* @param stopPolicy the action to take on the sink when the server is stopped
|
||||
* @param updateOptions the options to use during an update operation (optional)
|
||||
*
|
||||
* @author Chris Bono
|
||||
*/
|
||||
public record PulsarSink(SinkConfig config, FunctionStopPolicy stopPolicy,
|
||||
|
||||
@@ -27,10 +27,10 @@ import org.springframework.pulsar.PulsarException;
|
||||
|
||||
/**
|
||||
* Represents a Pulsar Source backed by a {@link SourceConfig}.
|
||||
*
|
||||
* @param config the source details
|
||||
* @param stopPolicy the action to take on the source when the server is stopped
|
||||
* @param updateOptions the options to use during an update operation (optional)
|
||||
*
|
||||
* @author Chris Bono
|
||||
*/
|
||||
public record PulsarSource(SourceConfig config, FunctionStopPolicy stopPolicy,
|
||||
|
||||
@@ -88,9 +88,9 @@ public class ConcurrentPulsarMessageListenerContainer<T> extends AbstractPulsarM
|
||||
}
|
||||
else {
|
||||
applicationContext.getBeanProvider(ObservationRegistry.class)
|
||||
.ifUnique(containerProperties::setObservationRegistry);
|
||||
.ifUnique(containerProperties::setObservationRegistry);
|
||||
applicationContext.getBeanProvider(PulsarListenerObservationConvention.class)
|
||||
.ifUnique(containerProperties::setObservationConvention);
|
||||
.ifUnique(containerProperties::setObservationConvention);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -262,9 +262,10 @@ public class DefaultPulsarMessageListenerContainer<T> extends AbstractPulsarMess
|
||||
populateAllNecessaryPropertiesIfNeedBe(propertiesToConsumer);
|
||||
|
||||
BatchReceivePolicy batchReceivePolicy = new BatchReceivePolicy.Builder()
|
||||
.maxNumMessages(containerProperties.getMaxNumMessages())
|
||||
.maxNumBytes(containerProperties.getMaxNumBytes())
|
||||
.timeout(containerProperties.getBatchTimeoutMillis(), TimeUnit.MILLISECONDS).build();
|
||||
.maxNumMessages(containerProperties.getMaxNumMessages())
|
||||
.maxNumBytes(containerProperties.getMaxNumBytes())
|
||||
.timeout(containerProperties.getBatchTimeoutMillis(), TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
|
||||
/*
|
||||
* topicNames and properties must not be added through the builder
|
||||
@@ -294,8 +295,10 @@ public class DefaultPulsarMessageListenerContainer<T> extends AbstractPulsarMess
|
||||
|
||||
private Map<String, Object> extractDirectConsumerProperties() {
|
||||
Properties propertyOverrides = this.containerProperties.getPulsarConsumerProperties();
|
||||
return propertyOverrides.entrySet().stream().collect(Collectors.toMap(e -> String.valueOf(e.getKey()),
|
||||
Map.Entry::getValue, (prev, next) -> next, HashMap::new));
|
||||
return propertyOverrides.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(e -> String.valueOf(e.getKey()), Map.Entry::getValue, (prev, next) -> next,
|
||||
HashMap::new));
|
||||
}
|
||||
|
||||
private void populateAllNecessaryPropertiesIfNeedBe(Map<String, Object> currentProperties) {
|
||||
@@ -509,7 +512,7 @@ public class DefaultPulsarMessageListenerContainer<T> extends AbstractPulsarMess
|
||||
throw new IllegalStateException(
|
||||
|
||||
"Exception occurred and message %s was not auto-nacked; switch to AckMode BATCH or RECORD to enable auto-nacks"
|
||||
.formatted(message.getMessageId()),
|
||||
.formatted(message.getMessageId()),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,11 +65,10 @@ public class PulsarDeadLetterPublishingRecoverer<T> implements PulsarMessageReco
|
||||
return (message, exception) -> {
|
||||
try {
|
||||
this.pulsarTemplate.newMessage(message.getValue())
|
||||
.withTopic(this.destinationResolver.apply(consumer, message))
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.property(EXCEPTION_THROWN_CAUSE,
|
||||
exception.getCause() != null ? exception.getCause().getMessage()
|
||||
: exception.getMessage()))
|
||||
.sendAsync();
|
||||
.withTopic(this.destinationResolver.apply(consumer, message))
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.property(EXCEPTION_THROWN_CAUSE,
|
||||
exception.getCause() != null ? exception.getCause().getMessage() : exception.getMessage()))
|
||||
.sendAsync();
|
||||
}
|
||||
catch (PulsarClientException e) {
|
||||
this.logger.error(e, "DLT publishing failed.");
|
||||
|
||||
@@ -232,8 +232,9 @@ public abstract class AbstractPulsarMessageToSpringMessageAdapter<V> {
|
||||
Type paramType = parameterizedType.getActualTypeArguments()[0];
|
||||
this.isPulsarMessageList = paramType instanceof ParameterizedType
|
||||
&& ((ParameterizedType) paramType).getRawType().equals(Message.class);
|
||||
boolean messageHasGeneric = paramType instanceof ParameterizedType && ((ParameterizedType) paramType)
|
||||
.getRawType().equals(org.springframework.messaging.Message.class);
|
||||
boolean messageHasGeneric = paramType instanceof ParameterizedType
|
||||
&& ((ParameterizedType) paramType).getRawType()
|
||||
.equals(org.springframework.messaging.Message.class);
|
||||
this.isSpringMessageList = paramType.equals(org.springframework.messaging.Message.class)
|
||||
|| messageHasGeneric;
|
||||
if (messageHasGeneric) {
|
||||
@@ -247,8 +248,9 @@ public abstract class AbstractPulsarMessageToSpringMessageAdapter<V> {
|
||||
else if (isFlux(parameterizedType.getRawType()) && parameterizedType.getActualTypeArguments().length == 1) {
|
||||
|
||||
Type paramType = parameterizedType.getActualTypeArguments()[0];
|
||||
boolean messageHasGeneric = paramType instanceof ParameterizedType && ((ParameterizedType) paramType)
|
||||
.getRawType().equals(org.springframework.messaging.Message.class);
|
||||
boolean messageHasGeneric = paramType instanceof ParameterizedType
|
||||
&& ((ParameterizedType) paramType).getRawType()
|
||||
.equals(org.springframework.messaging.Message.class);
|
||||
this.isSpringMessageFlux = paramType.equals(org.springframework.messaging.Message.class)
|
||||
|| messageHasGeneric;
|
||||
if (messageHasGeneric) {
|
||||
|
||||
@@ -37,13 +37,13 @@ public final class JacksonUtils {
|
||||
classLoader) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
|
||||
|
||||
private static final boolean JDK8_MODULE_PRESENT = ClassUtils
|
||||
.isPresent("com.fasterxml.jackson.datatype.jdk8.Jdk8Module", null);
|
||||
.isPresent("com.fasterxml.jackson.datatype.jdk8.Jdk8Module", null);
|
||||
|
||||
private static final boolean JAVA_TIME_MODULE_PRESENT = ClassUtils
|
||||
.isPresent("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", null);
|
||||
.isPresent("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", null);
|
||||
|
||||
private static final boolean JODA_MODULE_PRESENT = ClassUtils
|
||||
.isPresent("com.fasterxml.jackson.datatype.joda.JodaModule", null);
|
||||
.isPresent("com.fasterxml.jackson.datatype.joda.JodaModule", null);
|
||||
|
||||
/**
|
||||
* Determines if the Jackson JSON processor is on the classpath.
|
||||
@@ -60,8 +60,10 @@ public final class JacksonUtils {
|
||||
* @return the {@link ObjectMapper} instance.
|
||||
*/
|
||||
public static ObjectMapper enhancedObjectMapper() {
|
||||
ObjectMapper objectMapper = JsonMapper.builder().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false)
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build();
|
||||
ObjectMapper objectMapper = JsonMapper.builder()
|
||||
.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false)
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.build();
|
||||
if (JDK8_MODULE_PRESENT) {
|
||||
objectMapper.registerModule(Jdk8ModuleProvider.MODULE);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class JsonPulsarHeaderMapper extends AbstractPulsarHeaderMapper<ToPulsarH
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.debug(e, () -> "Could not map %s with type %s (will instead map w/ toString()) reason: %s"
|
||||
.formatted(name, className, e.getMessage()));
|
||||
.formatted(name, className, e.getMessage()));
|
||||
}
|
||||
return rawValue.toString();
|
||||
}
|
||||
@@ -228,7 +228,7 @@ public class JsonPulsarHeaderMapper extends AbstractPulsarHeaderMapper<ToPulsarH
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.error(e, () -> "Could not decode type (%s) for header (%s) using value (%s) due to: %s"
|
||||
.formatted(type, name, value, e.getMessage()));
|
||||
.formatted(type, name, value, e.getMessage()));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -250,7 +250,7 @@ public class JsonPulsarHeaderMapper extends AbstractPulsarHeaderMapper<ToPulsarH
|
||||
catch (Exception e) {
|
||||
logger.error(e,
|
||||
() -> "Could not decode non-trusted header type (%s) for header (%s) using value (%s) due to: %s"
|
||||
.formatted(nth.untrustedType(), name, nth.headerValue(), e.getMessage()));
|
||||
.formatted(nth.untrustedType(), name, nth.headerValue(), e.getMessage()));
|
||||
}
|
||||
return decodedValue;
|
||||
}
|
||||
@@ -283,6 +283,7 @@ public class JsonPulsarHeaderMapper extends AbstractPulsarHeaderMapper<ToPulsarH
|
||||
|
||||
/**
|
||||
* Represents a header that could not be decoded due to an untrusted type.
|
||||
*
|
||||
* @param headerValue the header value that could not be decoded
|
||||
* @param untrustedType the class name of the encoded header value
|
||||
*/
|
||||
@@ -295,6 +296,7 @@ public class JsonPulsarHeaderMapper extends AbstractPulsarHeaderMapper<ToPulsarH
|
||||
* is ultimately included as a separate {@link #JSON_TYPES} header on the outgoing
|
||||
* Pulsar message. This allows for the inbound consumer to decode the headers when/if
|
||||
* the message is later consumed.
|
||||
*
|
||||
* @param jsonTypes cumulative map of header name to classname for types that are
|
||||
* serialized as JSON
|
||||
*/
|
||||
@@ -305,6 +307,7 @@ public class JsonPulsarHeaderMapper extends AbstractPulsarHeaderMapper<ToPulsarH
|
||||
* Context used for {@link #toSpringHeaders} (inbound) that includes the cumulative
|
||||
* map of header name to classname for headers in the incoming message that were
|
||||
* serialized with JSON. This is used to decode the headers in the incoming message.
|
||||
*
|
||||
* @param jsonTypes cumulative map of header name to classname for types that were
|
||||
* serialized as JSON
|
||||
*/
|
||||
|
||||
@@ -200,7 +200,7 @@ class CachingPulsarProducerFactoryTests extends PulsarProducerFactoryTests {
|
||||
when(this.pulsarClient.newProducer(schema)).thenThrow(new RuntimeException("5150"));
|
||||
var producerFactory = producerFactory(pulsarClient, null, null);
|
||||
assertThatThrownBy(() -> producerFactory.createProducer(schema, "topic1")).isInstanceOf(RuntimeException.class)
|
||||
.hasMessage("5150");
|
||||
.hasMessage("5150");
|
||||
getAssertedProducerCache(producerFactory, Collections.emptyList());
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ class CachingPulsarProducerFactoryTests extends PulsarProducerFactoryTests {
|
||||
private CacheProvider<ProducerCacheKey<String>, Producer<String>> getAssertedProducerCache(
|
||||
PulsarProducerFactory<String> producerFactory, List<ProducerCacheKey<String>> expectedCacheKeys) {
|
||||
CacheProvider<ProducerCacheKey<String>, Producer<String>> producerCache = (CacheProvider<ProducerCacheKey<String>, Producer<String>>) ReflectionTestUtils
|
||||
.getField(producerFactory, "producerCache");
|
||||
.getField(producerFactory, "producerCache");
|
||||
assertThat(producerCache).isNotNull();
|
||||
if (ObjectUtils.isEmpty(expectedCacheKeys)) {
|
||||
assertThat(producerCache.asMap()).isEmpty();
|
||||
@@ -241,13 +241,15 @@ class CachingPulsarProducerFactoryTests extends PulsarProducerFactoryTests {
|
||||
@Test
|
||||
void nullSchemaIsNotAllowed() {
|
||||
assertThatThrownBy(() -> new ProducerCacheKey<>(null, "topic1", null, null))
|
||||
.isInstanceOf(IllegalArgumentException.class).hasMessage("'schema' must be non-null");
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("'schema' must be non-null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullTopicIsNotAllowed() {
|
||||
assertThatThrownBy(() -> new ProducerCacheKey<>(schema, null, null, null))
|
||||
.isInstanceOf(IllegalArgumentException.class).hasMessage("'topic' must be non-null");
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("'topic' must be non-null");
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "equals({0}) should be {2}")
|
||||
@@ -263,52 +265,47 @@ class CachingPulsarProducerFactoryTests extends PulsarProducerFactoryTests {
|
||||
var encryptionKeys1 = Set.of("key1");
|
||||
List<ProducerBuilderCustomizer<String>> customizers1 = List.of(p -> p.property("key", "value"));
|
||||
var key1 = new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, customizers1);
|
||||
return Stream
|
||||
.of(arguments(Named.of("differentClass", key1), "someStrangeObject", false),
|
||||
arguments(Named.of("null", key1), null, false),
|
||||
arguments(Named.of("sameInstance", key1), key1, true),
|
||||
arguments(Named.of("sameSchemaSameTopicSameNullEncryptionKeysSameNullCustomizers",
|
||||
return Stream.of(arguments(Named.of("differentClass", key1), "someStrangeObject", false),
|
||||
arguments(Named.of("null", key1), null, false),
|
||||
arguments(Named.of("sameInstance", key1), key1, true),
|
||||
arguments(
|
||||
Named.of("sameSchemaSameTopicSameNullEncryptionKeysSameNullCustomizers",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", null, null)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", null, null), true),
|
||||
arguments(
|
||||
Named.of("sameSchemaSameTopicSameNonNullEncryptionKeysSameNullCustomizers",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null), true),
|
||||
arguments(
|
||||
Named.of("differentSchemaInstanceSameSchemaType",
|
||||
new ProducerCacheKey<>(new StringSchema(), "topic1", encryptionKeys1,
|
||||
null)),
|
||||
new ProducerCacheKey<>(new StringSchema(), "topic1", encryptionKeys1, null), true),
|
||||
arguments(
|
||||
Named.of("differentSchemaType",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(Schema.INT64, "topic1", encryptionKeys1, null), false),
|
||||
arguments(
|
||||
Named.of("differentTopic",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1,
|
||||
customizers1)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic2", encryptionKeys1, customizers1),
|
||||
false),
|
||||
arguments(
|
||||
Named.of("differentNonNullEncryptionKeys",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", Set.of("key2"), null), false),
|
||||
arguments(
|
||||
Named.of("differentNullEncryptionKeys",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", null, null), false),
|
||||
arguments(
|
||||
Named.of("differentNonNullCustomizers",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1,
|
||||
customizers1)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1,
|
||||
List.of(p -> p.property("key", "value"))),
|
||||
false),
|
||||
arguments(
|
||||
Named.of("differentNullInterceptor",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1,
|
||||
customizers1)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", null, null), false));
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", null, null), true),
|
||||
arguments(
|
||||
Named.of("sameSchemaSameTopicSameNonNullEncryptionKeysSameNullCustomizers",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null), true),
|
||||
arguments(
|
||||
Named.of("differentSchemaInstanceSameSchemaType",
|
||||
new ProducerCacheKey<>(new StringSchema(), "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(new StringSchema(), "topic1", encryptionKeys1, null), true),
|
||||
arguments(
|
||||
Named.of("differentSchemaType",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(Schema.INT64, "topic1", encryptionKeys1, null), false),
|
||||
arguments(
|
||||
Named.of("differentTopic",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, customizers1)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic2", encryptionKeys1, customizers1), false),
|
||||
arguments(
|
||||
Named.of("differentNonNullEncryptionKeys",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", Set.of("key2"), null), false),
|
||||
arguments(
|
||||
Named.of("differentNullEncryptionKeys",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, null)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", null, null), false),
|
||||
arguments(
|
||||
Named.of("differentNonNullCustomizers",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, customizers1)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1,
|
||||
List.of(p -> p.property("key", "value"))),
|
||||
false),
|
||||
arguments(
|
||||
Named.of("differentNullInterceptor",
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", encryptionKeys1, customizers1)),
|
||||
new ProducerCacheKey<>(Schema.STRING, "topic1", null, null), false));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,8 +59,9 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
|
||||
@Test
|
||||
void testRecordAck() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = spy(new DefaultPulsarConsumerFactory<>(
|
||||
pulsarClient, defaultConfig("cons-ack-tests-011", "cons-ack-tests-sb-011")));
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
@@ -92,14 +93,15 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
|
||||
@Test
|
||||
void testBatchAck() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = spy(new DefaultPulsarConsumerFactory<>(
|
||||
pulsarClient, defaultConfig("cons-ack-tests-012", "cons-ack-tests-sb-012")));
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
CountDownLatch latch = new CountDownLatch(10);
|
||||
pulsarContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch.countDown());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch.countDown());
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
DefaultPulsarMessageListenerContainer<String> container = new DefaultPulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
@@ -113,17 +115,18 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
}
|
||||
assertThat(latch.await(30, TimeUnit.SECONDS)).isTrue();
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, never()).acknowledge(any(Message.class)));
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(
|
||||
() -> verify(containerConsumer, atLeastOnce()).acknowledgeCumulative(any(Message.class)));
|
||||
.untilAsserted(() -> verify(containerConsumer, never()).acknowledge(any(Message.class)));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, atLeastOnce()).acknowledgeCumulative(any(Message.class)));
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBatchAckButSomeRecordsFail() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = spy(new DefaultPulsarConsumerFactory<>(
|
||||
pulsarClient, defaultConfig("cons-ack-tests-013", "cons-ack-tests-sb-013")));
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
@@ -157,17 +160,18 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
// acknowledged.
|
||||
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, times(5)).negativeAcknowledge(any(Message.class)));
|
||||
.untilAsserted(() -> verify(containerConsumer, times(5)).negativeAcknowledge(any(Message.class)));
|
||||
|
||||
int ackCalls = ackCallCount.get();
|
||||
if (ackCalls < 5) {
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, atMost(4)).acknowledge(any(MessageId.class)));
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(
|
||||
() -> verify(containerConsumer, atLeastOnce()).acknowledgeCumulative(any(Message.class)));
|
||||
.untilAsserted(() -> verify(containerConsumer, atMost(4)).acknowledge(any(MessageId.class)));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(
|
||||
() -> verify(containerConsumer, atLeastOnce()).acknowledgeCumulative(any(Message.class)));
|
||||
if (ackCalls == 0) {
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(
|
||||
() -> verify(containerConsumer, times(5)).acknowledgeCumulative(any(Message.class)));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, times(5)).acknowledgeCumulative(any(Message.class)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -181,8 +185,9 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void testManualAckForRecordListener() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = spy(new DefaultPulsarConsumerFactory<>(
|
||||
pulsarClient, defaultConfig("cons-ack-tests-014", "cons-ack-tests-sb-014")));
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
@@ -216,7 +221,7 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
// invocation.
|
||||
assertThat(acksObjects.size()).isEqualTo(10);
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, times(10)).acknowledge(any(MessageId.class)));
|
||||
.untilAsserted(() -> verify(containerConsumer, times(10)).acknowledge(any(MessageId.class)));
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -225,8 +230,9 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void testBatchAckForBatchListener() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = spy(new DefaultPulsarConsumerFactory<>(
|
||||
pulsarClient, defaultConfig("cons-ack-tests-015", "cons-ack-tests-sb-015")));
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
@@ -252,10 +258,11 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
pulsarTemplate.sendAsync("hello john doe");
|
||||
}
|
||||
assertThat(latch.await(30, TimeUnit.SECONDS)).isTrue();
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(
|
||||
() -> verify(pulsarBatchMessageListener, times(1)).received(any(Consumer.class), any(List.class)));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, times(1)).acknowledgeCumulative(any(Message.class)));
|
||||
.untilAsserted(
|
||||
() -> verify(pulsarBatchMessageListener, times(1)).received(any(Consumer.class), any(List.class)));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, times(1)).acknowledgeCumulative(any(Message.class)));
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
}
|
||||
@@ -263,8 +270,9 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void testBatchNackForEntireBatchWhenUsingBatchListener() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = spy(new DefaultPulsarConsumerFactory<>(
|
||||
pulsarClient, defaultConfig("cons-ack-tests-016", "cons-ack-tests-sb-016")));
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
@@ -292,23 +300,24 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
assertThat(latch.await(30, TimeUnit.SECONDS)).isTrue();
|
||||
Thread.sleep(2_000);
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, times(1)).negativeAcknowledge(any(Messages.class)));
|
||||
.untilAsserted(() -> verify(containerConsumer, times(1)).negativeAcknowledge(any(Messages.class)));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, never()).acknowledge(any(Messages.class)));
|
||||
.untilAsserted(() -> verify(containerConsumer, never()).acknowledge(any(Messages.class)));
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void messagesAreProperlyAckdOnContainerStopBeforeExitingListenerThread() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
defaultConfig("duplicate-message-test", "duplicate-sub-1"));
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
AtomicInteger counter1 = new AtomicInteger(0);
|
||||
pulsarContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> counter1.getAndIncrement());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> counter1.getAndIncrement());
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
DefaultPulsarMessageListenerContainer<String> container1 = new DefaultPulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
@@ -330,7 +339,7 @@ class ConsumerAcknowledgmentTests implements PulsarTestContainerSupport {
|
||||
|
||||
AtomicInteger counter2 = new AtomicInteger(0);
|
||||
pulsarContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> counter2.getAndIncrement());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> counter2.getAndIncrement());
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
DefaultPulsarMessageListenerContainer<String> container2 = new DefaultPulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
|
||||
@@ -78,20 +78,25 @@ public class ConsumerBuilderConfigurationUtilTests {
|
||||
ConsumerBuilderConfigurationUtil.loadConf(builder, props);
|
||||
|
||||
assertThat(this.builder).extracting("conf")
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(ConsumerConfigurationData.class)).extracting(propName)
|
||||
.isEqualTo(expectedObj);
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(ConsumerConfigurationData.class))
|
||||
.extracting(propName)
|
||||
.isEqualTo(expectedObj);
|
||||
|
||||
assertThat(props).isEqualTo(propsBeforeUtil);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private static Stream<Arguments> loadConfTestProvider() {
|
||||
DeadLetterPolicy deadLetterPolicyOnBuilder = DeadLetterPolicy.builder().deadLetterTopic("dlt-topic")
|
||||
.maxRedeliverCount(1).build();
|
||||
DeadLetterPolicy deadLetterPolicyInProps = DeadLetterPolicy.builder().deadLetterTopic("dlt-topic")
|
||||
.maxRedeliverCount(2).build();
|
||||
DeadLetterPolicy deadLetterPolicyOnBuilder = DeadLetterPolicy.builder()
|
||||
.deadLetterTopic("dlt-topic")
|
||||
.maxRedeliverCount(1)
|
||||
.build();
|
||||
DeadLetterPolicy deadLetterPolicyInProps = DeadLetterPolicy.builder()
|
||||
.deadLetterTopic("dlt-topic")
|
||||
.maxRedeliverCount(2)
|
||||
.build();
|
||||
ConsumerBuilderCustomizer<String> deadLetterPolicyCustomizer = c -> c
|
||||
.deadLetterPolicy(deadLetterPolicyOnBuilder);
|
||||
.deadLetterPolicy(deadLetterPolicyOnBuilder);
|
||||
|
||||
MessageListener<String> messageListenerOnBuilder = mock(MessageListener.class);
|
||||
MessageListener<String> messageListenerInProps = mock(MessageListener.class);
|
||||
@@ -100,17 +105,17 @@ public class ConsumerBuilderConfigurationUtilTests {
|
||||
ConsumerEventListener consumerEventListenerOnBuilder = mock(ConsumerEventListener.class);
|
||||
ConsumerEventListener consumerEventListenerInProps = mock(ConsumerEventListener.class);
|
||||
ConsumerBuilderCustomizer<String> consumerEventListenerCustomizer = c -> c
|
||||
.consumerEventListener(consumerEventListenerOnBuilder);
|
||||
.consumerEventListener(consumerEventListenerOnBuilder);
|
||||
|
||||
RedeliveryBackoff nackRedeliveryBackoffOnBuilder = mock(RedeliveryBackoff.class);
|
||||
RedeliveryBackoff nackRedeliveryBackoffInProps = mock(RedeliveryBackoff.class);
|
||||
ConsumerBuilderCustomizer<String> nackRedeliveryBackoffCustomizer = c -> c
|
||||
.negativeAckRedeliveryBackoff(nackRedeliveryBackoffOnBuilder);
|
||||
.negativeAckRedeliveryBackoff(nackRedeliveryBackoffOnBuilder);
|
||||
|
||||
RedeliveryBackoff ackRedeliveryBackoffOnBuilder = mock(RedeliveryBackoff.class);
|
||||
RedeliveryBackoff ackRedeliveryBackoffInProps = mock(RedeliveryBackoff.class);
|
||||
ConsumerBuilderCustomizer<String> ackRedeliveryBackoffCustomizer = c -> c
|
||||
.ackTimeoutRedeliveryBackoff(ackRedeliveryBackoffOnBuilder);
|
||||
.ackTimeoutRedeliveryBackoff(ackRedeliveryBackoffOnBuilder);
|
||||
|
||||
CryptoKeyReader cryptoKeyReaderOnBuilder = mock(CryptoKeyReader.class);
|
||||
CryptoKeyReader cryptoKeyReaderInProps = mock(CryptoKeyReader.class);
|
||||
@@ -123,12 +128,12 @@ public class ConsumerBuilderConfigurationUtilTests {
|
||||
BatchReceivePolicy batchReceivePolicyOnBuilder = mock(BatchReceivePolicy.class);
|
||||
BatchReceivePolicy batchReceivePolicyInProps = mock(BatchReceivePolicy.class);
|
||||
ConsumerBuilderCustomizer<String> batchReceivePolicyCustomizer = c -> c
|
||||
.batchReceivePolicy(batchReceivePolicyOnBuilder);
|
||||
.batchReceivePolicy(batchReceivePolicyOnBuilder);
|
||||
|
||||
MessagePayloadProcessor payloadProcessorOnBuilder = mock(MessagePayloadProcessor.class);
|
||||
MessagePayloadProcessor payloadProcessorInProps = mock(MessagePayloadProcessor.class);
|
||||
ConsumerBuilderCustomizer<String> payloadProcessorCustomizer = c -> c
|
||||
.messagePayloadProcessor(payloadProcessorOnBuilder);
|
||||
.messagePayloadProcessor(payloadProcessorOnBuilder);
|
||||
|
||||
return Stream.of(arguments("loadConfNoDeadLetterPolicy", "deadLetterPolicy", null, null, null),
|
||||
arguments("loadConfDeadLetterPolicyOnBuilder", "deadLetterPolicy", deadLetterPolicyCustomizer, null,
|
||||
|
||||
@@ -48,8 +48,8 @@ class DefaultPulsarClientFactoryTests {
|
||||
@Test
|
||||
void constructWithNullCustomizer() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new DefaultPulsarClientFactory((PulsarClientBuilderCustomizer) null))
|
||||
.withMessage("customizer must not be null");
|
||||
.isThrownBy(() -> new DefaultPulsarClientFactory((PulsarClientBuilderCustomizer) null))
|
||||
.withMessage("customizer must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -78,15 +78,16 @@ class DefaultPulsarConsumerFactoryTests implements PulsarTestContainerSupport {
|
||||
void withoutSchema() {
|
||||
assertThatThrownBy(
|
||||
() -> consumerFactory.createConsumer(null, Collections.singletonList("topic0"), null, null, null))
|
||||
.isInstanceOf(NullPointerException.class).hasMessageContaining("Schema must be specified");
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
.hasMessageContaining("Schema must be specified");
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@Test
|
||||
void withSchemaOnly() {
|
||||
assertThatThrownBy(() -> consumerFactory.createConsumer(SCHEMA, null, null, null, null))
|
||||
.isInstanceOf(InvalidConfigurationException.class)
|
||||
.hasMessageContaining("Topic name must be set on the consumer builder");
|
||||
.isInstanceOf(InvalidConfigurationException.class)
|
||||
.hasMessageContaining("Topic name must be set on the consumer builder");
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@@ -94,8 +95,8 @@ class DefaultPulsarConsumerFactoryTests implements PulsarTestContainerSupport {
|
||||
void withSchemaAndTopics() {
|
||||
assertThatThrownBy(
|
||||
() -> consumerFactory.createConsumer(SCHEMA, Collections.singletonList("topic0"), null, null, null))
|
||||
.isInstanceOf(InvalidConfigurationException.class)
|
||||
.hasMessageContaining("Subscription name must be set on the consumer builder");
|
||||
.isInstanceOf(InvalidConfigurationException.class)
|
||||
.hasMessageContaining("Subscription name must be set on the consumer builder");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -180,7 +181,8 @@ class DefaultPulsarConsumerFactoryTests implements PulsarTestContainerSupport {
|
||||
void withoutSchema() {
|
||||
assertThatThrownBy(
|
||||
() -> consumerFactory.createConsumer(null, Collections.singletonList("topic0"), null, null, null))
|
||||
.isInstanceOf(NullPointerException.class).hasMessageContaining("Schema must be specified");
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
.hasMessageContaining("Schema must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -171,7 +171,7 @@ public class DefaultPulsarReaderFactoryTests implements PulsarTestContainerSuppo
|
||||
@Test
|
||||
void customizersAreAppliedLast() throws Exception {
|
||||
ReaderBuilderCustomizer<String> customizer = (readerBuilder) -> readerBuilder
|
||||
.topic("basic-pulsar-reader-topic");
|
||||
.topic("basic-pulsar-reader-topic");
|
||||
// The following code expects the above topic will override the passed in
|
||||
// 'foo-topic'
|
||||
try (var reader = pulsarReaderFactory.createReader(List.of("foo-topic"), MessageId.earliest, Schema.STRING,
|
||||
@@ -200,15 +200,18 @@ public class DefaultPulsarReaderFactoryTests implements PulsarTestContainerSuppo
|
||||
void missingTopic() {
|
||||
// topic name is not set in the API call or in the reader config.
|
||||
assertThatThrownBy(() -> pulsarReaderFactory.createReader(Collections.emptyList(), MessageId.earliest,
|
||||
Schema.STRING, Collections.emptyList())).isInstanceOf(PulsarClientException.class)
|
||||
.hasMessageContaining("Topic name must be set on the reader builder");
|
||||
Schema.STRING, Collections.emptyList()))
|
||||
.isInstanceOf(PulsarClientException.class)
|
||||
.hasMessageContaining("Topic name must be set on the reader builder");
|
||||
}
|
||||
|
||||
@Test
|
||||
void missingStartingMessageId() {
|
||||
assertThatThrownBy(() -> pulsarReaderFactory.createReader(List.of("my-reader-topic"), null, Schema.STRING,
|
||||
Collections.emptyList())).isInstanceOf(PulsarClientException.class).hasMessageContaining(
|
||||
"Start message id or start message from roll back must be specified but they cannot be specified at the same time");
|
||||
Collections.emptyList()))
|
||||
.isInstanceOf(PulsarClientException.class)
|
||||
.hasMessageContaining(
|
||||
"Start message id or start message from roll back must be specified but they cannot be specified at the same time");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -73,11 +73,11 @@ class DefaultSchemaResolverTests {
|
||||
Schema<?> previouslyMappedSchema = resolver.addCustomSchemaMapping(Foo.class, Schema.STRING);
|
||||
assertThat(previouslyMappedSchema).isNull();
|
||||
assertThat(resolver.getCustomSchemaMappings()).asInstanceOf(InstanceOfAssertFactories.MAP)
|
||||
.containsEntry(Foo.class, Schema.STRING);
|
||||
.containsEntry(Foo.class, Schema.STRING);
|
||||
previouslyMappedSchema = resolver.addCustomSchemaMapping(Foo.class, Schema.BOOL);
|
||||
assertThat(previouslyMappedSchema).isEqualTo(Schema.STRING);
|
||||
assertThat(resolver.getCustomSchemaMappings()).asInstanceOf(InstanceOfAssertFactories.MAP)
|
||||
.containsEntry(Foo.class, Schema.BOOL);
|
||||
.containsEntry(Foo.class, Schema.BOOL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -140,7 +140,7 @@ class DefaultSchemaResolverTests {
|
||||
assertThat(resolver.resolveSchema(new Foo("foo1")).orElseThrow()).isSameAs(fooSchema);
|
||||
assertThat(resolver.resolveSchema(new Bar<>("bar1")).orElseThrow()).isEqualTo(Schema.STRING);
|
||||
assertThat(resolver.resolveSchema(new Zaa("zaa1")).orElseThrow().getSchemaInfo())
|
||||
.isEqualTo(Schema.JSON(Zaa.class).getSchemaInfo());
|
||||
.isEqualTo(Schema.JSON(Zaa.class).getSchemaInfo());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -190,13 +190,13 @@ class DefaultSchemaResolverTests {
|
||||
@Test
|
||||
void customMessageTypes() {
|
||||
assertThatExceptionOfType(IllegalArgumentException.class)
|
||||
.isThrownBy(() -> resolver.resolveSchema(Foo.class, false).orElseThrow());
|
||||
.isThrownBy(() -> resolver.resolveSchema(Foo.class, false).orElseThrow());
|
||||
assertThat(resolver.resolveSchema(Foo.class, true).orElseThrow().getSchemaInfo())
|
||||
.isEqualTo(Schema.JSON(Foo.class).getSchemaInfo());
|
||||
.isEqualTo(Schema.JSON(Foo.class).getSchemaInfo());
|
||||
resolver.addCustomSchemaMapping(Foo.class, Schema.STRING);
|
||||
assertThat(resolver.resolveSchema(Foo.class, false).orElseThrow()).isEqualTo(Schema.STRING);
|
||||
assertThatExceptionOfType(IllegalArgumentException.class)
|
||||
.isThrownBy(() -> resolver.resolveSchema(Bar.class, false).orElseThrow());
|
||||
.isThrownBy(() -> resolver.resolveSchema(Bar.class, false).orElseThrow());
|
||||
assertThat(resolver.resolveSchema(Bar.class, true).orElseThrow()).isEqualTo(Schema.BYTES);
|
||||
}
|
||||
|
||||
@@ -237,37 +237,38 @@ class DefaultSchemaResolverTests {
|
||||
@Test
|
||||
void structSchemas() {
|
||||
assertThat(resolver.resolveSchema(SchemaType.JSON, ResolvableType.forType(Foo.class)).orElseThrow())
|
||||
.isInstanceOf(JSONSchema.class)
|
||||
.hasFieldOrPropertyWithValue("schema.fullName", sanitizedClassName(Foo.class));
|
||||
.isInstanceOf(JSONSchema.class)
|
||||
.hasFieldOrPropertyWithValue("schema.fullName", sanitizedClassName(Foo.class));
|
||||
assertThat(resolver.resolveSchema(SchemaType.AVRO, ResolvableType.forType(Foo.class)).orElseThrow())
|
||||
.isInstanceOf(AvroSchema.class)
|
||||
.hasFieldOrPropertyWithValue("schema.fullName", sanitizedClassName(Foo.class));
|
||||
.isInstanceOf(AvroSchema.class)
|
||||
.hasFieldOrPropertyWithValue("schema.fullName", sanitizedClassName(Foo.class));
|
||||
assertThat(resolver.resolveSchema(SchemaType.PROTOBUF, ResolvableType.forType(Person.class)).orElseThrow())
|
||||
.isInstanceOf(ProtobufSchema.class)
|
||||
.hasFieldOrPropertyWithValue("schema.fullName", sanitizedClassName(Proto.Person.class));
|
||||
.isInstanceOf(ProtobufSchema.class)
|
||||
.hasFieldOrPropertyWithValue("schema.fullName", sanitizedClassName(Proto.Person.class));
|
||||
ResolvableType kvType = ResolvableType.forClassWithGenerics(KeyValue.class, String.class, Integer.class);
|
||||
assertThat(resolver.resolveSchema(SchemaType.KEY_VALUE, kvType).orElseThrow())
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(KeyValueSchema.class)).satisfies((keyValueSchema -> {
|
||||
assertThat(keyValueSchema.getKeySchema()).isEqualTo(Schema.STRING);
|
||||
assertThat(keyValueSchema.getValueSchema()).isEqualTo(Schema.INT32);
|
||||
assertThat(keyValueSchema.getKeyValueEncodingType()).isEqualTo(KeyValueEncodingType.INLINE);
|
||||
}));
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(KeyValueSchema.class))
|
||||
.satisfies((keyValueSchema -> {
|
||||
assertThat(keyValueSchema.getKeySchema()).isEqualTo(Schema.STRING);
|
||||
assertThat(keyValueSchema.getValueSchema()).isEqualTo(Schema.INT32);
|
||||
assertThat(keyValueSchema.getKeyValueEncodingType()).isEqualTo(KeyValueEncodingType.INLINE);
|
||||
}));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(value = SchemaType.class, names = { "JSON", "AVRO", "PROTOBUF", "KEY_VALUE" })
|
||||
void structSchemasRequireMessageType(SchemaType schemaType) {
|
||||
assertThatExceptionOfType(NullPointerException.class)
|
||||
.isThrownBy(() -> resolver.resolveSchema(schemaType, null).orElseThrow())
|
||||
.withMessage("messageType must be specified for " + schemaType.name());
|
||||
.isThrownBy(() -> resolver.resolveSchema(schemaType, null).orElseThrow())
|
||||
.withMessage("messageType must be specified for " + schemaType.name());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(value = SchemaType.class, names = { "PROTOBUF_NATIVE", "AUTO", "AUTO_CONSUME", "AUTO_PUBLISH" })
|
||||
void unsupportedSchemaTypes(SchemaType unsupportedType) {
|
||||
assertThatExceptionOfType(IllegalArgumentException.class)
|
||||
.isThrownBy(() -> resolver.resolveSchema(unsupportedType, null).orElseThrow())
|
||||
.withMessage("Unsupported schema type: " + unsupportedType.name());
|
||||
.isThrownBy(() -> resolver.resolveSchema(unsupportedType, null).orElseThrow())
|
||||
.withMessage("Unsupported schema type: " + unsupportedType.name());
|
||||
}
|
||||
|
||||
private String sanitizedClassName(Class<?> clazz) {
|
||||
@@ -285,20 +286,21 @@ class DefaultSchemaResolverTests {
|
||||
@Test
|
||||
void primitiveMessageType() {
|
||||
assertThat(resolver.resolveSchema(SchemaType.NONE, ResolvableType.forType(String.class)).orElseThrow())
|
||||
.isEqualTo(Schema.STRING);
|
||||
.isEqualTo(Schema.STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
void customMessageTypeDefaultsToJson() {
|
||||
assertThat(resolver.resolveSchema(SchemaType.NONE, ResolvableType.forType(Foo.class)).orElseThrow())
|
||||
.extracting(Schema::getSchemaInfo).isEqualTo(Schema.JSON(Foo.class).getSchemaInfo());
|
||||
.extracting(Schema::getSchemaInfo)
|
||||
.isEqualTo(Schema.JSON(Foo.class).getSchemaInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void customMessageTypeRespectsCustomMappings() {
|
||||
resolver.addCustomSchemaMapping(Foo.class, Schema.STRING);
|
||||
assertThat(resolver.resolveSchema(SchemaType.NONE, ResolvableType.forType(Foo.class)).orElseThrow())
|
||||
.isEqualTo(Schema.STRING);
|
||||
.isEqualTo(Schema.STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -306,26 +308,26 @@ class DefaultSchemaResolverTests {
|
||||
ResolvableType kvType = ResolvableType.forClassWithGenerics(KeyValue.class, String.class,
|
||||
Integer.class);
|
||||
assertThat(resolver.resolveSchema(SchemaType.NONE, kvType).orElseThrow())
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(KeyValueSchema.class))
|
||||
.satisfies((keyValueSchema -> {
|
||||
assertThat(keyValueSchema.getKeySchema()).isEqualTo(Schema.STRING);
|
||||
assertThat(keyValueSchema.getValueSchema()).isEqualTo(Schema.INT32);
|
||||
assertThat(keyValueSchema.getKeyValueEncodingType()).isEqualTo(KeyValueEncodingType.INLINE);
|
||||
}));
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(KeyValueSchema.class))
|
||||
.satisfies((keyValueSchema -> {
|
||||
assertThat(keyValueSchema.getKeySchema()).isEqualTo(Schema.STRING);
|
||||
assertThat(keyValueSchema.getValueSchema()).isEqualTo(Schema.INT32);
|
||||
assertThat(keyValueSchema.getKeyValueEncodingType()).isEqualTo(KeyValueEncodingType.INLINE);
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customKeyValueMessageTypeDefaultsToJSONSchema() {
|
||||
ResolvableType kvType = ResolvableType.forClassWithGenerics(KeyValue.class, Foo.class, Zaa.class);
|
||||
assertThat(resolver.resolveSchema(SchemaType.NONE, kvType).orElseThrow())
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(KeyValueSchema.class))
|
||||
.satisfies((keyValueSchema -> {
|
||||
assertThat(keyValueSchema.getKeySchema().getSchemaInfo())
|
||||
.isEqualTo(Schema.JSON(Foo.class).getSchemaInfo());
|
||||
assertThat(keyValueSchema.getValueSchema().getSchemaInfo())
|
||||
.isEqualTo(Schema.JSON(Zaa.class).getSchemaInfo());
|
||||
assertThat(keyValueSchema.getKeyValueEncodingType()).isEqualTo(KeyValueEncodingType.INLINE);
|
||||
}));
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(KeyValueSchema.class))
|
||||
.satisfies((keyValueSchema -> {
|
||||
assertThat(keyValueSchema.getKeySchema().getSchemaInfo())
|
||||
.isEqualTo(Schema.JSON(Foo.class).getSchemaInfo());
|
||||
assertThat(keyValueSchema.getValueSchema().getSchemaInfo())
|
||||
.isEqualTo(Schema.JSON(Zaa.class).getSchemaInfo());
|
||||
assertThat(keyValueSchema.getKeyValueEncodingType()).isEqualTo(KeyValueEncodingType.INLINE);
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -336,12 +338,12 @@ class DefaultSchemaResolverTests {
|
||||
resolver.addCustomSchemaMapping(Bar.class, barSchema);
|
||||
ResolvableType kvType = ResolvableType.forClassWithGenerics(KeyValue.class, Foo.class, Bar.class);
|
||||
assertThat(resolver.resolveSchema(SchemaType.NONE, kvType).orElseThrow())
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(KeyValueSchema.class))
|
||||
.satisfies((keyValueSchema -> {
|
||||
assertThat(keyValueSchema.getKeySchema()).isSameAs(fooSchema);
|
||||
assertThat(keyValueSchema.getValueSchema()).isSameAs(barSchema);
|
||||
assertThat(keyValueSchema.getKeyValueEncodingType()).isEqualTo(KeyValueEncodingType.INLINE);
|
||||
}));
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(KeyValueSchema.class))
|
||||
.satisfies((keyValueSchema -> {
|
||||
assertThat(keyValueSchema.getKeySchema()).isSameAs(fooSchema);
|
||||
assertThat(keyValueSchema.getValueSchema()).isSameAs(barSchema);
|
||||
assertThat(keyValueSchema.getKeyValueEncodingType()).isEqualTo(KeyValueEncodingType.INLINE);
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -351,7 +353,7 @@ class DefaultSchemaResolverTests {
|
||||
record Foo(String value) {
|
||||
}
|
||||
|
||||
record Bar<T> (T value) {
|
||||
record Bar<T>(T value) {
|
||||
}
|
||||
|
||||
record Zaa(String value) {
|
||||
|
||||
@@ -77,7 +77,7 @@ class DefaultTopicResolverTests {
|
||||
<T> void resolveByMessageInstance(String testName, @Nullable String userTopic, T message,
|
||||
@Nullable String defaultTopic, @Nullable String expectedTopic) {
|
||||
assertThat(resolver.resolveTopic(userTopic, message, () -> defaultTopic).get().orElse(null))
|
||||
.isEqualTo(expectedTopic);
|
||||
.isEqualTo(expectedTopic);
|
||||
}
|
||||
|
||||
static Stream<Arguments> resolveByMessageInstanceProvider() {
|
||||
@@ -100,7 +100,7 @@ class DefaultTopicResolverTests {
|
||||
void resolveByMessageType(String testName, @Nullable String userTopic, Class<?> messageType,
|
||||
@Nullable String defaultTopic, @Nullable String expectedTopic) {
|
||||
assertThat(resolver.resolveTopic(userTopic, messageType, () -> defaultTopic).get().orElse(null))
|
||||
.isEqualTo(expectedTopic);
|
||||
.isEqualTo(expectedTopic);
|
||||
}
|
||||
|
||||
static Stream<Arguments> resolveByMessageTypeProvider() {
|
||||
@@ -141,11 +141,11 @@ class DefaultTopicResolverTests {
|
||||
String previouslyMappedTopic = resolver.addCustomTopicMapping(Foo.class, topic1);
|
||||
assertThat(previouslyMappedTopic).isNull();
|
||||
assertThat(resolver.getCustomTopicMappings()).asInstanceOf(InstanceOfAssertFactories.MAP)
|
||||
.containsEntry(Foo.class, topic1);
|
||||
.containsEntry(Foo.class, topic1);
|
||||
previouslyMappedTopic = resolver.addCustomTopicMapping(Foo.class, topic2);
|
||||
assertThat(previouslyMappedTopic).isEqualTo(topic1);
|
||||
assertThat(resolver.getCustomTopicMappings()).asInstanceOf(InstanceOfAssertFactories.MAP)
|
||||
.containsEntry(Foo.class, topic2);
|
||||
.containsEntry(Foo.class, topic2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -44,13 +44,15 @@ class FailoverConsumerTests implements PulsarTestContainerSupport {
|
||||
|
||||
@Test
|
||||
void testFailOverConsumersOnPartitionedTopic() throws Exception {
|
||||
PulsarAdmin admin = PulsarAdmin.builder().serviceHttpUrl(PulsarTestContainerSupport.getHttpServiceUrl())
|
||||
.build();
|
||||
PulsarAdmin admin = PulsarAdmin.builder()
|
||||
.serviceHttpUrl(PulsarTestContainerSupport.getHttpServiceUrl())
|
||||
.build();
|
||||
String topicName = "persistent://public/default/my-part-topic-1";
|
||||
admin.topics().createPartitionedTopic(topicName, 3);
|
||||
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("my-part-topic-1");
|
||||
@@ -63,7 +65,7 @@ class FailoverConsumerTests implements PulsarTestContainerSupport {
|
||||
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
pulsarContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch1.countDown());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch1.countDown());
|
||||
pulsarContainerProperties.setSubscriptionType(SubscriptionType.Failover);
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
DefaultPulsarMessageListenerContainer<String> container1 = new DefaultPulsarMessageListenerContainer<>(
|
||||
@@ -71,13 +73,13 @@ class FailoverConsumerTests implements PulsarTestContainerSupport {
|
||||
container1.start();
|
||||
|
||||
pulsarContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch2.countDown());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch2.countDown());
|
||||
DefaultPulsarMessageListenerContainer<String> container2 = new DefaultPulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
container2.start();
|
||||
|
||||
pulsarContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch3.countDown());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch3.countDown());
|
||||
DefaultPulsarMessageListenerContainer<String> container3 = new DefaultPulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
container3.start();
|
||||
@@ -87,11 +89,14 @@ class FailoverConsumerTests implements PulsarTestContainerSupport {
|
||||
PulsarTemplate<String> pulsarTemplate = new PulsarTemplate<>(pulsarProducerFactory);
|
||||
|
||||
pulsarTemplate.newMessage("hello john doe")
|
||||
.withProducerCustomizer(builder -> builder.messageRouter(new FooRouter())).sendAsync();
|
||||
.withProducerCustomizer(builder -> builder.messageRouter(new FooRouter()))
|
||||
.sendAsync();
|
||||
pulsarTemplate.newMessage("hello alice doe")
|
||||
.withProducerCustomizer(builder -> builder.messageRouter(new BarRouter())).sendAsync();
|
||||
.withProducerCustomizer(builder -> builder.messageRouter(new BarRouter()))
|
||||
.sendAsync();
|
||||
pulsarTemplate.newMessage("hello buzz doe")
|
||||
.withProducerCustomizer(builder -> builder.messageRouter(new BuzzRouter())).sendAsync();
|
||||
.withProducerCustomizer(builder -> builder.messageRouter(new BuzzRouter()))
|
||||
.sendAsync();
|
||||
|
||||
boolean await1 = latch1.await(10, TimeUnit.SECONDS);
|
||||
boolean await2 = latch2.await(10, TimeUnit.SECONDS);
|
||||
|
||||
@@ -145,7 +145,8 @@ public class PulsarAdministrationTests implements PulsarTestContainerSupport {
|
||||
|
||||
static {
|
||||
try (var pulsarAdmin = PulsarAdmin.builder()
|
||||
.serviceHttpUrl(PulsarTestContainerSupport.getHttpServiceUrl()).build()) {
|
||||
.serviceHttpUrl(PulsarTestContainerSupport.getHttpServiceUrl())
|
||||
.build()) {
|
||||
pulsarAdmin.namespaces().createNamespace(PUBLIC_GREEN_NAMESPACE);
|
||||
pulsarAdmin.namespaces().createNamespace(PUBLIC_BLUE_NAMESPACE);
|
||||
}
|
||||
@@ -157,13 +158,15 @@ public class PulsarAdministrationTests implements PulsarTestContainerSupport {
|
||||
@Bean
|
||||
PulsarTopic partitionedGreenTopic() {
|
||||
return PulsarTopic.builder("persistent://%s/partitioned-1".formatted(PUBLIC_GREEN_NAMESPACE))
|
||||
.numberOfPartitions(2).build();
|
||||
.numberOfPartitions(2)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
PulsarTopic partitionedBlueTopic() {
|
||||
return PulsarTopic.builder("persistent://%s/partitioned-1".formatted(PUBLIC_BLUE_NAMESPACE))
|
||||
.numberOfPartitions(2).build();
|
||||
.numberOfPartitions(2)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -203,8 +206,8 @@ public class PulsarAdministrationTests implements PulsarTestContainerSupport {
|
||||
assertThatTopicsExist(expectedTopics.stream().toList());
|
||||
PulsarTopic smallerTopic = PulsarTopic.builder("dpc-partitioned-1").numberOfPartitions(4).build();
|
||||
assertThatIllegalStateException().isThrownBy(() -> pulsarAdministration.createOrModifyTopics(smallerTopic))
|
||||
.withMessage(
|
||||
"Topic 'persistent://public/default/dpc-partitioned-1' found w/ 8 partitions but can't shrink to 4 - needs to be deleted first");
|
||||
.withMessage(
|
||||
"Topic 'persistent://public/default/dpc-partitioned-1' found w/ 8 partitions but can't shrink to 4 - needs to be deleted first");
|
||||
|
||||
}
|
||||
|
||||
@@ -230,8 +233,9 @@ public class PulsarAdministrationTests implements PulsarTestContainerSupport {
|
||||
var partitionedTopic = PulsarTopic.builder("ctt-foo").numberOfPartitions(3).build();
|
||||
pulsarAdministration.createOrModifyTopics(unpartitionedTopic);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> pulsarAdministration.createOrModifyTopics(partitionedTopic)).withMessage(
|
||||
"Topic 'persistent://public/default/ctt-foo' already exists un-partitioned - needs to be deleted first");
|
||||
.isThrownBy(() -> pulsarAdministration.createOrModifyTopics(partitionedTopic))
|
||||
.withMessage(
|
||||
"Topic 'persistent://public/default/ctt-foo' already exists un-partitioned - needs to be deleted first");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -240,8 +244,9 @@ public class PulsarAdministrationTests implements PulsarTestContainerSupport {
|
||||
var partitionedTopic = PulsarTopic.builder("ctt-bar").numberOfPartitions(3).build();
|
||||
pulsarAdministration.createOrModifyTopics(partitionedTopic);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> pulsarAdministration.createOrModifyTopics(unpartitionedTopic)).withMessage(
|
||||
"Topic 'persistent://public/default/ctt-bar' already exists partitioned - needs to be deleted first");
|
||||
.isThrownBy(() -> pulsarAdministration.createOrModifyTopics(unpartitionedTopic))
|
||||
.withMessage(
|
||||
"Topic 'persistent://public/default/ctt-bar' already exists partitioned - needs to be deleted first");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,8 +86,9 @@ abstract class PulsarProducerFactoryTests implements PulsarTestContainerSupport
|
||||
protected void assertThatProducerHasEncryptionKeys(Producer<String> producer, Set<String> encryptionKeys) {
|
||||
producer = actualProducer(producer);
|
||||
assertThat(producer).extracting("conf")
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(ProducerConfigurationData.class))
|
||||
.extracting(ProducerConfigurationData::getEncryptionKeys).isEqualTo(encryptionKeys);
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(ProducerConfigurationData.class))
|
||||
.extracting(ProducerConfigurationData::getEncryptionKeys)
|
||||
.isEqualTo(encryptionKeys);
|
||||
}
|
||||
|
||||
protected PulsarProducerFactory<String> newProducerFactory() {
|
||||
@@ -141,7 +142,7 @@ abstract class PulsarProducerFactoryTests implements PulsarTestContainerSupport
|
||||
@Test
|
||||
void withoutSchema() {
|
||||
assertThatNullPointerException().isThrownBy(() -> newProducerFactory().createProducer(null, "topic0"))
|
||||
.withMessageContaining("Schema must be specified");
|
||||
.withMessageContaining("Schema must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,7 +163,7 @@ abstract class PulsarProducerFactoryTests implements PulsarTestContainerSupport
|
||||
@Test
|
||||
void noTopicSpecifiedWithoutDefaultTopic() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> newProducerFactory().createProducer(schema, null))
|
||||
.withMessageContaining("Topic must be specified when no default topic is configured");
|
||||
.withMessageContaining("Topic must be specified when no default topic is configured");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -76,8 +76,10 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
void tearDown() throws PulsarClientException {
|
||||
// Make sure the producer was closed by the template (albeit indirectly as
|
||||
// client removes closed producers)
|
||||
await().atMost(Duration.ofSeconds(3)).untilAsserted(() -> assertThat(client).extracting("producers")
|
||||
.asInstanceOf(InstanceOfAssertFactories.COLLECTION).isEmpty());
|
||||
await().atMost(Duration.ofSeconds(3))
|
||||
.untilAsserted(() -> assertThat(client).extracting("producers")
|
||||
.asInstanceOf(InstanceOfAssertFactories.COLLECTION)
|
||||
.isEmpty());
|
||||
client.close();
|
||||
}
|
||||
|
||||
@@ -104,35 +106,36 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
true, message),
|
||||
arguments("simpleSendWithTopicAndSchema",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template
|
||||
.send("simpleSendWithTopicAndSchema", message, Schema.STRING),
|
||||
.send("simpleSendWithTopicAndSchema", message, Schema.STRING),
|
||||
false, message),
|
||||
arguments("simpleSendNullWithTopicAndSchema",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template
|
||||
.send("simpleSendNullWithTopicAndSchema", null, Schema.STRING),
|
||||
.send("simpleSendNullWithTopicAndSchema", null, Schema.STRING),
|
||||
false, null),
|
||||
|
||||
// Simple send async
|
||||
arguments("simpleSendAsyncWithDefaultTopic",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template.sendAsync(message).get(3,
|
||||
TimeUnit.SECONDS),
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template.sendAsync(message)
|
||||
.get(3, TimeUnit.SECONDS),
|
||||
true, message),
|
||||
arguments("simpleSendAsyncWithTopic",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template
|
||||
.sendAsync("simpleSendAsyncWithTopic", message).get(3, TimeUnit.SECONDS),
|
||||
.sendAsync("simpleSendAsyncWithTopic", message)
|
||||
.get(3, TimeUnit.SECONDS),
|
||||
false, message),
|
||||
arguments("simpleSendAsyncWithDefaultTopicAndSchema",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template
|
||||
.sendAsync(message, Schema.STRING).get(3, TimeUnit.SECONDS),
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (
|
||||
template) -> template.sendAsync(message, Schema.STRING).get(3, TimeUnit.SECONDS),
|
||||
true, message),
|
||||
arguments("simpleSendAsyncWithTopicAndSchema",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template
|
||||
.sendAsync("simpleSendAsyncWithTopicAndSchema", message, Schema.STRING)
|
||||
.get(3, TimeUnit.SECONDS),
|
||||
.sendAsync("simpleSendAsyncWithTopicAndSchema", message, Schema.STRING)
|
||||
.get(3, TimeUnit.SECONDS),
|
||||
false, message),
|
||||
arguments("simpleSendAsyncNullWithTopicAndSchema",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template
|
||||
.sendAsync("simpleSendAsyncNullWithTopicAndSchema", null, Schema.STRING)
|
||||
.get(3, TimeUnit.SECONDS),
|
||||
.sendAsync("simpleSendAsyncNullWithTopicAndSchema", null, Schema.STRING)
|
||||
.get(3, TimeUnit.SECONDS),
|
||||
false, null),
|
||||
|
||||
// Fluent send
|
||||
@@ -140,19 +143,23 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template.newMessage(message).send(),
|
||||
true, message),
|
||||
arguments("fluentSendWithTopic",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template.newMessage(message)
|
||||
.withTopic("fluentSendWithTopic").send(),
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (
|
||||
template) -> template.newMessage(message).withTopic("fluentSendWithTopic").send(),
|
||||
false, message),
|
||||
arguments("fluentSendWithDefaultTopicAndSchema",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template.newMessage(message)
|
||||
.withSchema(Schema.STRING).send(),
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (
|
||||
template) -> template.newMessage(message).withSchema(Schema.STRING).send(),
|
||||
true, message),
|
||||
arguments("fluentSendNullWithTopicAndSchema",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (template) -> template.newMessage(null)
|
||||
.withSchema(Schema.STRING).withTopic("fluentSendNullWithTopicAndSchema").send(),
|
||||
.withSchema(Schema.STRING)
|
||||
.withTopic("fluentSendNullWithTopicAndSchema")
|
||||
.send(),
|
||||
false, null),
|
||||
arguments("fluentSendAsync", (ThrowingConsumer<PulsarTemplate<String>>) (template) -> template
|
||||
.newMessage(message).sendAsync().get(3, TimeUnit.SECONDS), true, message)
|
||||
arguments("fluentSendAsync",
|
||||
(ThrowingConsumer<PulsarTemplate<String>>) (
|
||||
template) -> template.newMessage(message).sendAsync().get(3, TimeUnit.SECONDS),
|
||||
true, message)
|
||||
|
||||
);
|
||||
}
|
||||
@@ -160,7 +167,8 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void sendMessageWithMessageCustomizer() throws Exception {
|
||||
ThrowingConsumer<PulsarTemplate<String>> sendFunction = (template) -> template.newMessage("test-message")
|
||||
.withMessageCustomizer((mb) -> mb.key("test-key")).send();
|
||||
.withMessageCustomizer((mb) -> mb.key("test-key"))
|
||||
.send();
|
||||
Message<String> msg = sendAndConsume(sendFunction, "sendMessageWithMessageCustomizer", Schema.STRING,
|
||||
"test-message", true);
|
||||
assertThat(msg.getKey()).isEqualTo("test-key");
|
||||
@@ -169,7 +177,8 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void sendMessageWithSenderCustomizer() throws Exception {
|
||||
ThrowingConsumer<PulsarTemplate<String>> sendFunction = (template) -> template.newMessage("test-message")
|
||||
.withProducerCustomizer((sb) -> sb.producerName("test-producer")).send();
|
||||
.withProducerCustomizer((sb) -> sb.producerName("test-producer"))
|
||||
.send();
|
||||
Message<String> msg = sendAndConsume(sendFunction, "sendMessageWithSenderCustomizer", Schema.STRING,
|
||||
"test-message", true);
|
||||
assertThat(msg.getProducerName()).isEqualTo("test-producer");
|
||||
@@ -181,7 +190,7 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
String topic = "ptt-encryptionKeys-topic";
|
||||
PulsarProducerFactory<String> producerFactory = mock(PulsarProducerFactory.class);
|
||||
when(producerFactory.createProducer(Schema.STRING, topic, Set.of("key"), new ArrayList<>()))
|
||||
.thenReturn(client.newProducer(Schema.STRING).topic(topic).create());
|
||||
.thenReturn(client.newProducer(Schema.STRING).topic(topic).create());
|
||||
PulsarTemplate<String> pulsarTemplate = new PulsarTemplate<>(producerFactory);
|
||||
pulsarTemplate.newMessage("msg").withTopic(topic).withEncryptionKeys(Set.of("key")).send();
|
||||
verify(producerFactory).createProducer(Schema.STRING, topic, Set.of("key"), new ArrayList<>());
|
||||
@@ -228,7 +237,7 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
PulsarProducerFactory<String> senderFactory = new DefaultPulsarProducerFactory<>(client);
|
||||
PulsarTemplate<String> pulsarTemplate = new PulsarTemplate<>(senderFactory);
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> pulsarTemplate.send("test-message"))
|
||||
.withMessage("Topic must be specified when no default topic is configured");
|
||||
.withMessage("Topic must be specified when no default topic is configured");
|
||||
}
|
||||
|
||||
private <T> Message<T> sendAndConsume(ThrowingConsumer<PulsarTemplate<T>> sendFunction, String topic,
|
||||
@@ -241,8 +250,10 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
|
||||
private <T> Message<T> sendAndConsume(PulsarTemplate<T> template, ThrowingConsumer<PulsarTemplate<T>> sendFunction,
|
||||
String topic, Schema<T> schema, T expectedValue) throws Exception {
|
||||
try (org.apache.pulsar.client.api.Consumer<T> consumer = client.newConsumer(schema).topic(topic)
|
||||
.subscriptionName(topic + "-sub").subscribe()) {
|
||||
try (org.apache.pulsar.client.api.Consumer<T> consumer = client.newConsumer(schema)
|
||||
.topic(topic)
|
||||
.subscriptionName(topic + "-sub")
|
||||
.subscribe()) {
|
||||
sendFunction.accept(template);
|
||||
Message<T> msg = consumer.receive(3, TimeUnit.SECONDS);
|
||||
assertThat(msg).isNotNull();
|
||||
@@ -296,7 +307,7 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
"sendNullWithDefaultTopicFails");
|
||||
PulsarTemplate<String> pulsarTemplate = new PulsarTemplate<>(senderFactory);
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> pulsarTemplate.send(null, Schema.STRING))
|
||||
.withMessage("Topic must be specified when the message is null");
|
||||
.withMessage("Topic must be specified when the message is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -304,8 +315,8 @@ class PulsarTemplateTests implements PulsarTestContainerSupport {
|
||||
PulsarProducerFactory<Object> senderFactory = new DefaultPulsarProducerFactory<>(client);
|
||||
PulsarTemplate<Object> pulsarTemplate = new PulsarTemplate<>(senderFactory);
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> pulsarTemplate.send("sendNullWithoutSchemaFails", null, null))
|
||||
.withMessage("Schema must be specified when the message is null");
|
||||
.isThrownBy(() -> pulsarTemplate.send("sendNullWithoutSchemaFails", null, null))
|
||||
.withMessage("Schema must be specified when the message is null");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@ class ResolvedTests {
|
||||
void failedWithAdditionalMessage() {
|
||||
var resolved = Resolved.failed(new IllegalStateException("5150"));
|
||||
assertThatRuntimeException().isThrownBy(() -> resolved.orElseThrow(() -> "extra message"))
|
||||
.withMessage("extra message").withCause(new IllegalStateException("5150"));
|
||||
.withMessage("extra message")
|
||||
.withCause(new IllegalStateException("5150"));
|
||||
assertThat(resolved.get()).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@ class SchemaResolverTests {
|
||||
@Test
|
||||
void structSchemasRequireMessageType() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> resolver.resolveSchema(SchemaType.JSON, null, null).orElseThrow())
|
||||
.withMessage("messageType must be specified for JSON schema type");
|
||||
.isThrownBy(() -> resolver.resolveSchema(SchemaType.JSON, null, null).orElseThrow())
|
||||
.withMessage("messageType must be specified for JSON schema type");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,15 +71,15 @@ class SchemaResolverTests {
|
||||
@Test
|
||||
void keyValueSchemaRequiresMessageKeyType() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> resolver.resolveSchema(SchemaType.KEY_VALUE, Foo.class, null).orElseThrow())
|
||||
.withMessage("messageKeyType must be specified for KEY_VALUE schema type");
|
||||
.isThrownBy(() -> resolver.resolveSchema(SchemaType.KEY_VALUE, Foo.class, null).orElseThrow())
|
||||
.withMessage("messageKeyType must be specified for KEY_VALUE schema type");
|
||||
}
|
||||
|
||||
@Test
|
||||
void keyValueSchemaRequiresMessageType() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> resolver.resolveSchema(SchemaType.KEY_VALUE, null, String.class).orElseThrow())
|
||||
.withMessage("messageType must be specified for KEY_VALUE schema type");
|
||||
.isThrownBy(() -> resolver.resolveSchema(SchemaType.KEY_VALUE, null, String.class).orElseThrow())
|
||||
.withMessage("messageType must be specified for KEY_VALUE schema type");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -137,11 +137,14 @@ public class SharedSubscriptionConsumerTests implements PulsarTestContainerSuppo
|
||||
PulsarTemplate<String> pulsarTemplate = new PulsarTemplate<>(producerFactory);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
pulsarTemplate.newMessage("alice-" + i)
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.key("alice")).send();
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.key("alice"))
|
||||
.send();
|
||||
pulsarTemplate.newMessage("buzz-" + i)
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.key("buzz")).send();
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.key("buzz"))
|
||||
.send();
|
||||
pulsarTemplate.newMessage("john-" + i)
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.key("john")).send();
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.key("john"))
|
||||
.send();
|
||||
}
|
||||
logger.info("**** Sent all messages");
|
||||
|
||||
|
||||
@@ -524,7 +524,7 @@ class PulsarFunctionAdministrationTests {
|
||||
when(springPulsarAdmin.createAdminClient()).thenThrow(new PulsarClientException("NOPE"));
|
||||
functionAdmin.enforceStopPolicyOnUserDefinedFunctions();
|
||||
assertThat(output)
|
||||
.contains("Unable to enforce stop policy on functions - could not create PulsarAdmin: NOPE");
|
||||
.contains("Unable to enforce stop policy on functions - could not create PulsarAdmin: NOPE");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -62,8 +62,12 @@ class PulsarFunctionsTests {
|
||||
|
||||
private static final String JAR = "function1.jar";
|
||||
|
||||
private FunctionConfig functionConfig = FunctionConfig.builder().tenant(TENANT).namespace(NAMESPACE).name(NAME)
|
||||
.jar(JAR).build();
|
||||
private FunctionConfig functionConfig = FunctionConfig.builder()
|
||||
.tenant(TENANT)
|
||||
.namespace(NAMESPACE)
|
||||
.name(NAME)
|
||||
.jar(JAR)
|
||||
.build();
|
||||
|
||||
private PulsarFunction function = new PulsarFunction(functionConfig, null);
|
||||
|
||||
@@ -141,7 +145,8 @@ class PulsarFunctionsTests {
|
||||
PulsarAdminException paex = new PulsarAdminException("bad-stop");
|
||||
doThrow(paex).when(functions).stopFunction(anyString(), anyString(), anyString());
|
||||
assertThatThrownBy(() -> function.stop(pulsarAdmin)).isInstanceOf(PulsarException.class)
|
||||
.hasMessageContaining("bad-stop").hasCause(paex);
|
||||
.hasMessageContaining("bad-stop")
|
||||
.hasCause(paex);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -158,7 +163,8 @@ class PulsarFunctionsTests {
|
||||
PulsarAdminException paex = new PulsarAdminException("bad-delete");
|
||||
doThrow(paex).when(functions).deleteFunction(anyString(), anyString(), anyString());
|
||||
assertThatThrownBy(() -> function.delete(pulsarAdmin)).isInstanceOf(PulsarException.class)
|
||||
.hasMessageContaining("bad-delete").hasCause(paex);
|
||||
.hasMessageContaining("bad-delete")
|
||||
.hasCause(paex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -170,8 +176,12 @@ class PulsarFunctionsTests {
|
||||
|
||||
private static final String JAR = "sink1.jar";
|
||||
|
||||
private SinkConfig sinkConfig = SinkConfig.builder().tenant(TENANT).namespace(NAMESPACE).name(NAME).archive(JAR)
|
||||
.build();
|
||||
private SinkConfig sinkConfig = SinkConfig.builder()
|
||||
.tenant(TENANT)
|
||||
.namespace(NAMESPACE)
|
||||
.name(NAME)
|
||||
.archive(JAR)
|
||||
.build();
|
||||
|
||||
private PulsarSink sink = new PulsarSink(sinkConfig, null);
|
||||
|
||||
@@ -249,7 +259,8 @@ class PulsarFunctionsTests {
|
||||
PulsarAdminException paex = new PulsarAdminException("bad-stop");
|
||||
doThrow(paex).when(sinks).stopSink(anyString(), anyString(), anyString());
|
||||
assertThatThrownBy(() -> sink.stop(pulsarAdmin)).isInstanceOf(PulsarException.class)
|
||||
.hasMessageContaining("bad-stop").hasCause(paex);
|
||||
.hasMessageContaining("bad-stop")
|
||||
.hasCause(paex);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -266,7 +277,8 @@ class PulsarFunctionsTests {
|
||||
PulsarAdminException paex = new PulsarAdminException("bad-delete");
|
||||
doThrow(paex).when(sinks).deleteSink(anyString(), anyString(), anyString());
|
||||
assertThatThrownBy(() -> sink.delete(pulsarAdmin)).isInstanceOf(PulsarException.class)
|
||||
.hasMessageContaining("bad-delete").hasCause(paex);
|
||||
.hasMessageContaining("bad-delete")
|
||||
.hasCause(paex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -278,8 +290,12 @@ class PulsarFunctionsTests {
|
||||
|
||||
private static final String JAR = "source1.jar";
|
||||
|
||||
private SourceConfig sourceConfig = SourceConfig.builder().tenant(TENANT).namespace(NAMESPACE).name(NAME)
|
||||
.archive(JAR).build();
|
||||
private SourceConfig sourceConfig = SourceConfig.builder()
|
||||
.tenant(TENANT)
|
||||
.namespace(NAMESPACE)
|
||||
.name(NAME)
|
||||
.archive(JAR)
|
||||
.build();
|
||||
|
||||
private PulsarSource source = new PulsarSource(sourceConfig, null);
|
||||
|
||||
@@ -357,7 +373,8 @@ class PulsarFunctionsTests {
|
||||
PulsarAdminException paex = new PulsarAdminException("bad-stop");
|
||||
doThrow(paex).when(sources).stopSource(anyString(), anyString(), anyString());
|
||||
assertThatThrownBy(() -> source.stop(pulsarAdmin)).isInstanceOf(PulsarException.class)
|
||||
.hasMessageContaining("bad-stop").hasCause(paex);
|
||||
.hasMessageContaining("bad-stop")
|
||||
.hasCause(paex);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -374,7 +391,8 @@ class PulsarFunctionsTests {
|
||||
PulsarAdminException paex = new PulsarAdminException("bad-delete");
|
||||
doThrow(paex).when(sources).deleteSource(anyString(), anyString(), anyString());
|
||||
assertThatThrownBy(() -> source.delete(pulsarAdmin)).isInstanceOf(PulsarException.class)
|
||||
.hasMessageContaining("bad-delete").hasCause(paex);
|
||||
.hasMessageContaining("bad-delete")
|
||||
.hasCause(paex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class ConcurrentPulsarMessageListenerContainerTests {
|
||||
when(pulsarListenerEndpoint.getConcurrency()).thenReturn(1);
|
||||
|
||||
AbstractPulsarMessageListenerContainer<String> concurrentContainer = containerFactory
|
||||
.createListenerContainer(pulsarListenerEndpoint);
|
||||
.createListenerContainer(pulsarListenerEndpoint);
|
||||
|
||||
PulsarContainerProperties pulsarContainerProperties = concurrentContainer.getContainerProperties();
|
||||
assertThat(pulsarContainerProperties.getBatchTimeoutMillis()).isEqualTo(60_000);
|
||||
@@ -82,8 +82,11 @@ public class ConcurrentPulsarMessageListenerContainerTests {
|
||||
void deadLetterPolicyAppliedOnChildContainer() throws Exception {
|
||||
PulsarListenerMockComponents env = setupListenerMockComponents(SubscriptionType.Shared);
|
||||
ConcurrentPulsarMessageListenerContainer<String> concurrentContainer = env.concurrentContainer();
|
||||
DeadLetterPolicy deadLetterPolicy = DeadLetterPolicy.builder().maxRedeliverCount(5).deadLetterTopic("dlq-topic")
|
||||
.retryLetterTopic("retry-topic").build();
|
||||
DeadLetterPolicy deadLetterPolicy = DeadLetterPolicy.builder()
|
||||
.maxRedeliverCount(5)
|
||||
.deadLetterTopic("dlq-topic")
|
||||
.retryLetterTopic("retry-topic")
|
||||
.build();
|
||||
concurrentContainer.setDeadLetterPolicy(deadLetterPolicy);
|
||||
|
||||
concurrentContainer.start();
|
||||
@@ -96,8 +99,10 @@ public class ConcurrentPulsarMessageListenerContainerTests {
|
||||
void nackRedeliveryBackoffAppliedOnChildContainer() throws Exception {
|
||||
PulsarListenerMockComponents env = setupListenerMockComponents(SubscriptionType.Shared);
|
||||
ConcurrentPulsarMessageListenerContainer<String> concurrentContainer = env.concurrentContainer();
|
||||
RedeliveryBackoff redeliveryBackoff = MultiplierRedeliveryBackoff.builder().minDelayMs(1000)
|
||||
.maxDelayMs(5 * 1000).build();
|
||||
RedeliveryBackoff redeliveryBackoff = MultiplierRedeliveryBackoff.builder()
|
||||
.minDelayMs(1000)
|
||||
.maxDelayMs(5 * 1000)
|
||||
.build();
|
||||
concurrentContainer.setNegativeAckRedeliveryBackoff(redeliveryBackoff);
|
||||
|
||||
concurrentContainer.start();
|
||||
@@ -110,8 +115,10 @@ public class ConcurrentPulsarMessageListenerContainerTests {
|
||||
void ackTimeoutRedeliveryBackoffAppliedOnChildContainer() throws Exception {
|
||||
PulsarListenerMockComponents env = setupListenerMockComponents(SubscriptionType.Exclusive);
|
||||
ConcurrentPulsarMessageListenerContainer<String> concurrentContainer = env.concurrentContainer();
|
||||
RedeliveryBackoff redeliveryBackoff = MultiplierRedeliveryBackoff.builder().minDelayMs(1000)
|
||||
.maxDelayMs(5 * 1000).build();
|
||||
RedeliveryBackoff redeliveryBackoff = MultiplierRedeliveryBackoff.builder()
|
||||
.minDelayMs(1000)
|
||||
.maxDelayMs(5 * 1000)
|
||||
.build();
|
||||
concurrentContainer.setAckTimeoutRedeliveryBackoff(redeliveryBackoff);
|
||||
|
||||
concurrentContainer.start();
|
||||
@@ -163,8 +170,9 @@ public class ConcurrentPulsarMessageListenerContainerTests {
|
||||
|
||||
concurrentContainer.start();
|
||||
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> verify(pulsarConsumerFactory, times(3))
|
||||
.createConsumer(any(Schema.class), isNull(), isNull(), isNull(), anyList()));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(pulsarConsumerFactory, times(3)).createConsumer(any(Schema.class), isNull(),
|
||||
isNull(), isNull(), anyList()));
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> verify(consumer, times(3)).batchReceive());
|
||||
}
|
||||
|
||||
@@ -176,7 +184,7 @@ public class ConcurrentPulsarMessageListenerContainerTests {
|
||||
concurrentContainer.setConcurrency(3);
|
||||
|
||||
assertThatThrownBy(concurrentContainer::start).isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("concurrency > 1 is not allowed on Exclusive subscription type");
|
||||
.hasMessage("concurrency > 1 is not allowed on Exclusive subscription type");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -185,7 +193,7 @@ public class ConcurrentPulsarMessageListenerContainerTests {
|
||||
PulsarConsumerFactory<String> consumerFactory = mock(PulsarConsumerFactory.class);
|
||||
Consumer<String> consumer = mock(Consumer.class);
|
||||
when(consumerFactory.createConsumer(any(Schema.class), isNull(), isNull(), isNull(), anyList()))
|
||||
.thenReturn(consumer);
|
||||
.thenReturn(consumer);
|
||||
when(consumer.batchReceive()).thenReturn(mock(Messages.class));
|
||||
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
|
||||
@@ -54,8 +54,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void happyPathErrorHandlingForRecordMessageListener() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("default-error-handler-tests-1");
|
||||
@@ -88,11 +89,12 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
PulsarOperations.SendMessageBuilder<String> sendMessageBuilderMock = mock(
|
||||
PulsarOperations.SendMessageBuilder.class);
|
||||
|
||||
when(mockPulsarTemplate.newMessage("hello john doe").withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
when(mockPulsarTemplate.newMessage("hello john doe")
|
||||
.withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(
|
||||
() -> verify(messageListener, times(11)).received(any(Consumer.class), any(Message.class)));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(messageListener, times(11)).received(any(Consumer.class), any(Message.class)));
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> verify(sendMessageBuilderMock).sendAsync());
|
||||
|
||||
container.stop();
|
||||
@@ -102,8 +104,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void errorHandlingForRecordMessageListenerWithTransientError() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("default-error-handler-tests-2");
|
||||
@@ -137,8 +140,8 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
|
||||
pulsarTemplate.sendAsync("hello john doe");
|
||||
|
||||
await().atMost(Duration.ofSeconds(10)).untilAsserted(
|
||||
() -> verify(messageListener, times(4)).received(any(Consumer.class), any(Message.class)));
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(messageListener, times(4)).received(any(Consumer.class), any(Message.class)));
|
||||
verifyNoInteractions(mockPulsarTemplate);
|
||||
|
||||
container.stop();
|
||||
@@ -148,8 +151,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void everyOtherRecordThrowsNonTransientExceptionsRecordMessageListener() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<Integer> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("default-error-handler-tests-3");
|
||||
@@ -188,14 +192,15 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
PulsarOperations.SendMessageBuilder<Integer> sendMessageBuilderMock = mock(
|
||||
PulsarOperations.SendMessageBuilder.class);
|
||||
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class)).withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class))
|
||||
.withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
|
||||
// 5 records fail - 5 * (1 + 5 max retry) = 30 + 5 records don't fail = 35
|
||||
await().atMost(Duration.ofSeconds(30)).untilAsserted(
|
||||
() -> verify(messageListener, times(35)).received(any(Consumer.class), any(Message.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(5)).sendAsync());
|
||||
.untilAsserted(() -> verify(messageListener, times(35)).received(any(Consumer.class), any(Message.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(5)).sendAsync());
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -204,8 +209,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void batchRecordListenerFirstOneOnlyErrorAndRecover() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<Integer> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("default-error-handler-tests-4");
|
||||
@@ -257,14 +263,16 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
PulsarOperations.SendMessageBuilder<Integer> sendMessageBuilderMock = mock(
|
||||
PulsarOperations.SendMessageBuilder.class);
|
||||
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class)).withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class))
|
||||
.withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
|
||||
// 1 + 10 + 1 = 12 calls altogether
|
||||
await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> verify(pulsarBatchMessageListener, times(12))
|
||||
.received(any(Consumer.class), any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(1)).sendAsync());
|
||||
.untilAsserted(() -> verify(pulsarBatchMessageListener, times(12)).received(any(Consumer.class),
|
||||
any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(1)).sendAsync());
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -273,8 +281,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void batchRecordListenerRecordFailsInTheMiddle() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<Integer> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("default-error-handler-tests-5");
|
||||
@@ -324,14 +333,16 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
PulsarOperations.SendMessageBuilder<Integer> sendMessageBuilderMock = mock(
|
||||
PulsarOperations.SendMessageBuilder.class);
|
||||
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class)).withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class))
|
||||
.withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
|
||||
// 1 + 10 + 1 = 12 calls altogether
|
||||
await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> verify(pulsarBatchMessageListener, times(12))
|
||||
.received(any(Consumer.class), any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(1)).sendAsync());
|
||||
.untilAsserted(() -> verify(pulsarBatchMessageListener, times(12)).received(any(Consumer.class),
|
||||
any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(1)).sendAsync());
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -340,8 +351,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void batchRecordListenerRecordFailsTwiceInTheMiddle() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<Integer> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("default-error-handler-tests-6");
|
||||
@@ -391,14 +403,16 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
PulsarOperations.SendMessageBuilder<Integer> sendMessageBuilderMock = mock(
|
||||
PulsarOperations.SendMessageBuilder.class);
|
||||
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class)).withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class))
|
||||
.withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
|
||||
// 1 + 10 + 1 + 10 + 1 = 23 calls altogether
|
||||
await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> verify(pulsarBatchMessageListener, times(23))
|
||||
.received(any(Consumer.class), any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(2)).sendAsync());
|
||||
.untilAsserted(() -> verify(pulsarBatchMessageListener, times(23)).received(any(Consumer.class),
|
||||
any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(2)).sendAsync());
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -407,8 +421,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void batchRecordListenerRecordFailsInTheMiddleButTransientError() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<Integer> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("default-error-handler-tests-7");
|
||||
@@ -462,8 +477,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
pulsarTemplate.sendAsync(i);
|
||||
}
|
||||
// 1 + 3 + 1 = 5 calls altogether
|
||||
await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> verify(pulsarBatchMessageListener, times(4))
|
||||
.received(any(Consumer.class), any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(pulsarBatchMessageListener, times(4)).received(any(Consumer.class),
|
||||
any(List.class), any(Acknowledgement.class)));
|
||||
verifyNoInteractions(mockPulsarTemplate);
|
||||
|
||||
container.stop();
|
||||
@@ -473,8 +489,9 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void batchListenerFailsTransientErrorFollowedByNonTransient() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<Integer> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("default-error-handler-tests-8");
|
||||
@@ -533,13 +550,15 @@ public class DefaultPulsarConsumerErrorHandlerTests implements PulsarTestContain
|
||||
PulsarOperations.SendMessageBuilder<Integer> sendMessageBuilderMock = mock(
|
||||
PulsarOperations.SendMessageBuilder.class);
|
||||
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class)).withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
when(mockPulsarTemplate.newMessage(any(Integer.class))
|
||||
.withTopic(any(String.class))
|
||||
.withMessageCustomizer(any(TypedMessageBuilderCustomizer.class))).thenReturn(sendMessageBuilderMock);
|
||||
// 1 + 2 + 1 + 10 + 1 = 15 calls altogether
|
||||
await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> verify(pulsarBatchMessageListener, times(15))
|
||||
.received(any(Consumer.class), any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(1)).sendAsync());
|
||||
.untilAsserted(() -> verify(pulsarBatchMessageListener, times(15)).received(any(Consumer.class),
|
||||
any(List.class), any(Acknowledgement.class)));
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.untilAsserted(() -> verify(sendMessageBuilderMock, times(1)).sendAsync());
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
|
||||
@@ -63,8 +63,9 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
|
||||
@Test
|
||||
void basicDefaultConsumer() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("dpmlct-012");
|
||||
@@ -73,7 +74,7 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
pulsarContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch.countDown());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch.countDown());
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
DefaultPulsarMessageListenerContainer<String> container = new DefaultPulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
@@ -91,8 +92,9 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
@Disabled
|
||||
@Test
|
||||
void containerPauseAndResumeFeatureUsingWaitAndNotify() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("containerPauseResumeWaitNotify-topic");
|
||||
@@ -160,8 +162,9 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
|
||||
@Test
|
||||
void subscriptionInitialPositionEarliest() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("dpmlct-013");
|
||||
@@ -171,7 +174,7 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
CountDownLatch latch = new CountDownLatch(5);
|
||||
PulsarContainerProperties pulsarContainerProperties = new PulsarContainerProperties();
|
||||
pulsarContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch.countDown());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> latch.countDown());
|
||||
pulsarContainerProperties.setSchema(Schema.STRING);
|
||||
DefaultPulsarMessageListenerContainer<String> container = new DefaultPulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
@@ -191,8 +194,9 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
|
||||
@Test
|
||||
void subscriptionInitialPositionDefaultLatest() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("dpmlct-014");
|
||||
@@ -224,10 +228,13 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
|
||||
@Test
|
||||
void negativeAckRedeliveryBackoff() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
RedeliveryBackoff redeliveryBackoff = MultiplierRedeliveryBackoff.builder().minDelayMs(1000)
|
||||
.maxDelayMs(5 * 1000).build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
RedeliveryBackoff redeliveryBackoff = MultiplierRedeliveryBackoff.builder()
|
||||
.minDelayMs(1000)
|
||||
.maxDelayMs(5 * 1000)
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<String> pulsarConsumerFactory = spy(
|
||||
new DefaultPulsarConsumerFactory<>(pulsarClient, (consumerBuilder) -> {
|
||||
consumerBuilder.topic("dpmlct-015");
|
||||
@@ -263,7 +270,7 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
// but the probability for that is low as we have a long enough backoff
|
||||
// multiplier.
|
||||
await().atMost(Duration.ofSeconds(10))
|
||||
.untilAsserted(() -> verify(containerConsumer, times(6)).negativeAcknowledge(any(Message.class)));
|
||||
.untilAsserted(() -> verify(containerConsumer, times(6)).negativeAcknowledge(any(Message.class)));
|
||||
|
||||
container.stop();
|
||||
pulsarClient.close();
|
||||
@@ -271,10 +278,13 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
|
||||
@Test
|
||||
void deadLetterPolicyDefault() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DeadLetterPolicy deadLetterPolicy = DeadLetterPolicy.builder().maxRedeliverCount(1)
|
||||
.deadLetterTopic("dpmlct-016-dlq-topic").build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DeadLetterPolicy deadLetterPolicy = DeadLetterPolicy.builder()
|
||||
.maxRedeliverCount(1)
|
||||
.deadLetterTopic("dpmlct-016-dlq-topic")
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<Integer> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("dpmlct-016");
|
||||
@@ -288,7 +298,7 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
|
||||
PulsarContainerProperties dlqContainerProperties = new PulsarContainerProperties();
|
||||
dlqContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> dlqLatch.countDown());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> dlqLatch.countDown());
|
||||
dlqContainerProperties.setSchema(Schema.INT32);
|
||||
dlqContainerProperties.setSubscriptionType(SubscriptionType.Shared);
|
||||
dlqContainerProperties.setTopics(Set.of("dpmlct-016-dlq-topic"));
|
||||
@@ -327,10 +337,13 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
|
||||
@Test
|
||||
void deadLetterPolicyCustom() throws Exception {
|
||||
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DeadLetterPolicy deadLetterPolicy = DeadLetterPolicy.builder().maxRedeliverCount(5).deadLetterTopic("dlq-topic")
|
||||
.build();
|
||||
PulsarClient pulsarClient = PulsarClient.builder()
|
||||
.serviceUrl(PulsarTestContainerSupport.getPulsarBrokerUrl())
|
||||
.build();
|
||||
DeadLetterPolicy deadLetterPolicy = DeadLetterPolicy.builder()
|
||||
.maxRedeliverCount(5)
|
||||
.deadLetterTopic("dlq-topic")
|
||||
.build();
|
||||
DefaultPulsarConsumerFactory<Integer> pulsarConsumerFactory = new DefaultPulsarConsumerFactory<>(pulsarClient,
|
||||
(consumerBuilder) -> {
|
||||
consumerBuilder.topic("dpmlct-017");
|
||||
@@ -344,7 +357,7 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
|
||||
PulsarContainerProperties dlqContainerProperties = new PulsarContainerProperties();
|
||||
dlqContainerProperties
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> dlqLatch.countDown());
|
||||
.setMessageListener((PulsarRecordMessageListener<?>) (consumer, msg) -> dlqLatch.countDown());
|
||||
dlqContainerProperties.setSchema(Schema.INT32);
|
||||
dlqContainerProperties.setSubscriptionType(SubscriptionType.Shared);
|
||||
dlqContainerProperties.setTopics(Set.of("dlq-topic"));
|
||||
@@ -361,8 +374,9 @@ class DefaultPulsarMessageListenerContainerTests implements PulsarTestContainerS
|
||||
});
|
||||
pulsarContainerProperties.setSchema(Schema.INT32);
|
||||
pulsarContainerProperties.setSubscriptionType(SubscriptionType.Shared);
|
||||
pulsarContainerProperties.getPulsarConsumerProperties().put("deadLetterPolicy",
|
||||
DeadLetterPolicy.builder().maxRedeliverCount(1).deadLetterTopic("dlq-topic").build());
|
||||
pulsarContainerProperties.getPulsarConsumerProperties()
|
||||
.put("deadLetterPolicy",
|
||||
DeadLetterPolicy.builder().maxRedeliverCount(1).deadLetterTopic("dlq-topic").build());
|
||||
|
||||
DefaultPulsarMessageListenerContainer<Integer> container = new DefaultPulsarMessageListenerContainer<>(
|
||||
pulsarConsumerFactory, pulsarContainerProperties);
|
||||
|
||||
@@ -89,7 +89,7 @@ public final class Proto {
|
||||
}
|
||||
int mutable_bitField0_ = 0;
|
||||
com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet
|
||||
.newBuilder();
|
||||
.newBuilder();
|
||||
try {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
@@ -140,8 +140,8 @@ public final class Proto {
|
||||
@java.lang.Override
|
||||
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() {
|
||||
return org.springframework.pulsar.listener.Proto.internal_static_proto_Person_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(org.springframework.pulsar.listener.Proto.Person.class,
|
||||
org.springframework.pulsar.listener.Proto.Person.Builder.class);
|
||||
.ensureFieldAccessorsInitialized(org.springframework.pulsar.listener.Proto.Person.class,
|
||||
org.springframework.pulsar.listener.Proto.Person.Builder.class);
|
||||
}
|
||||
|
||||
private int bitField0_;
|
||||
@@ -409,8 +409,8 @@ public final class Proto {
|
||||
@java.lang.Override
|
||||
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() {
|
||||
return org.springframework.pulsar.listener.Proto.internal_static_proto_Person_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(org.springframework.pulsar.listener.Proto.Person.class,
|
||||
org.springframework.pulsar.listener.Proto.Person.Builder.class);
|
||||
.ensureFieldAccessorsInitialized(org.springframework.pulsar.listener.Proto.Person.class,
|
||||
org.springframework.pulsar.listener.Proto.Person.Builder.class);
|
||||
}
|
||||
|
||||
// Construct using
|
||||
@@ -640,7 +640,7 @@ public final class Proto {
|
||||
java.lang.Object ref = name_;
|
||||
if (ref instanceof String) {
|
||||
com.google.protobuf.ByteString b = com.google.protobuf.ByteString
|
||||
.copyFromUtf8((java.lang.String) ref);
|
||||
.copyFromUtf8((java.lang.String) ref);
|
||||
name_ = b;
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
throws Exception {
|
||||
|
||||
PulsarContainerProperties pulsarContainerProperties = registry.getListenerContainer("foo")
|
||||
.getContainerProperties();
|
||||
.getContainerProperties();
|
||||
Properties pulsarConsumerProperties = pulsarContainerProperties.getPulsarConsumerProperties();
|
||||
assertThat(pulsarConsumerProperties.size()).isEqualTo(2);
|
||||
assertThat(pulsarConsumerProperties.get("topicNames")).isEqualTo("foo-1");
|
||||
@@ -210,7 +210,7 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void ackModeAppliedToContainerFromListener(@Autowired PulsarListenerEndpointRegistry registry) {
|
||||
PulsarContainerProperties pulsarContainerProperties = registry.getListenerContainer("ackMode-test-id")
|
||||
.getContainerProperties();
|
||||
.getContainerProperties();
|
||||
assertThat(pulsarContainerProperties.getAckMode()).isEqualTo(AckMode.RECORD);
|
||||
}
|
||||
|
||||
@@ -271,8 +271,11 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
|
||||
@Bean
|
||||
public RedeliveryBackoff redeliveryBackoff() {
|
||||
return MultiplierRedeliveryBackoff.builder().minDelayMs(1000).maxDelayMs(5 * 1000).multiplier(2)
|
||||
.build();
|
||||
return MultiplierRedeliveryBackoff.builder()
|
||||
.minDelayMs(1000)
|
||||
.maxDelayMs(5 * 1000)
|
||||
.multiplier(2)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -317,8 +320,11 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
|
||||
@Bean
|
||||
public RedeliveryBackoff ackTimeoutRedeliveryBackoff() {
|
||||
return MultiplierRedeliveryBackoff.builder().minDelayMs(1000).maxDelayMs(3 * 1000).multiplier(2)
|
||||
.build();
|
||||
return MultiplierRedeliveryBackoff.builder()
|
||||
.minDelayMs(1000)
|
||||
.maxDelayMs(3 * 1000)
|
||||
.multiplier(2)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -417,8 +423,9 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
void exclusiveSubscriptionNotAllowedToHaveMultipleConsumers() {
|
||||
assertThatThrownBy(
|
||||
() -> new AnnotationConfigApplicationContext(TopLevelConfig.class, ConcurrencyConfig.class))
|
||||
.rootCause().isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("concurrency > 1 is not allowed on Exclusive subscription type");
|
||||
.rootCause()
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("concurrency > 1 is not allowed on Exclusive subscription type");
|
||||
}
|
||||
|
||||
@EnablePulsar
|
||||
@@ -811,9 +818,9 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void simpleListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-simple-listener")
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "simpleListenerWithHeaders"))
|
||||
.withTopic("simpleListenerWithHeaders").send();
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.property("foo", "simpleListenerWithHeaders"))
|
||||
.withTopic("simpleListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(simpleListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedData).isEqualTo("hello-simple-listener");
|
||||
assertThat(PulsarHeadersTest.messageId).isEqualTo(messageId);
|
||||
@@ -825,9 +832,10 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void pulsarMessageListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-pulsar-message-listener")
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "pulsarMessageListenerWithHeaders"))
|
||||
.withTopic("pulsarMessageListenerWithHeaders").send();
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "pulsarMessageListenerWithHeaders"))
|
||||
.withTopic("pulsarMessageListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(pulsarMessageListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedData).isEqualTo("hello-pulsar-message-listener");
|
||||
assertThat(PulsarHeadersTest.messageId).isEqualTo(messageId);
|
||||
@@ -839,9 +847,10 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void springMessagingMessageListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-spring-messaging-message-listener")
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.property("foo",
|
||||
"springMessagingMessageListenerWithHeaders"))
|
||||
.withTopic("springMessagingMessageListenerWithHeaders").send();
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "springMessagingMessageListenerWithHeaders"))
|
||||
.withTopic("springMessagingMessageListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(springMessagingMessageListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedData).isEqualTo("hello-spring-messaging-message-listener");
|
||||
assertThat(PulsarHeadersTest.messageId).isEqualTo(messageId);
|
||||
@@ -853,9 +862,10 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void simpleBatchListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-simple-batch-listener")
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "simpleBatchListenerWithHeaders"))
|
||||
.withTopic("simpleBatchListenerWithHeaders").send();
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "simpleBatchListenerWithHeaders"))
|
||||
.withTopic("simpleBatchListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(simpleBatchListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedBatchData).containsExactly("hello-simple-batch-listener");
|
||||
assertThat(batchMessageIds).containsExactly(messageId);
|
||||
@@ -866,13 +876,14 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void pulsarMessageBatchListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-pulsar-message-batch-listener")
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "pulsarMessageBatchListenerWithHeaders"))
|
||||
.withTopic("pulsarMessageBatchListenerWithHeaders").send();
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "pulsarMessageBatchListenerWithHeaders"))
|
||||
.withTopic("pulsarMessageBatchListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(pulsarMessageBatchListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedBatchData).containsExactly("hello-pulsar-message-batch-listener");
|
||||
assertThat(batchTopicNames)
|
||||
.containsExactly("persistent://public/default/pulsarMessageBatchListenerWithHeaders");
|
||||
.containsExactly("persistent://public/default/pulsarMessageBatchListenerWithHeaders");
|
||||
assertThat(batchFooValues).containsExactly("pulsarMessageBatchListenerWithHeaders");
|
||||
assertThat(batchMessageIds).containsExactly(messageId);
|
||||
}
|
||||
@@ -880,13 +891,14 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void springMessagingMessageBatchListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-spring-messaging-message-batch-listener")
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.property("foo",
|
||||
"springMessagingMessageBatchListenerWithHeaders"))
|
||||
.withTopic("springMessagingMessageBatchListenerWithHeaders").send();
|
||||
.withMessageCustomizer(messageBuilder -> messageBuilder.property("foo",
|
||||
"springMessagingMessageBatchListenerWithHeaders"))
|
||||
.withTopic("springMessagingMessageBatchListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(springMessagingMessageBatchListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedBatchData).containsExactly("hello-spring-messaging-message-batch-listener");
|
||||
assertThat(batchTopicNames)
|
||||
.containsExactly("persistent://public/default/springMessagingMessageBatchListenerWithHeaders");
|
||||
.containsExactly("persistent://public/default/springMessagingMessageBatchListenerWithHeaders");
|
||||
assertThat(batchFooValues).containsExactly("springMessagingMessageBatchListenerWithHeaders");
|
||||
assertThat(batchMessageIds).containsExactly(messageId);
|
||||
}
|
||||
@@ -894,13 +906,14 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void pulsarMessagesBatchListenerWithHeaders() throws Exception {
|
||||
MessageId messageId = pulsarTemplate.newMessage("hello-pulsar-messages-batch-listener")
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "pulsarMessagesBatchListenerWithHeaders"))
|
||||
.withTopic("pulsarMessagesBatchListenerWithHeaders").send();
|
||||
.withMessageCustomizer(
|
||||
messageBuilder -> messageBuilder.property("foo", "pulsarMessagesBatchListenerWithHeaders"))
|
||||
.withTopic("pulsarMessagesBatchListenerWithHeaders")
|
||||
.send();
|
||||
assertThat(pulsarMessagesBatchListenerLatch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(capturedBatchData).containsExactly("hello-pulsar-messages-batch-listener");
|
||||
assertThat(batchTopicNames)
|
||||
.containsExactly("persistent://public/default/pulsarMessagesBatchListenerWithHeaders");
|
||||
.containsExactly("persistent://public/default/pulsarMessagesBatchListenerWithHeaders");
|
||||
assertThat(batchFooValues).containsExactly("pulsarMessagesBatchListenerWithHeaders");
|
||||
assertThat(batchMessageIds).containsExactly(messageId);
|
||||
}
|
||||
@@ -982,8 +995,9 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
@Header(PulsarHeaders.MESSAGE_ID) List<MessageId> messageIds,
|
||||
@Header(PulsarHeaders.TOPIC_NAME) List<String> topicNames, @Header("foo") List<String> fooValues) {
|
||||
|
||||
capturedBatchData = data.stream().map(org.springframework.messaging.Message::getPayload)
|
||||
.collect(Collectors.toList());
|
||||
capturedBatchData = data.stream()
|
||||
.map(org.springframework.messaging.Message::getPayload)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
batchMessageIds = messageIds;
|
||||
batchTopicNames = topicNames;
|
||||
@@ -1027,7 +1041,7 @@ public class PulsarListenerTests implements PulsarTestContainerSupport {
|
||||
// wait until all 3 messages are received by the listener
|
||||
Awaitility.await().timeout(Duration.ofSeconds(10)).until(() -> latch.getCount() == 7);
|
||||
PulsarMessageListenerContainer container = pulsarListenerEndpointRegistry
|
||||
.getListenerContainer("consumerPauseListener");
|
||||
.getListenerContainer("consumerPauseListener");
|
||||
assertThat(container).isNotNull();
|
||||
container.pause();
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public class ObservationIntegrationTests extends SampleTestRunner implements Pul
|
||||
appContext.refresh();
|
||||
|
||||
ObservationIntegrationTestAppListeners listeners = appContext
|
||||
.getBean(ObservationIntegrationTestAppListeners.class);
|
||||
.getBean(ObservationIntegrationTestAppListeners.class);
|
||||
PulsarTemplate<String> template = appContext.getBean(PulsarTemplate.class);
|
||||
|
||||
String msg = "hello-" + System.currentTimeMillis();
|
||||
@@ -88,38 +88,42 @@ public class ObservationIntegrationTests extends SampleTestRunner implements Pul
|
||||
boolean listen2Completed = listeners.latchesByMessageListen2.get(msg).await(10, TimeUnit.SECONDS);
|
||||
assertThat(listen1Completed).withFailMessage(
|
||||
"Message %s not received in listen1 (latchesByMessageListen1 = %s and latchesByMessageListen2 = %s)",
|
||||
msg, listeners.latchesByMessageListen1, listeners.latchesByMessageListen2).isTrue();
|
||||
msg, listeners.latchesByMessageListen1, listeners.latchesByMessageListen2)
|
||||
.isTrue();
|
||||
assertThat(listen2Completed).withFailMessage(
|
||||
"Message %s not received in listen2 (latchesByMessageListen1 = %s and latchesByMessageListen2 = %s)",
|
||||
msg, listeners.latchesByMessageListen1, listeners.latchesByMessageListen2).isTrue();
|
||||
msg, listeners.latchesByMessageListen1, listeners.latchesByMessageListen2)
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
List<FinishedSpan> finishedSpans = bb.getFinishedSpans();
|
||||
SpansAssert.assertThat(finishedSpans).haveSameTraceId().hasSize(4);
|
||||
|
||||
List<FinishedSpan> producerSpans = finishedSpans.stream()
|
||||
.filter(span -> span.getKind().equals(Kind.PRODUCER)).toList();
|
||||
.filter(span -> span.getKind().equals(Kind.PRODUCER))
|
||||
.toList();
|
||||
SpanAssert.assertThat(producerSpans.get(0)).hasTag("spring.pulsar.template.name", "pulsarTemplate");
|
||||
SpanAssert.assertThat(producerSpans.get(1)).hasTag("spring.pulsar.template.name", "pulsarTemplate");
|
||||
|
||||
List<FinishedSpan> consumerSpans = finishedSpans.stream()
|
||||
.filter(span -> span.getKind().equals(Kind.CONSUMER)).toList();
|
||||
.filter(span -> span.getKind().equals(Kind.CONSUMER))
|
||||
.toList();
|
||||
SpanAssert.assertThat(consumerSpans.get(0)).hasTagWithKey("spring.pulsar.listener.id");
|
||||
assertThat(consumerSpans.get(0).getTags().get("spring.pulsar.listener.id")).isIn("obs1-id-0", "obs2-id-0");
|
||||
SpanAssert.assertThat(consumerSpans.get(1)).hasTagWithKey("spring.pulsar.listener.id");
|
||||
assertThat(consumerSpans.get(1).getTags().get("spring.pulsar.listener.id")).isIn("obs1-id-0", "obs2-id-0");
|
||||
assertThat(consumerSpans.get(0).getTags().get("spring.pulsar.listener.id"))
|
||||
.isNotEqualTo(consumerSpans.get(1).getTags().get("spring.pulsar.listener.id"));
|
||||
.isNotEqualTo(consumerSpans.get(1).getTags().get("spring.pulsar.listener.id"));
|
||||
|
||||
MeterRegistryAssert.assertThat(getMeterRegistry())
|
||||
.hasTimerWithNameAndTags("spring.pulsar.template",
|
||||
KeyValues.of("spring.pulsar.template.name", "pulsarTemplate"))
|
||||
.hasTimerWithNameAndTags("spring.pulsar.template",
|
||||
KeyValues.of("spring.pulsar.template.name", "pulsarTemplate"))
|
||||
.hasTimerWithNameAndTags("spring.pulsar.listener",
|
||||
KeyValues.of("spring.pulsar.listener.id", "obs1-id-0"))
|
||||
.hasTimerWithNameAndTags("spring.pulsar.listener",
|
||||
KeyValues.of("spring.pulsar.listener.id", "obs2-id-0"));
|
||||
.hasTimerWithNameAndTags("spring.pulsar.template",
|
||||
KeyValues.of("spring.pulsar.template.name", "pulsarTemplate"))
|
||||
.hasTimerWithNameAndTags("spring.pulsar.template",
|
||||
KeyValues.of("spring.pulsar.template.name", "pulsarTemplate"))
|
||||
.hasTimerWithNameAndTags("spring.pulsar.listener",
|
||||
KeyValues.of("spring.pulsar.listener.id", "obs1-id-0"))
|
||||
.hasTimerWithNameAndTags("spring.pulsar.listener",
|
||||
KeyValues.of("spring.pulsar.listener.id", "obs2-id-0"));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -154,12 +154,12 @@ public class ObservationTests implements PulsarTestContainerSupport {
|
||||
assertThat(span.getTags()).containsEntry(TAG2, TAG2_VALUE);
|
||||
|
||||
MeterRegistryAssert.assertThat(meterRegistry)
|
||||
.hasTimerWithNameAndTags("spring.pulsar.listener",
|
||||
KeyValues.of(LISTENER_ID_TAG, OBS1_ID, RECEIVER_EXTRA_TAG, OBS1_ID))
|
||||
.hasTimerWithNameAndTags("spring.pulsar.listener", KeyValues.of(LISTENER_ID_TAG, OBS2_ID));
|
||||
.hasTimerWithNameAndTags("spring.pulsar.listener",
|
||||
KeyValues.of(LISTENER_ID_TAG, OBS1_ID, RECEIVER_EXTRA_TAG, OBS1_ID))
|
||||
.hasTimerWithNameAndTags("spring.pulsar.listener", KeyValues.of(LISTENER_ID_TAG, OBS2_ID));
|
||||
assertThat(meterRegistry.find("spring.pulsar.template")
|
||||
.tags(TEMPLATE_NAME_TAG, TEMPLATE_NAME, SENDER_EXTRA_TAG, TEMPLATE_NAME).timer()).isNotNull()
|
||||
.extracting(Timer::count).isEqualTo(2L);
|
||||
.tags(TEMPLATE_NAME_TAG, TEMPLATE_NAME, SENDER_EXTRA_TAG, TEMPLATE_NAME)
|
||||
.timer()).isNotNull().extracting(Timer::count).isEqualTo(2L);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -238,18 +238,20 @@ public class ObservationTests implements PulsarTestContainerSupport {
|
||||
@Bean
|
||||
ObservationRegistry observationRegistry(Tracer tracer, Propagator propagator, MeterRegistry meterRegistry) {
|
||||
TestObservationRegistry observationRegistry = TestObservationRegistry.create();
|
||||
observationRegistry.observationConfig().observationHandler(
|
||||
// Composite will pick the first matching handler
|
||||
new ObservationHandler.FirstMatchingCompositeObservationHandler(
|
||||
// This is responsible for creating a child span on the sender
|
||||
// side
|
||||
new PropagatingSenderTracingObservationHandler<>(tracer, propagator),
|
||||
// This is responsible for creating a span on the receiver
|
||||
// side
|
||||
new PropagatingReceiverTracingObservationHandler<>(tracer, propagator),
|
||||
// This is responsible for creating a default span
|
||||
new DefaultTracingObservationHandler(tracer)))
|
||||
.observationHandler(new DefaultMeterObservationHandler(meterRegistry));
|
||||
observationRegistry.observationConfig()
|
||||
.observationHandler(
|
||||
// Composite will pick the first matching handler
|
||||
new ObservationHandler.FirstMatchingCompositeObservationHandler(
|
||||
// This is responsible for creating a child span on the
|
||||
// sender
|
||||
// side
|
||||
new PropagatingSenderTracingObservationHandler<>(tracer, propagator),
|
||||
// This is responsible for creating a span on the receiver
|
||||
// side
|
||||
new PropagatingReceiverTracingObservationHandler<>(tracer, propagator),
|
||||
// This is responsible for creating a default span
|
||||
new DefaultTracingObservationHandler(tracer)))
|
||||
.observationHandler(new DefaultMeterObservationHandler(meterRegistry));
|
||||
return observationRegistry;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,9 +130,11 @@ public class PulsarReaderTests implements PulsarTestContainerSupport {
|
||||
@Test
|
||||
void startMessageIdMissing() {
|
||||
assertThatThrownBy(() -> new AnnotationConfigApplicationContext(TopLevelConfig.class,
|
||||
PulsarReaderStartMessageIdMissing.class)).rootCause().isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage(
|
||||
"Start message id or start message from roll back must be specified but they cannot be specified at the same time");
|
||||
PulsarReaderStartMessageIdMissing.class))
|
||||
.rootCause()
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage(
|
||||
"Start message id or start message from roll back must be specified but they cannot be specified at the same time");
|
||||
}
|
||||
|
||||
@EnablePulsar
|
||||
|
||||
@@ -57,7 +57,7 @@ abstract class AbstractPulsarHeaderMapperTests {
|
||||
@Test
|
||||
void nullPulsarMessage() {
|
||||
assertThatNullPointerException().isThrownBy(() -> mapper().toSpringHeaders(null))
|
||||
.withMessage("pulsarMessage must not be null");
|
||||
.withMessage("pulsarMessage must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,7 +87,7 @@ abstract class AbstractPulsarHeaderMapperTests {
|
||||
// check metadata - sanity check metadata pulled in by existence of
|
||||
// MESSAGE_SIZE
|
||||
assertThat(springHeaders).containsKey(PulsarHeaders.MESSAGE_SIZE)
|
||||
.doesNotContainKey(PulsarHeaders.MESSAGE_ID);
|
||||
.doesNotContainKey(PulsarHeaders.MESSAGE_ID);
|
||||
// check user properties
|
||||
assertThat(springHeaders).containsKey("info").doesNotContainKey("foo");
|
||||
}
|
||||
@@ -121,7 +121,7 @@ abstract class AbstractPulsarHeaderMapperTests {
|
||||
@Test
|
||||
void nullSpringHeaders() {
|
||||
assertThatNullPointerException().isThrownBy(() -> mapper().toPulsarHeaders(null))
|
||||
.withMessage("springHeaders must not be null");
|
||||
.withMessage("springHeaders must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -157,7 +157,7 @@ abstract class AbstractPulsarHeaderMapperTests {
|
||||
springHeaders.put("foo", "bar");
|
||||
springHeaders.put("info", "5150");
|
||||
assertThat(mapper.toPulsarHeaders(new MessageHeaders(springHeaders))).doesNotContainKey("foo")
|
||||
.containsKeys("id", "timestamp"); // '*' allows id/ts
|
||||
.containsKeys("id", "timestamp"); // '*' allows id/ts
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -184,7 +184,7 @@ abstract class AbstractPulsarHeaderMapperTests {
|
||||
var springHeaders = new HashMap<String, Object>();
|
||||
springHeaders.put("foo", "bar");
|
||||
assertThat(mapper.toPulsarHeaders(new MessageHeaders(springHeaders))).containsKeys("id", "timestamp")
|
||||
.doesNotContainKey("foo");
|
||||
.doesNotContainKey("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -93,7 +93,8 @@ class JsonPulsarHeaderMapperTests extends AbstractPulsarHeaderMapperTests {
|
||||
@ValueSource(booleans = { true, false })
|
||||
void pulsarMessageWithUpstreamNth(boolean nowTrusted) throws JsonProcessingException {
|
||||
var mapper = JsonPulsarHeaderMapper.builder()
|
||||
.trustedPackages(nowTrusted ? UUID.class.getPackageName() : "com.acme").build();
|
||||
.trustedPackages(nowTrusted ? UUID.class.getPackageName() : "com.acme")
|
||||
.build();
|
||||
var uuid = UUID.randomUUID();
|
||||
var serializedUuid = "\"%s\"".formatted(uuid.toString());
|
||||
var upstreamNth = new NonTrustedHeaderType(serializedUuid, UUID.class.getName());
|
||||
@@ -118,9 +119,9 @@ class JsonPulsarHeaderMapperTests extends AbstractPulsarHeaderMapperTests {
|
||||
headers.put("foo", "bar");
|
||||
headers.put("uuid", uuid);
|
||||
assertThat(mapper().toPulsarHeaders(new MessageHeaders(headers))).containsEntry("foo", "bar")
|
||||
.containsEntry("uuid", "\"%s\"".formatted(uuid.toString()))
|
||||
.extractingByKey(JSON_TYPES, InstanceOfAssertFactories.STRING)
|
||||
.contains("\"uuid\":\"java.util.UUID\"");
|
||||
.containsEntry("uuid", "\"%s\"".formatted(uuid.toString()))
|
||||
.extractingByKey(JSON_TYPES, InstanceOfAssertFactories.STRING)
|
||||
.contains("\"uuid\":\"java.util.UUID\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,7 +130,7 @@ class JsonPulsarHeaderMapperTests extends AbstractPulsarHeaderMapperTests {
|
||||
var uuid = UUID.randomUUID();
|
||||
var headers = Collections.<String, Object>singletonMap("uuid", uuid);
|
||||
assertThat(mapper.toPulsarHeaders(new MessageHeaders(headers))).containsEntry("uuid", uuid.toString())
|
||||
.doesNotContainKey(JSON_TYPES);
|
||||
.doesNotContainKey(JSON_TYPES);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -175,8 +176,8 @@ class JsonPulsarHeaderMapperTests extends AbstractPulsarHeaderMapperTests {
|
||||
var payloadEnc = Base64.getEncoder().encodeToString(payload);
|
||||
var headers = Map.<String, Object>of("payload", payload);
|
||||
var pulsarHeaders = mapper().toPulsarHeaders(new MessageHeaders(headers));
|
||||
assertThat(pulsarHeaders).containsEntry("payload", "\"%s\"".formatted(payloadEnc)).containsEntry(JSON_TYPES,
|
||||
"{\"payload\":\"[B\"}");
|
||||
assertThat(pulsarHeaders).containsEntry("payload", "\"%s\"".formatted(payloadEnc))
|
||||
.containsEntry(JSON_TYPES, "{\"payload\":\"[B\"}");
|
||||
var pulsarMessage = mockPulsarMessage(true, pulsarHeaders);
|
||||
var springHeaders = mapper().toSpringHeaders(pulsarMessage);
|
||||
assertThat(springHeaders).containsEntry("payload", payload);
|
||||
|
||||
Reference in New Issue
Block a user