Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/replace componentscan #386

Merged
merged 9 commits into from
Oct 13, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CommonModelConvertersConfiguration {
/**
* Spring AutoConfiguration adding an {@link MonetaryAmountConverter} Bean to the spring context.
*/
@Configuration(proxyBeanMethods = false)
public class CommonModelConvertersAutoConfiguration {

@Bean
public MonetaryAmountConverter monetaryAmountConverter() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.github.stavshamir.springwolf.common_converters.configuration.CommonModelConvertersAutoConfiguration
Original file line number Diff line number Diff line change
@@ -1,29 +1,81 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.stavshamir.springwolf;

import io.github.stavshamir.springwolf.asyncapi.AsyncApiCustomizer;
import io.github.stavshamir.springwolf.asyncapi.AsyncApiService;
import io.github.stavshamir.springwolf.asyncapi.ChannelsService;
import io.github.stavshamir.springwolf.asyncapi.DefaultAsyncApiService;
import io.github.stavshamir.springwolf.asyncapi.DefaultChannelsService;
import io.github.stavshamir.springwolf.asyncapi.SpringwolfInitApplicationListener;
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.ChannelsScanner;
import io.github.stavshamir.springwolf.configuration.AsyncApiDocket;
import io.github.stavshamir.springwolf.configuration.AsyncApiDocketService;
import io.github.stavshamir.springwolf.configuration.DefaultAsyncApiDocketService;
import io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants;
import io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigProperties;
import io.github.stavshamir.springwolf.schemas.DefaultSchemasService;
import io.github.stavshamir.springwolf.schemas.SchemasService;
import io.github.stavshamir.springwolf.schemas.example.ExampleGenerator;
import io.github.stavshamir.springwolf.schemas.example.ExampleJsonGenerator;
import io.swagger.v3.core.converter.ModelConverter;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;

import java.util.List;
import java.util.Optional;

/**
* Spring Boot auto-configuration which loads all spring-beans for springwolf core and eventually loaded plugins.
* <p>
* This configuration uses the spring @{@link ComponentScan} mechanism to detect and load the necessary beans. Both
* the core components as well as all plugin components are located underneath the base package 'io.github.stavshamir.springwolf'
* so existing springwolf plugins are automatically loaded together with the springwolf core beans.
* Spring Boot auto-configuration which loads all spring-beans for springwolf core module.
* <p>
* To disable this auto-configuration, set the environment property {@code springwolf.enabled=false}.
* To disable springwolf support, set the environment property {@code springwolf.enabled=false}.
*/
@AutoConfiguration
@ComponentScan(
basePackages = {"io.github.stavshamir.springwolf"},
excludeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
@Import({SpringwolfWebConfiguration.class, SpringwolfScannerConfiguration.class})
@ConditionalOnProperty(name = SpringwolfConfigConstants.SPRINGWOLF_ENABLED, matchIfMissing = true)
public class SpringwolfAutoConfiguration {}
public class SpringwolfAutoConfiguration {

@Bean
public SpringwolfConfigProperties springwolfConfigProperties() {
return new SpringwolfConfigProperties();
}

@Bean
public SpringwolfInitApplicationListener springwolfInitApplicationListener(
AsyncApiService asyncApiService, SpringwolfConfigProperties configProperties) {
return new SpringwolfInitApplicationListener(asyncApiService, configProperties);
}

@Bean
public AsyncApiService asyncApiService(
AsyncApiDocketService asyncApiDocketService,
ChannelsService channelsService,
SchemasService schemasService,
List<AsyncApiCustomizer> customizers) {
return new DefaultAsyncApiService(asyncApiDocketService, channelsService, schemasService, customizers);
}

@Bean
public ChannelsService channelsService(List<? extends ChannelsScanner> channelsScanners) {
return new DefaultChannelsService(channelsScanners);
}

@Bean
public SchemasService schemasService(List<ModelConverter> modelConverters, ExampleGenerator exampleGenerator) {
return new DefaultSchemasService(modelConverters, exampleGenerator);
}

@Bean
public AsyncApiDocketService asyncApiDocketService(
Optional<AsyncApiDocket> optionalAsyncApiDocket, SpringwolfConfigProperties springwolfConfigProperties) {
return new DefaultAsyncApiDocketService(optionalAsyncApiDocket, springwolfConfigProperties);
}

@Bean
@ConditionalOnMissingBean
public ExampleGenerator exampleGenerator() {
return new ExampleJsonGenerator();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.stavshamir.springwolf;

import io.github.stavshamir.springwolf.asyncapi.scanners.beans.BeanMethodsScanner;
import io.github.stavshamir.springwolf.asyncapi.scanners.beans.DefaultBeanMethodsScanner;
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.ConsumerOperationDataScanner;
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.ProducerOperationDataScanner;
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.annotation.AsyncListenerAnnotationScanner;
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.annotation.AsyncPublisherAnnotationScanner;
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.annotation.MessageBindingProcessor;
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.annotation.OperationBindingProcessor;
import io.github.stavshamir.springwolf.asyncapi.scanners.classes.ComponentClassScanner;
import io.github.stavshamir.springwolf.asyncapi.scanners.classes.ConfigurationClassScanner;
import io.github.stavshamir.springwolf.configuration.AsyncApiDocketService;
import io.github.stavshamir.springwolf.schemas.SchemasService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.util.List;

import static io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_SCANNER_ASYNC_LISTENER_ENABLED;
import static io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_SCANNER_ASYNC_PUBLISHER_ENABLED;
import static io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_SCANNER_CONSUMER_DATA_ENABLED;
import static io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_SCANNER_PRODUCER_DATA_ENABLED;

/**
* Spring configuration defining the core scanner beans.
*/
@Configuration(proxyBeanMethods = false)
public class SpringwolfScannerConfiguration {

@Bean
public ComponentClassScanner componentClassScanner(
AsyncApiDocketService asyncApiDocketService, Environment environment) {
return new ComponentClassScanner(asyncApiDocketService, environment);
}

@Bean
public ConfigurationClassScanner configurationClassScanner(
AsyncApiDocketService asyncApiDocketService, Environment environment) {
return new ConfigurationClassScanner(asyncApiDocketService, environment);
}

@Bean
public BeanMethodsScanner beanMethodsScanner(ConfigurationClassScanner configurationClassScanner) {
return new DefaultBeanMethodsScanner(configurationClassScanner);
}

@Bean
@ConditionalOnProperty(name = SPRINGWOLF_SCANNER_CONSUMER_DATA_ENABLED, matchIfMissing = true)
public ConsumerOperationDataScanner consumerOperationDataScanner(
AsyncApiDocketService asyncApiDocketService, SchemasService schemasService) {
return new ConsumerOperationDataScanner(asyncApiDocketService, schemasService);
}

@Bean
@ConditionalOnProperty(name = SPRINGWOLF_SCANNER_PRODUCER_DATA_ENABLED, matchIfMissing = true)
public ProducerOperationDataScanner producerOperationDataScanner(
AsyncApiDocketService asyncApiDocketService, SchemasService schemasService) {
return new ProducerOperationDataScanner(asyncApiDocketService, schemasService);
}

@Bean
@ConditionalOnProperty(name = SPRINGWOLF_SCANNER_ASYNC_LISTENER_ENABLED, matchIfMissing = true)
public AsyncListenerAnnotationScanner asyncListenerAnnotationScanner(
ComponentClassScanner componentClassScanner,
SchemasService schemasService,
List<OperationBindingProcessor> operationBindingProcessors,
List<MessageBindingProcessor> messageBindingProcessors) {
return new AsyncListenerAnnotationScanner(
componentClassScanner, schemasService, operationBindingProcessors, messageBindingProcessors);
}

@Bean
@ConditionalOnProperty(name = SPRINGWOLF_SCANNER_ASYNC_PUBLISHER_ENABLED, matchIfMissing = true)
public AsyncPublisherAnnotationScanner asyncPublisherAnnotationScanner(
ComponentClassScanner componentClassScanner,
SchemasService schemasService,
List<OperationBindingProcessor> operationBindingProcessors,
List<MessageBindingProcessor> messageBindingProcessors) {
return new AsyncPublisherAnnotationScanner(
componentClassScanner, schemasService, operationBindingProcessors, messageBindingProcessors);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.stavshamir.springwolf;

import io.github.stavshamir.springwolf.asyncapi.AsyncApiSerializerService;
import io.github.stavshamir.springwolf.asyncapi.AsyncApiService;
import io.github.stavshamir.springwolf.asyncapi.DefaultAsyncApiSerializerService;
import io.github.stavshamir.springwolf.asyncapi.controller.ActuatorAsyncApiController;
import io.github.stavshamir.springwolf.asyncapi.controller.AsyncApiController;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_ENDPOINT_ACTUATOR_ENABLED;

/**
* Spring-Configuration defining the web controller beans.
*/
@Configuration(proxyBeanMethods = false)
public class SpringwolfWebConfiguration {

@Bean
@ConditionalOnProperty(name = SPRINGWOLF_ENDPOINT_ACTUATOR_ENABLED, havingValue = "false", matchIfMissing = true)
public AsyncApiController asyncApiController(
AsyncApiService asyncApiService, AsyncApiSerializerService asyncApiSerializerService) {
return new AsyncApiController(asyncApiService, asyncApiSerializerService);
}

@Bean
@ConditionalOnProperty(name = SPRINGWOLF_ENDPOINT_ACTUATOR_ENABLED, havingValue = "true")
public ActuatorAsyncApiController actuatorAsyncApiController(
AsyncApiService asyncApiService, AsyncApiSerializerService asyncApiSerializerService) {
return new ActuatorAsyncApiController(asyncApiService, asyncApiSerializerService);
}

@Bean
public AsyncApiSerializerService asyncApiSerializerService() {
return new DefaultAsyncApiSerializerService();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public Map<String, ChannelItem> findChannels() {
Map<String, ChannelItem> channels = scanner.scan();
foundChannelItems.addAll(channels.entrySet());
} catch (Exception e) {
log.error("An error was encountered during channel scanning with {}: {}", scanner, e.getMessage());
log.error("An error was encountered during channel scanning with {}: {}", scanner, e.getMessage(), e);
timonback marked this conversation as resolved.
Show resolved Hide resolved
}
}
return ChannelMerger.merge(foundChannelItems);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,14 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;

import static io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_ENDPOINT_ACTUATOR_ENABLED;

@Component
@Slf4j
@RestControllerEndpoint(id = "springwolf")
@RequiredArgsConstructor
@ConditionalOnProperty(name = SPRINGWOLF_ENDPOINT_ACTUATOR_ENABLED, havingValue = "true")
public class ActuatorAsyncApiController {

private final AsyncApiService asyncApiService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@
import io.github.stavshamir.springwolf.asyncapi.types.AsyncAPI;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import static io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_ENDPOINT_ACTUATOR_ENABLED;

@Slf4j
@RestController
@RequiredArgsConstructor
@ConditionalOnProperty(name = SPRINGWOLF_ENDPOINT_ACTUATOR_ENABLED, havingValue = "false", matchIfMissing = true)
public class AsyncApiController {

private final AsyncApiService asyncApiService;
Expand Down
timonback marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.AsyncHeaders;
import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.HeaderReference;
import io.github.stavshamir.springwolf.schemas.SchemasService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
Expand All @@ -35,15 +35,14 @@
import static java.util.stream.Collectors.toSet;

@Slf4j
@RequiredArgsConstructor
public abstract class AbstractClassLevelListenerScanner<
ClassAnnotation extends Annotation, MethodAnnotation extends Annotation>
implements ChannelsScanner {

@Autowired
private ComponentClassScanner componentClassScanner;
private final ComponentClassScanner componentClassScanner;

@Autowired
private SchemasService schemasService;
private final SchemasService schemasService;

private static final Comparator<Map.Entry<String, ChannelItem>> byPublishOperationName =
Comparator.comparing(it -> it.getValue().getPublish().getOperationId());
Expand Down
tvahrst marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.AsyncHeaders;
import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.HeaderReference;
import io.github.stavshamir.springwolf.schemas.SchemasService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
Expand All @@ -29,13 +29,12 @@
import static java.util.stream.Collectors.toSet;

@Slf4j
@RequiredArgsConstructor
public abstract class AbstractMethodLevelListenerScanner<T extends Annotation> implements ChannelsScanner {

@Autowired
private ComponentClassScanner componentClassScanner;
private final ComponentClassScanner componentClassScanner;

@Autowired
private SchemasService schemasService;
private final SchemasService schemasService;

@Override
public Map<String, ChannelItem> scan() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,14 @@
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.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_SCANNER_CONSUMER_DATA_ENABLED;

@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 @@ -6,18 +6,14 @@
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.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_SCANNER_PRODUCER_DATA_ENABLED;

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

private final AsyncApiDocketService asyncApiDocketService;
Expand Down
Loading