Browse Source

Merge pull request #40421 from quaff

* pr/40421:
  Polish 'Add `spring.rabbitmq.template.allowed-list-patterns` property'
  Add `spring.rabbitmq.template.allowed-list-patterns` property

Closes gh-40421
pull/40484/head
Phillip Webb 2 years ago
parent
commit
c5935ea421
  1. 14
      spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitProperties.java
  2. 17
      spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitTemplateConfigurer.java
  3. 62
      spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfigurationTests.java

14
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitProperties.java

@ -48,6 +48,7 @@ import org.springframework.util.unit.DataSize;
* @author Rafael Carvalho * @author Rafael Carvalho
* @author Scott Frederick * @author Scott Frederick
* @author Lasse Wulff * @author Lasse Wulff
* @author Yanming Zhou
* @since 1.0.0 * @since 1.0.0
*/ */
@ConfigurationProperties(prefix = "spring.rabbitmq") @ConfigurationProperties(prefix = "spring.rabbitmq")
@ -1015,6 +1016,11 @@ public class RabbitProperties {
*/ */
private boolean observationEnabled; private boolean observationEnabled;
/**
* Simple patterns for allowable packages/classes for deserialization.
*/
private List<String> allowedListPatterns;
public Retry getRetry() { public Retry getRetry() {
return this.retry; return this.retry;
} }
@ -1075,6 +1081,14 @@ public class RabbitProperties {
this.observationEnabled = observationEnabled; this.observationEnabled = observationEnabled;
} }
public List<String> getAllowedListPatterns() {
return this.allowedListPatterns;
}
public void setAllowedListPatterns(List<String> allowedListPatterns) {
this.allowedListPatterns = allowedListPatterns;
}
} }
public static class Retry { public static class Retry {

17
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitTemplateConfigurer.java

@ -21,14 +21,18 @@ import java.util.List;
import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.AllowedListDeserializingMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/** /**
* Configure {@link RabbitTemplate} with sensible defaults. * Configure {@link RabbitTemplate} with sensible defaults.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Yanming Zhou
* @since 2.3.0 * @since 2.3.0
*/ */
public class RabbitTemplateConfigurer { public class RabbitTemplateConfigurer {
@ -102,6 +106,19 @@ public class RabbitTemplateConfigurer {
map.from(templateProperties::getRoutingKey).to(template::setRoutingKey); map.from(templateProperties::getRoutingKey).to(template::setRoutingKey);
map.from(templateProperties::getDefaultReceiveQueue).whenNonNull().to(template::setDefaultReceiveQueue); map.from(templateProperties::getDefaultReceiveQueue).whenNonNull().to(template::setDefaultReceiveQueue);
map.from(templateProperties::isObservationEnabled).to(template::setObservationEnabled); map.from(templateProperties::isObservationEnabled).to(template::setObservationEnabled);
map.from(templateProperties::getAllowedListPatterns)
.whenNot(CollectionUtils::isEmpty)
.to((allowListPatterns) -> setAllowedListPatterns(template.getMessageConverter(), allowListPatterns));
}
private void setAllowedListPatterns(MessageConverter messageConverter, List<String> allowListPatterns) {
if (messageConverter instanceof AllowedListDeserializingMessageConverter allowedListDeserializingMessageConverter) {
allowedListDeserializingMessageConverter.setAllowedListPatterns(allowListPatterns);
return;
}
throw new InvalidConfigurationPropertyValueException("spring.rabbitmq.template.allow-list-patterns",
allowListPatterns,
"Allow list patterns can only be applied to a AllowedListDeserializingMessageConverter");
} }
private boolean determineMandatoryFlag() { private boolean determineMandatoryFlag() {

62
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfigurationTests.java

@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.amqp; package org.springframework.boot.autoconfigure.amqp;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -35,11 +36,14 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange; import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.InOrder; import org.mockito.InOrder;
import org.springframework.amqp.core.AcknowledgeMode; import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.AmqpAdmin; import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Message; import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.EnableRabbit; import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory; import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory;
@ -59,10 +63,13 @@ import org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory; import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.retry.MessageRecoverer; import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.support.converter.MessageConversionException;
import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.amqp.support.converter.SerializerMessageConverter;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration; import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@ -107,6 +114,7 @@ import static org.mockito.Mockito.mock;
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Phillip Webb * @author Phillip Webb
* @author Scott Frederick * @author Scott Frederick
* @author Yanming Zhou
*/ */
@ExtendWith(OutputCaptureExtension.class) @ExtendWith(OutputCaptureExtension.class)
class RabbitAutoConfigurationTests { class RabbitAutoConfigurationTests {
@ -796,6 +804,27 @@ class RabbitAutoConfigurationTests {
}); });
} }
@ParameterizedTest
@ValueSource(classes = { TestConfiguration.class, TestConfiguration6.class })
@SuppressWarnings("unchecked")
void customizeAllowedListPatterns(Class<?> configuration) {
this.contextRunner.withUserConfiguration(configuration)
.withPropertyValues("spring.rabbitmq.template.allowed-list-patterns:*")
.run((context) -> {
MessageConverter messageConverter = context.getBean(RabbitTemplate.class).getMessageConverter();
assertThat(messageConverter).extracting("allowedListPatterns")
.isInstanceOfSatisfying(Collection.class, (set) -> assertThat(set).contains("*"));
});
}
@Test
void customizeAllowedListPatternsWhenHasNoAllowedListDeserializingMessageConverter() {
this.contextRunner.withUserConfiguration(CustomMessageConverterConfiguration.class)
.withPropertyValues("spring.rabbitmq.template.allowed-list-patterns:*")
.run((context) -> assertThat(context).getFailure()
.hasRootCauseInstanceOf(InvalidConfigurationPropertyValueException.class));
}
@Test @Test
void noSslByDefault() { void noSslByDefault() {
this.contextRunner.withUserConfiguration(TestConfiguration.class).run((context) -> { this.contextRunner.withUserConfiguration(TestConfiguration.class).run((context) -> {
@ -1113,6 +1142,16 @@ class RabbitAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false)
static class TestConfiguration6 {
@Bean
MessageConverter messageConverter() {
return new SerializerMessageConverter();
}
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
static class MessageConvertersConfiguration { static class MessageConvertersConfiguration {
@ -1387,6 +1426,29 @@ class RabbitAutoConfigurationTests {
} }
@Configuration
static class CustomMessageConverterConfiguration {
@Bean
MessageConverter messageConverter() {
return new MessageConverter() {
@Override
public Message toMessage(Object object, MessageProperties messageProperties)
throws MessageConversionException {
return new Message(object.toString().getBytes());
}
@Override
public Object fromMessage(Message message) throws MessageConversionException {
return new String(message.getBody());
}
};
}
}
static class TestListener { static class TestListener {
@RabbitListener(queues = "test", autoStartup = "false") @RabbitListener(queues = "test", autoStartup = "false")

Loading…
Cancel
Save