Skip to content

Commit

Permalink
GH-342 - Allow disabling event externalization.
Browse files Browse the repository at this point in the history
We now expose spring.modulith.events.externalization.enabled that can be set to false to disable the event externalization completely. Useful in test cases, for example.
  • Loading branch information
odrotbohm committed Oct 23, 2023
1 parent 69fd64d commit 576b8f5
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.spel.support.StandardEvaluationContext;
Expand All @@ -40,6 +41,9 @@
@AutoConfiguration
@AutoConfigureAfter(EventExternalizationAutoConfiguration.class)
@ConditionalOnClass(RabbitTemplate.class)
@ConditionalOnProperty(name = "spring.modulith.events.externalization.enabled",
havingValue = "true",
matchIfMissing = true)
class RabbitEventExternalizerConfiguration {

private static final Logger logger = LoggerFactory.getLogger(RabbitEventExternalizerConfiguration.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.modulith.events.amqp;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitMessageOperations;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.modulith.events.EventExternalizationConfiguration;
import org.springframework.modulith.events.support.DelegatingEventExternalizer;

/**
* Integration tests for {@link RabbitEventExternalizerConfiguration}.
*
* @author Oliver Drotbohm
* @since 1.1
*/
class RabbitEventExternalizerConfigurationIntegrationTests {

@Test // GH-342
void registersExternalizerByDefault() {

basicSetup()
.run(ctxt -> {
assertThat(ctxt).hasSingleBean(DelegatingEventExternalizer.class);
});
}

@Test // GH-342
void disablesExternalizationIfConfigured() {

basicSetup()
.withPropertyValues("spring.modulith.events.externalization.enabled=false")
.run(ctxt -> {
assertThat(ctxt).doesNotHaveBean(DelegatingEventExternalizer.class);
});
}

private ApplicationContextRunner basicSetup() {

return new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(RabbitEventExternalizerConfiguration.class))
.withBean(EventExternalizationConfiguration.class, () -> EventExternalizationConfiguration.disabled())
.withBean(RabbitMessageOperations.class, () -> mock(RabbitMessageOperations.class));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ public static Selector externalizing() {
return new Selector();
}

/**
* Disables event externalization by not matching any events at all.
*
* @return will never be {@literal null}.
*/
public static EventExternalizationConfiguration disabled() {
return externalizing().select(__ -> false).build();
}

/**
* A {@link Predicate} to select all events annotated as to be externalized. The currently supported annotations are:
* <ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Role;
import org.springframework.context.event.EventListenerFactory;
import org.springframework.core.Ordered;
import org.springframework.modulith.events.EventExternalizationConfiguration;
import org.springframework.modulith.events.core.ConditionalEventListener;
import org.springframework.modulith.events.support.PersistentApplicationEventMulticaster;
import org.springframework.transaction.event.TransactionalApplicationListenerMethodAdapter;
import org.springframework.transaction.event.TransactionalEventListenerFactory;

Expand All @@ -40,6 +40,9 @@
* @author Oliver Drotbohm
* @since 1.1
*/
@ConditionalOnProperty(name = "spring.modulith.events.externalization.enabled",
havingValue = "true",
matchIfMissing = true)
@AutoConfiguration
@AutoConfigureAfter(EventPublicationConfiguration.class)
public class EventExternalizationAutoConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
"type": "java.lang.boolean",
"description": "Whether to republish outstanding event publications on restarts of the application.",
"defaultValue": "false"
},
{
"name": "spring.modulith.events.externalization.enabled",
"type": "java.lang.boolean",
"description": "Whether to enable event externalization.",
"defaultValue": "true"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.core.JmsOperations;
import org.springframework.modulith.events.EventExternalizationConfiguration;
Expand All @@ -36,6 +37,9 @@
@AutoConfiguration
@AutoConfigureAfter(EventExternalizationAutoConfiguration.class)
@ConditionalOnClass(JmsOperations.class)
@ConditionalOnProperty(name = "spring.modulith.events.externalization.enabled",
havingValue = "true",
matchIfMissing = true)
class JmsEventExternalizerConfiguration {

private static final Logger logger = LoggerFactory.getLogger(JmsEventExternalizerConfiguration.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.modulith.events.jms;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.jms.core.JmsOperations;
import org.springframework.modulith.events.EventExternalizationConfiguration;
import org.springframework.modulith.events.core.EventSerializer;
import org.springframework.modulith.events.support.DelegatingEventExternalizer;

/**
* Integration tests for {@link JmsEventExternalizerConfiguration}.
*
* @author Oliver Drotbohm
* @since 1.1
*/
class JmsEventExternalizerConfigurationIntegrationTests {

@Test // GH-342
void registersExternalizerByDefault() {

basicSetup()
.run(ctxt -> {
assertThat(ctxt).hasSingleBean(DelegatingEventExternalizer.class);
});
}

@Test // GH-342
void disablesExternalizationIfConfigured() {

basicSetup()
.withPropertyValues("spring.modulith.events.externalization.enabled=false")
.run(ctxt -> {
assertThat(ctxt).doesNotHaveBean(DelegatingEventExternalizer.class);
});
}

private ApplicationContextRunner basicSetup() {

return new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(JmsEventExternalizerConfiguration.class))
.withBean(EventExternalizationConfiguration.class, () -> EventExternalizationConfiguration.disabled())
.withBean(EventSerializer.class, () -> mock(EventSerializer.class))
.withBean(JmsOperations.class, () -> mock(JmsOperations.class));
}
}
8 changes: 8 additions & 0 deletions spring-modulith-events/spring-modulith-events-kafka/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
<optional>true</optional>
</dependency>

<!-- Testing -->

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.spel.support.StandardEvaluationContext;
Expand All @@ -37,9 +38,13 @@
* @author Oliver Drotbohm
* @since 1.1
*/

@AutoConfiguration
@AutoConfigureAfter(EventExternalizationAutoConfiguration.class)
@ConditionalOnClass(KafkaTemplate.class)
@ConditionalOnProperty(name = "spring.modulith.events.externalization.enabled",
havingValue = "true",
matchIfMissing = true)
class KafkaEventExternalizerConfiguration {

private static final Logger logger = LoggerFactory.getLogger(KafkaEventExternalizerConfiguration.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.modulith.events.kafka;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.kafka.core.KafkaOperations;
import org.springframework.modulith.events.EventExternalizationConfiguration;
import org.springframework.modulith.events.support.DelegatingEventExternalizer;

/**
* Integration tests for {@link KafkaEventExternalizerConfiguration}.
*
* @author Oliver Drotbohm
* @since 1.1
*/
class KafkaEventExternalizerConfigurationIntegrationTests {

@Test // GH-342
void registersExternalizerByDefault() {

basicSetup()
.run(ctxt -> {
assertThat(ctxt).hasSingleBean(DelegatingEventExternalizer.class);
});
}

@Test // GH-342
void disablesExternalizationIfConfigured() {

basicSetup()
.withPropertyValues("spring.modulith.events.externalization.enabled=false")
.run(ctxt -> {
assertThat(ctxt).doesNotHaveBean(DelegatingEventExternalizer.class);
});
}

private ApplicationContextRunner basicSetup() {

return new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(KafkaEventExternalizerConfiguration.class))
.withBean(EventExternalizationConfiguration.class, () -> EventExternalizationConfiguration.disabled())
.withBean(KafkaOperations.class, () -> mock(KafkaOperations.class));
}
}
4 changes: 4 additions & 0 deletions src/docs/antora/modules/ROOT/pages/appendix.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
|`true`
|Whether to configure defaults for the async processing termination, namely to wait for task completion for 2 seconds. See `TaskExecutionProperties` for details.

|`spring.modulith.events.externalization.enabled`
|`true`
|Whether to enable event externalization.

|`spring.modulith.events.jdbc.schema-initialization.enabled`
|`false`
|Whether to initialize the JDBC event publication schema.
Expand Down

0 comments on commit 576b8f5

Please sign in to comment.