Skip to content

Commit

Permalink
feat: Enable/Disable listeners
Browse files Browse the repository at this point in the history
Allows for more fine-grain configuration, avoiding exceptions if certain listeners are broken, or if multiple scanners discover the same consumer/producer

Co-authored-by: Timon Back <timonback@users.noreply.github.com>
  • Loading branch information
timonback and timonback committed Feb 18, 2023
1 parent bc48614 commit 61a71eb
Show file tree
Hide file tree
Showing 22 changed files with 227 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
package io.github.stavshamir.springwolf;

public class SpringWolfConfigConstants {
public static final String ENABLED = ".enabled";

public static final String SCANNER = ".scanner";

public static final String SPRINGWOLF_CONFIG_PREFIX = "springwolf";

public static final String SPRINGWOLF_ENABLED = SPRINGWOLF_CONFIG_PREFIX + ".enabled";
public static final String SPRINGWOLF_ENABLED = SPRINGWOLF_CONFIG_PREFIX + ENABLED;
public static final String SPRINGWOLF_PLUGIN_CONFIG_PREFIX = SPRINGWOLF_CONFIG_PREFIX + ".plugin";

public static final String SPRINGWOLF_SCANNER_PREFIX = SPRINGWOLF_CONFIG_PREFIX + SCANNER;
public static final String SPRINGWOLF_SCANNER_ASYNC_LISTENER_ENABLED = SPRINGWOLF_SCANNER_PREFIX + ".async-listener" + ENABLED;
public static final String SPRINGWOLF_SCANNER_ASYNC_PUBLISHER_ENABLED = SPRINGWOLF_SCANNER_PREFIX + ".async-publisher" + ENABLED;
public static final String SPRINGWOLF_SCANNER_CONSUMER_DATA_ENABLED = SPRINGWOLF_SCANNER_PREFIX + ".consumer-data" + ENABLED;
public static final String SPRINGWOLF_SCANNER_PRODUCER_DATA_ENABLED = SPRINGWOLF_SCANNER_PREFIX + ".producer-data" + ENABLED;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public class SpringWolfConfigProperties {
@Nullable
private ConfigDocket docket;

@Nullable
private Scanner scanner;

@Getter
@Setter
public static class ConfigDocket {
Expand Down Expand Up @@ -96,4 +99,60 @@ public static class Info {
}


@Getter
@Setter
public static class Scanner {

@Nullable
private static AsyncListener asyncListener;

@Nullable
private static AsyncPublisher asyncPublisher;

@Nullable
private static ConsumerData consumerData;

@Nullable
private static ProducerData producerData;

@Getter
@Setter
public static class AsyncListener {

/**
* This mirrors the ConfigConstant {@see SpringWolfConfigConstants#SPRINGWOLF_SCANNER_ASYNC_LISTENER_ENABLED}
*/
private boolean enabled = true;
}

@Getter
@Setter
public static class AsyncPublisher {

/**
* This mirrors the ConfigConstant {@see SpringWolfConfigConstants#SPRINGWOLF_SCANNER_ASYNC_PUBLISHER_ENABLED}
*/
private boolean enabled = true;
}

@Getter
@Setter
public static class ConsumerData {

/**
* This mirrors the ConfigConstant {@see SpringWolfConfigConstants#SPRINGWOLF_SCANNER_PRODUCER_DATA_ENABLED}
*/
private boolean enabled = true;
}

@Getter
@Setter
public static class ProducerData {

/**
* This mirrors the ConfigConstant {@see SpringWolfConfigConstants#SPRINGWOLF_SCANNER_RABBIT_LISTENER_ENABLED}
*/
private boolean enabled = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
import io.github.stavshamir.springwolf.schemas.SchemasService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static io.github.stavshamir.springwolf.SpringWolfConfigConstants.*;

@Slf4j
@RequiredArgsConstructor
@Component
@ConditionalOnProperty(name = SPRINGWOLF_SCANNER_CONSUMER_DATA_ENABLED, matchIfMissing = true)
public class ConsumerOperationDataScanner extends AbstractOperationDataScanner {

private final AsyncApiDocketService asyncApiDocketService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
import io.github.stavshamir.springwolf.schemas.SchemasService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static io.github.stavshamir.springwolf.SpringWolfConfigConstants.*;

@Slf4j
@RequiredArgsConstructor
@Component
@ConditionalOnProperty(name = SPRINGWOLF_SCANNER_PRODUCER_DATA_ENABLED, matchIfMissing = true)
public class ProducerOperationDataScanner extends AbstractOperationDataScanner {

private final AsyncApiDocketService asyncApiDocketService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.github.stavshamir.springwolf.schemas.SchemasService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
Expand All @@ -19,12 +20,14 @@
import java.util.*;
import java.util.stream.Collectors;

import static io.github.stavshamir.springwolf.SpringWolfConfigConstants.SPRINGWOLF_SCANNER_ASYNC_LISTENER_ENABLED;
import static java.util.stream.Collectors.toSet;

@Slf4j
@RequiredArgsConstructor
@Component
@Order(value = ChannelPriority.ASYNC_ANNOTATION)
@ConditionalOnProperty(name = SPRINGWOLF_SCANNER_ASYNC_LISTENER_ENABLED, matchIfMissing = true)
public class AsyncListenerAnnotationScanner extends AbstractOperationDataScanner implements EmbeddedValueResolverAware {
private StringValueResolver resolver;
private final ComponentClassScanner componentClassScanner;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.github.stavshamir.springwolf.schemas.SchemasService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
Expand All @@ -19,12 +20,14 @@
import java.util.*;
import java.util.stream.Collectors;

import static io.github.stavshamir.springwolf.SpringWolfConfigConstants.*;
import static java.util.stream.Collectors.toSet;

@Slf4j
@RequiredArgsConstructor
@Component
@Order(value = ChannelPriority.ASYNC_ANNOTATION)
@ConditionalOnProperty(name = SPRINGWOLF_SCANNER_ASYNC_PUBLISHER_ENABLED, matchIfMissing = true)
public class AsyncPublisherAnnotationScanner extends AbstractOperationDataScanner implements EmbeddedValueResolverAware {
private StringValueResolver resolver;
private final ComponentClassScanner componentClassScanner;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void testContextWithAsyncApiDocketBean() {
"springwolf.enabled=true",
"springwolf.docket.info.title=Info title was loaded from spring properties",
"springwolf.docket.info.version=1.0.0",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example.consumers",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example",
"springwolf.docket.servers.test-protocol.protocol=test",
"springwolf.docket.servers.test-protocol.url=some-server:1234",
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class DefaultAsyncApiDocketServiceIntegrationTest {
"springwolf.enabled=true",
"springwolf.docket.info.title=Info title was loaded from spring properties",
"springwolf.docket.info.version=1.0.0",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example.consumers",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example",
"springwolf.docket.servers.test-protocol.protocol=test",
"springwolf.docket.servers.test-protocol.url=some-server:1234"
})
Expand All @@ -53,7 +53,7 @@ public void testDocketContentShouldBeLoadedFromProperties() {
"springwolf.enabled=true",
"springwolf.docket.info.title=Docket was loaded from spring properties",
"springwolf.docket.info.version=1.0.0",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example.consumers",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example",
"springwolf.docket.servers.test-protocol.protocol=test",
"springwolf.docket.servers.test-protocol.url=some-server:1234"
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ spring.rabbitmq.password=guest
spring.application.name=Springwolf example project - Amqp

springwolf.enabled=true
springwolf.docket.base-package=io.github.stavshamir.springwolf.example.consumers
springwolf.docket.base-package=io.github.stavshamir.springwolf.example
springwolf.docket.info.title=${spring.application.name}
springwolf.docket.info.version=1.0.0
springwolf.docket.info.description=Springwolf example project to demonstrate springwolfs abilities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public void testContextWithAsyncApiDocketBean() {

assertThat(asyncApiService.getAsyncAPI()).isNotNull();
}

@Test
public void testAllChannelsAreFound() {
assertThat(asyncApiService.getAsyncAPI().getChannels()).hasSize(7);
}
}

@SpringBootTest(classes = SpringwolfExampleApplication.class)
Expand All @@ -35,7 +40,7 @@ public void testContextWithAsyncApiDocketBean() {
"springwolf.enabled=true",
"springwolf.docket.info.title=Info title was loaded from spring properties",
"springwolf.docket.info.version=1.0.0",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example.consumers",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example",
"springwolf.docket.servers.test-protocol.protocol=amqp",
"springwolf.docket.servers.test-protocol.url=some-server:1234",
})
Expand All @@ -52,5 +57,30 @@ public void testContextWithApplicationProperties() {

assertThat(asyncApiService.getAsyncAPI()).isNotNull();
}

@Test
public void testAllChannelsAreFound() {
// 2 channels defined in the AsyncDocket are not found (7 - 2 = 5)
assertThat(asyncApiService.getAsyncAPI().getChannels()).hasSize(5);
}
}

@SpringBootTest(classes = SpringwolfExampleApplication.class)
@TestPropertySource(properties = {
"springwolf.scanner.async-listener.enabled=false",
"springwolf.scanner.async-publisher.enabled=false",
"springwolf.scanner.consumer-data.enabled=false",
"springwolf.scanner.producer-data.enabled=false",
"springwolf.plugin.amqp.scanner.rabbit-listener.enabled=false",
})
public static class DisabledScannerTest {

@Autowired
private AsyncApiService asyncApiService;

@Test
public void testNoChannelsAreFound() {
assertThat(asyncApiService.getAsyncAPI().getChannels()).isEmpty();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void testContextWithAsyncApiDocketBean() {
"springwolf.enabled=true",
"springwolf.docket.info.title=Info title was loaded from spring properties",
"springwolf.docket.info.version=1.0.0",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example.consumers",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example",
"springwolf.docket.servers.test-protocol.protocol=kafka",
"springwolf.docket.servers.test-protocol.url=some-server:1234",
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ kafka.bootstrap.servers=${BOOTSTRAP_SERVER:localhost:29092}
spring.application.name=Springwolf example project - Kafka

springwolf.enabled=true
springwolf.docket.base-package=io.github.stavshamir.springwolf.example.consumers
springwolf.docket.base-package=io.github.stavshamir.springwolf.example
springwolf.docket.info.title=${spring.application.name}
springwolf.docket.info.version=1.0.0
springwolf.docket.info.description=Springwolf example project to demonstrate springwolfs abilities
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.github.stavshamir.springwolf.example;

import io.github.stavshamir.springwolf.asyncapi.AsyncApiService;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
Expand All @@ -14,7 +13,6 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;


@Nested
public class SpringContextTest {

@SpringBootTest(classes = SpringwolfExampleApplication.class)
Expand All @@ -33,6 +31,11 @@ public void testContextWithAsyncApiDocketBean() {

assertThat(asyncApiService.getAsyncAPI()).isNotNull();
}

@Test
public void testAllChannelsAreFound() {
assertThat(asyncApiService.getAsyncAPI().getChannels()).hasSize(5);
}
}

@SpringBootTest(classes = SpringwolfExampleApplication.class)
Expand All @@ -43,7 +46,7 @@ public void testContextWithAsyncApiDocketBean() {
"springwolf.enabled=true",
"springwolf.docket.info.title=Info title was loaded from spring properties",
"springwolf.docket.info.version=1.0.0",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example.consumers",
"springwolf.docket.base-package=io.github.stavshamir.springwolf.example",
"springwolf.docket.servers.test-protocol.protocol=kafka",
"springwolf.docket.servers.test-protocol.url=some-server:1234",
})
Expand All @@ -60,5 +63,33 @@ public void testContextWithApplicationProperties() {

assertThat(asyncApiService.getAsyncAPI()).isNotNull();
}

@Test
public void testAllChannelsAreFound() {
// 2 channels defined in the AsyncDocket are not found,
// however PRODUCER_TOPIC is also used in ExampleProducer (5 - 2 + 1 = 4)
assertThat(asyncApiService.getAsyncAPI().getChannels()).hasSize(4);
}
}

@SpringBootTest(classes = SpringwolfExampleApplication.class)
@EmbeddedKafka(partitions = 1, brokerProperties = { "listeners=PLAINTEXT://localhost:29092", "port=29092" })
@DirtiesContext
@TestPropertySource(properties = {
"springwolf.scanner.async-listener.enabled=false",
"springwolf.scanner.async-publisher.enabled=false",
"springwolf.scanner.consumer-data.enabled=false",
"springwolf.scanner.producer-data.enabled=false",
"springwolf.plugin.kafka.scanner.kafka-listener.enabled=false"
})
public static class DisabledScannerTest {

@Autowired
private AsyncApiService asyncApiService;

@Test
public void testNoChannelsAreFound() {
assertThat(asyncApiService.getAsyncAPI().getChannels()).isEmpty();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.stavshamir.springwolf;

import static io.github.stavshamir.springwolf.SpringWolfConfigConstants.ENABLED;
import static io.github.stavshamir.springwolf.SpringWolfConfigConstants.SCANNER;
import static io.github.stavshamir.springwolf.SpringWolfConfigConstants.SPRINGWOLF_PLUGIN_CONFIG_PREFIX;

public class SpringWolfAmqpConfigConstants {
Expand All @@ -8,5 +10,6 @@ public class SpringWolfAmqpConfigConstants {

public static final String SPRINGWOLF_AMQP_PLUGIN_PUBLISHING_ENABLED = "publishing.enabled";


public static final String SPRINGWOLF_SCANNER_RABBIT_LISTENER_ENABLED =
SPRINGWOLF_AMQP_CONFIG_PREFIX + SCANNER + ".rabbit-listener" + ENABLED;
}
Loading

0 comments on commit 61a71eb

Please sign in to comment.