Add updateCopyrights Gradle task

* Fix Checkstyle violations for `spring-config-common` and `spring-aggregator-function`
This commit is contained in:
Artem Bilan
2024-01-03 14:46:20 -05:00
parent f6eafc9511
commit 8e64a131f7
7 changed files with 100 additions and 57 deletions

View File

@@ -9,6 +9,7 @@ plugins {
id 'io.spring.javaformat' version "${javaFormatVersion}"
id 'com.github.spotbugs' version '6.0.4'
id 'com.google.protobuf' version '0.9.4' apply false
id 'org.ajoberstar.grgit' version '5.2.1'
}
description = 'Spring Functions Catlog'
@@ -19,6 +20,18 @@ ext {
apply from: 'dependencies.gradle'
ext {
modifiedFiles = files().from { files(grgit.status().unstaged.modified).filter { f -> f.name.endsWith('.java') } }
modifiedFiles.finalizeValueOnRead()
javadocLinks = [
'https://docs.oracle.com/en/java/javase/17/docs/api/',
'https://jakarta.ee/specifications/platform/10/apidocs/',
'https://docs.spring.io/spring-framework/docs/current/javadoc-api',
'https://docs.spring.io/spring-integration/docs/current/api/'
] as String[]
}
allprojects {
group = 'org.springframework.cloud.fn'
@@ -31,13 +44,6 @@ allprojects {
// maven { url 'https://repo.spring.io/libs-staging-local' }
}
ext.javadocLinks = [
'https://docs.oracle.com/en/java/javase/17/docs/api/',
'https://jakarta.ee/specifications/platform/10/apidocs/',
'https://docs.spring.io/spring-framework/docs/current/javadoc-api',
'https://docs.spring.io/spring-integration/docs/current/api/'
] as String[]
apply plugin: 'io.spring.dependency-management'
dependencyManagement {
@@ -55,13 +61,9 @@ allprojects {
mavenBom "org.springframework.boot:spring-boot-dependencies:$springBootVersion"
mavenBom "org.springframework.cloud:spring-cloud-dependencies:$springCloudVersion"
}
}
}
configure(javaProjects) { subproject ->
apply plugin: 'java-library'
apply plugin: 'eclipse'
@@ -110,6 +112,12 @@ configure(javaProjects) { subproject ->
}
}
checkstyle {
toolVersion = '10.3'
configDirectory = rootProject.file('etc/checkstyle')
ignoreFailures = true
}
// dependencies that are common across all java projects
dependencies {
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
@@ -135,17 +143,7 @@ configure(javaProjects) { subproject ->
testRuntimeOnly 'org.apache.logging.log4j:log4j-core'
testRuntimeOnly 'org.apache.logging.log4j:log4j-jcl'
}
[compileJava, compileTestJava]*.options*.compilerArgs = ['-Xlint:all,-options,-processing', '-parameters']
checkstyle {
toolVersion = '10.3'
configDirectory = rootProject.file('etc/checkstyle')
ignoreFailures = true
}
dependencies {
// NOTE: We explicitly specify checkstyle dep before javaformat checkstyle due to antlr class mismatch
checkstyle("com.puppycrawl.tools:checkstyle:${checkstyle.toolVersion}")
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}")
@@ -155,6 +153,8 @@ configure(javaProjects) { subproject ->
exclude 'org/springframework/cloud/fn/object/detection/protos'
}
[compileJava, compileTestJava]*.options*.compilerArgs = ['-Xlint:all,-options,-processing', '-parameters']
test {
maxHeapSize = '2g'
jvmArgs '-XX:+HeapDumpOnOutOfMemoryError'
@@ -165,6 +165,37 @@ configure(javaProjects) { subproject ->
logging.captureStandardOutput(LogLevel.INFO)
}
tasks.register('updateCopyrights') {
onlyIf { !isCI }
inputs.files(modifiedFiles.filter { f -> f.path.contains(subproject.name) })
outputs.dir('build/classes')
doLast {
def now = Calendar.instance.get(Calendar.YEAR) as String
inputs.files.each { file ->
def line
file.withReader { reader ->
while (line = reader.readLine()) {
def matcher = line =~ /Copyright (20\d\d)-?(20\d\d)?/
if (matcher.count) {
def beginningYear = matcher[0][1]
if (now != beginningYear && now != matcher[0][2]) {
def years = "$beginningYear-$now"
def sourceCode = file.text
sourceCode = sourceCode.replaceFirst(/20\d\d(-20\d\d)?/, years)
file.text = sourceCode
println "Copyright updated for file: $file"
}
break
}
}
}
}
}
}
compileJava.dependsOn updateCopyrights
jar {
manifest {
attributes(

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-2024 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.
@@ -18,14 +18,12 @@ package org.springframework.cloud.fn.common.config;
import java.beans.Introspector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.convert.converter.Converter;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
@@ -33,20 +31,24 @@ import org.springframework.expression.ParseException;
import org.springframework.expression.spel.standard.SpelExpression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.integration.config.IntegrationConverter;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.expression.SpelPropertyAccessorRegistrar;
import org.springframework.integration.json.JsonPropertyAccessor;
/**
* The auto-configuration to register a {@link SpelConverter} for configuration
* properties.
*
* @author David Turanski
* @author Christian Tzolov
* @author Chris Bono
* @author Artem Bilan
*/
@AutoConfiguration
@AutoConfigureAfter(name = "org.springframework.cloud.stream.config.SpelExpressionConverterConfiguration")
@ConditionalOnMissingClass("org.springframework.cloud.stream.config.SpelExpressionConverterConfiguration")
public class SpelExpressionConverterConfiguration {
/**
* Specific Application Context name to be used as Bean qualifier when the
* {@link EvaluationContext} is injected.
*/
public static final String INTEGRATION_EVALUATION_CONTEXT = "integrationEvaluationContext";
@Bean
public static SpelPropertyAccessorRegistrar spelPropertyAccessorRegistrar() {
return (new SpelPropertyAccessorRegistrar())
@@ -56,27 +58,27 @@ public class SpelExpressionConverterConfiguration {
@Bean
@ConfigurationPropertiesBinding
@IntegrationConverter
public Converter<String, Expression> spelConverter() {
return new SpelExpressionConverterConfiguration.SpelConverter();
public Converter<String, Expression> spelConverter(
@Qualifier(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME) EvaluationContext evaluationContext) {
return new SpelExpressionConverterConfiguration.SpelConverter(evaluationContext);
}
public static class SpelConverter implements Converter<String, Expression> {
private SpelExpressionParser parser = new SpelExpressionParser();
private static final SpelExpressionParser SPEL_EXPRESSION_PARSER = new SpelExpressionParser();
@Autowired
@Qualifier(INTEGRATION_EVALUATION_CONTEXT)
@Lazy
private EvaluationContext evaluationContext;
private final EvaluationContext evaluationContext;
public SpelConverter() {
public SpelConverter(EvaluationContext evaluationContext) {
this.evaluationContext = evaluationContext;
}
public Expression convert(String source) {
try {
Expression expression = this.parser.parseExpression(source);
if (expression instanceof SpelExpression) {
((SpelExpression) expression).setEvaluationContext(this.evaluationContext);
Expression expression = SPEL_EXPRESSION_PARSER.parseExpression(source);
if (expression instanceof SpelExpression spelExpression) {
spelExpression.setEvaluationContext(this.evaluationContext);
}
return expression;

View File

@@ -0,0 +1,4 @@
/**
* The common classes for all functions.
*/
package org.springframework.cloud.fn.common.config;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2023 the original author or authors.
* Copyright 2020-2024 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.
@@ -49,6 +49,8 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
/**
* The auto-configuration for aggregator function.
*
* @author Artem Bilan
* @author Corneil du Plessis
*/
@@ -65,7 +67,7 @@ public class AggregatorFunctionConfiguration {
@Bean
public Function<Flux<Message<?>>, Flux<Message<?>>> aggregatorFunction(FluxMessageChannel inputChannel,
FluxMessageChannel outputChannel) {
return input -> Flux.from(outputChannel)
return (input) -> Flux.from(outputChannel)
.doOnRequest((request) -> inputChannel.subscribeTo(input.map((
inputMessage) -> MessageBuilder.fromMessage(inputMessage).removeHeader("kafka_consumer").build())));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-2024 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.
@@ -57,7 +57,7 @@ class MessageStoreConfiguration {
static class Mongo {
@Bean
public MessageGroupStore messageStore(MongoTemplate mongoTemplate, AggregatorFunctionProperties properties) {
MessageGroupStore messageStore(MongoTemplate mongoTemplate, AggregatorFunctionProperties properties) {
if (StringUtils.hasText(properties.getMessageStoreEntity())) {
return new ConfigurableMongoDbMessageStore(mongoTemplate, properties.getMessageStoreEntity());
}
@@ -68,7 +68,7 @@ class MessageStoreConfiguration {
@Bean
@Primary
public MongoCustomConversions mongoDbCustomConversions() {
MongoCustomConversions mongoDbCustomConversions() {
return new MongoCustomConversions(
Arrays.asList(new MessageToBinaryConverter(), new BinaryToMessageConverter()));
}
@@ -82,7 +82,7 @@ class MessageStoreConfiguration {
static class Redis {
@Bean
public MessageGroupStore messageStore(RedisTemplate<?, ?> redisTemplate) {
MessageGroupStore messageStore(RedisTemplate<?, ?> redisTemplate) {
return new RedisMessageStore(redisTemplate.getConnectionFactory());
}
@@ -95,7 +95,7 @@ class MessageStoreConfiguration {
static class Jdbc {
@Bean
public MessageGroupStore messageStore(JdbcTemplate jdbcTemplate, AggregatorFunctionProperties properties) {
MessageGroupStore messageStore(JdbcTemplate jdbcTemplate, AggregatorFunctionProperties properties) {
JdbcMessageStore messageStore = new JdbcMessageStore(jdbcTemplate);
if (StringUtils.hasText(properties.getMessageStoreEntity())) {
messageStore.setTablePrefix(properties.getMessageStoreEntity());

View File

@@ -0,0 +1,4 @@
/**
* The aggregator function support classes.
*/
package org.springframework.cloud.fn.aggregator;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2022 the original author or authors.
* Copyright 2020-2024 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.
@@ -20,8 +20,6 @@ import java.time.Duration;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
@@ -41,8 +39,6 @@ import static org.assertj.core.api.Assertions.assertThat;
@TestPropertySource(properties = "aggregator.message-store-type=simple")
public class DefaultAggregatorTests extends AbstractAggregatorFunctionTests {
private static final Logger logger = LoggerFactory.getLogger(DefaultAggregatorTests.class);
@Test
public void test() {
Flux<Message<?>> input = Flux.just(
@@ -58,13 +54,17 @@ public class DefaultAggregatorTests extends AbstractAggregatorFunctionTests {
.build());
Flux<Message<?>> output = this.aggregatorFunction.apply(input.log("DefaultAggregatorTests:input"));
output.log("DefaultAggregatorTests:output").as(StepVerifier::create).assertNext((message) -> {
assertThat(message).extracting(Message::getPayload).asList().hasSize(2).contains("1", "2");
}).thenCancel().verify(Duration.ofSeconds(30));
output.log("DefaultAggregatorTests:output")
.as(StepVerifier::create)
.assertNext((message) -> assertThat(message).extracting(Message::getPayload)
.asList()
.hasSize(2)
.contains("1", "2"))
.thenCancel()
.verify(Duration.ofSeconds(30));
assertThat(this.messageGroupStore).isNull();
assertThat(this.aggregatingMessageHandler.getMessageStore()).isInstanceOf(SimpleMessageStore.class);
}
}