Adds checkstyles to project

This commit configures in the Puppycrawl checkstyle with the Spring JavaFormat.

To avoid the intrusive nature of such a change, the spring-grpc-core module is
the only one to have the checkstyles applied. I will handle the other modules as
time permits.

Signed-off-by: Chris Bono <chris.bono@gmail.com>
This commit is contained in:
Chris Bono
2024-11-06 23:13:27 -06:00
committed by Dave Syer
parent 33483bb500
commit daf8e046c3
31 changed files with 574 additions and 63 deletions

View File

@@ -10,6 +10,13 @@ Before submitting a PR, please run the following commands to ensure proper forma
The `-Pjavadoc` is a profile that enables Javadoc processing so as to avoid a long build time when developing.
<dl><dt><strong>📌 NOTE</strong></dt><dd>
We use the [Spring JavaFormat](https://github.com/spring-io/spring-javaformat) project to apply code formatting conventions as well as checkstyle rules for many of our code conventions.
The code can also be formatted from your IDE when the formatter plugin [has been installed](https://github.com/spring-projects-experimental/spring-grpc/wiki/Working-with-the-Code#install-the-spring-formatter-plugin).
</dd></dl>
## Contributing a New GRPC Features
To contribute a new feature, adhere to the following steps:

127
idea/codeStyleConfig.xml Normal file
View File

@@ -0,0 +1,127 @@
<code_scheme name="Spring gRPC" version="173">
<option name="AUTODETECT_INDENTS" value="false"/>
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="USE_TAB_CHARACTER" value="true"/>
</value>
</option>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
<option name="RIGHT_MARGIN" value="90"/>
<option name="ENABLE_JAVADOC_FORMATTING" value="false"/>
<option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
<option name="JD_KEEP_EMPTY_LINES" value="false"/>
<GroovyCodeStyleSettings>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true"
static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
</GroovyCodeStyleSettings>
<JavaCodeStyleSettings>
<option name="CLASS_NAMES_IN_JAVADOC" value="3"/>
<option name="INSERT_INNER_CLASS_IMPORTS" value="true"/>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value/>
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="" withSubpackages="true" static="true"/>
<emptyLine/>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true" static="false"/>
</value>
</option>
<option name="ENABLE_JAVADOC_FORMATTING" value="false"/>
<option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
<option name="JD_KEEP_INVALID_TAGS" value="false"/>
<option name="JD_KEEP_EMPTY_LINES" value="false"/>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" withSubpackages="false" static="false"/>
<package name="kotlinx.android.synthetic" withSubpackages="false"
static="false"/>
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="20"/>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="20"/>
</JetCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true"/>
</XML>
<editorconfig>
<option name="ENABLED" value="false"/>
</editorconfig>
<codeStyleSettings language="Groovy">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
<option name="BLANK_LINES_AROUND_FIELD" value="1"/>
<option name="BLANK_LINES_AROUND_FIELD_IN_INTERFACE" value="1"/>
<option name="ELSE_ON_NEW_LINE" value="true"/>
<option name="CATCH_ON_NEW_LINE" value="true"/>
<option name="FINALLY_ON_NEW_LINE" value="true"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true"/>
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true"/>
<option name="KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE" value="true"/>
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JSON">
<indentOptions>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
</code_scheme>

70
pom.xml
View File

@@ -78,7 +78,7 @@
<spring-boot.version>3.3.4</spring-boot.version>
<jackson.version>2.17.2</jackson.version>
<junit.version>5.10.5</junit.version>
<assertj.version>3.26.3</assertj.version>
<!-- documentation dependencies -->
<io.spring.maven.antora-version>0.0.4</io.spring.maven.antora-version>
<asciidoctorj-pdf.version>1.6.2</asciidoctorj-pdf.version> <!-- FIXME build failure with
@@ -103,8 +103,17 @@
<maven-site-plugin.version>4.0.0-M13</maven-site-plugin.version>
<maven-project-info-reports-plugin.version>3.4.5</maven-project-info-reports-plugin.version>
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
<spring-javaformat-maven-plugin.version>0.0.39</spring-javaformat-maven-plugin.version>
<!-- BEGIN format + checkstyle properties -->
<spring-javaformat-maven-plugin.version>0.0.43</spring-javaformat-maven-plugin.version>
<maven-checkstyle-plugin.version>3.6.0</maven-checkstyle-plugin.version>
<puppycrawl-tools-checkstyle.version>9.3</puppycrawl-tools-checkstyle.version>
<spring-javaformat-checkstyle.version>0.0.43</spring-javaformat-checkstyle.version>
<disable.format.checks>false</disable.format.checks>
<disable.checkstyle.checks>false</disable.checkstyle.checks>
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
<maven-checkstyle-plugin.failOnViolation>true</maven-checkstyle-plugin.failOnViolation>
<maven-checkstyle-plugin.includeTestSourceDirectory>true</maven-checkstyle-plugin.includeTestSourceDirectory>
<!-- END format + checkstyle properties -->
</properties>
<build>
@@ -117,12 +126,53 @@
<execution>
<phase>validate</phase>
<inherited>true</inherited>
<configuration>
<skip>${disable.format.checks}</skip>
</configuration>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${maven-checkstyle-plugin.version}</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>${puppycrawl-tools-checkstyle.version}</version>
</dependency>
<dependency>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-checkstyle</artifactId>
<version>${spring-javaformat-checkstyle.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>checkstyle-validation</id>
<phase>validate</phase>
<inherited>true</inherited>
<configuration>
<configLocation>src/checkstyle/checkstyle.xml</configLocation>
<propertyExpansion>
config_loc=src/checkstyle
</propertyExpansion>
<skip>${disable.checkstyle.checks}</skip>
<includeTestSourceDirectory>${maven-checkstyle-plugin.includeTestSourceDirectory}</includeTestSourceDirectory>
<failsOnError>${maven-checkstyle-plugin.failsOnError}</failsOnError>
<failOnViolation>${maven-checkstyle-plugin.failOnViolation}</failOnViolation>
<consoleOutput>true</consoleOutput>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
@@ -438,6 +488,20 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-bom</artifactId>
<version>${assertj.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.grpc</groupId>
@@ -16,8 +16,10 @@
<scm>
<url>https://github.com/spring-projects-experimental/spring-grpc</url>
<connection>git://github.com/spring-projects-experimental/spring-grpc.git</connection>
<developerConnection>git@github.com:spring-projects-experimental/spring-grpc.git</developerConnection>
<connection>git://github.com/spring-projects-experimental/spring-grpc.git
</connection>
<developerConnection>git@github.com:spring-projects-experimental/spring-grpc.git
</developerConnection>
</scm>
<dependencies>
@@ -70,7 +72,11 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>

View File

@@ -12,7 +12,8 @@
* 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.grpc.client;
import io.grpc.ChannelCredentials;
@@ -20,10 +21,13 @@ import io.grpc.InsecureChannelCredentials;
/**
* A provider for obtaining channel credentials for gRPC client.
*
* @author David Syer
*/
public interface ChannelCredentialsProvider {
static final ChannelCredentialsProvider INSECURE = path -> InsecureChannelCredentials.create();
/** Insecure credentials provider instance. */
ChannelCredentialsProvider INSECURE = path -> InsecureChannelCredentials.create();
ChannelCredentials getChannelCredentials(String path);

View File

@@ -12,7 +12,8 @@
* 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.grpc.client;
import java.util.ArrayList;
@@ -58,10 +59,10 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable
@Override
public ManagedChannelBuilder<?> createChannel(String authority) {
ManagedChannelBuilder<?> target = builders.computeIfAbsent(authority, path -> {
ManagedChannelBuilder<?> builder = newChannel(targets.getTarget(path),
credentials.getChannelCredentials(path));
for (GrpcChannelConfigurer configurer : configurers) {
ManagedChannelBuilder<?> target = this.builders.computeIfAbsent(authority, path -> {
ManagedChannelBuilder<?> builder = newChannel(this.targets.getTarget(path),
this.credentials.getChannelCredentials(path));
for (GrpcChannelConfigurer configurer : this.configurers) {
configurer.configure(path, builder);
}
return builder;
@@ -75,8 +76,8 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable
}
@Override
public void destroy() throws Exception {
for (ManagedChannel channel : channels.values()) {
public void destroy() {
for (ManagedChannel channel : this.channels.values()) {
channel.shutdown();
}
}
@@ -87,19 +88,20 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable
private final String authority;
public DisposableChannelBuilder(String authority, ManagedChannelBuilder<?> delegate) {
DisposableChannelBuilder(String authority, ManagedChannelBuilder<?> delegate) {
this.authority = authority;
this.delegate = delegate;
}
@Override
protected ManagedChannelBuilder<?> delegate() {
return delegate;
return this.delegate;
}
@Override
public ManagedChannel build() {
ManagedChannel channel = channels.computeIfAbsent(authority, name -> super.build());
ManagedChannel channel = DefaultGrpcChannelFactory.this.channels.computeIfAbsent(this.authority,
name -> super.build());
return channel;
}

View File

@@ -12,7 +12,8 @@
* 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.grpc.client;
import io.grpc.ManagedChannelBuilder;
@@ -20,6 +21,6 @@ import io.grpc.ManagedChannelBuilder;
@FunctionalInterface
public interface GrpcChannelConfigurer {
public void configure(String authority, ManagedChannelBuilder<?> builder);
void configure(String authority, ManagedChannelBuilder<?> builder);
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.grpc.client;
import io.grpc.ManagedChannelBuilder;

View File

@@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.grpc.client;
/**
* Identifies the negotiation used for starting up HTTP/2.
*
* @author David Syer
* @see io.grpc.netty.NegotiationType NegotiationType
*/
public enum NegotiationType {
@@ -39,4 +41,4 @@ public enum NegotiationType {
*/
PLAINTEXT;
}
}

View File

@@ -13,14 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.grpc.client;
import java.util.regex.Pattern;
public interface VirtualTargets {
static Pattern AUTHORITY_PATTERN = Pattern.compile("([^:]+)(?::(\\d+))?");
/** Regex to match the default authority pattern. */
Pattern AUTHORITY_PATTERN = Pattern.compile("([^:]+)(?::(\\d+))?");
/** Default VirtualTargets instance. */
VirtualTargets DEFAULT = path -> {
if (AUTHORITY_PATTERN.matcher(path).matches()) {
return "static://" + path;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2024-2024 the original author or authors.
* Copyright 2023-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.
@@ -13,12 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.grpc.internal;
public class GrpcUtils {
/**
* Provides convenience methods for various gRPC functions.
*
* @author David Syer
*/
public final class GrpcUtils {
private GrpcUtils() {
}
/** Default port to use. */
public static int DEFAULT_PORT = 9090;
/**
* Gets port given an address.
* @param address the address to extract port from
* @return the port
*/
public static int getPort(String address) {
String value = address;
if (value.contains(":")) {

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.grpc.internal;
import java.net.Socket;
@@ -36,9 +37,12 @@ import javax.net.ssl.X509TrustManager;
* trust manager. This trust manager does not perform any certificate validation and
* accepts all certificates. It is intended for testing or development purposes only and
* should not be used in production environments.
*
* @author David Syer
*/
public class InsecureTrustManagerFactory extends TrustManagerFactory {
/** Single instance of the factory. */
public static final TrustManagerFactory INSTANCE = new InsecureTrustManagerFactory();
private static final Provider provider = new Provider("", "0.0", "") {

View File

@@ -13,4 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.grpc;
package org.springframework.grpc;

View File

@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -26,10 +26,10 @@ import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.grpc.internal.GrpcUtils;
import com.google.common.collect.Lists;
import io.grpc.Grpc;
import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
@@ -46,9 +46,9 @@ import io.grpc.TlsServerCredentials.ClientAuth;
* <p>
* The server builder implementation is discovered via Java's SPI mechanism.
*
* @param <T> the type of server builder
* @author David Syer
* @author Chris Bono
* @param <T> the type of server builder
* @see ServerProvider#provider()
*/
public class DefaultGrpcServerFactory<T extends ServerBuilder<T>> implements GrpcServerFactory {
@@ -116,6 +116,7 @@ public class DefaultGrpcServerFactory<T extends ServerBuilder<T>> implements Grp
}
/**
* Get server credentials.
* @return some server credentials (default is insecure)
*/
protected ServerCredentials credentials() {
@@ -159,7 +160,7 @@ public class DefaultGrpcServerFactory<T extends ServerBuilder<T>> implements Grp
if (!serviceNames.add(serviceName)) {
throw new IllegalStateException("Found duplicate service implementation: " + serviceName);
}
logger.info("Registered gRPC service: " + serviceName);
this.logger.info("Registered gRPC service: " + serviceName);
builder.addService(service);
});
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2024-2024 the original author or authors.
* Copyright 2023-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -18,11 +18,11 @@
package org.springframework.grpc.server;
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
import io.grpc.Server;
import io.grpc.ServerServiceDefinition;
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
/**
* Factory interface that can be used to create a {@link Server gRPC Server}.
*

View File

@@ -1,11 +1,11 @@
/*
* Copyright (c) 2024-2024 The gRPC-Spring Authors
* Copyright 2023-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.grpc.server;
import io.grpc.ServerBuilder;
@@ -20,8 +21,8 @@ import io.grpc.ServerBuilder;
/**
* Callback interface that can be used to customize a {@link ServerBuilder}.
*
* @author Chris Bono
* @param <T> the type of server builder
* @author Chris Bono
*/
@FunctionalInterface
public interface ServerBuilderCustomizer<T extends ServerBuilder<T>> {

View File

@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,

View File

@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -19,14 +19,15 @@
package org.springframework.grpc.server.lifecycle;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.SmartLifecycle;
import org.springframework.grpc.server.GrpcServerFactory;
@@ -43,7 +44,7 @@ public class GrpcServerLifecycle implements SmartLifecycle {
private static final Log logger = LogFactory.getLog(GrpcServerLifecycle.class);
private static AtomicInteger serverCounter = new AtomicInteger(-1);
private static final AtomicInteger serverCounter = new AtomicInteger(-1);
private final GrpcServerFactory factory;
@@ -54,7 +55,7 @@ public class GrpcServerLifecycle implements SmartLifecycle {
private Server server;
/**
* Creates a new GrpcServerLifecycle
* Creates a new GrpcServerLifecycle.
* @param factory The server factory to use.
* @param shutdownGracePeriod The time to wait for the server to gracefully shut down.
* @param eventPublisher The event publisher to use.
@@ -150,7 +151,7 @@ public class GrpcServerLifecycle implements SmartLifecycle {
// the spring context
try {
if (millis > 0) {
localServer.awaitTermination(millis, MILLISECONDS);
localServer.awaitTermination(millis, TimeUnit.MILLISECONDS);
}
else if (millis == 0) {
// Do not wait

View File

@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -28,6 +28,8 @@ import io.grpc.Server;
/**
* The base event for {@link GrpcServerLifecycle}.
*
* @author Michael (yidongnan@gmail.com)
*/
public abstract class GrpcServerLifecycleEvent extends ApplicationEvent {

View File

@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -26,9 +26,9 @@ import io.grpc.Server;
* This event will be fired before the server starts to shutdown. The server will no
* longer process new requests.
*
* @author Daniel Theuke (daniel.theuke@heuboe.de)
* @see Server#shutdown()
* @see Server#isShutdown()
* @author Daniel Theuke (daniel.theuke@heuboe.de)
*/
public class GrpcServerShutdownEvent extends GrpcServerLifecycleEvent {

View File

@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -27,8 +27,8 @@ import io.grpc.Server;
/**
* This event will be fired after the server has been started.
*
* @see Server#start()
* @author Daniel Theuke (daniel.theuke@heuboe.de)
* @see Server#start()
*/
public class GrpcServerStartedEvent extends GrpcServerLifecycleEvent {

View File

@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -15,6 +15,7 @@
*
* Partial copy from net.devh:grpc-spring-boot-starter.
*/
package org.springframework.grpc.server.lifecycle;
import java.time.Clock;
@@ -25,8 +26,8 @@ import io.grpc.Server;
* This event will be fired after the server completed to shutdown. The server will no
* longer process requests.
*
* @see Server#isTerminated()
* @author Daniel Theuke (daniel.theuke@heuboe.de)
* @see Server#isTerminated()
*/
public class GrpcServerTerminatedEvent extends GrpcServerLifecycleEvent {

View File

@@ -1,6 +1,21 @@
/*
* Copyright 2023-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.
* 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.grpc.internal;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
@@ -8,36 +23,36 @@ class GrpcUtilsTests {
@Test
void testGetPortFromAddress() {
assertEquals(8080, GrpcUtils.getPort("localhost:8080"));
assertThat(GrpcUtils.getPort("localhost:8080")).isEqualTo(8080);
}
@Test
void testGetNoPort() {
assertEquals(9090, GrpcUtils.getPort("localhost"));
assertThat(GrpcUtils.getPort("localhost")).isEqualTo(9090);
}
@Test
void testGetPortFromAddressWithPath() {
String address = "example.com:1234/path";
assertEquals(1234, GrpcUtils.getPort(address));
assertThat(GrpcUtils.getPort(address)).isEqualTo(1234);
}
@Test
void testGetDomainAddress() {
String address = "unix:/some/file/somewhere";
assertEquals(-1, GrpcUtils.getPort(address));
assertThat(GrpcUtils.getPort(address)).isEqualTo(-1);
}
@Test
void testGetStaticSchema() {
String address = "static://localhost";
assertEquals(9090, GrpcUtils.getPort(address));
assertThat(GrpcUtils.getPort(address)).isEqualTo(9090);
}
@Test
void testGetInvalidAddress() {
String address = "invalid:broken";
assertEquals(9090, GrpcUtils.getPort(address)); // -1?
assertThat(GrpcUtils.getPort(address)).isEqualTo(9090); // -1?
}
}
}

View File

@@ -19,6 +19,7 @@
<configprops.path>${project.basedir}/src/main/antora/modules/ROOT/partials/_configprops.adoc</configprops.path>
<configprops.inclusionPattern>spring.grpc.*</configprops.inclusionPattern>
<jruby.version>9.4.6.0</jruby.version>
<disable.checkstyle.checks>true</disable.checkstyle.checks>
</properties>
<!-- Dependencies used to build the config props doc generator -->
<dependencies>
@@ -215,4 +216,4 @@
</repository>
</repositories>
</project>
</project>

View File

@@ -11,6 +11,13 @@ Before submitting a PR, please run the following commands to ensure proper forma
The `-Pjavadoc` is a profile that enables Javadoc processing so as to avoid a long build time when developing.
[NOTE]
====
We use the https://github.com/spring-io/spring-javaformat[Spring JavaFormat] project to apply code formatting conventions as well as checkstyle rules for many of our code conventions.
The code can also be formatted from your IDE when the formatter plugin https://github.com/spring-projects-experimental/spring-grpc/wiki/Working-with-the-Code#install-the-spring-formatter-plugin[has been installed].
====
== Contributing a New GRPC Features
To contribute a new feature, adhere to the following steps:
@@ -103,4 +110,3 @@ You may also be asked to rework the submission.
If asked to make corrections, simply push the changes against the same branch, and your pull request will be updated.
In other words, you do not need to create a new pull request when asked to make changes.

View File

@@ -20,6 +20,10 @@
<developerConnection>git@github.com:spring-projects-experimental/spring-grpc.git</developerConnection>
</scm>
<properties>
<disable.checkstyle.checks>true</disable.checkstyle.checks>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
@@ -101,4 +105,4 @@
</dependencies>
</project>
</project>

View File

@@ -0,0 +1,14 @@
^\Q/*\E$
^\Q * Copyright \E20\d\d(\-20\d\d)?\Q the original author or authors.\E$
^\Q *\E$
^\Q * Licensed under the Apache License, Version 2.0 (the "License");\E$
^\Q * you may not use this file except in compliance with the License.\E$
^\Q * You may obtain a copy of the License at\E$
^\Q *\E$
^\Q * https://www.apache.org/licenses/LICENSE-2.0\E$
^\Q *\E$
^\Q * Unless required by applicable law or agreed to in writing, software\E$
^\Q * distributed under the License is distributed on an "AS IS" BASIS,\E$
^\Q * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\E$
^\Q * See the License for the specific language governing permissions and\E$
^\Q * limitations under the License.\E$

View File

@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<suppress files="package-info\.java" checks=".*" />
<suppress files="[\\/]test[\\/]" checks="RequireThis|AvoidStaticImport|Javadoc*" />
<suppress files="Proto" checks=".*"/>
<suppress files=".*Tests" checks="HideUtilityClassConstructor" />
<suppress files=".*Tests" checks="RegexpSinglelineJava" id="toLowerCaseWithoutLocale"/>
<suppress files=".*Tests" checks="RegexpSinglelineJava" id="toUpperCaseWithoutLocale"/>
<suppress files="[\\/]spring-grpc-docs[\\/]" checks="JavadocPackage|JavadocType|JavadocVariable|SpringDeprecatedCheck" />
<suppress files="[\\/]spring-grpc-docs[\\/]" checks="SpringJavadoc" message="\@since" />
<suppress files="[\\/]spring-grpc-docs[\\/].*jooq" checks="AvoidStaticImport" />
</suppressions>

View File

@@ -0,0 +1,213 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="SuppressionFilter">
<property name="file" value="${config_loc}/checkstyle-suppressions.xml"/>
</module>
<!-- Root Checks -->
<module name="RegexpHeader">
<property name="headerFile" value="${config_loc}/checkstyle-header.txt"/>
<property name="fileExtensions" value="java"/>
</module>
<module name="NewlineAtEndOfFile"/>
<!-- TreeWalker Checks -->
<module name="TreeWalker">
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE:OFF"/>
<property name="onCommentFormat" value="CHECKSTYLE:ON"/>
</module>
<!-- Annotations -->
<module name="AnnotationUseStyle">
<property name="elementStyle" value="compact"/>
</module>
<module name="MissingOverride"/>
<module name="PackageAnnotation"/>
<module name="AnnotationLocation">
<property name="allowSamelineSingleParameterlessAnnotation"
value="false"/>
</module>
<!-- Block Checks -->
<module name="EmptyBlock">
<property name="option" value="text"/>
</module>
<module name="LeftCurly"/>
<module name="RightCurly">
<property name="option" value="alone"/>
</module>
<module name="NeedBraces"/>
<module name="AvoidNestedBlocks"/>
<!-- Class Design -->
<module name="FinalClass"/>
<module name="InterfaceIsType"/>
<module name="HideUtilityClassConstructor"/>
<module name="MutableException"/>
<module name="InnerTypeLast"/>
<module name="OneTopLevelClass"/>
<!-- Coding -->
<module name="CovariantEquals"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="InnerAssignment"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StringLiteralEquality"/>
<module name="NestedForDepth">
<property name="max" value="3"/>
</module>
<module name="NestedIfDepth">
<property name="max" value="4"/>
</module>
<module name="NestedTryDepth">
<property name="max" value="3"/>
</module>
<module name="MultipleVariableDeclarations"/>
<module name="RequireThis">
<property name="validateOnlyOverlapping" value="false"/>
<property name="checkMethods" value="false"/>
</module>
<module name="OneStatementPerLine"/>
<!-- Imports -->
<module name="AvoidStarImport"/>
<module name="AvoidStaticImport">
<property name="excludes"
value="org.assertj.core.api.Assertions.*,
java.util.Objects.requireNonNull,
org.assertj.core.api.InstanceOfAssertFactories.type,
org.awaitility.Awaitility.*,
org.junit.jupiter.api.Assertions.*,
org.junit.jupiter.params.provider.Arguments.*,
org.junit.Assert.*,
org.junit.Assume.*,
org.junit.internal.matchers.ThrowableMessageMatcher.*,
org.hamcrest.CoreMatchers.*,
org.hamcrest.MatcherAssert.*,
org.hamcrest.Matchers.*,
org.mockito.Mockito.*,
org.mockito.BDDMockito.*,
org.mockito.ArgumentMatchers.*,
org.springframework.kafka.test.hamcrest.KafkaMatchers.*,
org.springframework.kafka.test.assertj.KafkaConditions.*"/>
</module>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="true"/>
</module>
<module name="ImportOrder">
<property name="groups" value="java,/^javax?\./,org,org.springframework,*"/>
<property name="ordered" value="true"/>
<property name="separated" value="true"/>
<property name="option" value="top"/>
<property name="sortStaticImportsAlphabetically" value="true"/>
</module>
<!-- Javadoc Comments -->
<module name="JavadocType">
<property name="scope" value="package"/>
<property name="authorFormat" value=".+\s.+"/>
</module>
<module name="JavadocMethod">
</module>
<module name="JavadocVariable">
<property name="scope" value="public"/>
</module>
<module name="JavadocStyle">
<property name="checkEmptyJavadoc" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation">
<property name="offset" value="0"/>
</module>
<module name="AtclauseOrder">
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF"/>
<property name="tagOrder" value="@param, @author, @since, @see, @version, @serial, @deprecated"/>
</module>
<module name="AtclauseOrder">
<property name="target" value="METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
<property name="tagOrder" value="@param, @return, @throws, @since, @deprecated, @see"/>
</module>
<!-- Miscellaneous -->
<module name="CommentsIndentation">
<property name="tokens" value="BLOCK_COMMENT_BEGIN"/>
</module>
<module name="UpperEll"/>
<module name="ArrayTypeStyle"/>
<module name="OuterTypeFilename"/>
<!-- Modifiers -->
<module name="RedundantModifier"/>
<!-- Regexp -->
<module name="RegexpSinglelineJava">
<property name="format" value="^\t* +\t*\S"/>
<property name="message"
value="Line has leading space characters; indentation should be performed with tabs only."/>
<property name="ignoreComments" value="true"/>
</module>
<module name="RegexpSinglelineJava">
<property name="maximum" value="0"/>
<property name="format" value="org\.junit\.Assert\.assert"/>
<property name="message"
value="Please use AssertJ imports."/>
<property name="ignoreComments" value="true"/>
</module>
<module name="RegexpSinglelineJava">
<property name="maximum" value="0"/>
<property name="format" value="org\.junit\.jupiter\.api\.Assertions\.assert"/>
<property name="message"
value="Please use AssertJ imports."/>
<property name="ignoreComments" value="true"/>
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
<property name="id" value="toLowerCaseWithoutLocale"/>
<property name="format" value="\.toLowerCase\(\)"/>
<property name="maximum" value="0"/>
<property name="message"
value="String.toLowerCase() should be String.toLowerCase(Locale.ROOT)"/>
<property name="ignoreComments" value="true"/>
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
<property name="id" value="toUpperCaseWithoutLocale"/>
<property name="format" value="\.toUpperCase\(\)"/>
<property name="maximum" value="0"/>
<property name="message"
value="String.toUpperCase() should be String.toUpperCase(Locale.ROOT)"/>
<property name="ignoreComments" value="true"/>
</module>
<module name="Regexp">
<property name="format" value="[ \t]+$"/>
<property name="illegalPattern" value="true"/>
<property name="message" value="Trailing whitespace"/>
</module>
<module name="Regexp">
<property name="format" value="System.(out|err).print"/>
<property name="illegalPattern" value="true"/>
<property name="message" value="System.out or .err"/>
</module>
<!-- Whitespace -->
<module name="GenericWhitespace"/>
<module name="MethodParamPad"/>
<module name="NoWhitespaceAfter">
<property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS, ARRAY_DECLARATOR"/>
</module>
<module name="NoWhitespaceBefore"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround"/>
</module>
</module>