From 593518e7335b5227146ad83f28dba47ff335a14a Mon Sep 17 00:00:00 2001 From: Freeman Liu Date: Sat, 4 May 2024 17:00:00 +0800 Subject: [PATCH] Auto mapping google.api.http (#29) * just hold * Refactor JsonTranscoderRouterFunction * Rename to TranscodingRouterFunction * Keep goging * Add processUnaryCall method * Refactor GrpcUtil * Add some test code * Upgrade SB 3.3.0 * Fixes tests * Fixed spotbugs * Almost done * Error handling * Cancel call * Change the way to copy githooks * feat: keep goging ERP-9588 * Refactor * Keep going * Change class name to HeaderConverter * Change method name * Change base package to grpcstarter * GrpcService alias for Component * see Component#value() * Refactor * Refactor * Add transcoding webmvc/webflux * Use IdentityHashMap * Update application-grpc-starter-test-example.yml * Optimize test extension * Add T2 * rename to transcoding * Almost done * Add comment * server stream supports non Get method * optimize build * use api * fix tests * optimize examples * optimize build * fix githooks script * Update readme --- README.md | 4 +- build.gradle | 43 +- docs/en-us/client/onboarding.md | 2 +- docs/en-us/extension/json-transcoder.md | 4 +- docs/en-us/extension/metrics.md | 2 +- docs/en-us/extension/protobuf-validation.md | 4 +- docs/en-us/extension/test.md | 2 +- docs/en-us/extension/tracing.md | 2 +- docs/en-us/guide/quickstart.md | 8 +- docs/en-us/server/onboarding.md | 4 +- docs/zh-cn/client/onboarding.md | 2 +- docs/zh-cn/extension/json-transcoder.md | 4 +- docs/zh-cn/extension/metrics.md | 2 +- docs/zh-cn/extension/protobuf-validation.md | 4 +- docs/zh-cn/extension/test.md | 2 +- docs/zh-cn/extension/tracing.md | 2 +- docs/zh-cn/guide/quickstart.md | 8 +- docs/zh-cn/server/onboarding.md | 4 +- examples/grpc-sample-api/build.gradle | 8 + .../src/main/proto/sample/pet/v1/pet.proto | 23 - .../freeman/example/GrpcExceptionAdvice.java | 34 -- .../com/freeman/example/PersonController.java | 30 -- .../java/com/freeman/example/WebFluxApp.java | 14 - .../src/main/resources/application.yaml | 9 - .../freeman/example/GrpcExceptionAdvice.java | 34 -- .../com/freeman/example/PersonController.java | 40 -- .../freeman/example/SimpleServiceImpl.java | 24 - .../src/main/resources/application.yaml | 9 - .../example/AspectConfiguration.java | 30 -- .../example/MetricApp.java} | 10 +- .../example}/SimpleServiceImpl.java | 2 +- .../src/main/resources/application.yaml | 2 + .../java/com/freemanan/example/AppTest.java | 3 - .../grpcstarter/example/MetricsAppTest.java | 3 + examples/multi-module/api/build.gradle | 13 + .../multi-module/api/proto/user/user.proto | 20 + .../server}/build.gradle | 2 +- .../java/grpcstarter/example/UserApp.java} | 6 +- .../grpcstarter/example/UserServiceImpl.java | 21 + .../src/main/resources/application.yaml | 0 .../freemanan/example/ProtoValidateApp.java | 17 - .../controller/FooServiceController.java | 19 - .../examples/ProtoValidateApp.java | 24 + .../main/proto/{fm/foo/v1 => foo}/foo.proto | 8 +- .../examples}/ProtoValidateAppTest.java | 10 +- examples/quick-start/buf.yaml | 5 - examples/quick-start/build.gradle | 5 - .../com/freemanan/example/QuickStartApp.java | 32 -- .../example/FooServiceImpl.java} | 12 +- .../grpcstarter/example/QuickStartApp.java} | 9 +- .../example/SimpleServiceImpl.java} | 8 +- .../main/proto/{fm/foo/v1 => foo}/foo.proto | 6 +- .../src/main/resources/application.yaml | 2 +- .../example/QuickStartAppTest.java | 10 +- .../example/RefreshApp.java | 2 +- .../example/RefreshAppTest.java | 4 +- .../example/SimpleServiceImpl.java} | 4 +- .../example/TLSApp.java | 4 +- .../example/TLSAppTest.java | 2 +- examples/tracing/build.gradle | 1 - .../main/java/com/freemanan/example/App.java | 35 -- .../example}/SimpleApi.java | 2 +- .../example}/SimpleServiceImpl.java | 3 +- .../java/grpcstarter/example/TracingApp.java | 44 ++ .../src/main/resources/application.yaml | 5 - .../java/com/freemanan/example/AppTest.java | 3 - .../webflux/build.gradle | 5 +- .../example/TranscodingWebFluxApp.java | 53 ++ .../src/main/proto/simpleservice.proto | 35 ++ .../src/main/resources/application.yaml | 8 + .../example/TranscodingFluxIT.java | 37 ++ .../webmvc/build.gradle | 4 +- .../example/TranscodingMvcApp.java | 50 ++ .../webmvc/src/main/proto/simpleservice.proto | 35 ++ .../src/main/resources/application.yaml | 8 + .../grpcstarter/example/TranscodingMvcIT.java | 37 ++ examples/user/user-api/build.gradle | 13 - .../user/user-api/proto/fm/user/v1/user.proto | 22 - .../example/controller/UserController.java | 49 -- gradle.properties | 16 +- gradle/protobuf.gradle | 2 +- .../grpc => grpcstarter}/client/Cache.java | 6 +- .../grpc => grpcstarter}/client/Checker.java | 6 +- .../client/ConditionOnGrpcClientEnabled.java | 2 +- .../client/EnableGrpcClients.java | 2 +- .../client/GrpcChannelCreator.java | 4 +- .../client/GrpcChannelCustomizer.java | 2 +- .../client/GrpcClientAutoConfiguration.java | 6 +- .../client/GrpcClientCreator.java | 2 +- .../client/GrpcClientOptions.java | 2 +- .../GrpcClientOptionsClientInterceptor.java | 2 +- .../client/GrpcClientProperties.java | 2 +- ...entRefreshScopeRefreshedEventListener.java | 2 +- .../client/GrpcClientsRegistrar.java | 2 +- .../GrpcStubBeanDefinitionRegistry.java | 2 +- .../client/GrpcStubBeanRegistrar.java | 2 +- .../ShutdownEventBasedChannelCloser.java | 4 +- .../grpc => grpcstarter}/client/Util.java | 2 +- .../exception/GrpcClientFailureAnalyzer.java | 2 +- .../MissingChannelConfigurationException.java | 2 +- .../main/resources/META-INF/spring.factories | 2 +- ...ot.autoconfigure.AutoConfiguration.imports | 2 +- .../client/DynamicRefreshTests.java | 16 +- .../GrpcClientAutoConfigurationTest.java | 2 +- .../client/GrpcClientIT.java | 18 +- .../client/InProcessTest.java | 6 +- .../grpc => grpcstarter}/client/UtilTest.java | 4 +- .../src/test/java/issues/Issue23Test.java | 21 +- .../exceptionhandling/package-info.java | 15 - .../server/ConditionOnGrpcServerEnabled.java | 2 +- .../server/DefaultGrpcServer.java | 9 +- .../server/DummyGrpcServer.java | 7 +- .../server/GrpcContextKeys.java | 4 +- .../server/GrpcRequestContext.java | 2 +- .../GrpcRequestContextServerInterceptor.java | 4 +- .../server/GrpcServer.java | 9 +- .../server/GrpcServerAutoConfiguration.java | 12 +- .../server/GrpcServerCustomizer.java | 2 +- .../server/GrpcServerProperties.java | 4 +- .../server/GrpcServerShutdownEvent.java | 2 +- .../server/GrpcServerStartedEvent.java | 2 +- .../server/GrpcServerTerminatedEvent.java | 2 +- .../server/GrpcService.java | 14 +- .../grpc => grpcstarter}/server/Util.java | 2 +- .../server/feature/channelz/Channelz.java | 4 +- .../exceptionhandling/ExceptionHandling.java | 8 +- .../ExceptionHandlingServerInterceptor.java | 2 +- .../GrpcExceptionHandlerListener.java | 2 +- .../GrpcExceptionResolver.java | 2 +- .../GrpcUnhandledExceptionProcessor.java | 2 +- .../AnnotationBasedGrpcExceptionResolver.java | 4 +- .../DefaultGrpcExceptionAdvice.java | 2 +- .../annotation/GrpcAdvice.java | 10 +- .../annotation/GrpcExceptionHandler.java | 2 +- .../GrpcExceptionHandlerMethod.java | 2 +- .../exceptionhandling/package-info.java | 10 + .../server/feature/health/Health.java | 8 +- .../server/feature/health/HealthChecker.java | 2 +- .../health/HealthServerInterceptor.java | 2 +- .../datasource/DataSourceHealthChecker.java | 6 +- .../health/redis/RedisHealthChecker.java | 6 +- .../server/feature/reflection/Reflection.java | 4 +- ...ot.autoconfigure.AutoConfiguration.imports | 2 +- .../server/ChannelzIT.java | 2 +- .../server/GracefulShutdownIT.java | 4 +- .../GrpcResponseMetadataModifierIT.java | 10 +- .../server/GrpcServerIT.java | 2 +- .../grpc => grpcstarter}/server/HealthIT.java | 4 +- .../server/InProcessTest.java | 2 +- .../server/MaxResponseLengthIT.java | 6 +- .../ExceptionHandlingTests.java | 6 +- .../AnnotationBasedExceptionHandlingIT.java | 8 +- .../AbstractHandlerAdaptor.java | 193 -------- .../DefaultGrpcHeaderConverter.java | 89 ---- .../jsontranscoder/FutureAdapter.java | 60 --- .../GrpcJsonTranscoderAutoConfiguration.java | 91 ---- .../GrpcJsonTranscoderProperties.java | 18 - .../jsontranscoder/util/GrpcUtil.java | 60 --- .../util/JsonTranscoderUtil.java | 107 ---- .../jsontranscoder/util/ProtoUtil.java | 75 --- .../jsontranscoder/util/Tuple2.java | 25 - .../jsontranscoder/util/Tuple3.java | 24 - .../web/WebMvcGrpcServiceHandlerMapping.java | 58 --- .../web/WebMvcProtobufHandlerAdaptor.java | 146 ------ .../webflux/ControllerMethodResolver.java | 219 -------- .../webflux/GrpcHandlerResultHandler.java | 78 --- .../WebFluxGrpcServiceHandlerMapping.java | 62 --- .../WebFluxProtobufHandlerAdaptor.java | 182 ------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../jsontranscoder/JsonTranscoderIT.java | 256 ---------- .../grpc/extensions/jsontranscoder/U.java | 31 -- grpc-extensions/grpc-metrics/build.gradle | 5 +- .../metrics/GrpcMetricsAutoConfiguration.java | 10 +- .../metrics/GrpcMetricsProperties.java | 4 +- ...eredMetricCollectingClientInterceptor.java | 2 +- ...eredMetricCollectingServerInterceptor.java | 2 +- ...ot.autoconfigure.AutoConfiguration.imports | 2 +- .../extensions/metrics/MetricsZipkinIT.java | 31 -- .../extensions/metrics/Deps.java | 2 +- .../GrpcMetricsAutoConfigurationTest.java | 6 +- .../starter/grpc/extensions/test/NetUtil.java | 24 - .../test/GrpcTestAutoConfiguration.java | 4 +- .../test/GrpcTestBeanPostProcessor.java | 35 +- .../GrpcTestEnvironmentPostProcessor.java | 41 +- .../extensions/test/GrpcTestProperties.java | 8 +- .../extensions/test/InProcessName.java | 2 +- .../extensions/test/LocalGrpcPort.java | 4 +- .../extensions/test/StubUtil.java | 12 +- .../main/resources/META-INF/spring.factories | 2 +- ...ot.autoconfigure.AutoConfiguration.imports | 2 +- .../application-grpc-starter-test-example.yml | 2 + .../extensions/test/DefinedPortIT.java | 2 +- .../extensions/test/LocalGrpcPortTest.java | 2 +- .../extensions/test/RandomPortIT.java | 2 +- grpc-extensions/grpc-tracing/build.gradle | 6 +- .../tracing/GrpcTracingAutoConfiguration.java | 10 +- .../tracing/GrpcTracingProperties.java | 4 +- ...deredObservationGrpcClientInterceptor.java | 2 +- ...deredObservationGrpcServerInterceptor.java | 2 +- ...ot.autoconfigure.AutoConfiguration.imports | 2 +- .../GrpcTracingAutoConfigurationTest.java | 2 +- .../build.gradle | 9 +- .../transcoding/DefaultHeaderConverter.java | 72 +++ .../GrpcTranscodingAutoConfiguration.java | 70 +++ .../GrpcTranscodingProperties.java | 24 + .../transcoding/HeaderConverter.java} | 8 +- .../extensions/transcoding/JsonUtil.java | 91 ++++ .../ReactiveTranscodingRouterFunction.java | 261 ++++++++++ .../ServletTranscodingRouterFunction.java | 222 +++++++++ .../extensions/transcoding/Transcoder.java | 177 +++++++ .../transcoding/TranscodingGrpcServer.java | 153 ++++++ .../TranscodingRuntimeException.java | 29 ++ .../transcoding/TranscodingUtil.java | 42 ++ .../extensions/transcoding/Util.java | 468 ++++++++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../extensions/transcoding}/Deps.java | 2 +- .../transcoding/JsonTranscoderIT.java | 199 ++++++++ .../extensions/transcoding/TestUtil.java | 25 + .../transcoding/TranscoderTest.java | 170 +++++++ .../extensions/transcoding/UtilTest.java} | 68 ++- .../src/test/proto/transcoder_test.proto | 77 +++ .../GrpcValidationAutoConfiguration.java | 10 +- .../validation/GrpcValidationProperties.java | 2 +- .../OrderedValidatingClientInterceptor.java | 2 +- .../OrderedValidatingServerInterceptor.java | 2 +- .../ProtoValidateClientInterceptor.java | 6 +- .../ProtoValidateServerInterceptor.java | 4 +- .../validation/ValidationExceptionUtil.java | 4 +- ...ot.autoconfigure.AutoConfiguration.imports | 2 +- .../GrpcValidationAutoConfigurationTest.java | 2 +- .../PgvValidationClientDisabledIT.java | 6 +- .../PgvValidationClientServerDisabledIT.java | 6 +- .../validation/PgvValidationIT.java | 6 +- grpc-starter-dependencies/build.gradle | 9 +- .../grpc-starter-metrics/build.gradle | 1 + .../grpc-starter-tracing/build.gradle | 2 + .../build.gradle | 6 + .../build.gradle | 2 +- .../grpc-starter-webflux/build.gradle | 12 - settings.gradle | 30 +- 240 files changed, 2999 insertions(+), 2723 deletions(-) delete mode 100644 examples/grpc-sample-api/src/main/proto/sample/pet/v1/pet.proto delete mode 100644 examples/json-transcoder/webflux/src/main/java/com/freeman/example/GrpcExceptionAdvice.java delete mode 100644 examples/json-transcoder/webflux/src/main/java/com/freeman/example/PersonController.java delete mode 100644 examples/json-transcoder/webflux/src/main/java/com/freeman/example/WebFluxApp.java delete mode 100644 examples/json-transcoder/webflux/src/main/resources/application.yaml delete mode 100644 examples/json-transcoder/webmvc/src/main/java/com/freeman/example/GrpcExceptionAdvice.java delete mode 100644 examples/json-transcoder/webmvc/src/main/java/com/freeman/example/PersonController.java delete mode 100644 examples/json-transcoder/webmvc/src/main/java/com/freeman/example/SimpleServiceImpl.java delete mode 100644 examples/json-transcoder/webmvc/src/main/resources/application.yaml delete mode 100644 examples/metrics/src/main/java/com/freemanan/example/AspectConfiguration.java rename examples/metrics/src/main/java/{com/freemanan/example/App.java => grpcstarter/example/MetricApp.java} (84%) rename examples/metrics/src/main/java/{com/freemanan/example/controller => grpcstarter/example}/SimpleServiceImpl.java (95%) delete mode 100644 examples/metrics/src/test/java/com/freemanan/example/AppTest.java create mode 100644 examples/metrics/src/test/java/grpcstarter/example/MetricsAppTest.java create mode 100644 examples/multi-module/api/build.gradle create mode 100644 examples/multi-module/api/proto/user/user.proto rename examples/{user/user-server => multi-module/server}/build.gradle (69%) rename examples/{json-transcoder/webmvc/src/main/java/com/freeman/example/MvcApp.java => multi-module/server/src/main/java/grpcstarter/example/UserApp.java} (68%) create mode 100644 examples/multi-module/server/src/main/java/grpcstarter/example/UserServiceImpl.java rename examples/{user/user-server => multi-module/server}/src/main/resources/application.yaml (100%) delete mode 100644 examples/proto-validate/src/main/java/com/freemanan/example/ProtoValidateApp.java delete mode 100644 examples/proto-validate/src/main/java/com/freemanan/example/controller/FooServiceController.java create mode 100644 examples/proto-validate/src/main/java/grpcstarter/examples/ProtoValidateApp.java rename examples/proto-validate/src/main/proto/{fm/foo/v1 => foo}/foo.proto (80%) rename examples/proto-validate/src/test/java/{com/freemanan/example => grpcstarter/examples}/ProtoValidateAppTest.java (90%) delete mode 100644 examples/quick-start/buf.yaml delete mode 100644 examples/quick-start/src/main/java/com/freemanan/example/QuickStartApp.java rename examples/quick-start/src/main/java/{com/freemanan/example/controller/FooController.java => grpcstarter/example/FooServiceImpl.java} (59%) rename examples/{user/user-server/src/main/java/com/freemanan/example/App.java => quick-start/src/main/java/grpcstarter/example/QuickStartApp.java} (52%) rename examples/{tls/src/main/java/com/freemanan/example/controller/SimpleServiceController.java => quick-start/src/main/java/grpcstarter/example/SimpleServiceImpl.java} (75%) rename examples/quick-start/src/main/proto/{fm/foo/v1 => foo}/foo.proto (62%) rename examples/quick-start/src/test/java/{com/freemanan => grpcstarter}/example/QuickStartAppTest.java (85%) rename examples/refresh/src/main/java/{com/freemanan => grpcstarter}/example/RefreshApp.java (96%) rename examples/refresh/src/test/java/{com/freemanan => grpcstarter}/example/RefreshAppTest.java (95%) rename examples/{quick-start/src/main/java/com/freemanan/example/controller/SimpleServiceController.java => tls/src/main/java/grpcstarter/example/SimpleServiceImpl.java} (83%) rename examples/tls/src/main/java/{com/freemanan => grpcstarter}/example/TLSApp.java (78%) rename examples/tls/src/test/java/{com/freemanan => grpcstarter}/example/TLSAppTest.java (96%) delete mode 100644 examples/tracing/src/main/java/com/freemanan/example/App.java rename examples/tracing/src/main/java/{com/freemanan/example/api => grpcstarter/example}/SimpleApi.java (90%) rename examples/tracing/src/main/java/{com/freemanan/example/controller => grpcstarter/example}/SimpleServiceImpl.java (94%) create mode 100644 examples/tracing/src/main/java/grpcstarter/example/TracingApp.java delete mode 100644 examples/tracing/src/test/java/com/freemanan/example/AppTest.java rename examples/{json-transcoder => transcoding}/webflux/build.gradle (66%) create mode 100644 examples/transcoding/webflux/src/main/java/grpcstarter/example/TranscodingWebFluxApp.java create mode 100644 examples/transcoding/webflux/src/main/proto/simpleservice.proto create mode 100644 examples/transcoding/webflux/src/main/resources/application.yaml create mode 100644 examples/transcoding/webflux/src/test/java/grpcstarter/example/TranscodingFluxIT.java rename examples/{json-transcoder => transcoding}/webmvc/build.gradle (67%) create mode 100644 examples/transcoding/webmvc/src/main/java/grpcstarter/example/TranscodingMvcApp.java create mode 100644 examples/transcoding/webmvc/src/main/proto/simpleservice.proto create mode 100644 examples/transcoding/webmvc/src/main/resources/application.yaml create mode 100644 examples/transcoding/webmvc/src/test/java/grpcstarter/example/TranscodingMvcIT.java delete mode 100644 examples/user/user-api/build.gradle delete mode 100644 examples/user/user-api/proto/fm/user/v1/user.proto delete mode 100644 examples/user/user-server/src/main/java/com/freemanan/example/controller/UserController.java rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/Cache.java (93%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/Checker.java (94%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/ConditionOnGrpcClientEnabled.java (93%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/EnableGrpcClients.java (97%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcChannelCreator.java (97%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcChannelCustomizer.java (93%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientAutoConfiguration.java (93%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientCreator.java (99%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientOptions.java (94%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientOptionsClientInterceptor.java (97%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientProperties.java (99%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientRefreshScopeRefreshedEventListener.java (98%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientsRegistrar.java (98%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcStubBeanDefinitionRegistry.java (98%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcStubBeanRegistrar.java (99%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/ShutdownEventBasedChannelCloser.java (81%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/Util.java (99%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/exception/GrpcClientFailureAnalyzer.java (96%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/client/exception/MissingChannelConfigurationException.java (88%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/client/DynamicRefreshTests.java (90%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientAutoConfigurationTest.java (97%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/client/GrpcClientIT.java (91%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/client/InProcessTest.java (92%) rename grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/client/UtilTest.java (92%) delete mode 100644 grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/package-info.java rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/ConditionOnGrpcServerEnabled.java (93%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/DefaultGrpcServer.java (98%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/DummyGrpcServer.java (83%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcContextKeys.java (92%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcRequestContext.java (94%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcRequestContextServerInterceptor.java (95%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcServer.java (62%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcServerAutoConfiguration.java (81%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcServerCustomizer.java (87%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcServerProperties.java (98%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcServerShutdownEvent.java (90%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcServerStartedEvent.java (90%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcServerTerminatedEvent.java (91%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcService.java (54%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/Util.java (96%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/channelz/Channelz.java (88%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/ExceptionHandling.java (82%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/ExceptionHandlingServerInterceptor.java (95%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/GrpcExceptionHandlerListener.java (96%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/GrpcExceptionResolver.java (89%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/GrpcUnhandledExceptionProcessor.java (86%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/annotation/AnnotationBasedGrpcExceptionResolver.java (98%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/annotation/DefaultGrpcExceptionAdvice.java (87%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/annotation/GrpcAdvice.java (73%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/annotation/GrpcExceptionHandler.java (95%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/annotation/GrpcExceptionHandlerMethod.java (98%) create mode 100644 grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/package-info.java rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/health/Health.java (89%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/health/HealthChecker.java (83%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/health/HealthServerInterceptor.java (98%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/health/datasource/DataSourceHealthChecker.java (91%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/health/redis/RedisHealthChecker.java (91%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/reflection/Reflection.java (88%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/ChannelzIT.java (97%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/GracefulShutdownIT.java (95%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcResponseMetadataModifierIT.java (91%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/GrpcServerIT.java (98%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/HealthIT.java (97%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/InProcessTest.java (98%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/MaxResponseLengthIT.java (94%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/ExceptionHandlingTests.java (85%) rename grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/server/feature/exceptionhandling/annotation/AnnotationBasedExceptionHandlingIT.java (95%) delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/AbstractHandlerAdaptor.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/DefaultGrpcHeaderConverter.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/FutureAdapter.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcJsonTranscoderAutoConfiguration.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcJsonTranscoderProperties.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/GrpcUtil.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/JsonTranscoderUtil.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/ProtoUtil.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/Tuple2.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/Tuple3.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/web/WebMvcGrpcServiceHandlerMapping.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/web/WebMvcProtobufHandlerAdaptor.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/ControllerMethodResolver.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/GrpcHandlerResultHandler.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/WebFluxGrpcServiceHandlerMapping.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/WebFluxProtobufHandlerAdaptor.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/JsonTranscoderIT.java delete mode 100644 grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/U.java rename grpc-extensions/grpc-metrics/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/metrics/GrpcMetricsAutoConfiguration.java (88%) rename grpc-extensions/grpc-metrics/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/metrics/GrpcMetricsProperties.java (90%) rename grpc-extensions/grpc-metrics/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/metrics/OrderedMetricCollectingClientInterceptor.java (91%) rename grpc-extensions/grpc-metrics/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/metrics/OrderedMetricCollectingServerInterceptor.java (91%) delete mode 100644 grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/MetricsZipkinIT.java rename grpc-extensions/grpc-metrics/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/metrics/Deps.java (72%) rename grpc-extensions/grpc-metrics/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/metrics/GrpcMetricsAutoConfigurationTest.java (94%) delete mode 100644 grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/NetUtil.java rename grpc-extensions/grpc-test/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/GrpcTestAutoConfiguration.java (87%) rename grpc-extensions/grpc-test/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/GrpcTestBeanPostProcessor.java (79%) rename grpc-extensions/grpc-test/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/GrpcTestEnvironmentPostProcessor.java (63%) rename grpc-extensions/grpc-test/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/GrpcTestProperties.java (81%) rename grpc-extensions/grpc-test/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/InProcessName.java (91%) rename grpc-extensions/grpc-test/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/LocalGrpcPort.java (84%) rename grpc-extensions/grpc-test/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/StubUtil.java (87%) rename grpc-extensions/grpc-test/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/DefinedPortIT.java (93%) rename grpc-extensions/grpc-test/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/LocalGrpcPortTest.java (95%) rename grpc-extensions/grpc-test/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/test/RandomPortIT.java (93%) rename grpc-extensions/grpc-tracing/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/tracing/GrpcTracingAutoConfiguration.java (88%) rename grpc-extensions/grpc-tracing/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/tracing/GrpcTracingProperties.java (90%) rename grpc-extensions/grpc-tracing/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/tracing/OrderedObservationGrpcClientInterceptor.java (91%) rename grpc-extensions/grpc-tracing/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/tracing/OrderedObservationGrpcServerInterceptor.java (91%) rename grpc-extensions/grpc-tracing/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/tracing/GrpcTracingAutoConfigurationTest.java (98%) rename grpc-extensions/{grpc-json-transcoder => grpc-transcoding}/build.gradle (64%) create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/DefaultHeaderConverter.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingAutoConfiguration.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingProperties.java rename grpc-extensions/{grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcHeaderConverter.java => grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/HeaderConverter.java} (64%) create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/JsonUtil.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ReactiveTranscodingRouterFunction.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ServletTranscodingRouterFunction.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Transcoder.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingGrpcServer.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingRuntimeException.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingUtil.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Util.java create mode 100644 grpc-extensions/grpc-transcoding/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename grpc-extensions/{grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder => grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding}/Deps.java (86%) create mode 100644 grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/JsonTranscoderIT.java create mode 100644 grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/TestUtil.java create mode 100644 grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/TranscoderTest.java rename grpc-extensions/{grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/ProtoUtilTest.java => grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/UtilTest.java} (67%) create mode 100644 grpc-extensions/grpc-transcoding/src/test/proto/transcoder_test.proto rename grpc-extensions/grpc-validation/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/GrpcValidationAutoConfiguration.java (93%) rename grpc-extensions/grpc-validation/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/GrpcValidationProperties.java (96%) rename grpc-extensions/grpc-validation/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/OrderedValidatingClientInterceptor.java (89%) rename grpc-extensions/grpc-validation/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/OrderedValidatingServerInterceptor.java (89%) rename grpc-extensions/grpc-validation/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/ProtoValidateClientInterceptor.java (85%) rename grpc-extensions/grpc-validation/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/ProtoValidateServerInterceptor.java (93%) rename grpc-extensions/grpc-validation/src/main/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/ValidationExceptionUtil.java (94%) rename grpc-extensions/grpc-validation/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/GrpcValidationAutoConfigurationTest.java (98%) rename grpc-extensions/grpc-validation/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/PgvValidationClientDisabledIT.java (91%) rename grpc-extensions/grpc-validation/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/PgvValidationClientServerDisabledIT.java (90%) rename grpc-extensions/grpc-validation/src/test/java/{com/freemanan/starter/grpc => grpcstarter}/extensions/validation/PgvValidationIT.java (92%) create mode 100644 grpc-starters/grpc-starter-transcoding-webflux/build.gradle rename grpc-starters/{grpc-starter-web => grpc-starter-transcoding-webmvc}/build.gradle (68%) delete mode 100644 grpc-starters/grpc-starter-webflux/build.gradle diff --git a/README.md b/README.md index 4ba1d28b..2eef504d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build](https://img.shields.io/github/actions/workflow/status/DanielLiu1123/grpc-starter/build.yml?branch=main)](https://github.com/DanielLiu1123/grpc-starter/actions) [![Maven Central](https://img.shields.io/maven-central/v/io.github.danielliu1123/grpc-starter-dependencies?versionPrefix=3.)](https://central.sonatype.com/artifact/io.github.danielliu1123/grpc-starter-dependencies) -[![Maven Central](https://img.shields.io/maven-central/v/com.freemanan/grpc-starter-dependencies?versionPrefix=2.)](https://central.sonatype.com/artifact/com.freemanan/grpc-starter-dependencies) +[![Maven Central](https://img.shields.io/maven-central/v/io.github.danielliu1123/grpc-starter-dependencies?versionPrefix=2.)](https://central.sonatype.com/artifact/io.github.danielliu1123/grpc-starter-dependencies) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [Documentation](https://danielliu1123.github.io/grpc-starter) @@ -44,11 +44,11 @@ implementation("io.github.danielliu1123:grpc-boot-starter") ```java @SpringBootApplication -@EnableGrpcClients("io.grpc") public class SimpleApp extends SimpleServiceGrpc.SimpleServiceImplBase { public static void main(String[] args) { new SpringApplicationBuilder(SimpleApp.class) + .properties("grpc.client.base-packages=io.grpc") .properties("grpc.client.authority=127.0.0.1:9090") .run(args); } diff --git a/build.gradle b/build.gradle index a0b013a2..0bc1b483 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,9 @@ plugins { - id 'org.springframework.boot' version "${springBootVersion}" apply false - id 'io.spring.dependency-management' version "${springDependencyManagementVersion}" apply false - id "com.google.protobuf" version "${protobufGradlePluginVersion}" apply false - id 'com.diffplug.spotless' version "${spotlessVersion}" apply false + id "org.springframework.boot" version "${springBootVersion}" apply false + id "io.spring.dependency-management" version "${springDependencyManagementVersion}" apply false + id "com.diffplug.spotless" version "${spotlessVersion}" apply false id "com.github.spotbugs" version "${spotbugsVersion}" apply false - id "build.buf" version "${bufGradlePluginVersion}" apply false + id "com.google.protobuf" version "${protobufGradlePluginVersion}" apply false } allprojects { @@ -13,34 +12,33 @@ allprojects { return } - apply plugin: 'java' - apply plugin: 'java-library' + apply plugin: "java" + apply plugin: "java-library" java { - registerFeature('optionalSupport') { + registerFeature("optionalSupport") { usingSourceSet(sourceSets.main) } } repositories { - mavenLocal() mavenCentral() maven { url "https://repo.spring.io/snapshot" } maven { url "https://repo.spring.io/milestone" } } compileJava { - options.encoding = 'UTF-8' - options.compilerArgs << '-parameters' + options.encoding = "UTF-8" + options.compilerArgs << "-parameters" } compileTestJava { - options.encoding = 'UTF-8' - options.compilerArgs << '-parameters' + options.encoding = "UTF-8" + options.compilerArgs << "-parameters" } test { useJUnitPlatform() } // dependency management - apply plugin: 'io.spring.dependency-management' + apply plugin: "io.spring.dependency-management" dependencyManagement { imports { mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}" @@ -57,9 +55,9 @@ allprojects { compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsAnnotationsVersion}") } // spotless - apply plugin: 'com.diffplug.spotless' + apply plugin: "com.diffplug.spotless" spotless { - encoding 'UTF-8' + encoding "UTF-8" java { toggleOffOn() removeUnusedImports() @@ -69,7 +67,7 @@ allprojects { targetExclude "build/generated/**" - custom('Refuse wildcard imports', { + custom("Refuse wildcard imports", { if (it =~ /\nimport .*\*;/) { throw new IllegalStateException("Do not use wildcard imports, 'spotlessApply' cannot resolve this issue, please fix it manually.") } @@ -78,17 +76,10 @@ allprojects { } // spotbugs - apply plugin: 'com.github.spotbugs' + apply plugin: "com.github.spotbugs" spotbugs { spotbugsTest.enabled = false - omitVisitors.addAll 'FindReturnRef', 'DontReusePublicIdentifiers' + omitVisitors.addAll "FindReturnRef", "DontReusePublicIdentifiers" excludeFilter = file("${rootDir}/config/spotbugs/exclude.xml") } } - -tasks.register('installGitHook', Copy) { - from "$rootProject.rootDir/.githooks" - into { new File(rootProject.rootDir, '.git/hooks') } - fileMode 0775 -} -installGitHook diff --git a/docs/en-us/client/onboarding.md b/docs/en-us/client/onboarding.md index 6c7e53bf..0de7d3e5 100644 --- a/docs/en-us/client/onboarding.md +++ b/docs/en-us/client/onboarding.md @@ -3,7 +3,7 @@ 1. Add the dependency: ```groovy - implementation 'com.freemanan:grpc-client-boot-starter' + implementation 'io.github.danielliu1123:grpc-client-boot-starter' ``` 2. Configure the scanning of gRPC stubs: diff --git a/docs/en-us/extension/json-transcoder.md b/docs/en-us/extension/json-transcoder.md index 5880b170..87b5e2b3 100644 --- a/docs/en-us/extension/json-transcoder.md +++ b/docs/en-us/extension/json-transcoder.md @@ -8,8 +8,8 @@ HTTP/JSON call methods with just one set of gRPC implementations. 1. Add Dependencies ```groovy - implementation 'com.freemanan:grpc-boot-starter' - implementation 'com.freemanan:grpc-starter-web' + implementation 'io.github.danielliu1123:grpc-boot-starter' + implementation 'io.github.danielliu1123:grpc-starter-web' implementation 'io.grpc:grpc-testing-proto' // For demonstration purposes, using gRPC's simple service ``` diff --git a/docs/en-us/extension/metrics.md b/docs/en-us/extension/metrics.md index 852f4967..8c45a2bc 100644 --- a/docs/en-us/extension/metrics.md +++ b/docs/en-us/extension/metrics.md @@ -10,7 +10,7 @@ clients. 1. Add dependencies ```groovy - implementation("com.freemanan:grpc-starter-metrics") + implementation("io.github.danielliu1123:grpc-starter-metrics") // Actuator uses Micrometer as the metrics collection facade, here we use Prometheus // You can refer to the list of metric collectors supported by Micrometer at https://micrometer.io/docs/ implementation("io.micrometer:micrometer-registry-prometheus") diff --git a/docs/en-us/extension/protobuf-validation.md b/docs/en-us/extension/protobuf-validation.md index 628f080a..265fb5be 100644 --- a/docs/en-us/extension/protobuf-validation.md +++ b/docs/en-us/extension/protobuf-validation.md @@ -24,7 +24,7 @@ user 1. Add the dependency ```groovy - implementation("com.freemanan:grpc-starter-protovalidate") + implementation("io.github.danielliu1123:grpc-starter-protovalidate") ``` > In most cases, you only need the API module to depend on the `grpc-starter-protovalidate` module. @@ -59,7 +59,7 @@ user 1. Add the dependency ```groovy - implementation("com.freemanan:grpc-starter-validation") + implementation("io.github.danielliu1123:grpc-starter-validation") ``` > In most cases, you only need the API module to depend on the `grpc-starter-validation` module. diff --git a/docs/en-us/extension/test.md b/docs/en-us/extension/test.md index 8dfeffb3..9dac036e 100644 --- a/docs/en-us/extension/test.md +++ b/docs/en-us/extension/test.md @@ -7,7 +7,7 @@ The Test extension integrates with `SpringBootTest`. Add the dependency: ```groovy -testImplementation("com.freemanan:grpc-starter-test") +testImplementation("io.github.danielliu1123:grpc-starter-test") ``` After adding the dependency, the gRPC server will communicate using in-process by default. diff --git a/docs/en-us/extension/tracing.md b/docs/en-us/extension/tracing.md index c7ce1505..96e38781 100644 --- a/docs/en-us/extension/tracing.md +++ b/docs/en-us/extension/tracing.md @@ -16,7 +16,7 @@ clients. 2. Add dependencies ```groovy - implementation("com.freemanan:grpc-starter-tracing") + implementation("io.github.danielliu1123:grpc-starter-tracing") // You can refer to the list of tracing systems supported by Micrometer at https://micrometer.io/docs/tracing implementation("io.micrometer:micrometer-tracing-bridge-brave") ``` diff --git a/docs/en-us/guide/quickstart.md b/docs/en-us/guide/quickstart.md index 36e857ed..ca0ed78c 100644 --- a/docs/en-us/guide/quickstart.md +++ b/docs/en-us/guide/quickstart.md @@ -5,8 +5,8 @@ #### **Gradle** ```groovy -implementation platform('com.freemanan:grpc-starter-dependencies:3.2.4') -implementation 'com.freemanan:grpc-boot-starter' +implementation platform('io.github.danielliu1123:grpc-starter-dependencies:3.2.4') +implementation 'io.github.danielliu1123:grpc-boot-starter' ``` #### **Maven** @@ -15,7 +15,7 @@ implementation 'com.freemanan:grpc-boot-starter' - com.freemanan + io.github.danielliu1123 grpc-starter-dependencies 3.2.4 pom @@ -25,7 +25,7 @@ implementation 'com.freemanan:grpc-boot-starter' - com.freemanan + io.github.danielliu1123 grpc-boot-starter ``` diff --git a/docs/en-us/server/onboarding.md b/docs/en-us/server/onboarding.md index c7f5d513..85358d58 100644 --- a/docs/en-us/server/onboarding.md +++ b/docs/en-us/server/onboarding.md @@ -3,13 +3,13 @@ Add dependencies: ```groovy -implementation 'com.freemanan:grpc-server-boot-starter' +implementation 'io.github.danielliu1123:grpc-server-boot-starter' ``` or ```groovy -implementation 'com.freemanan:grpc-boot-starter' +implementation 'io.github.danielliu1123:grpc-boot-starter' ``` > `grpc-boot-starter` includes `grpc-server-boot-starter` and `grpc-client-boot-starter`. diff --git a/docs/zh-cn/client/onboarding.md b/docs/zh-cn/client/onboarding.md index b47b3cb1..a0f365c8 100644 --- a/docs/zh-cn/client/onboarding.md +++ b/docs/zh-cn/client/onboarding.md @@ -3,7 +3,7 @@ 1. 引入依赖 ```groovy - implementation 'com.freemanan:grpc-client-boot-starter' + implementation 'io.github.danielliu1123:grpc-client-boot-starter' ``` 2. 配置扫描 gRPC stubs diff --git a/docs/zh-cn/extension/json-transcoder.md b/docs/zh-cn/extension/json-transcoder.md index 70afa0b4..6c88ab51 100644 --- a/docs/zh-cn/extension/json-transcoder.md +++ b/docs/zh-cn/extension/json-transcoder.md @@ -7,8 +7,8 @@ JSON transcoder 扩展将 gRPC 服务转换为 HTTP/JSON 服务,**_只需要 1. 添加依赖 ```groovy - implementation 'com.freemanan:grpc-boot-starter' - implementation 'com.freemanan:grpc-starter-web' + implementation 'io.github.danielliu1123:grpc-boot-starter' + implementation 'io.github.danielliu1123:grpc-starter-web' implementation 'io.grpc:grpc-testing-proto' // 为了演示,使用 gRPC 提供的 simple service ``` diff --git a/docs/zh-cn/extension/metrics.md b/docs/zh-cn/extension/metrics.md index eff8ee96..dffac1f1 100644 --- a/docs/zh-cn/extension/metrics.md +++ b/docs/zh-cn/extension/metrics.md @@ -9,7 +9,7 @@ Metrics 扩展了 Spring Boot Actuator,为 gRPC 服务端和客户端提供了 1. 引入依赖 ```groovy - implementation("com.freemanan:grpc-starter-metrics") + implementation("io.github.danielliu1123:grpc-starter-metrics") // Actuator 使用 Micrometer 作为指标采集门面,这里使用 Prometheus // Micrometer 支持的指标采集器可以参考 https://micrometer.io/docs/ implementation("io.micrometer:micrometer-registry-prometheus") diff --git a/docs/zh-cn/extension/protobuf-validation.md b/docs/zh-cn/extension/protobuf-validation.md index c21e8a33..7d260406 100644 --- a/docs/zh-cn/extension/protobuf-validation.md +++ b/docs/zh-cn/extension/protobuf-validation.md @@ -22,7 +22,7 @@ user 1. 添加依赖项 ```groovy - implementation("com.freemanan:grpc-starter-protovalidate") + implementation("io.github.danielliu1123:grpc-starter-protovalidate") ``` > 在大多数情况下,您只需要 API 模块依赖 `grpc-starter-protovalidate` 模块。 @@ -57,7 +57,7 @@ user 1. 添加依赖项 ```groovy - implementation("com.freemanan:grpc-starter-validation") + implementation("io.github.danielliu1123:grpc-starter-validation") ``` > 在大多数情况下,您只需要 API 模块依赖 `grpc-starter-validation` 模块。 diff --git a/docs/zh-cn/extension/test.md b/docs/zh-cn/extension/test.md index 634dcf8f..b09d65b1 100644 --- a/docs/zh-cn/extension/test.md +++ b/docs/zh-cn/extension/test.md @@ -7,7 +7,7 @@ Test 扩展对 `SpringBootTest` 做了集成。 添加依赖: ```groovy -testImplementation("com.freemanan:grpc-starter-test") +testImplementation("io.github.danielliu1123:grpc-starter-test") ``` 添加依赖后 gRPC server 默认会使用 in-process 进行通信,可以通过 `@InProcessName` 注解获取 in-process name。 diff --git a/docs/zh-cn/extension/tracing.md b/docs/zh-cn/extension/tracing.md index cdcd6f8a..05ebdf7f 100644 --- a/docs/zh-cn/extension/tracing.md +++ b/docs/zh-cn/extension/tracing.md @@ -15,7 +15,7 @@ Tracing 扩展了 Spring Boot Actuator,为 gRPC 服务端和客户端提供了 2. 引入依赖 ```groovy - implementation("com.freemanan:grpc-starter-tracing") + implementation("io.github.danielliu1123:grpc-starter-tracing") // Micrometer 支持的 Tracing system 可以参考 https://micrometer.io/docs/tracing implementation("io.micrometer:micrometer-tracing-bridge-brave") ``` diff --git a/docs/zh-cn/guide/quickstart.md b/docs/zh-cn/guide/quickstart.md index f92d7f2a..b3769a82 100644 --- a/docs/zh-cn/guide/quickstart.md +++ b/docs/zh-cn/guide/quickstart.md @@ -5,8 +5,8 @@ #### ** Gradle ** ```groovy -implementation platform('com.freemanan:grpc-starter-dependencies:3.2.4') -implementation 'com.freemanan:grpc-boot-starter' +implementation platform('io.github.danielliu1123:grpc-starter-dependencies:3.2.4') +implementation 'io.github.danielliu1123:grpc-boot-starter' ``` #### ** Maven ** @@ -16,7 +16,7 @@ implementation 'com.freemanan:grpc-boot-starter' - com.freemanan + io.github.danielliu1123 grpc-starter-dependencies 3.2.4 pom @@ -26,7 +26,7 @@ implementation 'com.freemanan:grpc-boot-starter' - com.freemanan + io.github.danielliu1123 grpc-boot-starter ``` diff --git a/docs/zh-cn/server/onboarding.md b/docs/zh-cn/server/onboarding.md index b36174e1..3a01b774 100644 --- a/docs/zh-cn/server/onboarding.md +++ b/docs/zh-cn/server/onboarding.md @@ -3,13 +3,13 @@ 添加依赖: ```groovy -implementation 'com.freemanan:grpc-server-boot-starter' +implementation 'io.github.danielliu1123:grpc-server-boot-starter' ``` 或者 ```groovy -implementation 'com.freemanan:grpc-boot-starter' +implementation 'io.github.danielliu1123:grpc-boot-starter' ``` > grpc-boot-starter 包含了 grpc-server-boot-starter 和 grpc-client-boot-starter diff --git a/examples/grpc-sample-api/build.gradle b/examples/grpc-sample-api/build.gradle index 05cc60fb..ca306e67 100644 --- a/examples/grpc-sample-api/build.gradle +++ b/examples/grpc-sample-api/build.gradle @@ -7,3 +7,11 @@ dependencies { apply from: "${rootDir}/gradle/deploy.gradle" apply from: "${rootDir}/gradle/protobuf.gradle" + +sourceSets { + main { + proto { + srcDirs "proto" + } + } +} \ No newline at end of file diff --git a/examples/grpc-sample-api/src/main/proto/sample/pet/v1/pet.proto b/examples/grpc-sample-api/src/main/proto/sample/pet/v1/pet.proto deleted file mode 100644 index f0cba303..00000000 --- a/examples/grpc-sample-api/src/main/proto/sample/pet/v1/pet.proto +++ /dev/null @@ -1,23 +0,0 @@ -syntax = "proto3"; - -package sample.pet.v1; - -option java_multiple_files = true; -option java_package = "com.freemanan.sample.pet.v1"; - -import "google/protobuf/wrappers.proto"; - -message Pet { - string name = 1; - int32 age = 2; - repeated string favorite_foods = 3; -} - -message GetPetRequest { - string name = 1; -} - -service PetService { - rpc GetPet(GetPetRequest) returns (Pet); - rpc GetPetName(google.protobuf.StringValue) returns (google.protobuf.StringValue); -} diff --git a/examples/json-transcoder/webflux/src/main/java/com/freeman/example/GrpcExceptionAdvice.java b/examples/json-transcoder/webflux/src/main/java/com/freeman/example/GrpcExceptionAdvice.java deleted file mode 100644 index be23b0fd..00000000 --- a/examples/json-transcoder/webflux/src/main/java/com/freeman/example/GrpcExceptionAdvice.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.freeman.example; - -import com.freemanan.starter.grpc.extensions.jsontranscoder.util.GrpcUtil; -import io.grpc.StatusRuntimeException; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -/** - * @author Freeman - */ -@ControllerAdvice -public class GrpcExceptionAdvice { - - @ExceptionHandler(StatusRuntimeException.class) - public ResponseEntity handleStatusRuntimeException(StatusRuntimeException sre) { - HttpStatus httpStatus = GrpcUtil.toHttpStatus(sre.getStatus()); - return ResponseEntity.status(httpStatus) - .body(new ErrorResponse(httpStatus.value(), sre.getStatus().getDescription(), null)); - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class ErrorResponse { - private int code; - private String message; - private Object data; - } -} diff --git a/examples/json-transcoder/webflux/src/main/java/com/freeman/example/PersonController.java b/examples/json-transcoder/webflux/src/main/java/com/freeman/example/PersonController.java deleted file mode 100644 index 2f054239..00000000 --- a/examples/json-transcoder/webflux/src/main/java/com/freeman/example/PersonController.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.freeman.example; - -import com.freemanan.sample.pet.v1.GetPetRequest; -import com.freemanan.sample.pet.v1.Pet; -import com.freemanan.sample.pet.v1.PetServiceGrpc; -import com.freemanan.starter.grpc.server.GrpcService; -import io.grpc.stub.StreamObserver; -import org.springframework.web.bind.annotation.PostMapping; - -/** - * @author Freeman - */ -@GrpcService -public class PersonController extends PetServiceGrpc.PetServiceImplBase { - - @Override - @PostMapping("/grpcstarter.testing.v1.PersonService/GetPerson/**") - public void getPet(GetPetRequest request, StreamObserver responseObserver) { - Pet pet = Pet.newBuilder() - .setName(request.getName()) - .setAge(18) - .addFavoriteFoods("banana") - .build(); - if (request.getName().startsWith("err")) { - throw new IllegalArgumentException("error"); - } - responseObserver.onNext(pet); - responseObserver.onCompleted(); - } -} diff --git a/examples/json-transcoder/webflux/src/main/java/com/freeman/example/WebFluxApp.java b/examples/json-transcoder/webflux/src/main/java/com/freeman/example/WebFluxApp.java deleted file mode 100644 index cd48d6f0..00000000 --- a/examples/json-transcoder/webflux/src/main/java/com/freeman/example/WebFluxApp.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.freeman.example; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Freeman - */ -@SpringBootApplication -public class WebFluxApp { - public static void main(String[] args) { - SpringApplication.run(WebFluxApp.class, args); - } -} diff --git a/examples/json-transcoder/webflux/src/main/resources/application.yaml b/examples/json-transcoder/webflux/src/main/resources/application.yaml deleted file mode 100644 index ef3ff5cc..00000000 --- a/examples/json-transcoder/webflux/src/main/resources/application.yaml +++ /dev/null @@ -1,9 +0,0 @@ -grpc: - server: - reflection: - enabled: true - exception-handling: - use-default: false -server: - error: - include-message: always \ No newline at end of file diff --git a/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/GrpcExceptionAdvice.java b/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/GrpcExceptionAdvice.java deleted file mode 100644 index be23b0fd..00000000 --- a/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/GrpcExceptionAdvice.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.freeman.example; - -import com.freemanan.starter.grpc.extensions.jsontranscoder.util.GrpcUtil; -import io.grpc.StatusRuntimeException; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -/** - * @author Freeman - */ -@ControllerAdvice -public class GrpcExceptionAdvice { - - @ExceptionHandler(StatusRuntimeException.class) - public ResponseEntity handleStatusRuntimeException(StatusRuntimeException sre) { - HttpStatus httpStatus = GrpcUtil.toHttpStatus(sre.getStatus()); - return ResponseEntity.status(httpStatus) - .body(new ErrorResponse(httpStatus.value(), sre.getStatus().getDescription(), null)); - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class ErrorResponse { - private int code; - private String message; - private Object data; - } -} diff --git a/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/PersonController.java b/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/PersonController.java deleted file mode 100644 index 698bedfd..00000000 --- a/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/PersonController.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.freeman.example; - -import com.freemanan.sample.pet.v1.GetPetRequest; -import com.freemanan.sample.pet.v1.Pet; -import com.freemanan.sample.pet.v1.PetServiceGrpc; -import com.freemanan.starter.grpc.server.GrpcService; -import com.google.protobuf.StringValue; -import io.grpc.stub.StreamObserver; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Freeman - */ -@GrpcService -@RestController -public class PersonController extends PetServiceGrpc.PetServiceImplBase { - - @Override - @PostMapping("/grpcstarter.testing.v1.PersonService/GetPerson/**") - public void getPet(GetPetRequest request, StreamObserver responseObserver) { - Pet pet = Pet.newBuilder() - .setName(request.getName()) - .setAge(18) - .addFavoriteFoods("banana") - .build(); - if (request.getName().startsWith("err")) { - throw new IllegalArgumentException("error"); - } - responseObserver.onNext(pet); - responseObserver.onCompleted(); - } - - @Override - public void getPetName(StringValue request, StreamObserver responseObserver) { - StringValue name = StringValue.of(request.getValue()); - responseObserver.onNext(name); - responseObserver.onCompleted(); - } -} diff --git a/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/SimpleServiceImpl.java b/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/SimpleServiceImpl.java deleted file mode 100644 index 921b9cc5..00000000 --- a/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/SimpleServiceImpl.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.freeman.example; - -import com.freemanan.starter.grpc.server.GrpcService; -import io.grpc.stub.StreamObserver; -import io.grpc.testing.protobuf.SimpleRequest; -import io.grpc.testing.protobuf.SimpleResponse; -import io.grpc.testing.protobuf.SimpleServiceGrpc; -import org.springframework.web.bind.annotation.PostMapping; - -/** - * @author Freeman - */ -@GrpcService -public class SimpleServiceImpl extends SimpleServiceGrpc.SimpleServiceImplBase { - @Override - @PostMapping("/simple") - public void unaryRpc(SimpleRequest request, StreamObserver so) { - SimpleResponse response = SimpleResponse.newBuilder() - .setResponseMessage("Hello, I got your message: " + request.getRequestMessage()) - .build(); - so.onNext(response); - so.onCompleted(); - } -} diff --git a/examples/json-transcoder/webmvc/src/main/resources/application.yaml b/examples/json-transcoder/webmvc/src/main/resources/application.yaml deleted file mode 100644 index ef3ff5cc..00000000 --- a/examples/json-transcoder/webmvc/src/main/resources/application.yaml +++ /dev/null @@ -1,9 +0,0 @@ -grpc: - server: - reflection: - enabled: true - exception-handling: - use-default: false -server: - error: - include-message: always \ No newline at end of file diff --git a/examples/metrics/src/main/java/com/freemanan/example/AspectConfiguration.java b/examples/metrics/src/main/java/com/freemanan/example/AspectConfiguration.java deleted file mode 100644 index 4f657a6e..00000000 --- a/examples/metrics/src/main/java/com/freemanan/example/AspectConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.freemanan.example; - -import io.micrometer.core.aop.CountedAspect; -import io.micrometer.core.aop.TimedAspect; -import io.micrometer.core.instrument.MeterRegistry; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Freeman - */ -@Configuration(proxyBeanMethods = false) -public class AspectConfiguration { - - /** - * Make {@link io.micrometer.core.annotation.Counted} work. - */ - @Bean - public CountedAspect countedAspect(MeterRegistry registry) { - return new CountedAspect(registry); - } - - /** - * Make {@link io.micrometer.core.annotation.Timed} work. - */ - @Bean - public TimedAspect timedAspect(MeterRegistry registry) { - return new TimedAspect(registry); - } -} diff --git a/examples/metrics/src/main/java/com/freemanan/example/App.java b/examples/metrics/src/main/java/grpcstarter/example/MetricApp.java similarity index 84% rename from examples/metrics/src/main/java/com/freemanan/example/App.java rename to examples/metrics/src/main/java/grpcstarter/example/MetricApp.java index a42f2716..1e7ec721 100644 --- a/examples/metrics/src/main/java/com/freemanan/example/App.java +++ b/examples/metrics/src/main/java/grpcstarter/example/MetricApp.java @@ -1,6 +1,6 @@ -package com.freemanan.example; +package grpcstarter.example; -import com.freemanan.starter.grpc.client.EnableGrpcClients; +import grpcstarter.client.EnableGrpcClients; import io.grpc.testing.protobuf.SimpleRequest; import io.grpc.testing.protobuf.SimpleResponse; import io.grpc.testing.protobuf.SimpleServiceGrpc; @@ -17,10 +17,10 @@ */ @SpringBootApplication @EnableGrpcClients("io.grpc") -public class App implements ApplicationRunner { +public class MetricApp implements ApplicationRunner { private final Counter counter; - public App(MeterRegistry mr) { + public MetricApp(MeterRegistry mr) { this.counter = Counter.builder("app_run") .description("app run") .tags("app", "metrics-test") @@ -31,7 +31,7 @@ public App(MeterRegistry mr) { SimpleServiceGrpc.SimpleServiceBlockingStub stub; public static void main(String[] args) { - SpringApplication.run(App.class, args); + SpringApplication.run(MetricApp.class, args); } @Override diff --git a/examples/metrics/src/main/java/com/freemanan/example/controller/SimpleServiceImpl.java b/examples/metrics/src/main/java/grpcstarter/example/SimpleServiceImpl.java similarity index 95% rename from examples/metrics/src/main/java/com/freemanan/example/controller/SimpleServiceImpl.java rename to examples/metrics/src/main/java/grpcstarter/example/SimpleServiceImpl.java index b3e7d725..6037a976 100644 --- a/examples/metrics/src/main/java/com/freemanan/example/controller/SimpleServiceImpl.java +++ b/examples/metrics/src/main/java/grpcstarter/example/SimpleServiceImpl.java @@ -1,4 +1,4 @@ -package com.freemanan.example.controller; +package grpcstarter.example; import io.grpc.stub.StreamObserver; import io.grpc.testing.protobuf.SimpleRequest; diff --git a/examples/metrics/src/main/resources/application.yaml b/examples/metrics/src/main/resources/application.yaml index a83bde70..ded99e10 100644 --- a/examples/metrics/src/main/resources/application.yaml +++ b/examples/metrics/src/main/resources/application.yaml @@ -17,4 +17,6 @@ management: observations: key-values: app: ${spring.application.name:UNKNOWN} + annotations: + enabled: true debug: true diff --git a/examples/metrics/src/test/java/com/freemanan/example/AppTest.java b/examples/metrics/src/test/java/com/freemanan/example/AppTest.java deleted file mode 100644 index 00f474dc..00000000 --- a/examples/metrics/src/test/java/com/freemanan/example/AppTest.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.freemanan.example; - -class AppTest {} diff --git a/examples/metrics/src/test/java/grpcstarter/example/MetricsAppTest.java b/examples/metrics/src/test/java/grpcstarter/example/MetricsAppTest.java new file mode 100644 index 00000000..be39429d --- /dev/null +++ b/examples/metrics/src/test/java/grpcstarter/example/MetricsAppTest.java @@ -0,0 +1,3 @@ +package grpcstarter.example; + +class MetricsAppTest {} diff --git a/examples/multi-module/api/build.gradle b/examples/multi-module/api/build.gradle new file mode 100644 index 00000000..0a5cdc60 --- /dev/null +++ b/examples/multi-module/api/build.gradle @@ -0,0 +1,13 @@ +dependencies { + implementation(project(":grpc-starters:grpc-starter-protovalidate")) +} + +apply from: "${rootDir}/gradle/protobuf.gradle" + +sourceSets { + main { + proto { + srcDir "proto" + } + } +} diff --git a/examples/multi-module/api/proto/user/user.proto b/examples/multi-module/api/proto/user/user.proto new file mode 100644 index 00000000..c524834a --- /dev/null +++ b/examples/multi-module/api/proto/user/user.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package user; + +import "buf/validate/validate.proto"; + +option java_multiple_files = true; + +message CreateUserRequest { + string name = 1 [(buf.validate.field).string = {min_len: 1, max_len: 100}]; +} + +message User { + string id = 1; + string name = 2; +} + +service UserService { + rpc CreateUser (CreateUserRequest) returns (User) {} +} diff --git a/examples/user/user-server/build.gradle b/examples/multi-module/server/build.gradle similarity index 69% rename from examples/user/user-server/build.gradle rename to examples/multi-module/server/build.gradle index cf002ad7..b167a567 100644 --- a/examples/user/user-server/build.gradle +++ b/examples/multi-module/server/build.gradle @@ -3,6 +3,6 @@ plugins { } dependencies { - implementation(project(":examples:user:user-api")) + implementation(project(":examples:multi-module:api")) implementation(project(":grpc-starters:grpc-server-boot-starter")) } diff --git a/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/MvcApp.java b/examples/multi-module/server/src/main/java/grpcstarter/example/UserApp.java similarity index 68% rename from examples/json-transcoder/webmvc/src/main/java/com/freeman/example/MvcApp.java rename to examples/multi-module/server/src/main/java/grpcstarter/example/UserApp.java index 7195262f..787ddf8e 100644 --- a/examples/json-transcoder/webmvc/src/main/java/com/freeman/example/MvcApp.java +++ b/examples/multi-module/server/src/main/java/grpcstarter/example/UserApp.java @@ -1,4 +1,4 @@ -package com.freeman.example; +package grpcstarter.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -7,8 +7,8 @@ * @author Freeman */ @SpringBootApplication -public class MvcApp { +public class UserApp { public static void main(String[] args) { - SpringApplication.run(MvcApp.class, args); + SpringApplication.run(UserApp.class, args); } } diff --git a/examples/multi-module/server/src/main/java/grpcstarter/example/UserServiceImpl.java b/examples/multi-module/server/src/main/java/grpcstarter/example/UserServiceImpl.java new file mode 100644 index 00000000..6afb9689 --- /dev/null +++ b/examples/multi-module/server/src/main/java/grpcstarter/example/UserServiceImpl.java @@ -0,0 +1,21 @@ +package grpcstarter.example; + +import io.grpc.stub.StreamObserver; +import org.springframework.stereotype.Controller; +import user.CreateUserRequest; +import user.User; +import user.UserServiceGrpc; + +/** + * @author Freeman + */ +@Controller +public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase { + + @Override + public void createUser(CreateUserRequest request, StreamObserver responseObserver) { + User user = User.newBuilder().setId("100").setName(request.getName()).build(); + responseObserver.onNext(user); + responseObserver.onCompleted(); + } +} diff --git a/examples/user/user-server/src/main/resources/application.yaml b/examples/multi-module/server/src/main/resources/application.yaml similarity index 100% rename from examples/user/user-server/src/main/resources/application.yaml rename to examples/multi-module/server/src/main/resources/application.yaml diff --git a/examples/proto-validate/src/main/java/com/freemanan/example/ProtoValidateApp.java b/examples/proto-validate/src/main/java/com/freemanan/example/ProtoValidateApp.java deleted file mode 100644 index 2de48410..00000000 --- a/examples/proto-validate/src/main/java/com/freemanan/example/ProtoValidateApp.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.freemanan.example; - -import com.freemanan.starter.grpc.client.EnableGrpcClients; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Freeman - */ -@SpringBootApplication -@EnableGrpcClients({"com.freemanan"}) -public class ProtoValidateApp { - - public static void main(String[] args) { - SpringApplication.run(ProtoValidateApp.class, args); - } -} diff --git a/examples/proto-validate/src/main/java/com/freemanan/example/controller/FooServiceController.java b/examples/proto-validate/src/main/java/com/freemanan/example/controller/FooServiceController.java deleted file mode 100644 index 44716e21..00000000 --- a/examples/proto-validate/src/main/java/com/freemanan/example/controller/FooServiceController.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.freemanan.example.controller; - -import com.freemanan.foo.v1.api.Foo; -import com.freemanan.foo.v1.api.FooServiceGrpc; -import io.grpc.stub.StreamObserver; -import org.springframework.stereotype.Controller; - -/** - * @author Freeman - */ -@Controller -public class FooServiceController extends FooServiceGrpc.FooServiceImplBase { - - @Override - public void insertFoo(Foo request, StreamObserver responseObserver) { - responseObserver.onNext(request); - responseObserver.onCompleted(); - } -} diff --git a/examples/proto-validate/src/main/java/grpcstarter/examples/ProtoValidateApp.java b/examples/proto-validate/src/main/java/grpcstarter/examples/ProtoValidateApp.java new file mode 100644 index 00000000..3972c094 --- /dev/null +++ b/examples/proto-validate/src/main/java/grpcstarter/examples/ProtoValidateApp.java @@ -0,0 +1,24 @@ +package grpcstarter.examples; + +import foo.FooOuterClass; +import foo.FooServiceGrpc; +import io.grpc.stub.StreamObserver; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Freeman + */ +@SpringBootApplication +public class ProtoValidateApp extends FooServiceGrpc.FooServiceImplBase { + + public static void main(String[] args) { + SpringApplication.run(ProtoValidateApp.class, args); + } + + @Override + public void insertFoo(FooOuterClass.Foo request, StreamObserver responseObserver) { + responseObserver.onNext(request); + responseObserver.onCompleted(); + } +} diff --git a/examples/proto-validate/src/main/proto/fm/foo/v1/foo.proto b/examples/proto-validate/src/main/proto/foo/foo.proto similarity index 80% rename from examples/proto-validate/src/main/proto/fm/foo/v1/foo.proto rename to examples/proto-validate/src/main/proto/foo/foo.proto index 432e5fca..292363b3 100644 --- a/examples/proto-validate/src/main/proto/fm/foo/v1/foo.proto +++ b/examples/proto-validate/src/main/proto/foo/foo.proto @@ -1,12 +1,10 @@ syntax = "proto3"; -package fm.foo.v1; +package foo; import "google/protobuf/empty.proto"; import "buf/validate/validate.proto"; - -option java_multiple_files = true; -option java_package = "com.freemanan.foo.v1.api"; +import "google/api/annotations.proto"; message Foo { string id = 1 [(buf.validate.field).cel = { @@ -25,5 +23,5 @@ message Foo { } service FooService { - rpc InsertFoo(Foo) returns (Foo) {} + rpc InsertFoo (Foo) returns (Foo) {} } diff --git a/examples/proto-validate/src/test/java/com/freemanan/example/ProtoValidateAppTest.java b/examples/proto-validate/src/test/java/grpcstarter/examples/ProtoValidateAppTest.java similarity index 90% rename from examples/proto-validate/src/test/java/com/freemanan/example/ProtoValidateAppTest.java rename to examples/proto-validate/src/test/java/grpcstarter/examples/ProtoValidateAppTest.java index d5afba07..46b876b9 100644 --- a/examples/proto-validate/src/test/java/com/freemanan/example/ProtoValidateAppTest.java +++ b/examples/proto-validate/src/test/java/grpcstarter/examples/ProtoValidateAppTest.java @@ -1,12 +1,12 @@ -package com.freemanan.example; +package grpcstarter.examples; -import static com.freemanan.foo.v1.api.FooServiceGrpc.FooServiceBlockingStub; +import static foo.FooOuterClass.Foo; +import static foo.FooServiceGrpc.FooServiceBlockingStub; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; -import com.freemanan.foo.v1.api.Foo; -import com.freemanan.starter.grpc.extensions.test.InProcessName; -import com.freemanan.starter.grpc.extensions.test.StubUtil; +import grpcstarter.extensions.test.InProcessName; +import grpcstarter.extensions.test.StubUtil; import io.grpc.StatusRuntimeException; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/examples/quick-start/buf.yaml b/examples/quick-start/buf.yaml deleted file mode 100644 index 7354a032..00000000 --- a/examples/quick-start/buf.yaml +++ /dev/null @@ -1,5 +0,0 @@ -version: v1 - -lint: - ignore: - - 'fm/foo/v1' \ No newline at end of file diff --git a/examples/quick-start/build.gradle b/examples/quick-start/build.gradle index 281ab683..f6cc3858 100644 --- a/examples/quick-start/build.gradle +++ b/examples/quick-start/build.gradle @@ -1,6 +1,5 @@ plugins { id 'org.springframework.boot' - id 'build.buf' } dependencies { @@ -12,7 +11,3 @@ dependencies { } apply from: "${rootDir}/gradle/protobuf.gradle" - -buf { - enforceFormat = true -} diff --git a/examples/quick-start/src/main/java/com/freemanan/example/QuickStartApp.java b/examples/quick-start/src/main/java/com/freemanan/example/QuickStartApp.java deleted file mode 100644 index cf3dabcc..00000000 --- a/examples/quick-start/src/main/java/com/freemanan/example/QuickStartApp.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.freemanan.example; - -import com.freemanan.foo.v1.api.FooServiceGrpc; -import com.freemanan.starter.grpc.client.EnableGrpcClients; -import io.grpc.health.v1.HealthGrpc; -import io.grpc.reflection.v1alpha.ServerReflectionGrpc; -import io.grpc.testing.protobuf.SimpleServiceGrpc; -import org.springframework.boot.ApplicationRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -/** - * @author Freeman - */ -@SpringBootApplication -@EnableGrpcClients({"com.freemanan", "io.grpc"}) -public class QuickStartApp { - - public static void main(String[] args) { - SpringApplication.run(QuickStartApp.class, args); - } - - @Bean - ApplicationRunner runner( - HealthGrpc.HealthStub healthStub, - ServerReflectionGrpc.ServerReflectionStub serverReflectionStub, - FooServiceGrpc.FooServiceBlockingStub fooServiceBlockingStub, - SimpleServiceGrpc.SimpleServiceBlockingStub simpleServiceBlockingStub) { - return args -> {}; - } -} diff --git a/examples/quick-start/src/main/java/com/freemanan/example/controller/FooController.java b/examples/quick-start/src/main/java/grpcstarter/example/FooServiceImpl.java similarity index 59% rename from examples/quick-start/src/main/java/com/freemanan/example/controller/FooController.java rename to examples/quick-start/src/main/java/grpcstarter/example/FooServiceImpl.java index 738c4bc8..f4fce53e 100644 --- a/examples/quick-start/src/main/java/com/freemanan/example/controller/FooController.java +++ b/examples/quick-start/src/main/java/grpcstarter/example/FooServiceImpl.java @@ -1,15 +1,15 @@ -package com.freemanan.example.controller; +package grpcstarter.example; -import com.freemanan.foo.v1.api.Foo; -import com.freemanan.foo.v1.api.FooServiceGrpc; +import foo.Foo; +import foo.FooServiceGrpc; +import grpcstarter.server.GrpcService; import io.grpc.stub.StreamObserver; -import org.springframework.stereotype.Controller; /** * @author Freeman */ -@Controller -public class FooController extends FooServiceGrpc.FooServiceImplBase { +@GrpcService +public class FooServiceImpl extends FooServiceGrpc.FooServiceImplBase { @Override public void create(Foo request, StreamObserver responseObserver) { diff --git a/examples/user/user-server/src/main/java/com/freemanan/example/App.java b/examples/quick-start/src/main/java/grpcstarter/example/QuickStartApp.java similarity index 52% rename from examples/user/user-server/src/main/java/com/freemanan/example/App.java rename to examples/quick-start/src/main/java/grpcstarter/example/QuickStartApp.java index 578b6c36..08136547 100644 --- a/examples/user/user-server/src/main/java/com/freemanan/example/App.java +++ b/examples/quick-start/src/main/java/grpcstarter/example/QuickStartApp.java @@ -1,5 +1,6 @@ -package com.freemanan.example; +package grpcstarter.example; +import grpcstarter.client.EnableGrpcClients; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -7,8 +8,10 @@ * @author Freeman */ @SpringBootApplication -public class App { +@EnableGrpcClients({"foo", "io.grpc"}) +public class QuickStartApp { + public static void main(String[] args) { - SpringApplication.run(App.class, args); + SpringApplication.run(QuickStartApp.class, args); } } diff --git a/examples/tls/src/main/java/com/freemanan/example/controller/SimpleServiceController.java b/examples/quick-start/src/main/java/grpcstarter/example/SimpleServiceImpl.java similarity index 75% rename from examples/tls/src/main/java/com/freemanan/example/controller/SimpleServiceController.java rename to examples/quick-start/src/main/java/grpcstarter/example/SimpleServiceImpl.java index 9587fa2c..2275846b 100644 --- a/examples/tls/src/main/java/com/freemanan/example/controller/SimpleServiceController.java +++ b/examples/quick-start/src/main/java/grpcstarter/example/SimpleServiceImpl.java @@ -1,16 +1,16 @@ -package com.freemanan.example.controller; +package grpcstarter.example; +import grpcstarter.server.GrpcService; import io.grpc.stub.StreamObserver; import io.grpc.testing.protobuf.SimpleRequest; import io.grpc.testing.protobuf.SimpleResponse; import io.grpc.testing.protobuf.SimpleServiceGrpc; -import org.springframework.stereotype.Controller; /** * @author Freeman */ -@Controller -public class SimpleServiceController extends SimpleServiceGrpc.SimpleServiceImplBase { +@GrpcService +public class SimpleServiceImpl extends SimpleServiceGrpc.SimpleServiceImplBase { @Override public void unaryRpc(SimpleRequest request, StreamObserver responseObserver) { diff --git a/examples/quick-start/src/main/proto/fm/foo/v1/foo.proto b/examples/quick-start/src/main/proto/foo/foo.proto similarity index 62% rename from examples/quick-start/src/main/proto/fm/foo/v1/foo.proto rename to examples/quick-start/src/main/proto/foo/foo.proto index f54dade6..b9d0427d 100644 --- a/examples/quick-start/src/main/proto/fm/foo/v1/foo.proto +++ b/examples/quick-start/src/main/proto/foo/foo.proto @@ -1,12 +1,10 @@ syntax = "proto3"; -package fm.foo.v1; +package foo; import "buf/validate/validate.proto"; -import "google/protobuf/empty.proto"; option java_multiple_files = true; -option java_package = "com.freemanan.foo.v1.api"; message Foo { string id = 1 [(buf.validate.field).string = { @@ -18,6 +16,4 @@ message Foo { service FooService { rpc Create(Foo) returns (Foo) {} - rpc Stream(stream Foo) returns (stream Foo) {} - rpc ClintStream(stream Foo) returns (Foo) {} } diff --git a/examples/quick-start/src/main/resources/application.yaml b/examples/quick-start/src/main/resources/application.yaml index f726ccf3..45a8173c 100644 --- a/examples/quick-start/src/main/resources/application.yaml +++ b/examples/quick-start/src/main/resources/application.yaml @@ -7,7 +7,7 @@ grpc: channels: - authority: localhost:${grpc.server.port:9090} classes: - - com.freemanan.foo.v1.api.FooServiceGrpc.FooServiceBlockingStub + - foo.FooServiceGrpc.FooServiceBlockingStub stubs: - io.grpc.**.Health*Stub services: diff --git a/examples/quick-start/src/test/java/com/freemanan/example/QuickStartAppTest.java b/examples/quick-start/src/test/java/grpcstarter/example/QuickStartAppTest.java similarity index 85% rename from examples/quick-start/src/test/java/com/freemanan/example/QuickStartAppTest.java rename to examples/quick-start/src/test/java/grpcstarter/example/QuickStartAppTest.java index d41af0ee..87ac70ad 100644 --- a/examples/quick-start/src/test/java/com/freemanan/example/QuickStartAppTest.java +++ b/examples/quick-start/src/test/java/grpcstarter/example/QuickStartAppTest.java @@ -1,13 +1,13 @@ -package com.freemanan.example; +package grpcstarter.example; -import static com.freemanan.foo.v1.api.FooServiceGrpc.FooServiceBlockingStub; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceBlockingStub; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import com.freemanan.foo.v1.api.Foo; -import com.freemanan.starter.grpc.extensions.test.InProcessName; -import com.freemanan.starter.grpc.extensions.test.StubUtil; +import foo.Foo; +import foo.FooServiceGrpc.FooServiceBlockingStub; +import grpcstarter.extensions.test.InProcessName; +import grpcstarter.extensions.test.StubUtil; import io.grpc.StatusRuntimeException; import io.grpc.testing.protobuf.SimpleRequest; import org.junit.jupiter.api.Test; diff --git a/examples/refresh/src/main/java/com/freemanan/example/RefreshApp.java b/examples/refresh/src/main/java/grpcstarter/example/RefreshApp.java similarity index 96% rename from examples/refresh/src/main/java/com/freemanan/example/RefreshApp.java rename to examples/refresh/src/main/java/grpcstarter/example/RefreshApp.java index ec0b354a..dbfd8f37 100644 --- a/examples/refresh/src/main/java/com/freemanan/example/RefreshApp.java +++ b/examples/refresh/src/main/java/grpcstarter/example/RefreshApp.java @@ -1,4 +1,4 @@ -package com.freemanan.example; +package grpcstarter.example; import io.grpc.stub.StreamObserver; import io.grpc.testing.protobuf.SimpleRequest; diff --git a/examples/refresh/src/test/java/com/freemanan/example/RefreshAppTest.java b/examples/refresh/src/test/java/grpcstarter/example/RefreshAppTest.java similarity index 95% rename from examples/refresh/src/test/java/com/freemanan/example/RefreshAppTest.java rename to examples/refresh/src/test/java/grpcstarter/example/RefreshAppTest.java index 3db0c27e..ce7fd274 100644 --- a/examples/refresh/src/test/java/com/freemanan/example/RefreshAppTest.java +++ b/examples/refresh/src/test/java/grpcstarter/example/RefreshAppTest.java @@ -1,4 +1,4 @@ -package com.freemanan.example; +package grpcstarter.example; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; @@ -41,7 +41,7 @@ void testDeadline() { assertThatCode(() -> simpleStub.unaryRpc(request)) .isInstanceOf(StatusRuntimeException.class) - .hasMessageContaining("DEADLINE_EXCEEDED: deadline exceeded after"); + .hasMessageContaining("DEADLINE_EXCEEDED: CallOptions deadline exceeded after"); System.clearProperty("grpc.client.deadline"); } diff --git a/examples/quick-start/src/main/java/com/freemanan/example/controller/SimpleServiceController.java b/examples/tls/src/main/java/grpcstarter/example/SimpleServiceImpl.java similarity index 83% rename from examples/quick-start/src/main/java/com/freemanan/example/controller/SimpleServiceController.java rename to examples/tls/src/main/java/grpcstarter/example/SimpleServiceImpl.java index 9587fa2c..a987029e 100644 --- a/examples/quick-start/src/main/java/com/freemanan/example/controller/SimpleServiceController.java +++ b/examples/tls/src/main/java/grpcstarter/example/SimpleServiceImpl.java @@ -1,4 +1,4 @@ -package com.freemanan.example.controller; +package grpcstarter.example; import io.grpc.stub.StreamObserver; import io.grpc.testing.protobuf.SimpleRequest; @@ -10,7 +10,7 @@ * @author Freeman */ @Controller -public class SimpleServiceController extends SimpleServiceGrpc.SimpleServiceImplBase { +public class SimpleServiceImpl extends SimpleServiceGrpc.SimpleServiceImplBase { @Override public void unaryRpc(SimpleRequest request, StreamObserver responseObserver) { diff --git a/examples/tls/src/main/java/com/freemanan/example/TLSApp.java b/examples/tls/src/main/java/grpcstarter/example/TLSApp.java similarity index 78% rename from examples/tls/src/main/java/com/freemanan/example/TLSApp.java rename to examples/tls/src/main/java/grpcstarter/example/TLSApp.java index 87858f9c..ffe76304 100644 --- a/examples/tls/src/main/java/com/freemanan/example/TLSApp.java +++ b/examples/tls/src/main/java/grpcstarter/example/TLSApp.java @@ -1,6 +1,6 @@ -package com.freemanan.example; +package grpcstarter.example; -import com.freemanan.starter.grpc.client.EnableGrpcClients; +import grpcstarter.client.EnableGrpcClients; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/examples/tls/src/test/java/com/freemanan/example/TLSAppTest.java b/examples/tls/src/test/java/grpcstarter/example/TLSAppTest.java similarity index 96% rename from examples/tls/src/test/java/com/freemanan/example/TLSAppTest.java rename to examples/tls/src/test/java/grpcstarter/example/TLSAppTest.java index 61a58966..3d92be88 100644 --- a/examples/tls/src/test/java/com/freemanan/example/TLSAppTest.java +++ b/examples/tls/src/test/java/grpcstarter/example/TLSAppTest.java @@ -1,4 +1,4 @@ -package com.freemanan.example; +package grpcstarter.example; import static org.assertj.core.api.Assertions.assertThat; diff --git a/examples/tracing/build.gradle b/examples/tracing/build.gradle index 9aa77a0e..c9545e93 100644 --- a/examples/tracing/build.gradle +++ b/examples/tracing/build.gradle @@ -9,7 +9,6 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("io.micrometer:micrometer-tracing-bridge-brave") - implementation("io.github.danielliu1123:httpexchange-spring-boot-starter:3.2.4") testImplementation(project(":grpc-starters:grpc-starter-test")) } diff --git a/examples/tracing/src/main/java/com/freemanan/example/App.java b/examples/tracing/src/main/java/com/freemanan/example/App.java deleted file mode 100644 index ebee5def..00000000 --- a/examples/tracing/src/main/java/com/freemanan/example/App.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.freemanan.example; - -import com.freemanan.starter.grpc.client.EnableGrpcClients; -import io.github.danielliu1123.httpexchange.EnableExchangeClients; -import io.grpc.testing.protobuf.SimpleRequest; -import io.grpc.testing.protobuf.SimpleResponse; -import io.grpc.testing.protobuf.SimpleServiceGrpc; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Freeman - */ -@SpringBootApplication -@EnableGrpcClients("io.grpc") -@EnableExchangeClients -public class App implements ApplicationRunner { - - @Autowired - SimpleServiceGrpc.SimpleServiceBlockingStub stub; - - public static void main(String[] args) { - SpringApplication.run(App.class, args); - } - - @Override - public void run(ApplicationArguments args) { - SimpleResponse resp = stub.unaryRpc( - SimpleRequest.newBuilder().setRequestMessage("Hello").build()); - System.out.println(resp); - } -} diff --git a/examples/tracing/src/main/java/com/freemanan/example/api/SimpleApi.java b/examples/tracing/src/main/java/grpcstarter/example/SimpleApi.java similarity index 90% rename from examples/tracing/src/main/java/com/freemanan/example/api/SimpleApi.java rename to examples/tracing/src/main/java/grpcstarter/example/SimpleApi.java index b38cbc61..4591ff47 100644 --- a/examples/tracing/src/main/java/com/freemanan/example/api/SimpleApi.java +++ b/examples/tracing/src/main/java/grpcstarter/example/SimpleApi.java @@ -1,4 +1,4 @@ -package com.freemanan.example.api; +package grpcstarter.example; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.service.annotation.GetExchange; diff --git a/examples/tracing/src/main/java/com/freemanan/example/controller/SimpleServiceImpl.java b/examples/tracing/src/main/java/grpcstarter/example/SimpleServiceImpl.java similarity index 94% rename from examples/tracing/src/main/java/com/freemanan/example/controller/SimpleServiceImpl.java rename to examples/tracing/src/main/java/grpcstarter/example/SimpleServiceImpl.java index c6b02fb1..ddab8b4f 100644 --- a/examples/tracing/src/main/java/com/freemanan/example/controller/SimpleServiceImpl.java +++ b/examples/tracing/src/main/java/grpcstarter/example/SimpleServiceImpl.java @@ -1,6 +1,5 @@ -package com.freemanan.example.controller; +package grpcstarter.example; -import com.freemanan.example.api.SimpleApi; import io.grpc.stub.StreamObserver; import io.grpc.testing.protobuf.SimpleRequest; import io.grpc.testing.protobuf.SimpleResponse; diff --git a/examples/tracing/src/main/java/grpcstarter/example/TracingApp.java b/examples/tracing/src/main/java/grpcstarter/example/TracingApp.java new file mode 100644 index 00000000..029161f8 --- /dev/null +++ b/examples/tracing/src/main/java/grpcstarter/example/TracingApp.java @@ -0,0 +1,44 @@ +package grpcstarter.example; + +import grpcstarter.client.EnableGrpcClients; +import io.grpc.testing.protobuf.SimpleRequest; +import io.grpc.testing.protobuf.SimpleResponse; +import io.grpc.testing.protobuf.SimpleServiceGrpc; +import org.springframework.boot.ApplicationRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; +import org.springframework.web.client.RestClient; +import org.springframework.web.client.support.RestClientAdapter; +import org.springframework.web.service.invoker.HttpServiceProxyFactory; + +/** + * @author Freeman + */ +@SpringBootApplication +@EnableGrpcClients("io.grpc") +public class TracingApp { + + public static void main(String[] args) { + SpringApplication.run(TracingApp.class, args); + } + + @Bean + public SimpleApi simpleApi(RestClient.Builder builder, Environment env) { + builder.baseUrl("http://localhost:" + env.getProperty("server.port", "8080")); + var factory = HttpServiceProxyFactory.builder() + .exchangeAdapter(RestClientAdapter.create(builder.build())) + .build(); + return factory.createClient(SimpleApi.class); + } + + @Bean + ApplicationRunner runner(SimpleServiceGrpc.SimpleServiceBlockingStub stub) { + return args -> { + SimpleResponse resp = stub.unaryRpc( + SimpleRequest.newBuilder().setRequestMessage("Hello").build()); + System.out.println(resp); + }; + } +} diff --git a/examples/tracing/src/main/resources/application.yaml b/examples/tracing/src/main/resources/application.yaml index 6b5bea09..2a87ca4d 100644 --- a/examples/tracing/src/main/resources/application.yaml +++ b/examples/tracing/src/main/resources/application.yaml @@ -17,9 +17,4 @@ management: sampling: probability: 1.0 -http-exchange: - channels: - - base-url: http://localhost:${server.port:8080} - clients: - - '**.api.*Api' debug: true diff --git a/examples/tracing/src/test/java/com/freemanan/example/AppTest.java b/examples/tracing/src/test/java/com/freemanan/example/AppTest.java deleted file mode 100644 index 00f474dc..00000000 --- a/examples/tracing/src/test/java/com/freemanan/example/AppTest.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.freemanan.example; - -class AppTest {} diff --git a/examples/json-transcoder/webflux/build.gradle b/examples/transcoding/webflux/build.gradle similarity index 66% rename from examples/json-transcoder/webflux/build.gradle rename to examples/transcoding/webflux/build.gradle index 2e216b63..226a385d 100644 --- a/examples/json-transcoder/webflux/build.gradle +++ b/examples/transcoding/webflux/build.gradle @@ -7,7 +7,10 @@ dependencies { implementation(project(":grpc-starters:grpc-server-boot-starter")){ exclude(group: 'io.grpc', module: "grpc-netty-shaded") } - implementation(project(":grpc-starters:grpc-starter-webflux")) + implementation("io.grpc:grpc-netty") + implementation(project(":grpc-starters:grpc-starter-transcoding-webflux")) testImplementation("org.springframework.boot:spring-boot-starter-test") } + +apply from: "${rootDir}/gradle/protobuf.gradle" diff --git a/examples/transcoding/webflux/src/main/java/grpcstarter/example/TranscodingWebFluxApp.java b/examples/transcoding/webflux/src/main/java/grpcstarter/example/TranscodingWebFluxApp.java new file mode 100644 index 00000000..d12348e0 --- /dev/null +++ b/examples/transcoding/webflux/src/main/java/grpcstarter/example/TranscodingWebFluxApp.java @@ -0,0 +1,53 @@ +package grpcstarter.example; + +import static grpcstarter.server.GrpcContextKeys.ResponseMetadataModifier; +import static transcoding.flux.SimpleServiceGrpc.SimpleServiceImplBase; +import static transcoding.flux.Simpleservice.SimpleRequest; +import static transcoding.flux.Simpleservice.SimpleResponse; + +import io.grpc.Metadata; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import io.grpc.stub.StreamObserver; +import lombok.SneakyThrows; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Freeman + */ +@SpringBootApplication +public class TranscodingWebFluxApp extends SimpleServiceImplBase { + + public static void main(String[] args) { + SpringApplication.run(TranscodingWebFluxApp.class, args); + } + + @Override + public void unaryRpc(SimpleRequest request, StreamObserver r) { + if (request.getRequestMessage().contains("err")) { + var metadata = new Metadata(); + metadata.put(Metadata.Key.of("error", Metadata.ASCII_STRING_MARSHALLER), "invalid argument"); + throw new StatusRuntimeException(Status.INVALID_ARGUMENT, metadata); + } + + ResponseMetadataModifier.addConsumer( + metadata -> metadata.put(Metadata.Key.of("custom", Metadata.ASCII_STRING_MARSHALLER), "custom value")); + r.onNext(SimpleResponse.newBuilder() + .setResponseMessage("Hello " + request.getRequestMessage()) + .build()); + r.onCompleted(); + } + + @Override + @SneakyThrows + public void serverStreamingRpc(SimpleRequest request, StreamObserver r) { + for (int i = 0; i < 10; i++) { + r.onNext(SimpleResponse.newBuilder() + .setResponseMessage("message " + i) + .build()); + Thread.sleep(1000); + } + r.onCompleted(); + } +} diff --git a/examples/transcoding/webflux/src/main/proto/simpleservice.proto b/examples/transcoding/webflux/src/main/proto/simpleservice.proto new file mode 100644 index 00000000..4624292b --- /dev/null +++ b/examples/transcoding/webflux/src/main/proto/simpleservice.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; + +import "google/api/annotations.proto"; + +package transcoding.flux; + +// A simple service for test. +service SimpleService { + // Simple unary RPC. + rpc UnaryRpc (SimpleRequest) returns (SimpleResponse) { + option (google.api.http) = { + post: "/unary", + body: "*" + }; + } + + // Simple server-to-client streaming RPC. + rpc ServerStreamingRpc (SimpleRequest) returns (stream SimpleResponse) { + option (google.api.http) = { + get: "/serverstreaming" + }; + } +} + +// A simple request message type for test. +message SimpleRequest { + // An optional string message for test. + string requestMessage = 1; +} + +// A simple response message type for test. +message SimpleResponse { + // An optional string message for test. + string responseMessage = 1; +} \ No newline at end of file diff --git a/examples/transcoding/webflux/src/main/resources/application.yaml b/examples/transcoding/webflux/src/main/resources/application.yaml new file mode 100644 index 00000000..54c2759b --- /dev/null +++ b/examples/transcoding/webflux/src/main/resources/application.yaml @@ -0,0 +1,8 @@ +grpc: + server: + reflection: + enabled: true +spring: + webflux: + problemdetails: + enabled: true \ No newline at end of file diff --git a/examples/transcoding/webflux/src/test/java/grpcstarter/example/TranscodingFluxIT.java b/examples/transcoding/webflux/src/test/java/grpcstarter/example/TranscodingFluxIT.java new file mode 100644 index 00000000..8f9d175c --- /dev/null +++ b/examples/transcoding/webflux/src/test/java/grpcstarter/example/TranscodingFluxIT.java @@ -0,0 +1,37 @@ +package grpcstarter.example; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.HttpStatus; + +/** + * @author Freeman + */ +@SpringBootTest(webEnvironment = RANDOM_PORT) +class TranscodingFluxIT { + + @LocalServerPort + int port; + + @Autowired + TestRestTemplate rest; + + @Test + void testTranscoding() { + var response = + rest.postForEntity("http://localhost:" + port + "/unary", new SimpleRequest("foo"), String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getHeaders().getContentType()).hasToString("application/json"); + assertThat(response.getBody()).isEqualTo(""" + {"responseMessage":"Hello foo"}"""); + } + + record SimpleRequest(String requestMessage) {} +} diff --git a/examples/json-transcoder/webmvc/build.gradle b/examples/transcoding/webmvc/build.gradle similarity index 67% rename from examples/json-transcoder/webmvc/build.gradle rename to examples/transcoding/webmvc/build.gradle index 5284768b..9e9c01b9 100644 --- a/examples/json-transcoder/webmvc/build.gradle +++ b/examples/transcoding/webmvc/build.gradle @@ -5,7 +5,9 @@ plugins { dependencies { implementation(project(":examples:grpc-sample-api")) implementation(project(":grpc-starters:grpc-server-boot-starter")) - implementation(project(":grpc-starters:grpc-starter-web")) + implementation(project(":grpc-starters:grpc-starter-transcoding-webmvc")) testImplementation("org.springframework.boot:spring-boot-starter-test") } + +apply from: "${rootDir}/gradle/protobuf.gradle" diff --git a/examples/transcoding/webmvc/src/main/java/grpcstarter/example/TranscodingMvcApp.java b/examples/transcoding/webmvc/src/main/java/grpcstarter/example/TranscodingMvcApp.java new file mode 100644 index 00000000..5dceef14 --- /dev/null +++ b/examples/transcoding/webmvc/src/main/java/grpcstarter/example/TranscodingMvcApp.java @@ -0,0 +1,50 @@ +package grpcstarter.example; + +import static transcoding.mvc.SimpleServiceGrpc.SimpleServiceImplBase; + +import io.grpc.Metadata; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import io.grpc.stub.StreamObserver; +import lombok.SneakyThrows; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import transcoding.mvc.Simpleservice; +import transcoding.mvc.Simpleservice.SimpleRequest; + +/** + * @author Freeman + */ +@SpringBootApplication +public class TranscodingMvcApp extends SimpleServiceImplBase { + + public static void main(String[] args) { + SpringApplication.run(TranscodingMvcApp.class, args); + } + + @Override + public void unaryRpc(SimpleRequest request, StreamObserver r) { + if (request.getRequestMessage().contains("err")) { + var metadata = new Metadata(); + metadata.put(Metadata.Key.of("error", Metadata.ASCII_STRING_MARSHALLER), "invalid argument"); + throw new StatusRuntimeException(Status.INVALID_ARGUMENT, metadata); + } + + r.onNext(Simpleservice.SimpleResponse.newBuilder() + .setResponseMessage("Hello " + request.getRequestMessage()) + .build()); + r.onCompleted(); + } + + @Override + @SneakyThrows + public void serverStreamingRpc(SimpleRequest request, StreamObserver r) { + for (int i = 0; i < 10; i++) { + r.onNext(Simpleservice.SimpleResponse.newBuilder() + .setResponseMessage("message " + i) + .build()); + Thread.sleep(1000); + } + r.onCompleted(); + } +} diff --git a/examples/transcoding/webmvc/src/main/proto/simpleservice.proto b/examples/transcoding/webmvc/src/main/proto/simpleservice.proto new file mode 100644 index 00000000..82a8909d --- /dev/null +++ b/examples/transcoding/webmvc/src/main/proto/simpleservice.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; + +import "google/api/annotations.proto"; + +package transcoding.mvc; + +// A simple service for test. +service SimpleService { + // Simple unary RPC. + rpc UnaryRpc (SimpleRequest) returns (SimpleResponse) { + option (google.api.http) = { + post: "/unary", + body: "*" + }; + } + + // Simple server-to-client streaming RPC. + rpc ServerStreamingRpc (SimpleRequest) returns (stream SimpleResponse) { + option (google.api.http) = { + get: "/serverstreaming" + }; + } +} + +// A simple request message type for test. +message SimpleRequest { + // An optional string message for test. + string requestMessage = 1; +} + +// A simple response message type for test. +message SimpleResponse { + // An optional string message for test. + string responseMessage = 1; +} \ No newline at end of file diff --git a/examples/transcoding/webmvc/src/main/resources/application.yaml b/examples/transcoding/webmvc/src/main/resources/application.yaml new file mode 100644 index 00000000..f982bd41 --- /dev/null +++ b/examples/transcoding/webmvc/src/main/resources/application.yaml @@ -0,0 +1,8 @@ +grpc: + server: + reflection: + enabled: true +spring: + mvc: + problemdetails: + enabled: true \ No newline at end of file diff --git a/examples/transcoding/webmvc/src/test/java/grpcstarter/example/TranscodingMvcIT.java b/examples/transcoding/webmvc/src/test/java/grpcstarter/example/TranscodingMvcIT.java new file mode 100644 index 00000000..87b2fc7b --- /dev/null +++ b/examples/transcoding/webmvc/src/test/java/grpcstarter/example/TranscodingMvcIT.java @@ -0,0 +1,37 @@ +package grpcstarter.example; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.HttpStatus; + +/** + * @author Freeman + */ +@SpringBootTest(webEnvironment = RANDOM_PORT) +class TranscodingMvcIT { + + @LocalServerPort + int port; + + @Autowired + TestRestTemplate rest; + + @Test + void testTranscoding() { + var response = + rest.postForEntity("http://localhost:" + port + "/unary", new SimpleRequest("foo"), String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getHeaders().getContentType()).hasToString("application/json"); + assertThat(response.getBody()).isEqualTo(""" + {"responseMessage":"Hello foo"}"""); + } + + record SimpleRequest(String requestMessage) {} +} diff --git a/examples/user/user-api/build.gradle b/examples/user/user-api/build.gradle deleted file mode 100644 index 7c3c5095..00000000 --- a/examples/user/user-api/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -dependencies { - implementation(project(":grpc-starters:grpc-starter-validation")) -} - -apply from: "${rootDir}/gradle/protobuf-with-pgv.gradle" - -sourceSets { - main { - proto { - srcDir "proto" - } - } -} diff --git a/examples/user/user-api/proto/fm/user/v1/user.proto b/examples/user/user-api/proto/fm/user/v1/user.proto deleted file mode 100644 index 0e860325..00000000 --- a/examples/user/user-api/proto/fm/user/v1/user.proto +++ /dev/null @@ -1,22 +0,0 @@ -syntax = "proto3"; - -package fm.user.v1; - -import "google/protobuf/timestamp.proto"; -import "validate/validate.proto"; - -option java_package = "com.freemanan.user.v1.api"; -option java_multiple_files = true; - -message User { - string id = 1 [(validate.rules).string = {min_len: 1, max_len: 100}]; - string name = 2; -} - -service UserService { - rpc Create(User) returns (User) {} - rpc Read(User) returns (User) {} - rpc Update(User) returns (User) {} - rpc Delete(User) returns (User) {} - rpc List(User) returns (stream User) {} -} diff --git a/examples/user/user-server/src/main/java/com/freemanan/example/controller/UserController.java b/examples/user/user-server/src/main/java/com/freemanan/example/controller/UserController.java deleted file mode 100644 index fcae272e..00000000 --- a/examples/user/user-server/src/main/java/com/freemanan/example/controller/UserController.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.freemanan.example.controller; - -import com.freemanan.user.v1.api.User; -import com.freemanan.user.v1.api.UserServiceGrpc; -import io.grpc.stub.StreamObserver; -import org.springframework.stereotype.Controller; - -/** - * @author Freeman - */ -@Controller -public class UserController extends UserServiceGrpc.UserServiceImplBase { - @Override - public void create(User request, StreamObserver responseObserver) { - super.create(request, responseObserver); - } - - @Override - public void read(User request, StreamObserver responseObserver) { - super.read(request, responseObserver); - } - - @Override - public void update(User request, StreamObserver responseObserver) { - super.update(request, responseObserver); - } - - @Override - public void delete(User request, StreamObserver responseObserver) { - super.delete(request, responseObserver); - } - - @Override - public void list(User request, StreamObserver responseObserver) { - responseObserver.onNext(User.newBuilder() - .setId(request.getId()) - .setName(request.getName() + " 0") - .build()); - responseObserver.onNext(User.newBuilder() - .setId(request.getId()) - .setName(request.getName() + " 1") - .build()); - responseObserver.onNext(User.newBuilder() - .setId(request.getId()) - .setName(request.getName() + " 2") - .build()); - responseObserver.onCompleted(); - } -} diff --git a/gradle.properties b/gradle.properties index cdaecab9..61be6060 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,25 +1,27 @@ group=io.github.danielliu1123 -version=3.2.5-RC1-SNAPSHOT +version=3.3.0-RC1-SNAPSHOT # Spring related -springBootVersion=3.2.4 +springBootVersion=3.3.0-RC1 springCloudVersion=2023.0.1 springDependencyManagementVersion=1.1.4 # gRPC related protobufGradlePluginVersion=0.9.4 -# required JDK 11 -bufGradlePluginVersion=0.9.0 -grpcVersion=1.62.2 -# see https://central.sonatype.com/artifact/io.grpc/grpc-protobuf/dependencies +grpcVersion=1.63.0 +# https://central.sonatype.com/artifact/com.google.api/api-common +googleApiCommonVersion=2.31.0 +# https://central.sonatype.com/artifact/io.grpc/grpc-protobuf/dependencies protobufVersion=3.25.1 pgvVersion=1.0.4 # https://github.com/bufbuild/protovalidate-java protovalidateVersion=0.2.1 # Code quality +# https://plugins.gradle.org/plugin/com.diffplug.gradle.spotless spotlessVersion=6.25.0 -spotbugsVersion=6.0.9 +# https://plugins.gradle.org/plugin/com.github.spotbugs +spotbugsVersion=6.0.13 spotbugsAnnotationsVersion=4.8.3 # Others diff --git a/gradle/protobuf.gradle b/gradle/protobuf.gradle index 57e66cd1..ce870952 100644 --- a/gradle/protobuf.gradle +++ b/gradle/protobuf.gradle @@ -1,4 +1,4 @@ -apply plugin: 'com.google.protobuf' +apply plugin: "com.google.protobuf" protobuf { protoc { diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Cache.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Cache.java similarity index 93% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Cache.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Cache.java index e8ece50c..76fc1529 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Cache.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Cache.java @@ -1,7 +1,7 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; -import static com.freemanan.starter.grpc.client.Util.serviceName; -import static com.freemanan.starter.grpc.client.Util.shutdownChannel; +import static grpcstarter.client.Util.serviceName; +import static grpcstarter.client.Util.shutdownChannel; import io.grpc.ManagedChannel; import java.time.Duration; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Checker.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Checker.java similarity index 94% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Checker.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Checker.java index ec99a428..a006ee95 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Checker.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Checker.java @@ -1,7 +1,7 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; -import static com.freemanan.starter.grpc.client.Util.matchPattern; -import static com.freemanan.starter.grpc.client.Util.matchStubConfig; +import static grpcstarter.client.Util.matchPattern; +import static grpcstarter.client.Util.matchStubConfig; import io.grpc.stub.AbstractStub; import java.util.List; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/ConditionOnGrpcClientEnabled.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/ConditionOnGrpcClientEnabled.java similarity index 93% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/ConditionOnGrpcClientEnabled.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/ConditionOnGrpcClientEnabled.java index 79b28e85..5ceec1ca 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/ConditionOnGrpcClientEnabled.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/ConditionOnGrpcClientEnabled.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.stub.AbstractStub; import java.lang.annotation.ElementType; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/EnableGrpcClients.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/EnableGrpcClients.java similarity index 97% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/EnableGrpcClients.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/EnableGrpcClients.java index 9ffbfc66..7dc92736 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/EnableGrpcClients.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/EnableGrpcClients.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.stub.AbstractStub; import java.lang.annotation.ElementType; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcChannelCreator.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcChannelCreator.java similarity index 97% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcChannelCreator.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcChannelCreator.java index c0695f13..e6eb93fa 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcChannelCreator.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcChannelCreator.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; -import com.freemanan.starter.grpc.client.exception.MissingChannelConfigurationException; +import grpcstarter.client.exception.MissingChannelConfigurationException; import io.grpc.ClientInterceptor; import io.grpc.Grpc; import io.grpc.ManagedChannel; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcChannelCustomizer.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcChannelCustomizer.java similarity index 93% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcChannelCustomizer.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcChannelCustomizer.java index c45b6d0f..048ac3fe 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcChannelCustomizer.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcChannelCustomizer.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.ManagedChannelBuilder; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientAutoConfiguration.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientAutoConfiguration.java similarity index 93% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientAutoConfiguration.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientAutoConfiguration.java index c2d4cb2f..fa1a3c48 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientAutoConfiguration.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientAutoConfiguration.java @@ -1,8 +1,8 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; -import static com.freemanan.starter.grpc.client.Checker.checkUnusedConfig; +import static grpcstarter.client.Checker.checkUnusedConfig; -import com.freemanan.starter.grpc.server.GrpcServerShutdownEvent; +import grpcstarter.server.GrpcServerShutdownEvent; import org.springframework.beans.factory.DisposableBean; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientCreator.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientCreator.java similarity index 99% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientCreator.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientCreator.java index 4b7f8bf0..fbf75fa5 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientCreator.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientCreator.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.Channel; import io.grpc.ManagedChannel; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientOptions.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientOptions.java similarity index 94% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientOptions.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientOptions.java index df7e712f..c3a1f473 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientOptions.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientOptions.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.CallOptions; import io.grpc.Channel; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientOptionsClientInterceptor.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientOptionsClientInterceptor.java similarity index 97% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientOptionsClientInterceptor.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientOptionsClientInterceptor.java index d1de8b66..bceffbd3 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientOptionsClientInterceptor.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientOptionsClientInterceptor.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.CallOptions; import io.grpc.Channel; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientProperties.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientProperties.java similarity index 99% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientProperties.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientProperties.java index 7fcee055..f2bdb3c0 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientProperties.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientProperties.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import static java.util.Objects.isNull; import static java.util.stream.Collectors.toMap; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientRefreshScopeRefreshedEventListener.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientRefreshScopeRefreshedEventListener.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientRefreshScopeRefreshedEventListener.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientRefreshScopeRefreshedEventListener.java index 7c421c51..760147f7 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientRefreshScopeRefreshedEventListener.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientRefreshScopeRefreshedEventListener.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.stub.AbstractStub; import java.util.Arrays; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientsRegistrar.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientsRegistrar.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientsRegistrar.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientsRegistrar.java index 96ae44b4..712e7412 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcClientsRegistrar.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientsRegistrar.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import java.util.Collections; import java.util.Map; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcStubBeanDefinitionRegistry.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcStubBeanDefinitionRegistry.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcStubBeanDefinitionRegistry.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcStubBeanDefinitionRegistry.java index 0911051b..f02c79b5 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcStubBeanDefinitionRegistry.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcStubBeanDefinitionRegistry.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcStubBeanRegistrar.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcStubBeanRegistrar.java similarity index 99% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcStubBeanRegistrar.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcStubBeanRegistrar.java index 00abe545..0657cc1e 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/GrpcStubBeanRegistrar.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcStubBeanRegistrar.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.stub.AbstractStub; import java.util.Arrays; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/ShutdownEventBasedChannelCloser.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/ShutdownEventBasedChannelCloser.java similarity index 81% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/ShutdownEventBasedChannelCloser.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/ShutdownEventBasedChannelCloser.java index bb6b2b49..b4036f33 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/ShutdownEventBasedChannelCloser.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/ShutdownEventBasedChannelCloser.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; -import com.freemanan.starter.grpc.server.GrpcServerShutdownEvent; +import grpcstarter.server.GrpcServerShutdownEvent; import org.springframework.context.ApplicationListener; /** diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Util.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Util.java similarity index 99% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Util.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Util.java index 4ef7db4c..dd79e833 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/Util.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Util.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import io.grpc.ManagedChannel; import java.lang.reflect.Field; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/exception/GrpcClientFailureAnalyzer.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/exception/GrpcClientFailureAnalyzer.java similarity index 96% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/exception/GrpcClientFailureAnalyzer.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/exception/GrpcClientFailureAnalyzer.java index ff0c7bcf..184744d3 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/exception/GrpcClientFailureAnalyzer.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/exception/GrpcClientFailureAnalyzer.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client.exception; +package grpcstarter.client.exception; import org.springframework.boot.diagnostics.AbstractFailureAnalyzer; import org.springframework.boot.diagnostics.FailureAnalysis; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/exception/MissingChannelConfigurationException.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/exception/MissingChannelConfigurationException.java similarity index 88% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/exception/MissingChannelConfigurationException.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/exception/MissingChannelConfigurationException.java index 73022894..6c05069b 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/client/exception/MissingChannelConfigurationException.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/exception/MissingChannelConfigurationException.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client.exception; +package grpcstarter.client.exception; import lombok.Getter; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/resources/META-INF/spring.factories index a322b40c..1c60a6ac 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ org.springframework.boot.diagnostics.FailureAnalyzer=\ - com.freemanan.starter.grpc.client.exception.GrpcClientFailureAnalyzer + grpcstarter.client.exception.GrpcClientFailureAnalyzer diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 4f3c1f86..906a81b2 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1 @@ -com.freemanan.starter.grpc.client.GrpcClientAutoConfiguration +grpcstarter.client.GrpcClientAutoConfiguration diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/DynamicRefreshTests.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/DynamicRefreshTests.java similarity index 90% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/DynamicRefreshTests.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/DynamicRefreshTests.java index ffff9910..6d3449c6 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/DynamicRefreshTests.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/DynamicRefreshTests.java @@ -1,14 +1,15 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import static org.assertj.core.api.Assertions.assertThat; -import com.freemanan.starter.grpc.extensions.test.NetUtil; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; import io.grpc.testing.protobuf.SimpleRequest; import io.grpc.testing.protobuf.SimpleResponse; import io.grpc.testing.protobuf.SimpleServiceGrpc; +import java.net.ServerSocket; +import lombok.SneakyThrows; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -23,8 +24,8 @@ */ class DynamicRefreshTests { - static int port1 = NetUtil.getRandomPort(); - static int port2 = NetUtil.getRandomPort(); + static int port1 = getRandomPort(); + static int port2 = getRandomPort(); static Server server1; static Server server2; @@ -88,4 +89,11 @@ public void unaryRpc(SimpleRequest request, StreamObserver respo }) .build(); } + + @SneakyThrows + private static int getRandomPort() { + try (ServerSocket ss = new ServerSocket(0)) { + return ss.getLocalPort(); + } + } } diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/GrpcClientAutoConfigurationTest.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/GrpcClientAutoConfigurationTest.java similarity index 97% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/GrpcClientAutoConfigurationTest.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/GrpcClientAutoConfigurationTest.java index fb678159..135b26bd 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/GrpcClientAutoConfigurationTest.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/GrpcClientAutoConfigurationTest.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import static org.assertj.core.api.Assertions.assertThat; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/GrpcClientIT.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/GrpcClientIT.java similarity index 91% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/GrpcClientIT.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/GrpcClientIT.java index 2f5d8f9a..eaec9d35 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/GrpcClientIT.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/GrpcClientIT.java @@ -1,10 +1,10 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import static org.assertj.core.api.Assertions.assertThatCode; -import com.freemanan.sample.pet.v1.PetServiceGrpc; -import com.freemanan.starter.grpc.server.GrpcServerProperties; +import grpcstarter.server.GrpcServerProperties; import io.grpc.health.v1.HealthGrpc; +import io.grpc.testing.protobuf.SimpleServiceGrpc; import java.util.UUID; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -29,7 +29,7 @@ void testGrpcStubAutowired_whenNotConfigureBasePackages() { .run(); assertThatCode(() -> ctx.getBean(GrpcClientProperties.class)).doesNotThrowAnyException(); - assertThatCode(() -> ctx.getBean(PetServiceGrpc.PetServiceBlockingStub.class)) + assertThatCode(() -> ctx.getBean(SimpleServiceGrpc.SimpleServiceStub.class)) .isInstanceOf(NoSuchBeanDefinitionException.class); ctx.close(); @@ -40,11 +40,11 @@ void testGrpcStubAutowired_whenNotConfigureAuthority() { String name = UUID.randomUUID().toString(); ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Cfg.class) .properties(GrpcServerProperties.InProcess.PREFIX + ".name=" + name) - .properties(GrpcClientProperties.PREFIX + ".base-packages[0]=com") + .properties(GrpcClientProperties.PREFIX + ".base-packages[0]=io") .run(); assertThatCode(() -> ctx.getBean(GrpcClientProperties.class)).doesNotThrowAnyException(); - assertThatCode(() -> ctx.getBean(PetServiceGrpc.PetServiceBlockingStub.class)) + assertThatCode(() -> ctx.getBean(SimpleServiceGrpc.SimpleServiceStub.class)) .isInstanceOf(BeanCreationException.class) .rootCause() .hasMessageStartingWith("gRPC channel authority is not configured for stub"); @@ -58,11 +58,11 @@ void testGrpcStubAutowired_whenOK() { ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Cfg.class) .properties(GrpcServerProperties.InProcess.PREFIX + ".name=" + name) .properties(GrpcClientProperties.InProcess.PREFIX + ".name=" + name) - .properties(GrpcClientProperties.PREFIX + ".base-packages[0]=com") + .properties(GrpcClientProperties.PREFIX + ".base-packages[0]=io") .run(); assertThatCode(() -> ctx.getBean(GrpcClientProperties.class)).doesNotThrowAnyException(); - assertThatCode(() -> ctx.getBean(PetServiceGrpc.PetServiceBlockingStub.class)) + assertThatCode(() -> ctx.getBean(SimpleServiceGrpc.SimpleServiceStub.class)) .doesNotThrowAnyException(); ctx.close(); @@ -76,7 +76,7 @@ void testGrpcStubAutowired_whenDisableGrpcClient() { .run(); assertThatCode(() -> ctx.getBean(GrpcClientProperties.class)).isInstanceOf(NoSuchBeanDefinitionException.class); - assertThatCode(() -> ctx.getBean(PetServiceGrpc.PetServiceBlockingStub.class)) + assertThatCode(() -> ctx.getBean(SimpleServiceGrpc.SimpleServiceStub.class)) .isInstanceOf(NoSuchBeanDefinitionException.class); ctx.close(); diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/InProcessTest.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/InProcessTest.java similarity index 92% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/InProcessTest.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/InProcessTest.java index ccdee410..0e28e9b7 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/InProcessTest.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/InProcessTest.java @@ -1,9 +1,9 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; import static org.assertj.core.api.Assertions.assertThat; -import com.freemanan.starter.grpc.server.DefaultGrpcServer; -import com.freemanan.starter.grpc.server.GrpcService; +import grpcstarter.server.DefaultGrpcServer; +import grpcstarter.server.GrpcService; import io.grpc.Server; import io.grpc.stub.StreamObserver; import io.grpc.testing.protobuf.SimpleRequest; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/UtilTest.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/UtilTest.java similarity index 92% rename from grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/UtilTest.java rename to grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/UtilTest.java index bb669872..70709183 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/client/UtilTest.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/grpcstarter/client/UtilTest.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.client; +package grpcstarter.client; -import static com.freemanan.starter.grpc.client.Util.matchPattern; +import static grpcstarter.client.Util.matchPattern; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.Test; diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/issues/Issue23Test.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/issues/Issue23Test.java index 03822ada..25cd1a00 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/issues/Issue23Test.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/test/java/issues/Issue23Test.java @@ -1,16 +1,15 @@ package issues; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.util.ReflectionTestUtils.getField; -import com.freemanan.starter.grpc.client.EnableGrpcClients; +import grpcstarter.client.EnableGrpcClients; import io.grpc.health.v1.HealthGrpc; import io.grpc.testing.protobuf.SimpleServiceGrpc; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; -import org.springframework.test.util.ReflectionTestUtils; /** * @author Freeman @@ -20,20 +19,18 @@ class Issue23Test { @Test void testOneConfigCreateOneChannel() { - ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Cfg.class) + var ctx = new SpringApplicationBuilder(Cfg.class) .properties("grpc.client.authority=localhost:9090") .properties("grpc.server.enabled=false") .run(); - SimpleServiceGrpc.SimpleServiceBlockingStub simpleStub = - ctx.getBean(SimpleServiceGrpc.SimpleServiceBlockingStub.class); - SimpleServiceGrpc.SimpleServiceFutureStub simpleFutureStub = - ctx.getBean(SimpleServiceGrpc.SimpleServiceFutureStub.class); - HealthGrpc.HealthBlockingStub healthStub = ctx.getBean(HealthGrpc.HealthBlockingStub.class); + var simpleStub = ctx.getBean(SimpleServiceGrpc.SimpleServiceBlockingStub.class); + var simpleFutureStub = ctx.getBean(SimpleServiceGrpc.SimpleServiceFutureStub.class); + var healthStub = ctx.getBean(HealthGrpc.HealthBlockingStub.class); - assertThat(ReflectionTestUtils.getField(simpleStub, "channel")) - .isSameAs(ReflectionTestUtils.getField(simpleFutureStub, "channel")) - .isSameAs(ReflectionTestUtils.getField(healthStub, "channel")); + assertThat(getField(simpleStub, "channel")) + .isSameAs(getField(simpleFutureStub, "channel")) + .isSameAs(getField(healthStub, "channel")); ctx.close(); } diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/package-info.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/package-info.java deleted file mode 100644 index 24f12752..00000000 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/package-info.java +++ /dev/null @@ -1,15 +0,0 @@ -/** - * This package contains classes for exception handling. - * - *

Exception handling provides the following means: - *

    - *
  • implement {@link com.freemanan.starter.grpc.server.feature.exceptionhandling.GrpcExceptionResolver}
  • - *
  • {@code @GrpcAdvice} class with {@code GrpcExceptionHandler} annotated methods
  • - *
- */ -@NonNullApi -@NonNullFields -package com.freemanan.starter.grpc.server.feature.exceptionhandling; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/ConditionOnGrpcServerEnabled.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/ConditionOnGrpcServerEnabled.java similarity index 93% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/ConditionOnGrpcServerEnabled.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/ConditionOnGrpcServerEnabled.java index 20e48cfe..928c25b9 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/ConditionOnGrpcServerEnabled.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/ConditionOnGrpcServerEnabled.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import io.grpc.BindableService; import java.lang.annotation.ElementType; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/DefaultGrpcServer.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/DefaultGrpcServer.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/DefaultGrpcServer.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/DefaultGrpcServer.java index 81100fd6..8c9517fa 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/DefaultGrpcServer.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/DefaultGrpcServer.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.grpc.BindableService; @@ -9,6 +9,7 @@ import io.grpc.TlsServerCredentials; import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.internal.GrpcUtil; +import jakarta.annotation.Nullable; import java.io.IOException; import java.util.Optional; import java.util.concurrent.CountDownLatch; @@ -149,6 +150,12 @@ public int getPort() { return server.getPort(); } + @Nullable + @Override + public Object getServer() { + return server; + } + @Override public void stop() { if (isRunning.get()) { diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/DummyGrpcServer.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/DummyGrpcServer.java similarity index 83% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/DummyGrpcServer.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/DummyGrpcServer.java index 7f4b478a..1f9ce1b7 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/DummyGrpcServer.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/DummyGrpcServer.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; /** * Dummy gRPC server. @@ -32,4 +32,9 @@ public boolean isAutoStartup() { public int getPort() { return DUMMY_PORT; } + + @Override + public Object getServer() { + return null; + } } diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcContextKeys.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcContextKeys.java similarity index 92% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcContextKeys.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcContextKeys.java index f58a468b..77ff0587 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcContextKeys.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcContextKeys.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import io.grpc.Context; import io.grpc.Metadata; @@ -42,7 +42,7 @@ public static ResponseMetadataModifier get() { * * @param consumer {@link Consumer} to modify response headers/trailers */ - public static void addConsumers(Consumer consumer) { + public static void addConsumer(Consumer consumer) { ResponseMetadataModifier key = get(); if (key != null) { key.getConsumers().add(consumer); diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcRequestContext.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcRequestContext.java similarity index 94% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcRequestContext.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcRequestContext.java index edf3f3df..256c0938 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcRequestContext.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcRequestContext.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.grpc.Context; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcRequestContextServerInterceptor.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcRequestContextServerInterceptor.java similarity index 95% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcRequestContextServerInterceptor.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcRequestContextServerInterceptor.java index 858b67ce..eee95c32 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcRequestContextServerInterceptor.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcRequestContextServerInterceptor.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; -import static com.freemanan.starter.grpc.server.GrpcContextKeys.ResponseMetadataModifier; +import static grpcstarter.server.GrpcContextKeys.ResponseMetadataModifier; import io.grpc.Context; import io.grpc.Contexts; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServer.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServer.java similarity index 62% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServer.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServer.java index 12c69074..3fb7011b 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServer.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServer.java @@ -1,5 +1,6 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; +import jakarta.annotation.Nullable; import org.springframework.context.SmartLifecycle; /** @@ -13,4 +14,10 @@ public interface GrpcServer extends SmartLifecycle { * @return port number */ int getPort(); + + /** + * Get the server object. + */ + @Nullable + Object getServer(); } diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerAutoConfiguration.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerAutoConfiguration.java similarity index 81% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerAutoConfiguration.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerAutoConfiguration.java index dd5e1fb8..6b461f01 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerAutoConfiguration.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerAutoConfiguration.java @@ -1,11 +1,11 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; -import static com.freemanan.starter.grpc.server.Util.allInternalServices; +import static grpcstarter.server.Util.allInternalServices; -import com.freemanan.starter.grpc.server.feature.channelz.Channelz; -import com.freemanan.starter.grpc.server.feature.exceptionhandling.ExceptionHandling; -import com.freemanan.starter.grpc.server.feature.health.Health; -import com.freemanan.starter.grpc.server.feature.reflection.Reflection; +import grpcstarter.server.feature.channelz.Channelz; +import grpcstarter.server.feature.exceptionhandling.ExceptionHandling; +import grpcstarter.server.feature.health.Health; +import grpcstarter.server.feature.reflection.Reflection; import io.grpc.BindableService; import io.grpc.ServerBuilder; import io.grpc.ServerInterceptor; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerCustomizer.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerCustomizer.java similarity index 87% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerCustomizer.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerCustomizer.java index a5804afc..268f1585 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerCustomizer.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerCustomizer.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import io.grpc.ServerBuilder; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerProperties.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerProperties.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerProperties.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerProperties.java index a3d8ed55..05f3fdd8 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerProperties.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerProperties.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; -import com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation.DefaultGrpcExceptionAdvice; +import grpcstarter.server.feature.exceptionhandling.annotation.DefaultGrpcExceptionAdvice; import io.grpc.StatusException; import io.grpc.StatusRuntimeException; import io.grpc.TlsServerCredentials; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerShutdownEvent.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerShutdownEvent.java similarity index 90% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerShutdownEvent.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerShutdownEvent.java index 8a5091b9..49982848 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerShutdownEvent.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerShutdownEvent.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import io.grpc.Server; import org.springframework.context.ApplicationEvent; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerStartedEvent.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerStartedEvent.java similarity index 90% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerStartedEvent.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerStartedEvent.java index 0118ca7f..9226b115 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerStartedEvent.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerStartedEvent.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import io.grpc.Server; import org.springframework.context.ApplicationEvent; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerTerminatedEvent.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerTerminatedEvent.java similarity index 91% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerTerminatedEvent.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerTerminatedEvent.java index 9a568764..d7f24efe 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcServerTerminatedEvent.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerTerminatedEvent.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import io.grpc.Server; import org.springframework.context.ApplicationEvent; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcService.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcService.java similarity index 54% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcService.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcService.java index 956d43b2..d284a502 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/GrpcService.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcService.java @@ -1,24 +1,26 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; -import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Component; /** - * Alias for {@link Controller}, for gRPC service implementation. + * Mark a gRPC service implementation, an alias for {@link Component}. + * + *

This annotation is optional, can be replaced by any {@link Component} based annotation. * * @author Freeman */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -@Controller +@Component public @interface GrpcService { /** - * @see Controller#value() + * @see Component#value() */ - @AliasFor(annotation = Controller.class) + @AliasFor(annotation = Component.class) String value() default ""; } diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/Util.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/Util.java similarity index 96% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/Util.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/Util.java index d8e02045..139e9949 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/Util.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/Util.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import io.grpc.BindableService; import io.grpc.channelz.v1.ChannelzGrpc; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/channelz/Channelz.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/channelz/Channelz.java similarity index 88% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/channelz/Channelz.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/channelz/Channelz.java index 43b7b3de..ad99b189 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/channelz/Channelz.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/channelz/Channelz.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.server.feature.channelz; +package grpcstarter.server.feature.channelz; -import com.freemanan.starter.grpc.server.GrpcServerProperties; +import grpcstarter.server.GrpcServerProperties; import io.grpc.channelz.v1.ChannelzGrpc; import io.grpc.protobuf.services.ChannelzService; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandling.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandling.java similarity index 82% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandling.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandling.java index 232555a0..e748068c 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandling.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandling.java @@ -1,8 +1,8 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling; +package grpcstarter.server.feature.exceptionhandling; -import com.freemanan.starter.grpc.server.GrpcServerProperties; -import com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation.AnnotationBasedGrpcExceptionResolver; -import com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation.DefaultGrpcExceptionAdvice; +import grpcstarter.server.GrpcServerProperties; +import grpcstarter.server.feature.exceptionhandling.annotation.AnnotationBasedGrpcExceptionResolver; +import grpcstarter.server.feature.exceptionhandling.annotation.DefaultGrpcExceptionAdvice; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandlingServerInterceptor.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandlingServerInterceptor.java similarity index 95% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandlingServerInterceptor.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandlingServerInterceptor.java index b59bc9f5..9b72c5e6 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandlingServerInterceptor.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandlingServerInterceptor.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling; +package grpcstarter.server.feature.exceptionhandling; import io.grpc.Metadata; import io.grpc.ServerCall; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcExceptionHandlerListener.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcExceptionHandlerListener.java similarity index 96% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcExceptionHandlerListener.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcExceptionHandlerListener.java index 6d326e4e..255c86af 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcExceptionHandlerListener.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcExceptionHandlerListener.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling; +package grpcstarter.server.feature.exceptionhandling; import io.grpc.ForwardingServerCallListener.SimpleForwardingServerCallListener; import io.grpc.Metadata; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcExceptionResolver.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcExceptionResolver.java similarity index 89% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcExceptionResolver.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcExceptionResolver.java index c9451d3e..d21ddf74 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcExceptionResolver.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcExceptionResolver.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling; +package grpcstarter.server.feature.exceptionhandling; import io.grpc.Metadata; import io.grpc.ServerCall; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcUnhandledExceptionProcessor.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcUnhandledExceptionProcessor.java similarity index 86% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcUnhandledExceptionProcessor.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcUnhandledExceptionProcessor.java index efe98f20..efe1e2d7 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/GrpcUnhandledExceptionProcessor.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/GrpcUnhandledExceptionProcessor.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling; +package grpcstarter.server.feature.exceptionhandling; import io.grpc.Metadata; import io.grpc.ServerCall; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/AnnotationBasedGrpcExceptionResolver.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/AnnotationBasedGrpcExceptionResolver.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/AnnotationBasedGrpcExceptionResolver.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/AnnotationBasedGrpcExceptionResolver.java index 860a7fb1..a59b6db4 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/AnnotationBasedGrpcExceptionResolver.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/AnnotationBasedGrpcExceptionResolver.java @@ -1,10 +1,10 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation; +package grpcstarter.server.feature.exceptionhandling.annotation; import static java.util.Comparator.comparing; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.nullsLast; -import com.freemanan.starter.grpc.server.feature.exceptionhandling.GrpcExceptionResolver; +import grpcstarter.server.feature.exceptionhandling.GrpcExceptionResolver; import io.grpc.Metadata; import io.grpc.ServerCall; import io.grpc.Status; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/DefaultGrpcExceptionAdvice.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/DefaultGrpcExceptionAdvice.java similarity index 87% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/DefaultGrpcExceptionAdvice.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/DefaultGrpcExceptionAdvice.java index c5d8a422..c1172d2c 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/DefaultGrpcExceptionAdvice.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/DefaultGrpcExceptionAdvice.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation; +package grpcstarter.server.feature.exceptionhandling.annotation; import io.grpc.StatusException; import io.grpc.StatusRuntimeException; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcAdvice.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcAdvice.java similarity index 73% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcAdvice.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcAdvice.java index 36c9b62f..cede002f 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcAdvice.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcAdvice.java @@ -1,10 +1,12 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation; +package grpcstarter.server.feature.exceptionhandling.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.springframework.core.Ordered; import org.springframework.core.annotation.AliasFor; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** @@ -13,13 +15,13 @@ * *

Usually used with {@link GrpcExceptionHandler @GrpcExceptionHandler} together. * - *

{@link GrpcAdvice} can work with {@link org.springframework.core.annotation.Order} and {@link org.springframework.core.Ordered}, + *

{@link GrpcAdvice} can work with {@link Order} and {@link Ordered}, * exceptions will be handled in order. * * @author Freeman * @see GrpcExceptionHandler - * @see org.springframework.core.annotation.Order - * @see org.springframework.core.Ordered + * @see Order + * @see Ordered */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcExceptionHandler.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcExceptionHandler.java similarity index 95% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcExceptionHandler.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcExceptionHandler.java index 2a5f7752..076a67f1 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcExceptionHandler.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcExceptionHandler.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation; +package grpcstarter.server.feature.exceptionhandling.annotation; import io.grpc.Metadata; import io.grpc.ServerCall; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcExceptionHandlerMethod.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcExceptionHandlerMethod.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcExceptionHandlerMethod.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcExceptionHandlerMethod.java index 3c93f9fa..1e6d2698 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/GrpcExceptionHandlerMethod.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/annotation/GrpcExceptionHandlerMethod.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation; +package grpcstarter.server.feature.exceptionhandling.annotation; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.grpc.Metadata; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/package-info.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/package-info.java new file mode 100644 index 00000000..58eea821 --- /dev/null +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/exceptionhandling/package-info.java @@ -0,0 +1,10 @@ +/** + * This package contains classes for exception handling. + * + *

Exception handling provides the following means: + *

    + *
  • implement {@link grpcstarter.server.feature.exceptionhandling.GrpcExceptionResolver}
  • + *
  • {@code @GrpcAdvice} class with {@code GrpcExceptionHandler} annotated methods
  • + *
+ */ +package grpcstarter.server.feature.exceptionhandling; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/Health.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/Health.java similarity index 89% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/Health.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/Health.java index 8fef17ba..3b8af7b0 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/Health.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/Health.java @@ -1,8 +1,8 @@ -package com.freemanan.starter.grpc.server.feature.health; +package grpcstarter.server.feature.health; -import com.freemanan.starter.grpc.server.GrpcServerProperties; -import com.freemanan.starter.grpc.server.feature.health.datasource.DataSourceHealthChecker; -import com.freemanan.starter.grpc.server.feature.health.redis.RedisHealthChecker; +import grpcstarter.server.GrpcServerProperties; +import grpcstarter.server.feature.health.datasource.DataSourceHealthChecker; +import grpcstarter.server.feature.health.redis.RedisHealthChecker; import io.grpc.health.v1.HealthGrpc; import io.grpc.protobuf.services.HealthStatusManager; import org.springframework.beans.factory.ObjectProvider; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/HealthChecker.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/HealthChecker.java similarity index 83% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/HealthChecker.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/HealthChecker.java index 5f674fda..755d9fd4 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/HealthChecker.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/HealthChecker.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.health; +package grpcstarter.server.feature.health; /** * @author Freeman diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/HealthServerInterceptor.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/HealthServerInterceptor.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/HealthServerInterceptor.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/HealthServerInterceptor.java index 463d8d42..11b91363 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/HealthServerInterceptor.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/HealthServerInterceptor.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server.feature.health; +package grpcstarter.server.feature.health; import static io.grpc.protobuf.services.HealthStatusManager.SERVICE_NAME_ALL_SERVICES; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/datasource/DataSourceHealthChecker.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/datasource/DataSourceHealthChecker.java similarity index 91% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/datasource/DataSourceHealthChecker.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/datasource/DataSourceHealthChecker.java index bc92fa11..a4f00b2d 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/datasource/DataSourceHealthChecker.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/datasource/DataSourceHealthChecker.java @@ -1,7 +1,7 @@ -package com.freemanan.starter.grpc.server.feature.health.datasource; +package grpcstarter.server.feature.health.datasource; -import com.freemanan.starter.grpc.server.GrpcServerProperties; -import com.freemanan.starter.grpc.server.feature.health.HealthChecker; +import grpcstarter.server.GrpcServerProperties; +import grpcstarter.server.feature.health.HealthChecker; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.ArrayList; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/redis/RedisHealthChecker.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/redis/RedisHealthChecker.java similarity index 91% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/redis/RedisHealthChecker.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/redis/RedisHealthChecker.java index 6203467a..b90a6f90 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/health/redis/RedisHealthChecker.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/health/redis/RedisHealthChecker.java @@ -1,7 +1,7 @@ -package com.freemanan.starter.grpc.server.feature.health.redis; +package grpcstarter.server.feature.health.redis; -import com.freemanan.starter.grpc.server.GrpcServerProperties; -import com.freemanan.starter.grpc.server.feature.health.HealthChecker; +import grpcstarter.server.GrpcServerProperties; +import grpcstarter.server.feature.health.HealthChecker; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/reflection/Reflection.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/reflection/Reflection.java similarity index 88% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/reflection/Reflection.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/reflection/Reflection.java index fdd0ce35..3221a15b 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/com/freemanan/starter/grpc/server/feature/reflection/Reflection.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/feature/reflection/Reflection.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.server.feature.reflection; +package grpcstarter.server.feature.reflection; -import com.freemanan.starter.grpc.server.GrpcServerProperties; +import grpcstarter.server.GrpcServerProperties; import io.grpc.protobuf.services.ProtoReflectionService; import io.grpc.reflection.v1alpha.ServerReflectionGrpc; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 059a6073..3b70a4c1 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1 @@ -com.freemanan.starter.grpc.server.GrpcServerAutoConfiguration \ No newline at end of file +grpcstarter.server.GrpcServerAutoConfiguration \ No newline at end of file diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/ChannelzIT.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/ChannelzIT.java similarity index 97% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/ChannelzIT.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/ChannelzIT.java index 310fd315..95bf93e0 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/ChannelzIT.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/ChannelzIT.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import static org.assertj.core.api.Assertions.assertThatCode; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GracefulShutdownIT.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GracefulShutdownIT.java similarity index 95% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GracefulShutdownIT.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GracefulShutdownIT.java index 30ace0ab..bedeb86f 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GracefulShutdownIT.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GracefulShutdownIT.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; -import static com.freemanan.starter.grpc.extensions.test.StubUtil.createStub; +import static grpcstarter.extensions.test.StubUtil.createStub; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceBlockingStub; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceImplBase; import static org.assertj.core.api.Assertions.assertThat; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GrpcResponseMetadataModifierIT.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GrpcResponseMetadataModifierIT.java similarity index 91% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GrpcResponseMetadataModifierIT.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GrpcResponseMetadataModifierIT.java index 64baa3d5..4ab69c6d 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GrpcResponseMetadataModifierIT.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GrpcResponseMetadataModifierIT.java @@ -1,13 +1,13 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; -import static com.freemanan.starter.grpc.server.GrpcContextKeys.ResponseMetadataModifier; +import static grpcstarter.server.GrpcContextKeys.ResponseMetadataModifier; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceBlockingStub; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceImplBase; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; -import com.freemanan.starter.grpc.extensions.test.InProcessName; -import com.freemanan.starter.grpc.extensions.test.StubUtil; +import grpcstarter.extensions.test.InProcessName; +import grpcstarter.extensions.test.StubUtil; import io.grpc.Metadata; import io.grpc.Status; import io.grpc.StatusRuntimeException; @@ -76,7 +76,7 @@ public void unaryRpc(SimpleRequest request, StreamObserver respo .setResponseMessage(request.getRequestMessage()) .build(); - ResponseMetadataModifier.addConsumers( + ResponseMetadataModifier.addConsumer( metadata -> metadata.put(Metadata.Key.of("status", Metadata.ASCII_STRING_MARSHALLER), "ok")); responseObserver.onNext(response); diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GrpcServerIT.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GrpcServerIT.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GrpcServerIT.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GrpcServerIT.java index 0329425c..6e4bdba9 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/GrpcServerIT.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/GrpcServerIT.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/HealthIT.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/HealthIT.java similarity index 97% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/HealthIT.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/HealthIT.java index 2bf03c34..adf49b58 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/HealthIT.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/HealthIT.java @@ -1,11 +1,11 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import static io.grpc.health.v1.HealthCheckResponse.ServingStatus; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import com.freemanan.starter.grpc.server.feature.health.HealthChecker; +import grpcstarter.server.feature.health.HealthChecker; import io.grpc.ManagedChannel; import io.grpc.StatusRuntimeException; import io.grpc.health.v1.HealthCheckRequest; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/InProcessTest.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/InProcessTest.java similarity index 98% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/InProcessTest.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/InProcessTest.java index 7df8efc2..3bb38964 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/InProcessTest.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/InProcessTest.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import static org.assertj.core.api.Assertions.assertThat; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/MaxResponseLengthIT.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/MaxResponseLengthIT.java similarity index 94% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/MaxResponseLengthIT.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/MaxResponseLengthIT.java index 7ed93495..4c78cf05 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/MaxResponseLengthIT.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/MaxResponseLengthIT.java @@ -1,12 +1,12 @@ -package com.freemanan.starter.grpc.server; +package grpcstarter.server; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceBlockingStub; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceImplBase; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; -import com.freemanan.starter.grpc.extensions.test.InProcessName; -import com.freemanan.starter.grpc.extensions.test.StubUtil; +import grpcstarter.extensions.test.InProcessName; +import grpcstarter.extensions.test.StubUtil; import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandlingTests.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandlingTests.java similarity index 85% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandlingTests.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandlingTests.java index e1f41dba..9f187e4c 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/ExceptionHandlingTests.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/feature/exceptionhandling/ExceptionHandlingTests.java @@ -1,9 +1,9 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling; +package grpcstarter.server.feature.exceptionhandling; import static org.assertj.core.api.Assertions.assertThat; -import com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation.AnnotationBasedGrpcExceptionResolver; -import com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation.DefaultGrpcExceptionAdvice; +import grpcstarter.server.feature.exceptionhandling.annotation.AnnotationBasedGrpcExceptionResolver; +import grpcstarter.server.feature.exceptionhandling.annotation.DefaultGrpcExceptionAdvice; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.runner.ApplicationContextRunner; diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/AnnotationBasedExceptionHandlingIT.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/feature/exceptionhandling/annotation/AnnotationBasedExceptionHandlingIT.java similarity index 95% rename from grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/AnnotationBasedExceptionHandlingIT.java rename to grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/feature/exceptionhandling/annotation/AnnotationBasedExceptionHandlingIT.java index 7b3d876a..b348b2df 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/com/freemanan/starter/grpc/server/feature/exceptionhandling/annotation/AnnotationBasedExceptionHandlingIT.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/test/java/grpcstarter/server/feature/exceptionhandling/annotation/AnnotationBasedExceptionHandlingIT.java @@ -1,13 +1,13 @@ -package com.freemanan.starter.grpc.server.feature.exceptionhandling.annotation; +package grpcstarter.server.feature.exceptionhandling.annotation; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceBlockingStub; import static io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceImplBase; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; -import com.freemanan.starter.grpc.extensions.test.InProcessName; -import com.freemanan.starter.grpc.extensions.test.StubUtil; -import com.freemanan.starter.grpc.server.GrpcService; +import grpcstarter.extensions.test.InProcessName; +import grpcstarter.extensions.test.StubUtil; +import grpcstarter.server.GrpcService; import io.grpc.Metadata; import io.grpc.ServerCall; import io.grpc.Status; diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/AbstractHandlerAdaptor.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/AbstractHandlerAdaptor.java deleted file mode 100644 index 29fcd803..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/AbstractHandlerAdaptor.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder; - -import com.freemanan.starter.grpc.server.GrpcServerProperties; -import com.freemanan.starter.grpc.server.GrpcServerShutdownEvent; -import com.freemanan.starter.grpc.server.GrpcServerStartedEvent; -import com.google.protobuf.Message; -import com.google.protobuf.util.JsonFormat; -import io.grpc.BindableService; -import io.grpc.Channel; -import io.grpc.ClientInterceptor; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.stub.AbstractStub; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.core.Ordered; -import org.springframework.http.HttpStatus; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; -import org.springframework.util.unit.DataSize; -import org.springframework.web.server.ResponseStatusException; - -/** - * @author Freeman - */ -public abstract class AbstractHandlerAdaptor - implements ApplicationListener, BeanFactoryAware, Ordered { - private static final Logger log = LoggerFactory.getLogger(AbstractHandlerAdaptor.class); - - public static final int ORDER = 0; - private static final String GET_DEFAULT_INSTANCE = "getDefaultInstance"; - private static final Method withInterceptorsMethod; - private static final JsonFormat.Parser parser = JsonFormat.parser().ignoringUnknownFields(); - - static { - withInterceptorsMethod = getWithInterceptorsMethod(); - } - - private final Map, Object> beanClassToStub = new ConcurrentHashMap<>(); - /** - * key: stubClassName#methodName - */ - private final Map keyToMethod = new ConcurrentHashMap<>(); - - private final Map, Message> messageClassToDefaultInstance = new ConcurrentHashMap<>(); - protected BeanFactory beanFactory; - private ManagedChannel channel; - - private static Method doGetStubMethod(Object stubToUse, Method method, Message msg) { - try { - return stubToUse.getClass().getMethod(method.getName(), msg.getClass()); - } catch (NoSuchMethodException e) { - throw new IllegalStateException(e); - } - } - - private static Class getImplBeanClass(Class beanClass) { - Class superclass = beanClass.getSuperclass(); - if (Arrays.stream(superclass.getInterfaces()).anyMatch(clz -> clz == BindableService.class)) { - return superclass; - } - return getImplBeanClass(superclass); - } - - private static Method getWithInterceptorsMethod() { - try { - return AbstractStub.class.getMethod("withInterceptors", ClientInterceptor[].class); - } catch (NoSuchMethodException e) { - throw new IllegalStateException(e); - } - } - - protected Object applyInterceptor4Stub(ClientInterceptor clientInterceptor, Object stub) { - try { - return withInterceptorsMethod.invoke(stub, (Object) new ClientInterceptor[] {clientInterceptor}); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new IllegalStateException(e); - } - } - - protected Message convert2ProtobufMessage(Class messageClass, InputStream is) { - Message defaultInstance = messageClassToDefaultInstance.computeIfAbsent(messageClass, k -> { - try { - return ((Message) messageClass.getMethod(GET_DEFAULT_INSTANCE).invoke(null)); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - if (log.isWarnEnabled()) { - log.warn("Failed to invoke method '{}' of class {}", GET_DEFAULT_INSTANCE, messageClass, e); - } - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage(), e); - } - }); - - Message.Builder builder = defaultInstance.toBuilder(); - try (InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) { - parser.merge(reader, builder); - return builder.build(); - } catch (IOException e) { - if (log.isWarnEnabled()) { - log.warn("Failed to parse JSON to Message {}", messageClass, e); - } - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage(), e); - } - } - - protected Object doGetStub(Class beanClass) { - Class grpcClass = getImplBeanClass(beanClass).getEnclosingClass(); - try { - return ReflectionUtils.invokeMethod( - grpcClass.getMethod(getNewStubMethodName(), Channel.class), null, channel); - } catch (NoSuchMethodException e) { - throw new IllegalStateException(e); - } - } - - protected Method getInvokeMethod(Object stubToUse, Method method, Message msg) { - String key = stubToUse.getClass().getCanonicalName() + "#" + method.getName(); - return keyToMethod.computeIfAbsent(key, k -> doGetStubMethod(stubToUse, method, msg)); - } - - protected Object getStub(Class beanClass) { - return beanClassToStub.computeIfAbsent(beanClass, this::doGetStub); - } - - public abstract String getNewStubMethodName(); - - @Override - public int getOrder() { - return ORDER; - } - - @Override - public void onApplicationEvent(ApplicationEvent event) { - if (event instanceof GrpcServerStartedEvent) { - onGrpcServerStartedEvent((GrpcServerStartedEvent) event); - } - if (event instanceof GrpcServerShutdownEvent && channel != null) { - channel.shutdown(); - } - } - - private void onGrpcServerStartedEvent(GrpcServerStartedEvent event) { - GrpcServerProperties properties = beanFactory.getBean(GrpcServerProperties.class); - boolean usingInProcess = properties.getInProcess() != null - && StringUtils.hasText(properties.getInProcess().getName()); - - ManagedChannelBuilder builder = usingInProcess - ? ManagedChannelBuilder.forTarget(properties.getInProcess().getName()) - : ManagedChannelBuilder.forAddress( - "127.0.0.1", event.getSource().getPort()); - - Optional.ofNullable(properties.getMaxInboundMessageSize()) - .map(DataSize::toBytes) - .map(Long::intValue) - .ifPresent(builder::maxInboundMessageSize); - Optional.ofNullable(properties.getMaxInboundMetadataSize()) - .map(DataSize::toBytes) - .map(Long::intValue) - .ifPresent(builder::maxInboundMetadataSize); - - builder.usePlaintext(); - - setChannel(builder); - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; - } - - /** - * Give a chance to customize the channel. - * - * @param builder ManagedChannelBuilder - */ - protected void setChannel(ManagedChannelBuilder builder) { - this.channel = builder.build(); - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/DefaultGrpcHeaderConverter.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/DefaultGrpcHeaderConverter.java deleted file mode 100644 index be2df02d..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/DefaultGrpcHeaderConverter.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import io.grpc.Metadata; -import io.grpc.internal.GrpcUtil; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import org.springframework.http.HttpHeaders; -import org.springframework.util.ReflectionUtils; - -/** - * @author Freeman - */ -public class DefaultGrpcHeaderConverter implements GrpcHeaderConverter { - - private final Set removeHeaders; - - @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") - public DefaultGrpcHeaderConverter() { - this.removeHeaders = getRemoveHeaders(); - } - - @Override - public Metadata toRequestMetadata(HttpHeaders headers) { - // remove http internal headers - new HashSet<>(headers.keySet()).stream().filter(removeHeaderPredicate()).forEach(headers::remove); - - Metadata metadata = new Metadata(); - headers.forEach((k, values) -> { - Metadata.Key key = Metadata.Key.of(k, Metadata.ASCII_STRING_MARSHALLER); - values.forEach(v -> metadata.put(key, v)); - }); - return metadata; - } - - @Override - public HttpHeaders toResponseHeader(Metadata headers) { - // remove grpc internal headers - new HashSet<>(headers.keys()) - .stream() - .filter(removeMetadataPredicate()) - .forEach(key -> headers.removeAll(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER))); - - // remove content-type - headers.removeAll(GrpcUtil.CONTENT_TYPE_KEY); - - HttpHeaders result = new HttpHeaders(); - headers.keys().forEach(key -> Optional.ofNullable( - headers.getAll(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER))) - .ifPresent(values -> values.forEach(value -> result.add(key, value)))); - return result; - } - - protected Set getRemoveHeaders() { - Set headerKeys = findPublicStaticFinalStringFieldNames(HttpHeaders.class); - Set result = new TreeSet<>(headerKeys); - - // do not remove cookies - result.removeIf(HttpHeaders.COOKIE::equalsIgnoreCase); - return result; - } - - protected static Set findPublicStaticFinalStringFieldNames(Class clazz) { - return Arrays.stream(clazz.getDeclaredFields()) - .filter(f -> Modifier.isPublic(f.getModifiers()) - && Modifier.isStatic(f.getModifiers()) - && Modifier.isFinal(f.getModifiers()) - && f.getType() == String.class) - .map(f -> ReflectionUtils.getField(f, null)) - .filter(Objects::nonNull) - .map(Object::toString) - .collect(Collectors.toSet()); - } - - protected Predicate removeHeaderPredicate() { - return key -> removeHeaders.stream().anyMatch(key::equalsIgnoreCase); - } - - protected Predicate removeMetadataPredicate() { - return key -> key.toLowerCase().startsWith("grpc-"); - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/FutureAdapter.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/FutureAdapter.java deleted file mode 100644 index 2ac0efe3..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/FutureAdapter.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import java.util.concurrent.CompletableFuture; - -/** - * {@link CompletableFuture} adapter for {@link ListenableFuture}. - * - * @param The type of the future result - */ -public class FutureAdapter { - - private final CompletableFuture completableFuture; - - private FutureAdapter(ListenableFuture listenableFuture) { - this.completableFuture = new CompletableFuture() { - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - boolean cancelled = listenableFuture.cancel(mayInterruptIfRunning); - super.cancel(cancelled); - return cancelled; - } - }; - - Futures.addCallback( - listenableFuture, - new FutureCallback() { - @Override - public void onSuccess(T result) { - completableFuture.complete(result); - } - - @Override - public void onFailure(Throwable ex) { - completableFuture.completeExceptionally(ex); - } - }, - directExecutor()); - } - - private CompletableFuture getCompletableFuture() { - return completableFuture; - } - - /** - * Converts a {@link ListenableFuture} to a {@link CompletableFuture}. - * - * @param listenableFuture The listenable future to adapt - * @param The type of the future result - * @return The adapted {@link CompletableFuture} - */ - public static CompletableFuture toCompletable(ListenableFuture listenableFuture) { - FutureAdapter listenableFutureAdapter = new FutureAdapter<>(listenableFuture); - return listenableFutureAdapter.getCompletableFuture(); - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcJsonTranscoderAutoConfiguration.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcJsonTranscoderAutoConfiguration.java deleted file mode 100644 index 3db0cc93..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcJsonTranscoderAutoConfiguration.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder; - -import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.REACTIVE; -import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.SERVLET; - -import com.freemanan.starter.grpc.extensions.jsontranscoder.web.WebMvcGrpcServiceHandlerMapping; -import com.freemanan.starter.grpc.extensions.jsontranscoder.web.WebMvcProtobufHandlerAdaptor; -import com.freemanan.starter.grpc.extensions.jsontranscoder.webflux.GrpcHandlerResultHandler; -import com.freemanan.starter.grpc.extensions.jsontranscoder.webflux.WebFluxGrpcServiceHandlerMapping; -import com.freemanan.starter.grpc.extensions.jsontranscoder.webflux.WebFluxProtobufHandlerAdaptor; -import io.grpc.BindableService; -import io.grpc.Metadata; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.http.HttpHeaders; -import org.springframework.http.codec.ServerCodecConfigurer; - -/** - * @author Freeman - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnClass({Metadata.class, HttpHeaders.class}) -@ConditionalOnProperty(prefix = GrpcJsonTranscoderProperties.PREFIX, name = "enabled", matchIfMissing = true) -@EnableConfigurationProperties(GrpcJsonTranscoderProperties.class) -public class GrpcJsonTranscoderAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public GrpcHeaderConverter defaultGrpcHeaderConverter() { - return new DefaultGrpcHeaderConverter(); - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnWebApplication(type = SERVLET) - static class WebMvc { - - @Bean - @ConditionalOnMissingBean - public WebMvcGrpcServiceHandlerMapping webMvcGrpcServiceHandlerMapping( - ObjectProvider grpcServices) { - return new WebMvcGrpcServiceHandlerMapping(grpcServices); - } - - @Bean - @ConditionalOnMissingBean - public WebMvcProtobufHandlerAdaptor webMvcProtobufHandlerAdaptor(GrpcHeaderConverter grpcHeaderConverter) { - return new WebMvcProtobufHandlerAdaptor(grpcHeaderConverter); - } - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnWebApplication(type = REACTIVE) - static class WebFlux { - - @Bean - @ConditionalOnMissingBean - public WebFluxGrpcServiceHandlerMapping webFluxGrpcServiceHandlerMapping( - ObjectProvider grpcServices) { - return new WebFluxGrpcServiceHandlerMapping(grpcServices); - } - - @Bean - @ConditionalOnMissingBean - public WebFluxProtobufHandlerAdaptor webFluxProtobufHandlerAdaptor( - @Qualifier("webFluxAdapterRegistry") ReactiveAdapterRegistry reactiveAdapterRegistry, - ServerCodecConfigurer serverCodecConfigurer, - ConfigurableApplicationContext applicationContext, - GrpcHeaderConverter grpcHeaderConverter) { - return new WebFluxProtobufHandlerAdaptor( - reactiveAdapterRegistry, - applicationContext, - serverCodecConfigurer.getReaders(), - grpcHeaderConverter); - } - - @Bean - @ConditionalOnMissingBean - public GrpcHandlerResultHandler grpcHandlerResultHandler() { - return new GrpcHandlerResultHandler(); - } - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcJsonTranscoderProperties.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcJsonTranscoderProperties.java deleted file mode 100644 index 982d8a41..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcJsonTranscoderProperties.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * @author Freeman - */ -@Data -@ConfigurationProperties(GrpcJsonTranscoderProperties.PREFIX) -public class GrpcJsonTranscoderProperties { - public static final String PREFIX = "grpc.json-transcoder"; - - /** - * Whether to enable transcoder-json auto-configuration, default {@code true}. - */ - private boolean enabled = true; -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/GrpcUtil.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/GrpcUtil.java deleted file mode 100644 index d21a83b2..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/GrpcUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.util; - -import io.grpc.Status; -import lombok.experimental.UtilityClass; -import org.springframework.http.HttpStatus; - -/** - * @author Freeman - */ -@UtilityClass -public class GrpcUtil { - - /** - * Convert gRPC status to http status. - * - * @param grpcStatus grpc status - * @return http status - * @see statuscodes - */ - public static HttpStatus toHttpStatus(Status grpcStatus) { - switch (grpcStatus.getCode()) { - case OK: - return HttpStatus.OK; - case CANCELLED: - return HttpStatus.BAD_REQUEST; // NOTE: 499 is non-standard http/1.1 code, use 400 instead - case UNKNOWN: - return HttpStatus.INTERNAL_SERVER_ERROR; - case INVALID_ARGUMENT: - return HttpStatus.BAD_REQUEST; - case DEADLINE_EXCEEDED: - return HttpStatus.GATEWAY_TIMEOUT; - case NOT_FOUND: - return HttpStatus.NOT_FOUND; - case ALREADY_EXISTS: - return HttpStatus.CONFLICT; - case PERMISSION_DENIED: - return HttpStatus.FORBIDDEN; - case RESOURCE_EXHAUSTED: - return HttpStatus.TOO_MANY_REQUESTS; - case FAILED_PRECONDITION: - return HttpStatus.BAD_REQUEST; - case ABORTED: - return HttpStatus.CONFLICT; - case OUT_OF_RANGE: - return HttpStatus.BAD_REQUEST; - case UNIMPLEMENTED: - return HttpStatus.NOT_IMPLEMENTED; - case INTERNAL: - return HttpStatus.INTERNAL_SERVER_ERROR; - case UNAVAILABLE: - return HttpStatus.SERVICE_UNAVAILABLE; - case DATA_LOSS: - return HttpStatus.INTERNAL_SERVER_ERROR; - case UNAUTHENTICATED: - return HttpStatus.UNAUTHORIZED; - default: - return HttpStatus.INTERNAL_SERVER_ERROR; - } - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/JsonTranscoderUtil.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/JsonTranscoderUtil.java deleted file mode 100644 index 0610a222..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/JsonTranscoderUtil.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.util; - -import static io.grpc.MethodDescriptor.MethodType.UNARY; - -import com.google.protobuf.Message; -import io.grpc.BindableService; -import io.grpc.ServerMethodDefinition; -import io.grpc.stub.StreamObserver; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import lombok.experimental.UtilityClass; -import org.springframework.aop.framework.AopProxyUtils; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.http.HttpHeaders; -import org.springframework.http.InvalidMediaTypeException; -import org.springframework.http.MediaType; -import org.springframework.util.CollectionUtils; -import org.springframework.util.MimeTypeUtils; -import org.springframework.util.ReflectionUtils; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.server.NotAcceptableStatusException; - -/** - * @author Freeman - */ -@UtilityClass -public class JsonTranscoderUtil { - - public static boolean isUnaryGrpcMethod(Method method) { - return method.getParameterCount() == 2 - && Message.class.isAssignableFrom(method.getParameterTypes()[0]) - && StreamObserver.class.isAssignableFrom(method.getParameterTypes()[1]); - } - - private static Method findMethod(BindableService service, String fullMethodName) { - ServerMethodDefinition smd = service.bindService().getMethod(fullMethodName); - if (smd == null) { - return null; - } - if (smd.getMethodDescriptor().getType() != UNARY) { - // only support unary method ! - return null; - } - String methodName = smd.getMethodDescriptor().getBareMethodName(); - if (methodName == null) { - return null; - } - Method[] methods = ReflectionUtils.getAllDeclaredMethods(AopProxyUtils.ultimateTargetClass(service)); - for (Method method : methods) { - if (isUnaryGrpcMethod(method) && method.getName().equalsIgnoreCase(methodName)) { - return method; - } - } - return null; - } - - public static Map getPathToMethod(ObjectProvider grpcServiceProvider) { - return grpcServiceProvider.stream() - .map(bs -> Tuple2.of(bs.bindService(), bs)) - .flatMap(en -> en.getT1().getMethods().stream() - .map(m -> Tuple2.of(m.getMethodDescriptor().getFullMethodName(), en.getT2()))) - .map(en -> Tuple3.of(en.getT1(), en.getT2(), findMethod(en.getT2(), en.getT1()))) - .filter(en -> en.getT3() != null) - .map(en -> Tuple2.of("/" + en.getT1(), new HandlerMethod(en.getT2(), en.getT3()))) - .collect(Collectors.toMap(Tuple2::getT1, Tuple2::getT2)); - } - - public static boolean isGrpcHandleMethod(Object handler) { - return handler instanceof HandlerMethod && isUnaryGrpcMethod(((HandlerMethod) handler).getMethod()); - } - - /** - * @param json json string - * @return true if json string is a json object or json array - */ - public static boolean isJson(String json) { - return (json.startsWith("{") && json.endsWith("}")) || (json.startsWith("[") && json.endsWith("]")); - } - - public static List getAccept(HttpHeaders headers) { - try { - List mediaTypes = headers.getAccept(); - MimeTypeUtils.sortBySpecificity(mediaTypes); - return !CollectionUtils.isEmpty(mediaTypes) ? mediaTypes : Collections.singletonList(MediaType.ALL); - } catch (InvalidMediaTypeException ex) { - String value = headers.getFirst(HttpHeaders.ACCEPT); - throw new NotAcceptableStatusException( - "Could not parse 'Accept' header [" + value + "]: " + ex.getMessage()); - } - } - - public static boolean anyCompatible(List mediaTypes, MediaType otherMediaType) { - for (MediaType mediaType : mediaTypes) { - if (mediaType.isCompatibleWith(otherMediaType)) { - return true; - } - } - return false; - } - - public static NotAcceptableStatusException notAcceptableException() { - return new NotAcceptableStatusException("Could not find acceptable representation"); - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/ProtoUtil.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/ProtoUtil.java deleted file mode 100644 index e6af07d7..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/ProtoUtil.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.util; - -import com.google.protobuf.BoolValue; -import com.google.protobuf.BytesValue; -import com.google.protobuf.DoubleValue; -import com.google.protobuf.FloatValue; -import com.google.protobuf.Int32Value; -import com.google.protobuf.Int64Value; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.Message; -import com.google.protobuf.StringValue; -import com.google.protobuf.UInt32Value; -import com.google.protobuf.UInt64Value; -import com.google.protobuf.Value; -import com.google.protobuf.util.JsonFormat; -import lombok.experimental.UtilityClass; - -/** - * @author Freeman - */ -@UtilityClass -public class ProtoUtil { - - private static final JsonFormat.Printer printer = JsonFormat.printer().omittingInsignificantWhitespace(); - - /** - * Check if protobuf message is simple value. - * - * @param message protobuf message - * @return true if message is simple value - */ - public static boolean isSimpleValueMessage(Message message) { - if (isWrapperType(message.getClass())) { - return true; - } - if (message instanceof Value) { - Value value = (Value) message; - Value.KindCase kind = value.getKindCase(); - return kind == Value.KindCase.NULL_VALUE - || kind == Value.KindCase.NUMBER_VALUE - || kind == Value.KindCase.STRING_VALUE - || kind == Value.KindCase.BOOL_VALUE; - } - return false; - } - - /** - * Convert a protobuf message to JSON string. - * - *

Wrapper types (Int32Value, Int64Value, etc.) will be converted to simple value. - *

If kind of {@link Value} is {@link Value.KindCase#NULL_VALUE}, {@link Value.KindCase#BOOL_VALUE}, {@link Value.KindCase#NUMBER_VALUE} or {@link Value.KindCase#STRING_VALUE}, it will be converted to simple value. - * - * @param message protobuf message - * @return JSON string - */ - public static String toJson(Message message) { - try { - return printer.print(message); - } catch (InvalidProtocolBufferException e) { - throw new IllegalStateException("Can't convert message to JSON", e); - } - } - - private static boolean isWrapperType(Class clz) { - return BoolValue.class.isAssignableFrom(clz) - || Int32Value.class.isAssignableFrom(clz) - || Int64Value.class.isAssignableFrom(clz) - || UInt32Value.class.isAssignableFrom(clz) - || UInt64Value.class.isAssignableFrom(clz) - || FloatValue.class.isAssignableFrom(clz) - || DoubleValue.class.isAssignableFrom(clz) - || StringValue.class.isAssignableFrom(clz) - || BytesValue.class.isAssignableFrom(clz); - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/Tuple2.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/Tuple2.java deleted file mode 100644 index 575fbb2d..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/Tuple2.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.util; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.ToString; - -/** - * @author Freeman - */ -@Getter -@EqualsAndHashCode -@ToString -public class Tuple2 { - public final A t1; - public final B t2; - - protected Tuple2(A t1, B t2) { - this.t1 = t1; - this.t2 = t2; - } - - public static Tuple2 of(A a, B b) { - return new Tuple2<>(a, b); - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/Tuple3.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/Tuple3.java deleted file mode 100644 index 8cff6ddf..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/Tuple3.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.util; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.ToString; - -/** - * @author Freeman - */ -@Getter -@EqualsAndHashCode(callSuper = true) -@ToString -public class Tuple3 extends Tuple2 { - public final C t3; - - protected Tuple3(A t1, B t2, C t3) { - super(t1, t2); - this.t3 = t3; - } - - public static Tuple3 of(A a, B b, C c) { - return new Tuple3<>(a, b, c); - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/web/WebMvcGrpcServiceHandlerMapping.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/web/WebMvcGrpcServiceHandlerMapping.java deleted file mode 100644 index 69de2980..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/web/WebMvcGrpcServiceHandlerMapping.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.web; - -import com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil; -import io.grpc.BindableService; -import jakarta.servlet.http.HttpServletRequest; -import java.util.Map; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.http.HttpMethod; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; -import org.springframework.web.servlet.handler.AbstractHandlerMapping; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - -/** - * Provide default routes for those gRPC services without custom http routes. - * - *

The default route is: POST /xx.v1.ServiceName/MethodName - * - * @author Freeman - */ -public class WebMvcGrpcServiceHandlerMapping extends AbstractHandlerMapping { - public static final int ORDER = 10; - - /** - * path -> service - * - *

path: /xx.v1.ServiceName/MethodName - */ - private final Map pathToMethod; - - public WebMvcGrpcServiceHandlerMapping(ObjectProvider grpcServiceProvider) { - this.pathToMethod = JsonTranscoderUtil.getPathToMethod(grpcServiceProvider); - } - - @Override - protected HandlerMethod getHandlerInternal(HttpServletRequest request) { - if (!HttpMethod.POST.name().equalsIgnoreCase(request.getMethod())) { - return null; - } - for (Map.Entry entry : pathToMethod.entrySet()) { - if (entry.getKey().equalsIgnoreCase(request.getRequestURI())) { - return entry.getValue(); - } - } - return null; - } - - /** - * Must after {@link RequestMappingHandlerMapping}, it will process {@link RequestMapping} for us for free! - * - * @see WebMvcConfigurationSupport#requestMappingHandlerMapping - */ - @Override - public int getOrder() { - return ORDER; - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/web/WebMvcProtobufHandlerAdaptor.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/web/WebMvcProtobufHandlerAdaptor.java deleted file mode 100644 index 99ec9c36..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/web/WebMvcProtobufHandlerAdaptor.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.web; - -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil.anyCompatible; -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil.getAccept; -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil.isGrpcHandleMethod; -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil.isJson; -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil.notAcceptableException; -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.ProtoUtil.toJson; -import static org.springframework.http.MediaType.APPLICATION_JSON; - -import com.freemanan.starter.grpc.extensions.jsontranscoder.AbstractHandlerAdaptor; -import com.freemanan.starter.grpc.extensions.jsontranscoder.GrpcHeaderConverter; -import com.google.protobuf.Message; -import io.grpc.Metadata; -import io.grpc.StatusRuntimeException; -import io.grpc.stub.MetadataUtils; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.charset.StandardCharsets; -import java.util.concurrent.atomic.AtomicReference; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.server.ServletServerHttpRequest; -import org.springframework.http.server.ServletServerHttpResponse; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerAdapter; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; - -/** - * @author Freeman - */ -public class WebMvcProtobufHandlerAdaptor extends AbstractHandlerAdaptor implements HandlerAdapter { - - private static final String NEW_BLOCKING_STUB = "newBlockingStub"; - - private final GrpcHeaderConverter grpcHeaderConverter; - - public WebMvcProtobufHandlerAdaptor(GrpcHeaderConverter grpcHeaderConverter) { - this.grpcHeaderConverter = grpcHeaderConverter; - } - - @Override - public boolean supports(Object handler) { - return isGrpcHandleMethod(handler); - } - - @Override - public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - HandlerMethod hm = (HandlerMethod) handler; - Method method = hm.getMethod(); - Class beanClass = hm.getBeanType(); - - // create message - Message message = convert2ProtobufMessage(method.getParameterTypes()[0], request.getInputStream()); - - // create metadata - ServletServerHttpRequest req = new ServletServerHttpRequest(request); - Metadata metadata = grpcHeaderConverter.toRequestMetadata(req.getHeaders()); - - // get gRPC blocking stub to use - Object stub = getStub(beanClass); - - // apply metadata to stub - stub = applyInterceptor4Stub(MetadataUtils.newAttachHeadersInterceptor(metadata), stub); - - // capture gRPC response header/trailer - AtomicReference responseHeader = new AtomicReference<>(); - AtomicReference responseTrailer = new AtomicReference<>(); - stub = applyInterceptor4Stub( - MetadataUtils.newCaptureMetadataInterceptor(responseHeader, responseTrailer), stub); - - // find gRPC stub method to call - Method stubMethod = getInvokeMethod(stub, method, message); - - // call gRPC stub method - Message grpcResponse; - try { - grpcResponse = (Message) stubMethod.invoke(stub, message); - } catch (InvocationTargetException ite) { - Throwable te = ite.getTargetException(); - if (te instanceof StatusRuntimeException) { - throw (StatusRuntimeException) te; - } - throw ite; - } - - // convert gRPC response header to HTTP header - Metadata responseMetadata = responseHeader.get(); - if (responseMetadata != null) { - HttpHeaders headers = grpcHeaderConverter.toResponseHeader(responseMetadata); - headers.forEach((k, values) -> values.forEach(v -> response.addHeader(k, v))); - } - - try (ServletServerHttpResponse resp = new ServletServerHttpResponse(response)) { - // convert gRPC response message (Protobuf) to JSON - String json = toJson(grpcResponse); - if (isJson(json)) { - if (anyCompatible(getAccept(req.getHeaders()), APPLICATION_JSON)) { - resp.getHeaders().setContentType(APPLICATION_JSON); - resp.getBody().write(json.getBytes(StandardCharsets.UTF_8)); - resp.getBody().flush(); - return null; - } - throw notAcceptableException(); - } - - MediaType mt = new MediaType(MediaType.TEXT_PLAIN, StandardCharsets.UTF_8); - if (anyCompatible(getAccept(req.getHeaders()), mt)) { - resp.getHeaders().setContentType(mt); - resp.getBody().write(json.getBytes(StandardCharsets.UTF_8)); - resp.getBody().flush(); - return null; - } - throw notAcceptableException(); - } - } - - /** - * @see RequestMappingHandlerAdapter#getLastModifiedInternal - */ - @Override - @Deprecated - public long getLastModified(HttpServletRequest request, Object handler) { - return -1; - } - - /** - * Must before {@link RequestMappingHandlerAdapter} - * - * @see AbstractHandlerMethodAdapter#getOrder() - */ - @Override - public int getOrder() { - return ORDER; - } - - @Override - public String getNewStubMethodName() { - return NEW_BLOCKING_STUB; - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/ControllerMethodResolver.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/ControllerMethodResolver.java deleted file mode 100644 index f003672c..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/ControllerMethodResolver.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2002-2022 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 com.freemanan.starter.grpc.extensions.jsontranscoder.webflux; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.KotlinDetector; -import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.web.method.ControllerAdviceBean; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.method.annotation.ExceptionHandlerMethodResolver; -import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; -import org.springframework.web.reactive.result.method.InvocableHandlerMethod; -import org.springframework.web.reactive.result.method.annotation.ContinuationHandlerMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.CookieValueMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.ErrorsMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.ExpressionValueMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.HttpEntityMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.MatrixVariableMapMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.MatrixVariableMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.ModelAttributeMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.ModelMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.PathVariableMapMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.PathVariableMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.PrincipalMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.RequestAttributeMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.RequestBodyMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.RequestHeaderMapMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.RequestHeaderMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.RequestParamMapMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.RequestParamMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.RequestPartMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.ServerWebExchangeMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.SessionAttributeMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.SessionStatusMethodArgumentResolver; -import org.springframework.web.reactive.result.method.annotation.WebSessionMethodArgumentResolver; - -/** - * Copy form {@link org.springframework.web.reactive.result.method.annotation.ControllerMethodResolver}. - * - * @author Freeman - */ -class ControllerMethodResolver { - - private final List exceptionHandlerResolvers; - - private final Map, ExceptionHandlerMethodResolver> exceptionHandlerCache = new ConcurrentHashMap<>(64); - - private final Map exceptionHandlerAdviceCache = - new LinkedHashMap<>(64); - - @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") - ControllerMethodResolver( - ReactiveAdapterRegistry adapterRegistry, - ConfigurableApplicationContext context, - List> readers) { - - Assert.notNull(context, "ApplicationContext is required"); - Assert.notNull(readers, "HttpMessageReader List is required"); - - this.exceptionHandlerResolvers = exceptionHandlerResolvers(adapterRegistry, context); - - initControllerAdviceCaches(context); - } - - private static List exceptionHandlerResolvers( - ReactiveAdapterRegistry adapterRegistry, ConfigurableApplicationContext context) { - - return initResolvers(adapterRegistry, context, false, Collections.emptyList()); - } - - private static List initResolvers( - ReactiveAdapterRegistry adapterRegistry, - ConfigurableApplicationContext context, - boolean supportDataBinding, - List> readers) { - - ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); - boolean requestMappingMethod = !readers.isEmpty() && supportDataBinding; - - // Annotation-based... - List result = new ArrayList<>(30); - result.add(new RequestParamMethodArgumentResolver(beanFactory, adapterRegistry, false)); - result.add(new RequestParamMapMethodArgumentResolver(adapterRegistry)); - result.add(new PathVariableMethodArgumentResolver(beanFactory, adapterRegistry)); - result.add(new PathVariableMapMethodArgumentResolver(adapterRegistry)); - result.add(new MatrixVariableMethodArgumentResolver(beanFactory, adapterRegistry)); - result.add(new MatrixVariableMapMethodArgumentResolver(adapterRegistry)); - if (!readers.isEmpty()) { - result.add(new RequestBodyMethodArgumentResolver(readers, adapterRegistry)); - result.add(new RequestPartMethodArgumentResolver(readers, adapterRegistry)); - } - if (supportDataBinding) { - result.add(new ModelAttributeMethodArgumentResolver(adapterRegistry, false)); - } - result.add(new RequestHeaderMethodArgumentResolver(beanFactory, adapterRegistry)); - result.add(new RequestHeaderMapMethodArgumentResolver(adapterRegistry)); - result.add(new CookieValueMethodArgumentResolver(beanFactory, adapterRegistry)); - result.add(new ExpressionValueMethodArgumentResolver(beanFactory, adapterRegistry)); - result.add(new SessionAttributeMethodArgumentResolver(beanFactory, adapterRegistry)); - result.add(new RequestAttributeMethodArgumentResolver(beanFactory, adapterRegistry)); - - // Type-based... - if (!readers.isEmpty()) { - result.add(new HttpEntityMethodArgumentResolver(readers, adapterRegistry)); - } - result.add(new ModelMethodArgumentResolver(adapterRegistry)); - if (supportDataBinding) { - result.add(new ErrorsMethodArgumentResolver(adapterRegistry)); - } - result.add(new ServerWebExchangeMethodArgumentResolver(adapterRegistry)); - result.add(new PrincipalMethodArgumentResolver(adapterRegistry)); - if (requestMappingMethod) { - result.add(new SessionStatusMethodArgumentResolver()); - } - result.add(new WebSessionMethodArgumentResolver(adapterRegistry)); - if (KotlinDetector.isKotlinPresent()) { - result.add(new ContinuationHandlerMethodArgumentResolver()); - } - - // Custom... - // result.addAll(customResolvers.getCustomResolvers()); - - // Catch-all... - result.add(new RequestParamMethodArgumentResolver(beanFactory, adapterRegistry, true)); - if (supportDataBinding) { - result.add(new ModelAttributeMethodArgumentResolver(adapterRegistry, true)); - } - - return result; - } - - private void initControllerAdviceCaches(ApplicationContext applicationContext) { - List beans = ControllerAdviceBean.findAnnotatedBeans(applicationContext); - for (ControllerAdviceBean bean : beans) { - Class beanType = bean.getBeanType(); - if (beanType != null) { - ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType); - if (resolver.hasExceptionMappings()) { - this.exceptionHandlerAdviceCache.put(bean, resolver); - } - } - } - } - - /** - * Look for an {@code @ExceptionHandler} method within the class of the given - * controller method, and also within {@code @ControllerAdvice} classes that - * are applicable to the class of the given controller method. - * - * @param ex the exception to find a handler for - * @param handlerMethod the controller method that raised the exception, or - * if {@code null}, check only {@code @ControllerAdvice} classes. - */ - @Nullable - public InvocableHandlerMethod getExceptionHandlerMethod(Throwable ex, @Nullable HandlerMethod handlerMethod) { - - Class handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null); - Object exceptionHandlerObject = null; - Method exceptionHandlerMethod = null; - - if (handlerType != null) { - // Controller-local first... - exceptionHandlerObject = handlerMethod.getBean(); - exceptionHandlerMethod = this.exceptionHandlerCache - .computeIfAbsent(handlerType, ExceptionHandlerMethodResolver::new) - .resolveMethodByThrowable(ex); - } - - if (exceptionHandlerMethod == null) { - // Global exception handlers... - for (Map.Entry entry : - this.exceptionHandlerAdviceCache.entrySet()) { - ControllerAdviceBean advice = entry.getKey(); - if (advice.isApplicableToBeanType(handlerType)) { - exceptionHandlerMethod = entry.getValue().resolveMethodByThrowable(ex); - if (exceptionHandlerMethod != null) { - exceptionHandlerObject = advice.resolveBean(); - break; - } - } - } - } - - if (exceptionHandlerObject == null || exceptionHandlerMethod == null) { - return null; - } - - InvocableHandlerMethod invocable = new InvocableHandlerMethod(exceptionHandlerObject, exceptionHandlerMethod); - invocable.setArgumentResolvers(this.exceptionHandlerResolvers); - return invocable; - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/GrpcHandlerResultHandler.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/GrpcHandlerResultHandler.java deleted file mode 100644 index a30b862e..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/GrpcHandlerResultHandler.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.webflux; - -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil.isJson; -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.ProtoUtil.toJson; - -import com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil; -import com.google.protobuf.Message; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.function.Supplier; -import org.springframework.core.MethodParameter; -import org.springframework.core.Ordered; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.HandlerResult; -import org.springframework.web.reactive.HandlerResultHandler; -import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -/** - * @author Freeman - */ -public class GrpcHandlerResultHandler implements HandlerResultHandler, Ordered { - - public static final int ORDER = 0; - - @Override - public boolean supports(HandlerResult result) { - MethodParameter retType = result.getReturnTypeSource(); - return retType.getParameterType() == Void.TYPE && result.getReturnValue() instanceof Message; - } - - @Override - public Mono handleResult(ServerWebExchange exchange, HandlerResult result) { - Message message = (Message) result.getReturnValue(); - Supplier errorSupplier = JsonTranscoderUtil::notAcceptableException; - String json = toJson(message); - if (isJson(json)) { - if (anyCompatible(exchange, MediaType.APPLICATION_JSON)) { - exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON); - return exchange.getResponse() - .writeWith(Mono.just( - exchange.getResponse().bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8)))); - } - return Mono.error(errorSupplier); - } - // simple value using content-type text/plain;charset=UTF-8 - MediaType mt = new MediaType(MediaType.TEXT_PLAIN, StandardCharsets.UTF_8); - if (anyCompatible(exchange, mt)) { - exchange.getResponse().getHeaders().setContentType(mt); - return exchange.getResponse() - .writeWith(Mono.just( - exchange.getResponse().bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8)))); - } - return Mono.error(errorSupplier); - } - - private static boolean anyCompatible(ServerWebExchange exchange, MediaType otherMediaType) { - List mediaTypes = - JsonTranscoderUtil.getAccept(exchange.getRequest().getHeaders()); - for (MediaType mediaType : mediaTypes) { - if (mediaType.isCompatibleWith(otherMediaType)) { - return true; - } - } - return false; - } - - /** - * {@link ResponseBodyResultHandler} order is 100. - * - * @see ResponseBodyResultHandler - */ - @Override - public int getOrder() { - return ORDER; - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/WebFluxGrpcServiceHandlerMapping.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/WebFluxGrpcServiceHandlerMapping.java deleted file mode 100644 index c41633ae..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/WebFluxGrpcServiceHandlerMapping.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.webflux; - -import com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil; -import io.grpc.BindableService; -import java.util.Map; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.http.HttpMethod; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.reactive.config.WebFluxConfigurationSupport; -import org.springframework.web.reactive.handler.AbstractHandlerMapping; -import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -/** - * Provide default routes for those gRPC services without custom http routes. - * - *

The default route is: POST /xx.v1.ServiceName/MethodName - * - * @author Freeman - */ -public class WebFluxGrpcServiceHandlerMapping extends AbstractHandlerMapping { - - public static final int ORDER = 10; - - /** - * path -> service - * - *

path: /xx.v1.ServiceName/MethodName - */ - private final Map pathToMethod; - - public WebFluxGrpcServiceHandlerMapping(ObjectProvider grpcServiceProvider) { - this.pathToMethod = JsonTranscoderUtil.getPathToMethod(grpcServiceProvider); - } - - @Override - protected Mono getHandlerInternal(ServerWebExchange exchange) { - HttpMethod method = exchange.getRequest().getMethod(); - if (method != HttpMethod.POST) { - return Mono.empty(); - } - String path = exchange.getRequest().getPath().toString(); - for (Map.Entry entry : pathToMethod.entrySet()) { - if (entry.getKey().equalsIgnoreCase(path)) { - return Mono.just(entry.getValue()); - } - } - return Mono.empty(); - } - - /** - * Must after {@link RequestMappingHandlerMapping}, it will process {@link RequestMapping} for us for free! - * - * @see WebFluxConfigurationSupport#requestMappingHandlerMapping - */ - @Override - public int getOrder() { - return ORDER; - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/WebFluxProtobufHandlerAdaptor.java b/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/WebFluxProtobufHandlerAdaptor.java deleted file mode 100644 index 82c6ce18..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/webflux/WebFluxProtobufHandlerAdaptor.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.webflux; - -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.JsonTranscoderUtil.isGrpcHandleMethod; - -import com.freemanan.starter.grpc.extensions.jsontranscoder.AbstractHandlerAdaptor; -import com.freemanan.starter.grpc.extensions.jsontranscoder.FutureAdapter; -import com.freemanan.starter.grpc.extensions.jsontranscoder.GrpcHeaderConverter; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.protobuf.Message; -import io.grpc.Metadata; -import io.grpc.stub.MetadataUtils; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.core.io.buffer.DataBufferUtils; -import org.springframework.http.HttpHeaders; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.lang.Nullable; -import org.springframework.util.ReflectionUtils; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.reactive.BindingContext; -import org.springframework.web.reactive.DispatchExceptionHandler; -import org.springframework.web.reactive.HandlerAdapter; -import org.springframework.web.reactive.HandlerMapping; -import org.springframework.web.reactive.HandlerResult; -import org.springframework.web.reactive.result.method.InvocableHandlerMethod; -import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -/** - * @author Freeman - */ -public class WebFluxProtobufHandlerAdaptor extends AbstractHandlerAdaptor - implements HandlerAdapter, DispatchExceptionHandler { - private static final Logger log = LoggerFactory.getLogger(WebFluxProtobufHandlerAdaptor.class); - - private static final String NEW_FUTURE_STUB = "newFutureStub"; - - private final ControllerMethodResolver resolver; - private final GrpcHeaderConverter grpcHeaderConverter; - - public WebFluxProtobufHandlerAdaptor( - ReactiveAdapterRegistry adapterRegistry, - ConfigurableApplicationContext context, - List> readers, - GrpcHeaderConverter grpcHeaderConverter) { - this.resolver = new ControllerMethodResolver(adapterRegistry, context, readers); - this.grpcHeaderConverter = grpcHeaderConverter; - } - - @SuppressWarnings("unchecked") - private static ListenableFuture getFutureStubResponse(Object futureStub, Message msg, Method method) { - return (ListenableFuture) ReflectionUtils.invokeMethod(method, futureStub, msg); - } - - @Override - public boolean supports(Object handler) { - return isGrpcHandleMethod(handler); - } - - @Override - public Mono handle(ServerWebExchange exchange, Object handler) { - HandlerMethod hm = ((HandlerMethod) handler); - Method method = hm.getMethod(); - Class messageType = method.getParameterTypes()[0]; - Class beanClass = hm.getBeanType(); - - DispatchExceptionHandler exceptionHandler = - (exchange2, ex) -> handleException(exchange, ex, (HandlerMethod) handler, new BindingContext()); - - AtomicReference responseHeader = new AtomicReference<>(); - AtomicReference responseTrailer = new AtomicReference<>(); - - return DataBufferUtils.join(exchange.getRequest().getBody()) - .map(dataBuffer -> convert2ProtobufMessage(messageType, dataBuffer.asInputStream())) - // invoke grpc method - .flatMap(msg -> { - Object stub = getStub(beanClass); - - // make sure headers are modifiable - HttpHeaders headers = new HttpHeaders(); - headers.putAll(exchange.getRequest().getHeaders()); - Metadata metadata = grpcHeaderConverter.toRequestMetadata(headers); - - // apply metadata to stub - stub = applyInterceptor4Stub(MetadataUtils.newAttachHeadersInterceptor(metadata), stub); - - // capture gRPC response header/trailer - stub = applyInterceptor4Stub( - MetadataUtils.newCaptureMetadataInterceptor(responseHeader, responseTrailer), stub); - - Method m = getInvokeMethod(stub, method, msg); - ListenableFuture resp = getFutureStubResponse(stub, msg, m); - return Mono.fromFuture(FutureAdapter.toCompletable(resp)); - }) - .doOnNext(msg -> { - // convert gRPC response header to HTTP header - Metadata responseMetadata = responseHeader.get(); - if (responseMetadata != null) { - HttpHeaders headers = grpcHeaderConverter.toResponseHeader(responseMetadata); - headers.forEach((k, values) -> values.forEach( - v -> exchange.getResponse().getHeaders().add(k, v))); - } - }) - .map(message -> new HandlerResult(hm, message, hm.getReturnType())) - .doOnNext(handlerResult -> handlerResult.setExceptionHandler(exceptionHandler)) - .onErrorResume(ex -> exceptionHandler.handleError(exchange, ex)); - } - - private Mono handleException( - ServerWebExchange exchange, - Throwable exception, - @Nullable HandlerMethod handlerMethod, - @Nullable BindingContext bindingContext) { - - // Success and error responses may use different content types - exchange.getAttributes().remove(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); - exchange.getResponse().getHeaders().clearContentHeaders(); - - InvocableHandlerMethod invocable = this.resolver.getExceptionHandlerMethod(exception, handlerMethod); - - if (invocable != null) { - ArrayList exceptions = new ArrayList<>(); - try { - if (log.isDebugEnabled()) { - log.debug("{} using @ExceptionHandler {}", exchange.getLogPrefix(), invocable); - } - if (bindingContext != null) { - bindingContext.getModel().asMap().clear(); - } else { - bindingContext = new BindingContext(); - } - - // Expose causes as provided arguments as well - Throwable exToExpose = exception; - while (exToExpose != null) { - exceptions.add(exToExpose); - Throwable cause = exToExpose.getCause(); - exToExpose = (cause != exToExpose ? cause : null); - } - Object[] arguments = new Object[exceptions.size() + 1]; - exceptions.toArray(arguments); // efficient arraycopy call in ArrayList - arguments[arguments.length - 1] = handlerMethod; - - return invocable.invoke(exchange, bindingContext, arguments); - } catch (Throwable invocationEx) { - // Any other than the original exception (or a cause) is unintended here, - // probably an accident (e.g. failed assertion or the like). - if (!exceptions.contains(invocationEx) && log.isWarnEnabled()) { - log.warn(exchange.getLogPrefix() + "Failure in @ExceptionHandler " + invocable, invocationEx); - } - } - } - return Mono.error(exception); - } - - /** - * Must before {@link RequestMappingHandlerAdapter}! - * - * @see RequestMappingHandlerAdapter - */ - @Override - public int getOrder() { - return ORDER; - } - - @Override - public String getNewStubMethodName() { - return NEW_FUTURE_STUB; - } - - @Override - public Mono handleError(ServerWebExchange exchange, Throwable ex) { - return handleException(exchange, ex, null, null); - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grpc-extensions/grpc-json-transcoder/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index b6e429c2..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -com.freemanan.starter.grpc.extensions.jsontranscoder.GrpcJsonTranscoderAutoConfiguration \ No newline at end of file diff --git a/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/JsonTranscoderIT.java b/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/JsonTranscoderIT.java deleted file mode 100644 index 835828d2..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/JsonTranscoderIT.java +++ /dev/null @@ -1,256 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder; - -import static com.freemanan.starter.grpc.extensions.jsontranscoder.Deps.WEB_FLUX_STARTER; -import static com.freemanan.starter.grpc.extensions.jsontranscoder.Deps.WEB_MVC_STARTER; -import static org.assertj.core.api.Assertions.assertThat; - -import com.freemanan.cr.core.anno.Action; -import com.freemanan.cr.core.anno.ClasspathReplacer; -import com.freemanan.sample.pet.v1.GetPetRequest; -import com.freemanan.sample.pet.v1.Pet; -import com.freemanan.sample.pet.v1.PetServiceGrpc; -import com.freemanan.starter.grpc.server.GrpcService; -import com.google.protobuf.StringValue; -import io.grpc.ForwardingServerCall; -import io.grpc.Metadata; -import io.grpc.ServerCall; -import io.grpc.ServerCallHandler; -import io.grpc.ServerInterceptor; -import io.grpc.stub.StreamObserver; -import java.nio.charset.StandardCharsets; -import org.junit.jupiter.api.Test; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -/** - * @author Freeman - */ -class JsonTranscoderIT { - - @Test - @ClasspathReplacer(@Action(WEB_FLUX_STARTER)) - void testWebFluxTranscoderJson() { - int port = U.randomPort(); - ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Cfg.class) - .properties("server.port=" + port) - .run(); - - WebTestClient client = U.webclient(port); - - // test native path - WebTestClient.ResponseSpec resp = client.post() - .uri("/sample.pet.v1.PetService/GetPet") - .contentType(MediaType.APPLICATION_JSON) - .bodyValue("{\"name\":\"pet\"}") - .exchange(); - resp.expectStatus().isOk(); - resp.expectHeader().contentType(MediaType.APPLICATION_JSON); - resp.expectHeader().valueEquals("request-id", "001"); - resp.expectBody().json("{\"name\":\"pet\",\"age\":1}"); - - // test path alias - resp = client.post() - .uri("/v1/pets/get") - .contentType(MediaType.APPLICATION_JSON) - .bodyValue("{\"name\":\"pet\"}") - .exchange(); - resp.expectStatus().isOk(); - resp.expectHeader().contentType(MediaType.APPLICATION_JSON); - resp.expectHeader().valueEquals("request-id", "001"); - resp.expectBody().json("{\"name\":\"pet\",\"age\":1}"); - - ctx.close(); - } - - @Test - @ClasspathReplacer(@Action(WEB_FLUX_STARTER)) - void testWebFluxTranscoderJson_whenSimpleValue() { - int port = U.randomPort(); - ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Cfg.class) - .properties("server.port=" + port) - .run(); - - WebTestClient client = U.webclient(port); - - // wrapper type parses as JSON is simple value format - // google.protobuf.StringValue convert to JSON, the result is "foo", not {"value":"foo"} - // So, when convert JSON string to google.protobuf.StringValue, the input string must be "foo", not - // {"value":"foo"} - WebTestClient.ResponseSpec resp = client.post() - .uri("/sample.pet.v1.PetService/GetPetName") - .bodyValue("\"Freeman\"") - .exchange(); - resp.expectStatus().isOk(); - resp.expectHeader().contentType(new MediaType(MediaType.TEXT_PLAIN, StandardCharsets.UTF_8)); - resp.expectBody(String.class).isEqualTo("\"Freeman\""); - - // test wrong format - resp = client.post() - .uri("/sample.pet.v1.PetService/GetPetName") - .contentType(MediaType.APPLICATION_JSON) - .bodyValue("{\"value\":\"Freeman\"}") - .exchange(); - resp.expectStatus().is4xxClientError(); - - ctx.close(); - } - - // @Test - @ClasspathReplacer(@Action(WEB_FLUX_STARTER)) - void testWebFluxExceptionHandling() { - int port = U.randomPort(); - ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Cfg.class) - .properties("server.port=" + port) - .run(); - - WebTestClient client = U.webclient(port); - - // test native path - WebTestClient.ResponseSpec resp = client.post() - .uri("/sample.pet.v1.PetService/GetPet") - .contentType(MediaType.APPLICATION_JSON) - .bodyValue("{\"name\":\"error\"}") - .exchange(); - resp.expectStatus().is5xxServerError(); - resp.expectHeader().contentType(MediaType.APPLICATION_JSON); - resp.expectHeader().doesNotExist("request-id"); - resp.expectBody().json("{\"code\":2,\"data\":null,\"message\":\"UNKNOWN\"}"); - - ctx.close(); - } - - // =========================== - // Web Mvc - // =========================== - - @Test - @ClasspathReplacer(@Action(WEB_MVC_STARTER)) - void testWebMvcTranscoderJson() { - int port = U.randomPort(); - ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Cfg.class) - .properties("server.port=" + port) - .run(); - - TestRestTemplate client = U.restTemplate(); - - // test native path - ResponseEntity resp = client.exchange( - "http://localhost:" + port + "/sample.pet.v1.PetService/GetPet", - HttpMethod.POST, - new HttpEntity<>("{\"name\":\"pet\"}"), - String.class); - assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(resp.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); - assertThat(resp.getHeaders().get("request-id")).containsExactly("001"); - assertThat(resp.getBody()).isNotBlank(); - assertThat(resp.getBody().replaceAll("\\s+", "")).isEqualTo("{\"name\":\"pet\",\"age\":1}"); - - // test path alias - resp = client.exchange( - "http://localhost:" + port + "/v1/pets/get", - HttpMethod.POST, - new HttpEntity<>("{\"name\":\"pet\"}"), - String.class); - assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(resp.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); - assertThat(resp.getHeaders().get("request-id")).containsExactly("001"); - assertThat(resp.getBody()).isNotBlank(); - assertThat(resp.getBody().replaceAll("\\s+", "")).isEqualTo("{\"name\":\"pet\",\"age\":1}"); - - // wrapper type parses as JSON is simple value format - // google.protobuf.StringValue convert to JSON, the result is "foo", not {"value":"foo"} - // So, when convert JSON string to google.protobuf.StringValue, the input string must be "foo", not - // {"value":"foo"} - resp = client.exchange( - "http://localhost:" + port + "/sample.pet.v1.PetService/GetPetName", - HttpMethod.POST, - new HttpEntity<>("\"Freeman\""), - String.class); - assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(resp.getHeaders().getContentType()) - .isEqualTo(new MediaType(MediaType.TEXT_PLAIN, StandardCharsets.UTF_8)); - assertThat(resp.getBody()).isNotBlank(); - assertThat(resp.getBody()).isEqualTo("\"Freeman\""); - - // test wrong format - resp = client.exchange( - "http://localhost:" + port + "/sample.pet.v1.PetService/GetPetName", - HttpMethod.POST, - new HttpEntity<>("{\"value\":\"Freeman\"}"), - String.class); - assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); - - // test exception handling - // resp = client.exchange( - // "http://localhost:" + port + "/sample.pet.v1.PetService/GetPet", - // HttpMethod.POST, - // new HttpEntity<>("{\"name\":\"error\"}"), - // String.class); - // assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - // assertThat(resp.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); - // assertThat(resp.getHeaders()).doesNotContainKey("request-id"); - // assertThat(resp.getBody()).isEqualTo("{\"code\":2,\"data\":null,\"message\":\"UNKNOWN\"}"); - - ctx.close(); - } - - @Configuration(proxyBeanMethods = false) - @EnableAutoConfiguration - @GrpcService - @RestControllerAdvice - static class Cfg extends PetServiceGrpc.PetServiceImplBase implements ServerInterceptor { - @Override - @PostMapping("/v1/pets/get") - public void getPet(GetPetRequest request, StreamObserver ro) { - if (request.getName().startsWith("err")) { - throw new IllegalArgumentException("invalid name: " + request.getName()); - } - ro.onNext(Pet.newBuilder().setName(request.getName()).setAge(1).build()); - ro.onCompleted(); - } - - @Override - public void getPetName(StringValue request, StreamObserver ro) { - ro.onNext(StringValue.of(request.getValue())); - ro.onCompleted(); - } - - @Override - public ServerCall.Listener interceptCall( - ServerCall call, Metadata headers, ServerCallHandler next) { - ForwardingServerCall.SimpleForwardingServerCall c = - new ForwardingServerCall.SimpleForwardingServerCall<>(call) { - @Override - public void sendHeaders(Metadata headers) { - headers.put(Metadata.Key.of("request-id", Metadata.ASCII_STRING_MARSHALLER), "001"); - super.sendHeaders(headers); - } - }; - return next.startCall(c, headers); - } - - /** - * TODO(Freeman): why use './gradlew build' will occur ClassNotFound exception (org.springframework.http.HttpStatus)? - * but use IDEA run test is ok. - */ - // @ExceptionHandler - // public ResponseEntity> handle(StatusRuntimeException e) { - // Map map = new HashMap<>(); - // map.put("code", e.getStatus().getCode().value()); - // map.put("message", e.getMessage()); - // map.put("data", null); - // return ResponseEntity.status(GrpcUtil.toHttpStatus(e.getStatus())).body(map); - // } - } -} diff --git a/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/U.java b/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/U.java deleted file mode 100644 index 6da14082..00000000 --- a/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/U.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder; - -import java.io.IOException; -import java.net.ServerSocket; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Freeman - */ -public class U { - - /** - * @return a random port - */ - public static int randomPort() { - try (ServerSocket serverSocket = new ServerSocket(0)) { - return serverSocket.getLocalPort(); - } catch (IOException e) { - throw new IllegalStateException("Failed to find available port", e); - } - } - - public static WebTestClient webclient(int port) { - return WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build(); - } - - public static TestRestTemplate restTemplate() { - return new TestRestTemplate(); - } -} diff --git a/grpc-extensions/grpc-metrics/build.gradle b/grpc-extensions/grpc-metrics/build.gradle index ec3df865..efaee311 100644 --- a/grpc-extensions/grpc-metrics/build.gradle +++ b/grpc-extensions/grpc-metrics/build.gradle @@ -2,7 +2,7 @@ dependencies { compileOnly(project(":grpc-boot-autoconfigure:grpc-server-boot-autoconfigure")) compileOnly(project(":grpc-boot-autoconfigure:grpc-client-boot-autoconfigure")) - api("org.springframework.boot:spring-boot-starter-actuator") + compileOnly("org.springframework.boot:spring-boot-starter-actuator") compileOnly("io.micrometer:micrometer-registry-prometheus") compileOnly("io.micrometer:micrometer-registry-otlp") @@ -12,8 +12,7 @@ dependencies { testImplementation(project(":grpc-starters:grpc-starter-test")) testImplementation(project(":grpc-starters:grpc-boot-starter")) - testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") + testImplementation("org.springframework.boot:spring-boot-starter-actuator") testImplementation("com.freemanan:classpath-replacer-junit5:${classpathReplacerVersion}") } diff --git a/grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsAutoConfiguration.java b/grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/GrpcMetricsAutoConfiguration.java similarity index 88% rename from grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsAutoConfiguration.java rename to grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/GrpcMetricsAutoConfiguration.java index 8e341fc8..988ace6f 100644 --- a/grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsAutoConfiguration.java +++ b/grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/GrpcMetricsAutoConfiguration.java @@ -1,9 +1,9 @@ -package com.freemanan.starter.grpc.extensions.metrics; +package grpcstarter.extensions.metrics; -import com.freemanan.starter.grpc.client.ConditionOnGrpcClientEnabled; -import com.freemanan.starter.grpc.client.GrpcClientProperties; -import com.freemanan.starter.grpc.server.ConditionOnGrpcServerEnabled; -import com.freemanan.starter.grpc.server.GrpcServerProperties; +import grpcstarter.client.ConditionOnGrpcClientEnabled; +import grpcstarter.client.GrpcClientProperties; +import grpcstarter.server.ConditionOnGrpcServerEnabled; +import grpcstarter.server.GrpcServerProperties; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.binder.grpc.MetricCollectingClientInterceptor; import io.micrometer.core.instrument.binder.grpc.MetricCollectingServerInterceptor; diff --git a/grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsProperties.java b/grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/GrpcMetricsProperties.java similarity index 90% rename from grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsProperties.java rename to grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/GrpcMetricsProperties.java index f064d991..eb47b1fe 100644 --- a/grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsProperties.java +++ b/grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/GrpcMetricsProperties.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.extensions.metrics; +package grpcstarter.extensions.metrics; -import static com.freemanan.starter.grpc.extensions.metrics.GrpcMetricsProperties.PREFIX; +import static grpcstarter.extensions.metrics.GrpcMetricsProperties.PREFIX; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/OrderedMetricCollectingClientInterceptor.java b/grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/OrderedMetricCollectingClientInterceptor.java similarity index 91% rename from grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/OrderedMetricCollectingClientInterceptor.java rename to grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/OrderedMetricCollectingClientInterceptor.java index 9ffde2dc..c980bd4a 100644 --- a/grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/OrderedMetricCollectingClientInterceptor.java +++ b/grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/OrderedMetricCollectingClientInterceptor.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.metrics; +package grpcstarter.extensions.metrics; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.binder.grpc.MetricCollectingClientInterceptor; diff --git a/grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/OrderedMetricCollectingServerInterceptor.java b/grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/OrderedMetricCollectingServerInterceptor.java similarity index 91% rename from grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/OrderedMetricCollectingServerInterceptor.java rename to grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/OrderedMetricCollectingServerInterceptor.java index 70efeaf5..ee316e0b 100644 --- a/grpc-extensions/grpc-metrics/src/main/java/com/freemanan/starter/grpc/extensions/metrics/OrderedMetricCollectingServerInterceptor.java +++ b/grpc-extensions/grpc-metrics/src/main/java/grpcstarter/extensions/metrics/OrderedMetricCollectingServerInterceptor.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.metrics; +package grpcstarter.extensions.metrics; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.binder.grpc.MetricCollectingServerInterceptor; diff --git a/grpc-extensions/grpc-metrics/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grpc-extensions/grpc-metrics/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index d96d0115..892f404d 100644 --- a/grpc-extensions/grpc-metrics/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/grpc-extensions/grpc-metrics/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1 @@ -com.freemanan.starter.grpc.extensions.metrics.GrpcMetricsAutoConfiguration \ No newline at end of file +grpcstarter.extensions.metrics.GrpcMetricsAutoConfiguration \ No newline at end of file diff --git a/grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/MetricsZipkinIT.java b/grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/MetricsZipkinIT.java deleted file mode 100644 index 84956d96..00000000 --- a/grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/MetricsZipkinIT.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.freemanan.starter.grpc.extensions.metrics; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -@SpringBootTest(classes = MetricsZipkinIT.Cfg.class) -@Testcontainers(disabledWithoutDocker = true) -class MetricsZipkinIT { - - @Container - static GenericContainer zipkin = new GenericContainer<>("openzipkin/zipkin:latest").withExposedPorts(9411); - - @DynamicPropertySource - static void zipkinProperties(DynamicPropertyRegistry registry) { - registry.add("management.zipkin.tracing.endpoint", () -> "http://localhost:" + zipkin.getFirstMappedPort()); - } - - @Test - void testZipkin() {} - - @Configuration(proxyBeanMethods = false) - @EnableAutoConfiguration - static class Cfg {} -} diff --git a/grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/Deps.java b/grpc-extensions/grpc-metrics/src/test/java/grpcstarter/extensions/metrics/Deps.java similarity index 72% rename from grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/Deps.java rename to grpc-extensions/grpc-metrics/src/test/java/grpcstarter/extensions/metrics/Deps.java index f155bcc7..17ba7f10 100644 --- a/grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/Deps.java +++ b/grpc-extensions/grpc-metrics/src/test/java/grpcstarter/extensions/metrics/Deps.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.metrics; +package grpcstarter.extensions.metrics; /** * @author Freeman diff --git a/grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsAutoConfigurationTest.java b/grpc-extensions/grpc-metrics/src/test/java/grpcstarter/extensions/metrics/GrpcMetricsAutoConfigurationTest.java similarity index 94% rename from grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsAutoConfigurationTest.java rename to grpc-extensions/grpc-metrics/src/test/java/grpcstarter/extensions/metrics/GrpcMetricsAutoConfigurationTest.java index e0e2b50e..08276bad 100644 --- a/grpc-extensions/grpc-metrics/src/test/java/com/freemanan/starter/grpc/extensions/metrics/GrpcMetricsAutoConfigurationTest.java +++ b/grpc-extensions/grpc-metrics/src/test/java/grpcstarter/extensions/metrics/GrpcMetricsAutoConfigurationTest.java @@ -1,12 +1,12 @@ -package com.freemanan.starter.grpc.extensions.metrics; +package grpcstarter.extensions.metrics; -import static com.freemanan.starter.grpc.extensions.metrics.Deps.SPRING_BOOT_VERSION; +import static grpcstarter.extensions.metrics.Deps.SPRING_BOOT_VERSION; import static org.assertj.core.api.Assertions.assertThatCode; import com.freemanan.cr.core.anno.Action; import com.freemanan.cr.core.anno.ClasspathReplacer; import com.freemanan.cr.core.anno.Verb; -import com.freemanan.starter.grpc.server.GrpcServerProperties; +import grpcstarter.server.GrpcServerProperties; import io.micrometer.core.aop.CountedAspect; import io.micrometer.core.aop.TimedAspect; import io.micrometer.observation.aop.ObservedAspect; diff --git a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/NetUtil.java b/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/NetUtil.java deleted file mode 100644 index ce09e03a..00000000 --- a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/NetUtil.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.freemanan.starter.grpc.extensions.test; - -import java.net.ServerSocket; -import lombok.SneakyThrows; -import lombok.experimental.UtilityClass; - -/** - * @author Freeman - */ -@UtilityClass -public class NetUtil { - - /** - * Get a random port. - * - * @return port - */ - @SneakyThrows - public static int getRandomPort() { - try (ServerSocket ss = new ServerSocket(0)) { - return ss.getLocalPort(); - } - } -} diff --git a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestAutoConfiguration.java b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestAutoConfiguration.java similarity index 87% rename from grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestAutoConfiguration.java rename to grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestAutoConfiguration.java index 00cee061..53c174b5 100644 --- a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestAutoConfiguration.java +++ b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestAutoConfiguration.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.extensions.test; +package grpcstarter.extensions.test; -import com.freemanan.starter.grpc.server.GrpcServerStartedEvent; +import grpcstarter.server.GrpcServerStartedEvent; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestBeanPostProcessor.java b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestBeanPostProcessor.java similarity index 79% rename from grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestBeanPostProcessor.java rename to grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestBeanPostProcessor.java index d779d524..ad66b74f 100644 --- a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestBeanPostProcessor.java +++ b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestBeanPostProcessor.java @@ -1,11 +1,11 @@ -package com.freemanan.starter.grpc.extensions.test; +package grpcstarter.extensions.test; -import com.freemanan.starter.grpc.server.GrpcServerProperties; -import com.freemanan.starter.grpc.server.GrpcServerStartedEvent; +import grpcstarter.server.GrpcServerProperties; +import grpcstarter.server.GrpcServerStartedEvent; import jakarta.annotation.Nullable; import java.lang.reflect.Field; import java.util.Arrays; -import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.Map; import java.util.Optional; import org.springframework.aop.framework.AopProxyUtils; @@ -25,7 +25,7 @@ class GrpcTestBeanPostProcessor implements ApplicationListener, BeanPostProcessor, BeanFactoryAware, DisposableBean { - private final Map beansToInject = new HashMap<>(); + private final Map beanToInjected = new IdentityHashMap<>(); private BeanFactory beanFactory; private int port; @@ -42,7 +42,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { boolean isTestInstance = isTestInstance(bean); if (isTestInstance || hasRelevantAnnotations(bean)) { - beansToInject.put(bean, false); + beanToInjected.put(bean, false); // This bean is test class instance, test class instance inject fields after Spring context initialization // see org.springframework.test.context.support.DependencyInjectionTestExecutionListener#injectDependencies if (isTestInstance) { @@ -60,12 +60,12 @@ public void onApplicationEvent(GrpcServerStartedEvent event) { .map(GrpcServerProperties.InProcess::getName) .orElse(null); - beansToInject.keySet().forEach(this::injectFields); + beanToInjected.keySet().forEach(this::injectFields); } @Override public void destroy() { - beansToInject.clear(); + beanToInjected.clear(); } private boolean isTestInstance(Object bean) { @@ -74,25 +74,32 @@ private boolean isTestInstance(Object bean) { private boolean hasRelevantAnnotations(Object bean) { return Arrays.stream(AopProxyUtils.ultimateTargetClass(bean).getDeclaredFields()) - .anyMatch(field -> AnnotationUtils.findAnnotation(field, InProcessName.class) != null - || AnnotationUtils.findAnnotation(field, LocalGrpcPort.class) != null); + .anyMatch(field -> hasInProcessNameAnnotation(field) || hasLocalGrpcPortAnnotation(field)); } private void injectFields(Object bean) { - if (Boolean.TRUE.equals(beansToInject.get(bean))) { + if (Boolean.TRUE.equals(beanToInjected.get(bean))) { // Already injected return; } ReflectionUtils.doWithFields(AopProxyUtils.ultimateTargetClass(bean), field -> { - if (AnnotationUtils.findAnnotation(field, InProcessName.class) != null) { + if (hasInProcessNameAnnotation(field)) { injectInProcessName(bean, field); - } else if (AnnotationUtils.findAnnotation(field, LocalGrpcPort.class) != null) { + } else if (hasLocalGrpcPortAnnotation(field)) { injectLocalGrpcPort(bean, field); } }); - beansToInject.put(bean, true); + beanToInjected.put(bean, true); + } + + private static boolean hasLocalGrpcPortAnnotation(Field field) { + return AnnotationUtils.findAnnotation(field, LocalGrpcPort.class) != null; + } + + private static boolean hasInProcessNameAnnotation(Field field) { + return AnnotationUtils.findAnnotation(field, InProcessName.class) != null; } private void injectInProcessName(Object bean, Field field) { diff --git a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestEnvironmentPostProcessor.java b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestEnvironmentPostProcessor.java similarity index 63% rename from grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestEnvironmentPostProcessor.java rename to grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestEnvironmentPostProcessor.java index 94d55961..943ee760 100644 --- a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestEnvironmentPostProcessor.java +++ b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestEnvironmentPostProcessor.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.extensions.test; +package grpcstarter.extensions.test; -import com.freemanan.starter.grpc.server.GrpcServerProperties; +import grpcstarter.server.GrpcServerProperties; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -20,14 +20,14 @@ * @author Freeman */ public class GrpcTestEnvironmentPostProcessor implements EnvironmentPostProcessor { - private static final boolean SPRING_BOOT_TEST_ENV = + private static final boolean SPRING_BOOT_TEST_PRESENT = ClassUtils.isPresent("org.springframework.boot.test.context.SpringBootTest", null); - private static final boolean GRPC_SERVER_STARTER_EXISTS = - ClassUtils.isPresent("com.freemanan.starter.grpc.server.GrpcServerProperties", null); + private static final boolean GRPC_SERVER_STARTER_PRESENT = + ClassUtils.isPresent("grpcstarter.server.GrpcServerProperties", null); @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - if (!SPRING_BOOT_TEST_ENV) { + if (!SPRING_BOOT_TEST_PRESENT || !GRPC_SERVER_STARTER_PRESENT) { return; } @@ -49,27 +49,22 @@ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringAp Map configMap = new HashMap<>(); switch (port) { - case IN_PROCESS: - if (GRPC_SERVER_STARTER_EXISTS) { - String serverProperty = GrpcServerProperties.InProcess.PREFIX + ".name"; - if (!environment.containsProperty(serverProperty)) { - // use in-process if not manually configured - String name = UUID.randomUUID().toString(); - configMap.put(serverProperty, name); - } - } else { - throw new IllegalStateException("gRPC client or server starter not found"); + case IN_PROCESS -> { + String serverProperty = GrpcServerProperties.InProcess.PREFIX + ".name"; + if (!environment.containsProperty(serverProperty)) { + // not manually configured + String name = UUID.randomUUID().toString(); + configMap.put(serverProperty, name); } - break; - case RANDOM_PORT: + } + case RANDOM_PORT -> { String portProperty = GrpcServerProperties.PREFIX + ".port"; configMap.put(portProperty, 0); - break; - case DEFINED_PORT: + } + case DEFINED_PORT -> { // do nothing - break; - default: - throw new IllegalArgumentException("Unknown port type: " + port); + } + default -> throw new IllegalArgumentException("Unknown port type: " + port); } MapPropertySource ps = new MapPropertySource("grpc.extensions.test.property_source", configMap); diff --git a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestProperties.java b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestProperties.java similarity index 81% rename from grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestProperties.java rename to grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestProperties.java index 634502a0..18632d6a 100644 --- a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/GrpcTestProperties.java +++ b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/GrpcTestProperties.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.test; +package grpcstarter.extensions.test; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -31,15 +31,11 @@ public static class Server { /** * Port configuration, default is {@link PortType#IN_PROCESS}, which means start grpc server with in-process transport. * - *

- * NOTE: if {@code grpc-client-starter} is not in classpath, will fall back to {@link PortType#RANDOM_PORT}. + * @see PortType */ private PortType portType = PortType.IN_PROCESS; } - /** - * If used as a static internal class of {@link Server}, the IDE's automatic prompt will be lost :) - */ public enum PortType { /** * Start grpc server with in-process transport. diff --git a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/InProcessName.java b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/InProcessName.java similarity index 91% rename from grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/InProcessName.java rename to grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/InProcessName.java index 9f90f110..f2030d74 100644 --- a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/InProcessName.java +++ b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/InProcessName.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.test; +package grpcstarter.extensions.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/LocalGrpcPort.java b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/LocalGrpcPort.java similarity index 84% rename from grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/LocalGrpcPort.java rename to grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/LocalGrpcPort.java index 385f18a4..29022d9a 100644 --- a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/LocalGrpcPort.java +++ b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/LocalGrpcPort.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.test; +package grpcstarter.extensions.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -11,7 +11,7 @@ *

Example: * *

{@code
- * @SpringBootTest
+ * @SpringBootTest(properties = "grpc.test.server.port-type=RANDOM_PORT")
  * class FooTest{
  *     @LocalGrpcPort
  *     int port;
diff --git a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/StubUtil.java b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/StubUtil.java
similarity index 87%
rename from grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/StubUtil.java
rename to grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/StubUtil.java
index 180dbba3..18746b6e 100644
--- a/grpc-extensions/grpc-test/src/main/java/com/freemanan/starter/grpc/extensions/test/StubUtil.java
+++ b/grpc-extensions/grpc-test/src/main/java/grpcstarter/extensions/test/StubUtil.java
@@ -1,4 +1,4 @@
-package com.freemanan.starter.grpc.extensions.test;
+package grpcstarter.extensions.test;
 
 import io.grpc.Channel;
 import io.grpc.inprocess.InProcessChannelBuilder;
@@ -24,8 +24,8 @@ public class StubUtil {
      * Create a gRPC stub instance using in-process channel.
      *
      * @param inProcessName in-process server name
-     * @param stubClass    stub class
-     * @param          stub type
+     * @param stubClass     stub class
+     * @param            stub type
      * @return gRPC stub instance
      */
     @SuppressWarnings("unchecked")
@@ -43,10 +43,10 @@ public static > T createStub(String inProcessName, Cla
     private static String getStubMethodName(Class stubClass) {
         if (stubClass.getName().endsWith(BLOCKING_STUB)) {
             return NEW_BLOCKING_STUB_METHOD;
-        } else if (stubClass.getName().endsWith(FUTURE_STUB)) {
+        }
+        if (stubClass.getName().endsWith(FUTURE_STUB)) {
             return NEW_FUTURE_STUB_METHOD;
-        } else {
-            return NEW_STUB_METHOD;
         }
+        return NEW_STUB_METHOD;
     }
 }
diff --git a/grpc-extensions/grpc-test/src/main/resources/META-INF/spring.factories b/grpc-extensions/grpc-test/src/main/resources/META-INF/spring.factories
index e4d1af1a..aa617dff 100644
--- a/grpc-extensions/grpc-test/src/main/resources/META-INF/spring.factories
+++ b/grpc-extensions/grpc-test/src/main/resources/META-INF/spring.factories
@@ -1,2 +1,2 @@
 org.springframework.boot.env.EnvironmentPostProcessor=\
-  com.freemanan.starter.grpc.extensions.test.GrpcTestEnvironmentPostProcessor
+  grpcstarter.extensions.test.GrpcTestEnvironmentPostProcessor
diff --git a/grpc-extensions/grpc-test/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grpc-extensions/grpc-test/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index c8c0c6cf..b12d6724 100644
--- a/grpc-extensions/grpc-test/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/grpc-extensions/grpc-test/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1 +1 @@
-com.freemanan.starter.grpc.extensions.test.GrpcTestAutoConfiguration
+grpcstarter.extensions.test.GrpcTestAutoConfiguration
diff --git a/grpc-extensions/grpc-test/src/main/resources/application-grpc-starter-test-example.yml b/grpc-extensions/grpc-test/src/main/resources/application-grpc-starter-test-example.yml
index 591bc4cc..4c4168df 100644
--- a/grpc-extensions/grpc-test/src/main/resources/application-grpc-starter-test-example.yml
+++ b/grpc-extensions/grpc-test/src/main/resources/application-grpc-starter-test-example.yml
@@ -1,4 +1,6 @@
 grpc:
   test:
+    enabled: true
     server:
+      enabled: true
       port-type: in_process
diff --git a/grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/DefinedPortIT.java b/grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/DefinedPortIT.java
similarity index 93%
rename from grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/DefinedPortIT.java
rename to grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/DefinedPortIT.java
index 0f0cc861..c9b12d86 100644
--- a/grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/DefinedPortIT.java
+++ b/grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/DefinedPortIT.java
@@ -1,4 +1,4 @@
-package com.freemanan.starter.grpc.extensions.test;
+package grpcstarter.extensions.test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/LocalGrpcPortTest.java b/grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/LocalGrpcPortTest.java
similarity index 95%
rename from grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/LocalGrpcPortTest.java
rename to grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/LocalGrpcPortTest.java
index 757dc493..086810b6 100644
--- a/grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/LocalGrpcPortTest.java
+++ b/grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/LocalGrpcPortTest.java
@@ -1,4 +1,4 @@
-package com.freemanan.starter.grpc.extensions.test;
+package grpcstarter.extensions.test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/RandomPortIT.java b/grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/RandomPortIT.java
similarity index 93%
rename from grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/RandomPortIT.java
rename to grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/RandomPortIT.java
index ac28d813..038421d6 100644
--- a/grpc-extensions/grpc-test/src/test/java/com/freemanan/starter/grpc/extensions/test/RandomPortIT.java
+++ b/grpc-extensions/grpc-test/src/test/java/grpcstarter/extensions/test/RandomPortIT.java
@@ -1,4 +1,4 @@
-package com.freemanan.starter.grpc.extensions.test;
+package grpcstarter.extensions.test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/grpc-extensions/grpc-tracing/build.gradle b/grpc-extensions/grpc-tracing/build.gradle
index cfacb6b0..a7558d2b 100644
--- a/grpc-extensions/grpc-tracing/build.gradle
+++ b/grpc-extensions/grpc-tracing/build.gradle
@@ -2,8 +2,8 @@ dependencies {
     compileOnly(project(":grpc-boot-autoconfigure:grpc-server-boot-autoconfigure"))
     compileOnly(project(":grpc-boot-autoconfigure:grpc-client-boot-autoconfigure"))
 
-    api("org.springframework.boot:spring-boot-starter-actuator")
-    api("io.micrometer:micrometer-tracing")
+    compileOnly("org.springframework.boot:spring-boot-starter-actuator")
+    compileOnly("io.micrometer:micrometer-tracing")
 
     compileOnly("io.micrometer:micrometer-tracing-bridge-otel")
     compileOnly("io.micrometer:micrometer-tracing-bridge-brave")
@@ -12,6 +12,8 @@ dependencies {
 
     testImplementation(project(":grpc-starters:grpc-starter-test"))
     testImplementation(project(":grpc-starters:grpc-boot-starter"))
+    testImplementation("org.springframework.boot:spring-boot-starter-actuator")
+    testImplementation("io.micrometer:micrometer-tracing")
     testImplementation("com.freemanan:classpath-replacer-junit5:${classpathReplacerVersion}")
 }
 
diff --git a/grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingAutoConfiguration.java b/grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/GrpcTracingAutoConfiguration.java
similarity index 88%
rename from grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingAutoConfiguration.java
rename to grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/GrpcTracingAutoConfiguration.java
index 6a518dd7..3d772f3a 100644
--- a/grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingAutoConfiguration.java
+++ b/grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/GrpcTracingAutoConfiguration.java
@@ -1,9 +1,9 @@
-package com.freemanan.starter.grpc.extensions.tracing;
+package grpcstarter.extensions.tracing;
 
-import com.freemanan.starter.grpc.client.ConditionOnGrpcClientEnabled;
-import com.freemanan.starter.grpc.client.GrpcClientProperties;
-import com.freemanan.starter.grpc.server.ConditionOnGrpcServerEnabled;
-import com.freemanan.starter.grpc.server.GrpcServerProperties;
+import grpcstarter.client.ConditionOnGrpcClientEnabled;
+import grpcstarter.client.GrpcClientProperties;
+import grpcstarter.server.ConditionOnGrpcServerEnabled;
+import grpcstarter.server.GrpcServerProperties;
 import io.micrometer.core.instrument.binder.grpc.ObservationGrpcClientInterceptor;
 import io.micrometer.core.instrument.binder.grpc.ObservationGrpcServerInterceptor;
 import io.micrometer.observation.ObservationRegistry;
diff --git a/grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingProperties.java b/grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/GrpcTracingProperties.java
similarity index 90%
rename from grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingProperties.java
rename to grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/GrpcTracingProperties.java
index 4ed3b25e..48414322 100644
--- a/grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingProperties.java
+++ b/grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/GrpcTracingProperties.java
@@ -1,6 +1,6 @@
-package com.freemanan.starter.grpc.extensions.tracing;
+package grpcstarter.extensions.tracing;
 
-import static com.freemanan.starter.grpc.extensions.tracing.GrpcTracingProperties.PREFIX;
+import static grpcstarter.extensions.tracing.GrpcTracingProperties.PREFIX;
 
 import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/OrderedObservationGrpcClientInterceptor.java b/grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/OrderedObservationGrpcClientInterceptor.java
similarity index 91%
rename from grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/OrderedObservationGrpcClientInterceptor.java
rename to grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/OrderedObservationGrpcClientInterceptor.java
index 8cd9ba02..525bbaa1 100644
--- a/grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/OrderedObservationGrpcClientInterceptor.java
+++ b/grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/OrderedObservationGrpcClientInterceptor.java
@@ -1,4 +1,4 @@
-package com.freemanan.starter.grpc.extensions.tracing;
+package grpcstarter.extensions.tracing;
 
 import io.micrometer.core.instrument.binder.grpc.ObservationGrpcClientInterceptor;
 import io.micrometer.observation.ObservationRegistry;
diff --git a/grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/OrderedObservationGrpcServerInterceptor.java b/grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/OrderedObservationGrpcServerInterceptor.java
similarity index 91%
rename from grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/OrderedObservationGrpcServerInterceptor.java
rename to grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/OrderedObservationGrpcServerInterceptor.java
index 68afc4bc..0812b9be 100644
--- a/grpc-extensions/grpc-tracing/src/main/java/com/freemanan/starter/grpc/extensions/tracing/OrderedObservationGrpcServerInterceptor.java
+++ b/grpc-extensions/grpc-tracing/src/main/java/grpcstarter/extensions/tracing/OrderedObservationGrpcServerInterceptor.java
@@ -1,4 +1,4 @@
-package com.freemanan.starter.grpc.extensions.tracing;
+package grpcstarter.extensions.tracing;
 
 import io.micrometer.core.instrument.binder.grpc.ObservationGrpcServerInterceptor;
 import io.micrometer.observation.ObservationRegistry;
diff --git a/grpc-extensions/grpc-tracing/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grpc-extensions/grpc-tracing/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index aa280725..ff2a2ca4 100644
--- a/grpc-extensions/grpc-tracing/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/grpc-extensions/grpc-tracing/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1 +1 @@
-com.freemanan.starter.grpc.extensions.tracing.GrpcTracingAutoConfiguration
\ No newline at end of file
+grpcstarter.extensions.tracing.GrpcTracingAutoConfiguration
\ No newline at end of file
diff --git a/grpc-extensions/grpc-tracing/src/test/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingAutoConfigurationTest.java b/grpc-extensions/grpc-tracing/src/test/java/grpcstarter/extensions/tracing/GrpcTracingAutoConfigurationTest.java
similarity index 98%
rename from grpc-extensions/grpc-tracing/src/test/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingAutoConfigurationTest.java
rename to grpc-extensions/grpc-tracing/src/test/java/grpcstarter/extensions/tracing/GrpcTracingAutoConfigurationTest.java
index 9775e896..7ba2e0a2 100644
--- a/grpc-extensions/grpc-tracing/src/test/java/com/freemanan/starter/grpc/extensions/tracing/GrpcTracingAutoConfigurationTest.java
+++ b/grpc-extensions/grpc-tracing/src/test/java/grpcstarter/extensions/tracing/GrpcTracingAutoConfigurationTest.java
@@ -1,4 +1,4 @@
-package com.freemanan.starter.grpc.extensions.tracing;
+package grpcstarter.extensions.tracing;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
diff --git a/grpc-extensions/grpc-json-transcoder/build.gradle b/grpc-extensions/grpc-transcoding/build.gradle
similarity index 64%
rename from grpc-extensions/grpc-json-transcoder/build.gradle
rename to grpc-extensions/grpc-transcoding/build.gradle
index 11888a0a..77393e1b 100644
--- a/grpc-extensions/grpc-json-transcoder/build.gradle
+++ b/grpc-extensions/grpc-transcoding/build.gradle
@@ -1,18 +1,21 @@
 dependencies {
     api(project(":grpc-boot-autoconfigure:grpc-server-boot-autoconfigure"))
+    api("org.springframework:spring-web")
+    api("com.fasterxml.jackson.core:jackson-databind")
     api("com.google.protobuf:protobuf-java-util")
+    api("com.google.api:api-common:${googleApiCommonVersion}")
 
     compileOnly("org.springframework.boot:spring-boot-starter-web")
     compileOnly("org.springframework.boot:spring-boot-starter-webflux")
 
     annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
 
-    testCompileOnly("org.springframework.boot:spring-boot-starter-web")
-    testCompileOnly("org.springframework.boot:spring-boot-starter-webflux")
+    testImplementation("org.springframework.boot:spring-boot-starter-web")
+    testImplementation("org.springframework.boot:spring-boot-starter-webflux")
     testImplementation(project(":grpc-starters:grpc-starter-test"))
     testImplementation(project(":grpc-starters:grpc-boot-starter"))
     testImplementation("com.freemanan:classpath-replacer-junit5:${classpathReplacerVersion}")
 }
 
 apply from: "${rootDir}/gradle/deploy.gradle"
-apply from: "${rootDir}/gradle/protobuf-with-pgv.gradle"
+apply from: "${rootDir}/gradle/protobuf.gradle"
diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/DefaultHeaderConverter.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/DefaultHeaderConverter.java
new file mode 100644
index 00000000..07797904
--- /dev/null
+++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/DefaultHeaderConverter.java
@@ -0,0 +1,72 @@
+package grpcstarter.extensions.transcoding;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import io.grpc.Metadata;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.springframework.http.HttpHeaders;
+import org.springframework.util.ReflectionUtils;
+
+/**
+ * @author Freeman
+ */
+public class DefaultHeaderConverter implements HeaderConverter {
+
+    private final Set removeHeaders; // lower case
+
+    @SuppressFBWarnings("CT_CONSTRUCTOR_THROW")
+    public DefaultHeaderConverter() {
+        this.removeHeaders = getRemoveHeaders();
+    }
+
+    @Override
+    public Metadata toMetadata(HttpHeaders headers) {
+        Metadata metadata = new Metadata();
+        headers.forEach((k, values) -> {
+            if (!removeHeaders.contains(k.toLowerCase())) {
+                values.forEach(v -> metadata.put(Metadata.Key.of(k, Metadata.ASCII_STRING_MARSHALLER), v));
+            }
+        });
+        return metadata;
+    }
+
+    @Override
+    public HttpHeaders toHttpHeaders(Metadata headers) {
+        HttpHeaders result = new HttpHeaders();
+        for (String key : headers.keys()) {
+            if (!removeHeaders.contains(key.toLowerCase())
+                    && !key.startsWith("grpc-")
+                    && !key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {
+                Optional.ofNullable(headers.getAll(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER)))
+                        .ifPresent(values -> values.forEach(value -> result.add(key, value)));
+            }
+        }
+        return result;
+    }
+
+    private Set getRemoveHeaders() {
+        Set result = new LinkedHashSet<>(findPublicStaticFinalStringFieldNames(HttpHeaders.class));
+
+        result.removeIf(HttpHeaders.COOKIE::equalsIgnoreCase); // keep cookie
+        result.removeIf(HttpHeaders.AUTHORIZATION::equalsIgnoreCase); // keep authorization
+        return result;
+    }
+
+    private static Set findPublicStaticFinalStringFieldNames(Class clazz) {
+        return Arrays.stream(clazz.getDeclaredFields())
+                .filter(f -> Modifier.isPublic(f.getModifiers())
+                        && Modifier.isStatic(f.getModifiers())
+                        && Modifier.isFinal(f.getModifiers())
+                        && f.getType() == String.class)
+                .map(f -> ReflectionUtils.getField(f, null))
+                .filter(Objects::nonNull)
+                .map(Object::toString)
+                .map(String::toLowerCase)
+                .collect(Collectors.toSet());
+    }
+}
diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingAutoConfiguration.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingAutoConfiguration.java
new file mode 100644
index 00000000..c743ebf1
--- /dev/null
+++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingAutoConfiguration.java
@@ -0,0 +1,70 @@
+package grpcstarter.extensions.transcoding;
+
+import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.REACTIVE;
+import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.SERVLET;
+
+import grpcstarter.server.GrpcServerCustomizer;
+import grpcstarter.server.GrpcServerProperties;
+import io.grpc.BindableService;
+import io.grpc.Metadata;
+import io.grpc.ServerInterceptor;
+import java.util.List;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * @author Freeman
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnClass({Metadata.class, HttpHeaders.class})
+@ConditionalOnProperty(prefix = GrpcTranscodingProperties.PREFIX, name = "enabled", matchIfMissing = true)
+@EnableConfigurationProperties(GrpcTranscodingProperties.class)
+public class GrpcTranscodingAutoConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean
+    public HeaderConverter defaultHeaderConverter() {
+        return new DefaultHeaderConverter();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    public TranscodingGrpcServer transcodingGrpcServer(
+            GrpcServerProperties properties,
+            GrpcTranscodingProperties transcodingProperties,
+            ObjectProvider serviceProvider,
+            ObjectProvider interceptorProvider,
+            ObjectProvider customizers) {
+        return new TranscodingGrpcServer(
+                properties, serviceProvider, interceptorProvider, customizers, transcodingProperties);
+    }
+
+    @Configuration(proxyBeanMethods = false)
+    @ConditionalOnWebApplication(type = SERVLET)
+    static class WebMvc {
+
+        @Bean
+        public ServletTranscodingRouterFunction webMvcTranscodingRouterFunction(
+                List services, HeaderConverter headerConverter, GrpcTranscodingProperties properties) {
+            return new ServletTranscodingRouterFunction(services, headerConverter, properties);
+        }
+    }
+
+    @Configuration(proxyBeanMethods = false)
+    @ConditionalOnWebApplication(type = REACTIVE)
+    static class WebFlux {
+
+        @Bean
+        public ReactiveTranscodingRouterFunction webFluxTranscodingRouterFunction(
+                List services, HeaderConverter headerConverter, GrpcTranscodingProperties properties) {
+            return new ReactiveTranscodingRouterFunction(services, headerConverter, properties);
+        }
+    }
+}
diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingProperties.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingProperties.java
new file mode 100644
index 00000000..5300d26a
--- /dev/null
+++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingProperties.java
@@ -0,0 +1,24 @@
+package grpcstarter.extensions.transcoding;
+
+import java.util.UUID;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author Freeman
+ */
+@Data
+@ConfigurationProperties(GrpcTranscodingProperties.PREFIX)
+public class GrpcTranscodingProperties {
+    public static final String PREFIX = "grpc.transcoding";
+
+    /**
+     * Whether to enable transcoding auto-configuration, default {@code true}.
+     */
+    private boolean enabled = true;
+
+    /**
+     * In-process name for gRPC transcoding server, default is a random UUID.
+     */
+    private String inProcessName = UUID.randomUUID().toString();
+}
diff --git a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcHeaderConverter.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/HeaderConverter.java
similarity index 64%
rename from grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcHeaderConverter.java
rename to grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/HeaderConverter.java
index 9fc523d6..2f56a51b 100644
--- a/grpc-extensions/grpc-json-transcoder/src/main/java/com/freemanan/starter/grpc/extensions/jsontranscoder/GrpcHeaderConverter.java
+++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/HeaderConverter.java
@@ -1,4 +1,4 @@
-package com.freemanan.starter.grpc.extensions.jsontranscoder;
+package grpcstarter.extensions.transcoding;
 
 import io.grpc.Metadata;
 import org.springframework.http.HttpHeaders;
@@ -6,19 +6,19 @@
 /**
  * @author Freeman
  */
-public interface GrpcHeaderConverter {
+public interface HeaderConverter {
 
     /**
      * Convert http headers to gRPC metadata before the request sent.
      *
      * @param headers {@link HttpHeaders}
      */
-    Metadata toRequestMetadata(HttpHeaders headers);
+    Metadata toMetadata(HttpHeaders headers);
 
     /**
      * Convert gRPC metadata to http headers after the response received.
      *
      * @param headers {@link Metadata}
      */
-    HttpHeaders toResponseHeader(Metadata headers);
+    HttpHeaders toHttpHeaders(Metadata headers);
 }
diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/JsonUtil.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/JsonUtil.java
new file mode 100644
index 00000000..c813b7af
--- /dev/null
+++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/JsonUtil.java
@@ -0,0 +1,91 @@
+package grpcstarter.extensions.transcoding;
+
+import static grpcstarter.extensions.transcoding.Util.isSimpleValueMessage;
+import static grpcstarter.extensions.transcoding.Util.stringifySimpleValueMessage;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Message;
+import com.google.protobuf.MessageOrBuilder;
+import com.google.protobuf.util.JsonFormat;
+import java.io.IOException;
+import lombok.experimental.UtilityClass;
+import org.springframework.beans.BeanUtils;
+import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
+
+/**
+ * Utility class for JSON serialization, aimed to support both Java bean and Protobuf {@link Message}.
+ *
+ * @author Freeman
+ */
+@UtilityClass
+class JsonUtil {
+
+    private static final ObjectMapper om;
+    private static final JsonFormat.Printer printer;
+
+    static {
+        om = new Jackson2ObjectMapperBuilder()
+                .failOnEmptyBeans(false)
+                .modules(new SimpleModule().addSerializer(new ProtoMessageSerializer()))
+                .build();
+        printer = JsonFormat.printer().omittingInsignificantWhitespace();
+    }
+
+    /**
+     * Convert the Java bean or Protobuf {@link Message} to JSON string.
+     *
+     * 

For Java Bean: include all fields, even if they are null. + *

For Protobuf {@link Message}: use {@link JsonFormat.Printer#print(MessageOrBuilder)}'s default behavior, default value will be omitted. + * + * @param obj the object/{@link Message} to encode + * @return json string + */ + public static String toJson(Object obj) { + if (obj instanceof Message m) { + if (isSimpleValueMessage(m)) { + return stringifySimpleValueMessage(m); + } + try { + return printer.print(m); + } catch (InvalidProtocolBufferException e) { + throw new IllegalArgumentException(e); + } + } + + if (BeanUtils.isSimpleValueType(obj.getClass())) { + return String.valueOf(obj); + } + + try { + return om.writeValueAsString(obj); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException(e); + } + } + + public static boolean canParseJson(Object obj) { + if (obj instanceof Message m) { + return !isSimpleValueMessage(m); + } + return !BeanUtils.isSimpleValueType(obj.getClass()); + } + + private static final class ProtoMessageSerializer extends StdSerializer { + + private ProtoMessageSerializer() { + super(MessageOrBuilder.class); + } + + @Override + public void serialize(MessageOrBuilder value, JsonGenerator gen, SerializerProvider serializers) + throws IOException { + gen.writeRawValue(printer.print(value)); + } + } +} diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ReactiveTranscodingRouterFunction.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ReactiveTranscodingRouterFunction.java new file mode 100644 index 00000000..9261a4d3 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ReactiveTranscodingRouterFunction.java @@ -0,0 +1,261 @@ +package grpcstarter.extensions.transcoding; + +import static grpcstarter.extensions.transcoding.JsonUtil.canParseJson; +import static grpcstarter.extensions.transcoding.TranscodingUtil.toHttpStatus; +import static grpcstarter.extensions.transcoding.Util.URI_TEMPLATE_VARIABLES_ATTRIBUTE; +import static grpcstarter.extensions.transcoding.Util.buildRequestMessage; +import static grpcstarter.extensions.transcoding.Util.getInProcessChannel; +import static grpcstarter.extensions.transcoding.Util.getReactiveRoutes; +import static grpcstarter.extensions.transcoding.Util.shutdown; +import static grpcstarter.extensions.transcoding.Util.trim; +import static io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING; +import static io.grpc.MethodDescriptor.MethodType.UNARY; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import grpcstarter.extensions.transcoding.Util.Route; +import io.grpc.BindableService; +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptors; +import io.grpc.Metadata; +import io.grpc.StatusRuntimeException; +import io.grpc.stub.ClientCalls; +import io.grpc.stub.MetadataUtils; +import io.grpc.stub.StreamObserver; +import jakarta.annotation.Nonnull; +import java.io.IOException; +import java.io.InputStream; +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.codec.ServerSentEvent; +import org.springframework.web.reactive.function.server.HandlerFunction; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.ResponseStatusException; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * @author Freeman + * @since 3.3.0 + */ +public class ReactiveTranscodingRouterFunction + implements RouterFunction, + HandlerFunction, + SmartInitializingSingleton, + DisposableBean { + + private static final String MATCHING_ROUTE = ReactiveTranscodingRouterFunction.class.getName() + ".matchingRoute"; + + /** + * grpc full method name -> route + * + *

e.g. "grpc.testing.SimpleService/UnaryRpc" -> Route + */ + private final Map> methodNameRoutes = new HashMap<>(); + + private final List> routes = new ArrayList<>(); + private final HeaderConverter headerConverter; + private final GrpcTranscodingProperties properties; + + private Channel channel; + + public ReactiveTranscodingRouterFunction( + List services, HeaderConverter headerConverter, GrpcTranscodingProperties properties) { + getReactiveRoutes(services, methodNameRoutes, routes); + this.headerConverter = headerConverter; + this.properties = properties; + } + + @Override + public void afterSingletonsInstantiated() { + channel = getInProcessChannel(properties.getInProcessName()); + } + + @Override + @Nonnull + public Mono> route(@Nonnull ServerRequest request) { + if (Objects.equals(request.method(), HttpMethod.POST)) { + var route = methodNameRoutes.get(trim(request.path(), '/')); + if (route != null) { + request.attributes().put(MATCHING_ROUTE, route); + return Mono.just(this); + } + } + + for (var route : routes) { + if (route.predicate().test(request) + || route.additionalPredicates().stream().anyMatch(p -> p.test(request))) { + request.attributes().put(MATCHING_ROUTE, route); + return Mono.just(this); + } + } + + return Mono.empty(); + } + + @Override + @Nonnull + @SuppressWarnings("unchecked") + public Mono handle(@Nonnull ServerRequest request) { + var route = (Route) request.attributes().get(MATCHING_ROUTE); + + var methodType = route.invokeMethod().getType(); + + if (methodType == UNARY) { + return processUnaryCall(request, route); + } + + if (methodType == SERVER_STREAMING) { + return processServerStreamingCall(request, route); + } + + throw new ResponseStatusException(BAD_REQUEST, "Unsupported rpc method type: " + methodType); + } + + @SuppressWarnings("unchecked") + private static ClientCall getCall(Channel channel, Route route) { + return (ClientCall) channel.newCall(route.invokeMethod(), CallOptions.DEFAULT); + } + + private Mono processServerStreamingCall(ServerRequest request, Route route) { + return request.bodyToMono(DataBuffer.class) + .defaultIfEmpty(request.exchange().getResponse().bufferFactory().wrap(new byte[0])) + .flatMap(buf -> { + var transcoder = getTranscoder(request, buf); + var msg = getMessage(route, transcoder); + // forwards http headers + var chan = ClientInterceptors.intercept( + channel, + MetadataUtils.newAttachHeadersInterceptor( + headerConverter.toMetadata(request.headers().asHttpHeaders()))); + var call = getCall(chan, route); + var response = Flux.>create( + sink -> ClientCalls.asyncServerStreamingCall(call, msg, new StreamObserver<>() { + @Override + public void onNext(Object o) { + String json = JsonUtil.toJson(transcoder.out((Message) o, route.httpRule())); + sink.next(ServerSentEvent.builder() + .data(json) + .build()); + } + + @Override + public void onError(Throwable throwable) { + if (throwable instanceof StatusRuntimeException sre) { + sink.error(new TranscodingRuntimeException( + toHttpStatus(sre.getStatus()), sre.getMessage(), null)); + } else { + sink.error(throwable); + } + } + + @Override + public void onCompleted() { + sink.complete(); + } + })); + return ServerResponse.ok().body(response, ServerSentEvent.class); + }); + } + + private static Transcoder getTranscoder(ServerRequest request, DataBuffer buf) { + return Transcoder.create(new Transcoder.Variable( + getBytes(buf), + convert(request.queryParams()), + request.exchange().getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE))); + } + + private Mono processUnaryCall(ServerRequest request, Route route) { + return request.bodyToMono(DataBuffer.class) + .defaultIfEmpty(request.exchange().getResponse().bufferFactory().wrap(new byte[0])) + .flatMap(buf -> { + var transcoder = getTranscoder(request, buf); + Message msg = getMessage(route, transcoder); + var headers = new AtomicReference(); + var trailers = new AtomicReference(); + var chan = ClientInterceptors.intercept( + channel, + MetadataUtils.newCaptureMetadataInterceptor(headers, trailers), + MetadataUtils.newAttachHeadersInterceptor( + headerConverter.toMetadata(request.headers().asHttpHeaders()))); + var call = getCall(chan, route); + return Mono.create(sink -> ClientCalls.asyncUnaryCall(call, msg, new StreamObserver<>() { + @Override + public void onNext(Object o) { + var builder = ServerResponse.ok().headers(h -> { + Metadata m = headers.get(); + if (m != null) { + h.addAll(headerConverter.toHttpHeaders(m)); + } + }); + var body = transcoder.out((Message) o, route.httpRule()); + if (canParseJson(body)) { + builder.contentType(MediaType.APPLICATION_JSON); + } + builder.body(Mono.just(JsonUtil.toJson(body)), String.class) + .subscribe(sink::success, sink::error); + } + + @Override + public void onError(Throwable throwable) { + if (throwable instanceof StatusRuntimeException sre) { + Metadata t = trailers.get(); + sink.error(new TranscodingRuntimeException( + toHttpStatus(sre.getStatus()), + sre.getMessage(), + t != null ? headerConverter.toHttpHeaders(t) : null)); + } else { + sink.error(throwable); + } + } + + @Override + public void onCompleted() { + sink.success(); + } + })); + }); + } + + private static Message getMessage(Route route, Transcoder transcoder) { + try { + return buildRequestMessage(transcoder, route); + } catch (InvalidProtocolBufferException e) { + throw new ResponseStatusException(BAD_REQUEST, e.getMessage(), e); + } + } + + private static byte[] getBytes(DataBuffer buf) { + try (InputStream is = buf.asInputStream(true)) { + return is.readAllBytes(); + } catch (IOException e) { + throw new IllegalStateException("Failed to read DataBuffer", e); + } + } + + private static Map convert(Map> map) { + return map.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toArray(String[]::new))); + } + + @Override + public void destroy() throws Exception { + shutdown(channel, Duration.ofSeconds(15)); + } +} diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ServletTranscodingRouterFunction.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ServletTranscodingRouterFunction.java new file mode 100644 index 00000000..d87e2074 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ServletTranscodingRouterFunction.java @@ -0,0 +1,222 @@ +package grpcstarter.extensions.transcoding; + +import static grpcstarter.extensions.transcoding.JsonUtil.canParseJson; +import static grpcstarter.extensions.transcoding.TranscodingUtil.toHttpStatus; +import static grpcstarter.extensions.transcoding.Util.Route; +import static grpcstarter.extensions.transcoding.Util.URI_TEMPLATE_VARIABLES_ATTRIBUTE; +import static grpcstarter.extensions.transcoding.Util.buildRequestMessage; +import static grpcstarter.extensions.transcoding.Util.fillRoutes; +import static grpcstarter.extensions.transcoding.Util.getInProcessChannel; +import static grpcstarter.extensions.transcoding.Util.trim; +import static io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING; +import static io.grpc.MethodDescriptor.MethodType.UNARY; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.util.StreamUtils.copyToByteArray; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import io.grpc.BindableService; +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptors; +import io.grpc.Metadata; +import io.grpc.StatusRuntimeException; +import io.grpc.stub.ClientCalls; +import io.grpc.stub.MetadataUtils; +import io.grpc.stub.StreamObserver; +import jakarta.annotation.Nonnull; +import java.io.IOException; +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import lombok.SneakyThrows; +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.web.server.ResponseStatusException; +import org.springframework.web.servlet.function.HandlerFunction; +import org.springframework.web.servlet.function.RouterFunction; +import org.springframework.web.servlet.function.ServerRequest; +import org.springframework.web.servlet.function.ServerResponse; + +/** + * @author Freeman + * @since 3.3.0 + */ +public class ServletTranscodingRouterFunction + implements RouterFunction, HandlerFunction, SmartInitializingSingleton { + + private static final String MATCHING_ROUTE = ServletTranscodingRouterFunction.class + ".matchingRoute"; + + /** + * grpc full method name -> route + * + *

e.g. "grpc.testing.SimpleService/UnaryRpc" -> Route + */ + private final Map> methodNameRoutes = new HashMap<>(); + + private final List> routes = new ArrayList<>(); + private final HeaderConverter headerConverter; + private final GrpcTranscodingProperties properties; + + private Channel channel; + + public ServletTranscodingRouterFunction( + List services, HeaderConverter headerConverter, GrpcTranscodingProperties properties) { + fillRoutes(services, methodNameRoutes, routes); + this.headerConverter = headerConverter; + this.properties = properties; + } + + @Override + public void afterSingletonsInstantiated() { + channel = getInProcessChannel(properties.getInProcessName()); + } + + @Override + @Nonnull + public Optional> route(@Nonnull ServerRequest request) { + if (Objects.equals(request.method(), HttpMethod.POST)) { + var route = methodNameRoutes.get(trim(request.path(), '/')); + if (route != null) { + request.attributes().put(MATCHING_ROUTE, route); + return Optional.of(this); + } + } + + for (var route : routes) { + if (route.predicate().test(request) + || route.additionalPredicates().stream().anyMatch(p -> p.test(request))) { + request.attributes().put(MATCHING_ROUTE, route); + return Optional.of(this); + } + } + + return Optional.empty(); + } + + @Override + @Nonnull + @SuppressWarnings("unchecked") + public ServerResponse handle(@Nonnull ServerRequest request) { + var route = (Util.Route) request.attributes().get(MATCHING_ROUTE); + + var methodType = route.invokeMethod().getType(); + + if (methodType == UNARY) { + return processUnaryCall(request, route); + } + + if (methodType == SERVER_STREAMING) { + return processServerStreamingCall(request, route); + } + + throw new ResponseStatusException(BAD_REQUEST, "Unsupported rpc method type: " + methodType); + } + + @SuppressWarnings("unchecked") + private static ClientCall getCall(Channel channel, Route route) { + return (ClientCall) channel.newCall(route.invokeMethod(), CallOptions.DEFAULT); + } + + @SuppressWarnings("unchecked") + private static Transcoder getTranscoder(ServerRequest request) { + try { + return Transcoder.create(new Transcoder.Variable( + copyToByteArray(request.servletRequest().getInputStream()), + request.servletRequest().getParameterMap(), + ((Map) request.servletRequest().getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE)))); + } catch (IOException e) { + throw new IllegalStateException("getInputStream failed", e); + } + } + + private ServerResponse processUnaryCall(ServerRequest request, Route route) { + var headers = new AtomicReference(); + var trailers = new AtomicReference(); + var transcoder = getTranscoder(request); + var req = getMessage(route, transcoder); + var chan = ClientInterceptors.intercept( + channel, + MetadataUtils.newCaptureMetadataInterceptor(headers, trailers), + MetadataUtils.newAttachHeadersInterceptor( + headerConverter.toMetadata(request.headers().asHttpHeaders()))); + var call = getCall(chan, route); + Message responseMessage; + try { + responseMessage = (Message) ClientCalls.blockingUnaryCall(call, req); + } catch (StatusRuntimeException e) { + // TODO(Freeman): Not control by problemdetails.enabled, Spring bug? + Metadata t = trailers.get(); + throw new TranscodingRuntimeException( + toHttpStatus(e.getStatus()), e.getMessage(), t != null ? headerConverter.toHttpHeaders(t) : null); + } + + var builder = ServerResponse.ok().headers(h -> { + Metadata m = headers.get(); + if (m != null) { + h.addAll(headerConverter.toHttpHeaders(m)); + } + }); + var body = transcoder.out(responseMessage, route.httpRule()); + if (canParseJson(body)) { + builder.contentType(MediaType.APPLICATION_JSON); + } + return builder.body(JsonUtil.toJson(body)); + } + + private ServerResponse processServerStreamingCall(ServerRequest request, Route route) { + var transcoder = getTranscoder(request); + var req = getMessage(route, transcoder); + // forwards http headers + var chan = ClientInterceptors.intercept( + channel, + MetadataUtils.newAttachHeadersInterceptor( + headerConverter.toMetadata(request.headers().asHttpHeaders()))); + var call = getCall(chan, route); + return ServerResponse.sse( + (sse -> { + // Cancel the call when SSE error occurs, possibly due to client disconnect + sse.onError(t -> call.cancel("SSE error", null)); + + ClientCalls.asyncServerStreamingCall(call, req, new StreamObserver<>() { + @Override + @SneakyThrows + public void onNext(Object value) { + String json = JsonUtil.toJson(transcoder.out((Message) value, route.httpRule())); + sse.data(json); + } + + @Override + public void onError(Throwable t) { + if (t instanceof StatusRuntimeException sre) { + sse.error(new TranscodingRuntimeException( + toHttpStatus(sre.getStatus()), sre.getMessage(), null)); + } else { + sse.error(t); + } + } + + @Override + public void onCompleted() { + sse.complete(); + } + }); + }), + Duration.ZERO); + } + + private static Message getMessage(Route route, Transcoder transcoder) { + try { + return buildRequestMessage(transcoder, route); + } catch (InvalidProtocolBufferException e) { + throw new ResponseStatusException(BAD_REQUEST, e.getMessage(), e); + } + } +} diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Transcoder.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Transcoder.java new file mode 100644 index 00000000..132e6724 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Transcoder.java @@ -0,0 +1,177 @@ +package grpcstarter.extensions.transcoding; + +import static com.google.protobuf.Descriptors.FieldDescriptor.Type; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.api.HttpRule; +import com.google.protobuf.ByteString; +import com.google.protobuf.Descriptors; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import com.google.protobuf.util.JsonFormat; +import jakarta.annotation.Nonnull; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +/** + * @author Freeman + */ +class Transcoder { + + private static final JsonFormat.Parser parser = JsonFormat.parser().ignoringUnknownFields(); + + private final Variable variable; + + private Transcoder(Variable variable) { + this.variable = variable; + } + + public static Transcoder create(Variable variable) { + return new Transcoder(variable); + } + + public void into(@Nonnull Message.Builder messageBuilder, @Nonnull HttpRule httpRule) + throws InvalidProtocolBufferException { + // Note that when using `*` in the body mapping, it is not possible to + // have HTTP parameters, as all fields not bound by the path end in + // the body. This makes this option more rarely used in practice when + // defining REST APIs. The common usage of `*` is in custom methods + // which don't use the URL at all for transferring data. + + // Any fields in the request message which are not bound by the path template + // automatically become HTTP query parameters if there is no HTTP request body. + + Optional.ofNullable(variable.parameters()).orElseGet(Map::of).forEach((key, values) -> { + String[] fieldPath = key.split("\\."); + + // Navigate to the last field descriptor + Message.Builder lastBuilder = messageBuilder; + for (int i = 0; i < fieldPath.length - 1; i++) { + Descriptors.FieldDescriptor field = + lastBuilder.getDescriptorForType().findFieldByName(fieldPath[i]); + if (noBuilder(field)) return; + + lastBuilder = lastBuilder.getFieldBuilder(field); + } + + Descriptors.FieldDescriptor field = + lastBuilder.getDescriptorForType().findFieldByName(fieldPath[fieldPath.length - 1]); + if (!isValueType(field)) return; + + if (field.isRepeated()) { + for (String value : values) { + lastBuilder.addRepeatedField(field, parseValue(field, value)); + } + } else { + if (values.length > 0) { + setValueField(lastBuilder, field, values[0]); + } + } + }); + + // The special name `*` can be used in the body mapping to define that + // every field not bound by the path template should be mapped to the + // request body. + + if (!httpRule.getBody().isBlank()) { + String bodyString = Optional.ofNullable(variable.body()) + .map(e -> new String(e, UTF_8)) + .orElse(""); + if (!bodyString.isBlank()) { + if (Objects.equals(httpRule.getBody(), "*")) { + merge(messageBuilder, bodyString); + } else { + Descriptors.FieldDescriptor field = + messageBuilder.getDescriptorForType().findFieldByName(httpRule.getBody()); + if (noBuilder(field)) return; + + Message.Builder fieldBuilder = messageBuilder.getFieldBuilder(field); + if (fieldBuilder != null) { + merge(fieldBuilder, bodyString); + } + } + } + } + + // The path variables **must not** capture the leading "/" character. The reason + // is that the most common use case "{var}" does not capture the leading "/" + // character. For consistency, all path variables must share the same behavior. + + // The path variables **must not** refer to any repeated or mapped field, + // because client libraries are not capable of handling such variable expansion. + Optional.ofNullable(variable.pathVariables()).orElseGet(Map::of).forEach((key, value) -> { + Descriptors.FieldDescriptor field = + messageBuilder.getDescriptorForType().findFieldByName(key); + if (!isValueType(field)) return; + setValueField(messageBuilder, field, value); + }); + } + + public Object out(@Nonnull Message response, @Nonnull HttpRule httpRule) { + if (!httpRule.getResponseBody().isBlank()) { + Descriptors.FieldDescriptor field = + response.getDescriptorForType().findFieldByName(httpRule.getResponseBody()); + if (field != null) { + return response.getField(field); + } + } + return response; + } + + private static void merge(Message.Builder messageBuilder, String bodyString) throws InvalidProtocolBufferException { + parser.merge(bodyString, messageBuilder); + } + + private static boolean noBuilder(Descriptors.FieldDescriptor field) { + return field == null || field.isRepeated() || field.isMapField() || field.getType() != Type.MESSAGE; + } + + private static void setValueField(Message.Builder lastBuilder, Descriptors.FieldDescriptor field, String values) { + if (lastBuilder == null || field == null || values == null) return; + if (isValueType(field)) { + lastBuilder.setField(field, parseValue(field, values)); + } + } + + private static boolean isValueType(Descriptors.FieldDescriptor field) { + return field != null + && switch (field.getJavaType()) { + case INT, LONG, FLOAT, DOUBLE, BOOLEAN, STRING, BYTE_STRING, ENUM -> true; + default -> false; + }; + } + + private static Object parseValue(Descriptors.FieldDescriptor field, String value) { + return switch (field.getJavaType()) { + case INT -> Integer.parseInt(value); + case LONG -> Long.parseLong(value); + case FLOAT -> Float.parseFloat(value); + case DOUBLE -> Double.parseDouble(value); + case BOOLEAN -> Boolean.parseBoolean(value); + case STRING -> value; + case BYTE_STRING -> ByteString.copyFrom(value.getBytes(UTF_8)); + case ENUM -> { + if (value.isBlank()) { + yield field.getEnumType().getValues().get(0); + } + if (Character.isDigit(value.charAt(0))) { + try { + var e = field.getEnumType().findValueByNumber(Integer.parseInt(value)); + if (e != null) yield e; + } catch (NumberFormatException ignored) { + } + } else { + var e = field.getEnumType().findValueByName(value); + if (e != null) yield e; + } + throw new IllegalArgumentException( + "Can't parse enum value '" + value + "' for field '" + field.getName() + "'"); + } + case MESSAGE -> throw new IllegalArgumentException( + "Direct parsing to message type not supported, field " + field.getName()); + }; + } + + public record Variable(byte[] body, Map parameters, Map pathVariables) {} +} diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingGrpcServer.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingGrpcServer.java new file mode 100644 index 00000000..a31d9b38 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingGrpcServer.java @@ -0,0 +1,153 @@ +package grpcstarter.extensions.transcoding; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import grpcstarter.server.GrpcServerCustomizer; +import grpcstarter.server.GrpcServerProperties; +import io.grpc.BindableService; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.ServerInterceptor; +import io.grpc.inprocess.InProcessServerBuilder; +import java.io.IOException; +import java.util.Optional; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.context.SmartLifecycle; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.util.unit.DataSize; + +/** + * @author Freeman + * @since 3.3.0 + */ +public class TranscodingGrpcServer implements SmartLifecycle { + private static final Logger log = LoggerFactory.getLogger(TranscodingGrpcServer.class); + + private final Server server; + private final AtomicBoolean isRunning = new AtomicBoolean(false); + private final CountDownLatch latch = new CountDownLatch(1); + private final GrpcServerProperties properties; + private final GrpcTranscodingProperties transcodingProperties; + + @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") + public TranscodingGrpcServer( + GrpcServerProperties properties, + ObjectProvider serviceProvider, + ObjectProvider interceptorProvider, + ObjectProvider customizers, + GrpcTranscodingProperties transcodingProperties) { + this.properties = properties; + this.transcodingProperties = transcodingProperties; + this.server = + buildGrpcServer(properties, transcodingProperties, serviceProvider, interceptorProvider, customizers); + } + + private static Server buildGrpcServer( + GrpcServerProperties properties, + GrpcTranscodingProperties transcodingProperties, + ObjectProvider serviceProvider, + ObjectProvider interceptorProvider, + ObjectProvider customizers) { + ServerBuilder builder = InProcessServerBuilder.forName(transcodingProperties.getInProcessName()); + + // add services + serviceProvider.forEach(builder::addService); + + // add interceptors, gRPC applies interceptors in reversed order + interceptorProvider.stream() + .sorted(AnnotationAwareOrderComparator.INSTANCE.reversed()) + .forEach(builder::intercept); + + Optional.ofNullable(properties.getMaxInboundMessageSize()) + .map(DataSize::toBytes) + .map(Long::intValue) + .ifPresent(builder::maxInboundMessageSize); + Optional.ofNullable(properties.getMaxInboundMetadataSize()) + .map(DataSize::toBytes) + .map(Long::intValue) + .ifPresent(builder::maxInboundMetadataSize); + + // apply customizers + customizers.orderedStream().forEach(customizer -> customizer.customize(builder)); + + return builder.build(); + } + + @Override + public void start() { + if (isRunning()) { + return; + } + try { + server.start(); + isRunning.set(true); + if (log.isInfoEnabled()) { + log.info("gRPC transcoding in-process server started: {}", transcodingProperties.getInProcessName()); + } + + waitUntilShutdown(); + } catch (IOException e) { + gracefulShutdown(); + throw new IllegalStateException(e); + } + } + + @Override + public void stop() { + if (isRunning.get()) { + gracefulShutdown(); + isRunning.set(false); + latch.countDown(); + } + } + + @Override + public boolean isRunning() { + return isRunning.get(); + } + + private void waitUntilShutdown() { + new Thread( + () -> { + try { + // wait here until terminating + latch.await(); + } catch (InterruptedException e) { + log.warn("gRPC transcoding server await termination interrupted", e); + Thread.currentThread().interrupt(); + } + }, + "grpc-transcoding-termination-awaiter") + .start(); + } + + private void gracefulShutdown() { + long start = System.currentTimeMillis(); + + // stop accepting new calls + server.shutdown(); + + try { + long time = properties.getShutdownTimeout(); + if (time > 0L) { + server.awaitTermination(time, TimeUnit.MILLISECONDS); + } else { + server.awaitTermination(); + } + } catch (InterruptedException e) { + log.warn("gRPC transcoding server graceful shutdown interrupted", e); + Thread.currentThread().interrupt(); + } + if (!server.isTerminated()) { + server.shutdownNow(); + } + + if (log.isInfoEnabled()) { + log.info("gRPC transcoding server graceful shutdown in {} ms", System.currentTimeMillis() - start); + } + } +} diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingRuntimeException.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingRuntimeException.java new file mode 100644 index 00000000..7903de95 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingRuntimeException.java @@ -0,0 +1,29 @@ +package grpcstarter.extensions.transcoding; + +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; +import org.springframework.web.server.ResponseStatusException; + +/** + * @author Freeman + */ +public class TranscodingRuntimeException extends ResponseStatusException { + + private final HttpHeaders headers = new HttpHeaders(); + + public TranscodingRuntimeException(HttpStatusCode status, @Nullable String reason, @Nullable HttpHeaders headers) { + super(status, reason); + + if (headers != null) { + this.headers.putAll(headers); + } + } + + @Override + @Nonnull + public HttpHeaders getHeaders() { + return headers; + } +} diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingUtil.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingUtil.java new file mode 100644 index 00000000..f86d2f0d --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingUtil.java @@ -0,0 +1,42 @@ +package grpcstarter.extensions.transcoding; + +import io.grpc.Status; +import lombok.experimental.UtilityClass; +import org.springframework.http.HttpStatus; + +/** + * @author Freeman + */ +@UtilityClass +public class TranscodingUtil { + + /** + * Convert gRPC status to HTTP status. + * + * @param grpcStatus {@link Status} + * @return {@link HttpStatus} + * @see Handling Errors + */ + public static HttpStatus toHttpStatus(Status grpcStatus) { + return switch (grpcStatus.getCode()) { + case OK -> HttpStatus.OK; + case CANCELLED -> HttpStatus.BAD_REQUEST; // NOTE: 499 is non-standard http/1.1 code, use 400 instead + case UNKNOWN -> HttpStatus.INTERNAL_SERVER_ERROR; + case INVALID_ARGUMENT -> HttpStatus.BAD_REQUEST; + case DEADLINE_EXCEEDED -> HttpStatus.GATEWAY_TIMEOUT; + case NOT_FOUND -> HttpStatus.NOT_FOUND; + case ALREADY_EXISTS -> HttpStatus.CONFLICT; + case PERMISSION_DENIED -> HttpStatus.FORBIDDEN; + case RESOURCE_EXHAUSTED -> HttpStatus.TOO_MANY_REQUESTS; + case FAILED_PRECONDITION -> HttpStatus.BAD_REQUEST; + case ABORTED -> HttpStatus.CONFLICT; + case OUT_OF_RANGE -> HttpStatus.BAD_REQUEST; + case UNIMPLEMENTED -> HttpStatus.NOT_IMPLEMENTED; + case INTERNAL -> HttpStatus.INTERNAL_SERVER_ERROR; + case UNAVAILABLE -> HttpStatus.SERVICE_UNAVAILABLE; + case DATA_LOSS -> HttpStatus.INTERNAL_SERVER_ERROR; + case UNAUTHENTICATED -> HttpStatus.UNAUTHORIZED; + default -> HttpStatus.INTERNAL_SERVER_ERROR; + }; + } +} diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Util.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Util.java new file mode 100644 index 00000000..30f003f0 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Util.java @@ -0,0 +1,468 @@ +package grpcstarter.extensions.transcoding; + +import com.google.api.AnnotationsProto; +import com.google.api.HttpRule; +import com.google.api.pathtemplate.PathTemplate; +import com.google.protobuf.BoolValue; +import com.google.protobuf.BytesValue; +import com.google.protobuf.DescriptorProtos; +import com.google.protobuf.Descriptors; +import com.google.protobuf.DoubleValue; +import com.google.protobuf.FloatValue; +import com.google.protobuf.Int32Value; +import com.google.protobuf.Int64Value; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import com.google.protobuf.StringValue; +import com.google.protobuf.UInt32Value; +import com.google.protobuf.UInt64Value; +import com.google.protobuf.Value; +import io.grpc.BindableService; +import io.grpc.Channel; +import io.grpc.ManagedChannel; +import io.grpc.MethodDescriptor; +import io.grpc.ServerMethodDefinition; +import io.grpc.ServerServiceDefinition; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.protobuf.ProtoFileDescriptorSupplier; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import java.lang.reflect.Method; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import lombok.experimental.UtilityClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.util.ConcurrentReferenceHashMap; +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.function.ServerRequest; + +/** + * @author Freeman + */ +@UtilityClass +class Util { + private static final Logger log = LoggerFactory.getLogger(Util.class); + + public static final String URI_TEMPLATE_VARIABLES_ATTRIBUTE = Util.class + ".matchingPattern"; + + /** + * Cache for the default message of the method input type. + * + *

The key is the full name of the method input type, the value is the default message instance. + */ + static final Map methodCache = new ConcurrentReferenceHashMap<>(); + + private static List> fillRoutes( + Map> methodNameRoutes, + List> routes, + List definitions, + BiFunction> predicateCreator) { + for (ServerServiceDefinition ssd : definitions) { + Descriptors.ServiceDescriptor serviceDescriptor = Util.getServiceDescriptor(ssd); + if (serviceDescriptor == null) { + continue; + } + + Map methodNameToMethodDescriptor = + serviceDescriptor.getMethods().stream() + .collect(Collectors.toMap( + com.google.protobuf.Descriptors.MethodDescriptor::getName, Function.identity())); + + ssd.getMethods().stream() + .map(ServerMethodDefinition::getMethodDescriptor) + .forEach(invokeMethod -> { + var methodDescriptor = methodNameToMethodDescriptor.get(invokeMethod.getBareMethodName()); + if (methodDescriptor == null) { + return; + } + + methodNameRoutes.put( + invokeMethod.getFullMethodName(), + new Route<>( + HttpRule.newBuilder().setBody("*").build(), + invokeMethod, + methodDescriptor, + t -> false, + List.of())); + + if (methodDescriptor.getOptions().hasExtension(AnnotationsProto.http)) { + HttpRule httpRule = methodDescriptor.getOptions().getExtension(AnnotationsProto.http); + Optional.ofNullable(createRouteWithBindings( + httpRule, invokeMethod, methodDescriptor, predicateCreator)) + .ifPresent(routes::add); + } + }); + } + return routes; + } + + @Nullable + private static Util.Route createRouteWithBindings( + HttpRule httpRule, + MethodDescriptor invokeMethod, + Descriptors.MethodDescriptor methodDescriptor, + BiFunction> predicateCreator) { + List> additionalPredicates = new ArrayList<>(); + // Process only one level of additional_bindings + for (HttpRule binding : httpRule.getAdditionalBindingsList()) { + HttpMethod method = extractHttpMethod(binding); + String path = extractPath(binding); + if (method != null && path != null) { + additionalPredicates.add(predicateCreator.apply(method, PathTemplate.create(path))); + } + } + + HttpMethod mainMethod = extractHttpMethod(httpRule); + String mainPath = extractPath(httpRule); + if (mainMethod != null && mainPath != null) { + Predicate mainPredicate = predicateCreator.apply(mainMethod, PathTemplate.create(mainPath)); + return new Route<>(httpRule, invokeMethod, methodDescriptor, mainPredicate, additionalPredicates); + } + return null; + } + + @Nullable + private static HttpMethod extractHttpMethod(HttpRule httpRule) { + return switch (httpRule.getPatternCase()) { + case GET -> HttpMethod.GET; + case PUT -> HttpMethod.PUT; + case POST -> HttpMethod.POST; + case DELETE -> HttpMethod.DELETE; + case PATCH -> HttpMethod.PATCH; + case CUSTOM -> HttpMethod.valueOf(httpRule.getCustom().getKind()); + case PATTERN_NOT_SET -> null; + default -> throw new IllegalArgumentException("Unsupported HTTP method: " + httpRule.getPatternCase()); + }; + } + + @Nullable + private static String extractPath(HttpRule httpRule) { + return switch (httpRule.getPatternCase()) { + case GET -> httpRule.getGet(); + case PUT -> httpRule.getPut(); + case POST -> httpRule.getPost(); + case DELETE -> httpRule.getDelete(); + case PATCH -> httpRule.getPatch(); + case CUSTOM -> httpRule.getCustom().getPath(); + case PATTERN_NOT_SET -> null; + default -> throw new IllegalArgumentException("Unsupported HTTP pattern: " + httpRule.getPatternCase()); + }; + } + + public static List listDefinition(List services) { + return services.stream().map(BindableService::bindService).toList(); + } + + public static List> fillRoutes( + List services, + Map> methodNameRoutes, + List> routes) { + return fillRoutes(methodNameRoutes, routes, listDefinition(services), ServletPredicate::new); + } + + public static List> getReactiveRoutes( + List services, + Map> methodNameRoutes, + List> routes) { + return fillRoutes(methodNameRoutes, routes, listDefinition(services), ReactivePredicate::new); + } + + static String snakeToPascal(String input) { + if (input == null || input.isEmpty()) return input; + + StringBuilder result = new StringBuilder(input.length()); + boolean toUpperCase = true; + + for (char c : input.toCharArray()) { + if (c == '_') { + toUpperCase = true; + } else { + result.append(toUpperCase ? Character.toUpperCase(c) : c); + toUpperCase = false; + } + } + + return result.toString(); + } + + @Nullable + private static Descriptors.ServiceDescriptor getServiceDescriptor(ServerServiceDefinition definition) { + Object schemaDescriptor = definition.getServiceDescriptor().getSchemaDescriptor(); + if (schemaDescriptor instanceof ProtoFileDescriptorSupplier protoFileDescriptorSupplier) { + Descriptors.FileDescriptor fileDescriptor = protoFileDescriptorSupplier.getFileDescriptor(); + String serviceName = definition.getServiceDescriptor().getName(); + return fileDescriptor.getServices().stream() + .filter(serviceDescriptor -> serviceDescriptor.getFullName().equals(serviceName)) + .findFirst() + .orElseThrow(); + } + return null; + } + + static Message getDefaultMessage(Descriptors.Descriptor descriptor) { + DescriptorProtos.FileOptions options = descriptor.getFile().getOptions(); + String javaPackage = options.hasJavaPackage() + ? options.getJavaPackage() + : descriptor.getFile().getPackage(); + List classNames = new ArrayList<>(2); + if (options.getJavaMultipleFiles()) { + classNames.add(javaPackage + "." + Util.getClassName(descriptor)); + } else { + if (options.hasJavaOuterClassname()) { + classNames.add( + javaPackage + "." + options.getJavaOuterClassname() + "$" + Util.getClassName(descriptor)); + } else { + String name = descriptor.getFile().getName(); // "google/protobuf/empty.proto" + String fileName = name.substring(name.lastIndexOf('/') + 1); // "empty.proto" + + // If there’s a service, enum, or message (including nested types) in the file with the same name, + // “OuterClass” will be appended to the wrapper class’s name. + // See https://protobuf.dev/reference/java/java-generated/#invocation + String outerClassName = snakeToPascal(fileName.replace(".proto", "")); // "Empty" + classNames.add("%s.%sOuterClass$%s" + .formatted( + javaPackage, + outerClassName, + getClassName(descriptor))); // "com.google.protobuf.EmptyOuterClass$Empty" + classNames.add("%s.%s$%s" + .formatted( + javaPackage, + outerClassName, + getClassName(descriptor))); // "com.google.protobuf.Empty$Empty" + } + } + + Class clazz = null; + for (String className : classNames) { + try { + clazz = Class.forName(className); + break; + } catch (ClassNotFoundException ignored) { + // no-op + } + } + + if (clazz == null) { + throw new IllegalStateException("Unable to find Protobuf Message type: " + classNames); + } + + try { + Method defaultInstance = clazz.getMethod("getDefaultInstance"); + return ((Message) defaultInstance.invoke(null)); + } catch (Exception ex) { + throw new IllegalStateException( + "Invalid Protobuf Message type: no invocable newBuilder() method on " + clazz, ex); + } + } + + public static String getClassName(Descriptors.Descriptor descriptor) { + String className = ""; + while (descriptor != null) { + className = descriptor.getName() + (StringUtils.hasText(className) ? "$" + className : ""); + descriptor = descriptor.getContainingType(); + } + return className; + } + + public static ManagedChannel getInProcessChannel(String name) { + return InProcessChannelBuilder.forName(name).usePlaintext().build(); + } + + public static Message buildRequestMessage(Transcoder transcoder, Route route) + throws InvalidProtocolBufferException { + Message.Builder messageBuilder = methodCache + .computeIfAbsent( + route.methodDescriptor().getInputType().getFullName(), + k -> getDefaultMessage(route.methodDescriptor().getInputType())) + .toBuilder(); + + transcoder.into(messageBuilder, route.httpRule()); + + return messageBuilder.build(); + } + + public static void shutdown(Channel channel, Duration timeout) { + if (!(channel instanceof ManagedChannel mc) || mc.isShutdown() || mc.isTerminated()) { + return; + } + + long ms = timeout.toMillis(); + // Close the gRPC managed-channel if not shut down already. + try { + mc.shutdown(); + if (!mc.awaitTermination(ms, TimeUnit.MILLISECONDS)) { + log.warn("Graceful shutdown timed out: {}ms, channel: {}", ms, mc); + } + } catch (InterruptedException e) { + log.warn("Interrupted gracefully shutting down channel: {}", mc); + Thread.currentThread().interrupt(); + } + + // Forcefully shut down if still not terminated. + if (!mc.isTerminated()) { + try { + mc.shutdownNow(); + if (!mc.awaitTermination(15, TimeUnit.SECONDS)) { + log.warn("Forcefully shutdown timed out: 15s, channel: {}. ", mc); + } + } catch (InterruptedException e) { + log.warn("Interrupted forcefully shutting down channel: {}. ", mc); + Thread.currentThread().interrupt(); + } + } + } + + /** + * Check if the protobuf message is a simple value. + * + * @param message protobuf message + * @return true if the message is simple value + */ + public static boolean isSimpleValueMessage(Message message) { + if (isWrapperType(message.getClass())) { + return true; + } + if (message instanceof Value value) { + Value.KindCase kind = value.getKindCase(); + return kind == Value.KindCase.NULL_VALUE + || kind == Value.KindCase.NUMBER_VALUE + || kind == Value.KindCase.STRING_VALUE + || kind == Value.KindCase.BOOL_VALUE; + } + return false; + } + + /** + * Stringify the simple value message. + * + * @param message protobuf message + * @return string representation of the simple value message, {@code null} if the message is not simple value + */ + public static String stringifySimpleValueMessage(Message message) { + if (message instanceof BoolValue boolValue) { + return String.valueOf(boolValue.getValue()); + } + if (message instanceof Int32Value int32Value) { + return String.valueOf(int32Value.getValue()); + } + if (message instanceof Int64Value int64Value) { + return String.valueOf(int64Value.getValue()); + } + if (message instanceof UInt32Value uInt32Value) { + return String.valueOf(uInt32Value.getValue()); + } + if (message instanceof UInt64Value uInt64Value) { + return String.valueOf(uInt64Value.getValue()); + } + if (message instanceof FloatValue floatValue) { + return String.valueOf(floatValue.getValue()); + } + if (message instanceof DoubleValue doubleValue) { + return String.valueOf(doubleValue.getValue()); + } + if (message instanceof StringValue stringValue) { + return stringValue.getValue(); + } + if (message instanceof BytesValue bytesValue) { + return bytesValue.getValue().toStringUtf8(); + } + if (message instanceof Value value) { + return switch (value.getKindCase()) { + case NULL_VALUE -> "null"; + case NUMBER_VALUE -> String.valueOf(value.getNumberValue()); + case STRING_VALUE -> value.getStringValue(); + case BOOL_VALUE -> String.valueOf(value.getBoolValue()); + default -> null; + }; + } + return null; + } + + private static boolean isWrapperType(Class clz) { + return BoolValue.class.isAssignableFrom(clz) + || Int32Value.class.isAssignableFrom(clz) + || Int64Value.class.isAssignableFrom(clz) + || UInt32Value.class.isAssignableFrom(clz) + || UInt64Value.class.isAssignableFrom(clz) + || FloatValue.class.isAssignableFrom(clz) + || DoubleValue.class.isAssignableFrom(clz) + || StringValue.class.isAssignableFrom(clz) + || BytesValue.class.isAssignableFrom(clz); + } + + private static boolean isMatch( + HttpMethod requestMethod, + HttpMethod httpMethod, + @Nonnull String path, + PathTemplate pathTemplate, + Map attributes) { + if (!Objects.equals(requestMethod, httpMethod)) return false; + + path = trim(path, '/'); + if (path.contains(":") && !pathTemplate.endsWithCustomVerb()) { + return false; + } + + Map result = pathTemplate.match(path); + if (result == null) { + return false; + } + + attributes.put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, result); + return true; + } + + static String trim(String str, char c) { + if (str == null || str.isEmpty()) { + return str; + } + + int start = 0; + int end = str.length(); + + while (start < end && str.charAt(start) == c) { + start++; + } + + while (end > start && str.charAt(end - 1) == c) { + end--; + } + + return str.substring(start, end); + } + + record Route( + @Nonnull HttpRule httpRule, + @Nonnull MethodDescriptor invokeMethod, + @Nonnull Descriptors.MethodDescriptor methodDescriptor, + @Nonnull Predicate predicate, + @Nonnull List> additionalPredicates) {} + + record ServletPredicate(HttpMethod httpMethod, PathTemplate pathTemplate) implements Predicate { + + @Override + public boolean test(ServerRequest request) { + return isMatch(request.method(), httpMethod, request.path(), pathTemplate, request.attributes()); + } + } + + record ReactivePredicate(HttpMethod httpMethod, PathTemplate pathTemplate) + implements Predicate { + + @Override + public boolean test(org.springframework.web.reactive.function.server.ServerRequest request) { + return isMatch(request.method(), httpMethod, request.path(), pathTemplate, request.attributes()); + } + } +} diff --git a/grpc-extensions/grpc-transcoding/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grpc-extensions/grpc-transcoding/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..935824a6 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +grpcstarter.extensions.transcoding.GrpcTranscodingAutoConfiguration \ No newline at end of file diff --git a/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/Deps.java b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/Deps.java similarity index 86% rename from grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/Deps.java rename to grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/Deps.java index 3b1f906a..9cc5d952 100644 --- a/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/Deps.java +++ b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/Deps.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder; +package grpcstarter.extensions.transcoding; /** * @author Freeman diff --git a/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/JsonTranscoderIT.java b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/JsonTranscoderIT.java new file mode 100644 index 00000000..12e028c3 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/JsonTranscoderIT.java @@ -0,0 +1,199 @@ +package grpcstarter.extensions.transcoding; + +import static grpcstarter.extensions.transcoding.TestUtil.randomPort; +import static grpcstarter.extensions.transcoding.TestUtil.restTemplate; +import static grpcstarter.server.GrpcContextKeys.ResponseMetadataModifier; +import static org.assertj.core.api.Assertions.assertThat; +import static transcoding.TranscoderTest.SimpleRequest; +import static transcoding.TranscoderTest.SimpleResponse; + +import com.google.protobuf.Empty; +import com.google.protobuf.StringValue; +import io.grpc.Metadata; +import io.grpc.stub.StreamObserver; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import transcoding.SimpleServiceGrpc; +import transcoding.TranscoderTest; + +class JsonTranscoderIT { + + @ParameterizedTest + @ValueSource(strings = {"SERVLET", "REACTIVE"}) + void testTranscoderJson(String webType) { + int port = randomPort(); + var ctx = new SpringApplicationBuilder(Cfg.class) + .properties("server.port=" + port) + .web(WebApplicationType.valueOf(webType)) + .run(); + + var client = restTemplate(); + + // full path + var resp = client.exchange( + "http://localhost:" + port + "/transcoding.SimpleService/UnaryRpc", + HttpMethod.POST, + new HttpEntity<>( + """ + { + "requestMessage": "Hi" + } + """), + String.class); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(resp.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); + assertThat(resp.getBody()).isNotBlank(); + assertThat(resp.getBody()).isEqualTo(""" + {"responseMessage":"Hi, Hi"}"""); + + // path alias + resp = client.exchange( + "http://localhost:" + port + "/v1/unaryrpc", + HttpMethod.POST, + new HttpEntity<>( + """ + { + "requestMessage": "Hi" + } + """), + String.class); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(resp.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); + assertThat(resp.getHeaders().get("request-id")).containsExactly("001"); + assertThat(resp.getBody()).isNotBlank(); + assertThat(resp.getBody()).isEqualTo(""" + {"responseMessage":"Hi, Hi"}"""); + + // wrapper type parses as JSON is simple value format + // google.protobuf.StringValue convert to JSON, the result is "foo", not {"value":"foo"} + resp = client.exchange( + "http://localhost:" + port + "/v1/unaryrpc", + HttpMethod.POST, + new HttpEntity<>( + """ + { + "int32_wrapper": 1 + } + """), + String.class); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); + + // test wrong format + resp = client.exchange( + "http://localhost:" + port + "/v1/unaryrpc", + HttpMethod.POST, + new HttpEntity<>( + """ + { + "int32_wrapper": { + "value": 1 + } + } + """), + String.class); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + + ctx.close(); + } + + @ParameterizedTest + @ValueSource(strings = {"SERVLET", "REACTIVE"}) + void testUseAnotherPackageRequestMessage(String webType) { + int port = randomPort(); + var ctx = new SpringApplicationBuilder(Cfg.class) + .properties("server.port=" + port) + .web(WebApplicationType.valueOf(webType)) + .run(); + + var client = restTemplate(); + + var resp = client.postForEntity( + "http://localhost:" + port + "/transcoding.SimpleService/UseAnotherPackageRequestRpc", + null, + String.class); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(resp.getHeaders().getContentType()).hasToString("text/plain;charset=UTF-8"); + assertThat(resp.getBody()).isEqualTo("Hello"); + + ctx.close(); + } + + @ParameterizedTest + @ValueSource(strings = {"SERVLET", "REACTIVE"}) + void testUseSubMessageRequestRpc(String webType) { + int port = randomPort(); + var ctx = new SpringApplicationBuilder(Cfg.class) + .properties("server.port=" + port) + .web(WebApplicationType.valueOf(webType)) + .run(); + + var client = restTemplate(); + + var resp = client.postForEntity( + "http://localhost:" + port + "/transcoding.SimpleService/UseSubMessageRequestRpc", + new HttpEntity<>(""" + {"message":"Hello"}"""), + String.class); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(resp.getHeaders().getContentType()).hasToString("application/json"); + assertThat(resp.getBody()).isEqualTo(""" + {"message":"Hello"}"""); + + ctx.close(); + } + + @Configuration(proxyBeanMethods = false) + @EnableAutoConfiguration + static class Cfg extends SimpleServiceGrpc.SimpleServiceImplBase { + + @Override + public void unaryRpc(SimpleRequest request, StreamObserver ro) { + if (request.getRequestMessage().startsWith("err")) { + throw new IllegalArgumentException("invalid name: " + request.getRequestMessage()); + } + + ResponseMetadataModifier.addConsumer( + metadata -> metadata.put(Metadata.Key.of("request-id", Metadata.ASCII_STRING_MARSHALLER), "001")); + + ro.onNext(SimpleResponse.newBuilder() + .setResponseMessage("Hi, " + request.getRequestMessage()) + .build()); + ro.onCompleted(); + } + + @Override + public void serverStreamingRpc(SimpleRequest request, StreamObserver ro) { + ro.onNext(SimpleResponse.newBuilder() + .setResponseMessage("Hi, " + request.getRequestMessage()) + .build()); + ro.onNext(SimpleResponse.newBuilder() + .setResponseMessage("Hi, " + request.getRequestMessage()) + .build()); + ro.onCompleted(); + } + + @Override + public void useAnotherPackageRequestRpc(Empty request, StreamObserver responseObserver) { + responseObserver.onNext(StringValue.of("Hello")); + responseObserver.onCompleted(); + } + + @Override + public void useSubMessageRequestRpc( + TranscoderTest.UseSubMessageRequestRpcRequest.SubMessage request, + StreamObserver responseObserver) { + responseObserver.onNext(TranscoderTest.UseSubMessageRequestRpcResponse.SubMessage.newBuilder() + .setMessage("Hello") + .build()); + responseObserver.onCompleted(); + } + } +} diff --git a/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/TestUtil.java b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/TestUtil.java new file mode 100644 index 00000000..448a70d7 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/TestUtil.java @@ -0,0 +1,25 @@ +package grpcstarter.extensions.transcoding; + +import java.net.ServerSocket; +import lombok.SneakyThrows; +import org.springframework.boot.test.web.client.TestRestTemplate; + +/** + * @author Freeman + */ +class TestUtil { + + /** + * @return a random port + */ + @SneakyThrows + public static int randomPort() { + try (ServerSocket serverSocket = new ServerSocket(0)) { + return serverSocket.getLocalPort(); + } + } + + public static TestRestTemplate restTemplate() { + return new TestRestTemplate(); + } +} diff --git a/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/TranscoderTest.java b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/TranscoderTest.java new file mode 100644 index 00000000..e5975b32 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/TranscoderTest.java @@ -0,0 +1,170 @@ +package grpcstarter.extensions.transcoding; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import com.google.api.HttpRule; +import java.util.Map; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; + +/** + * {@link Transcoder} tester. + */ +class TranscoderTest { + + @Test + void testInto() { + var request = buildRequest( + Map.of("requestMessage", "y3"), + """ + {"some_message": "x1", "requestMessage": "y1"} + """, + Map.of( + "some_message", new String[] {"x2"}, + "requestMessage", new String[] {"y2"})); + + assertThat(request.getSomeMessage()).isEqualTo("x2"); // body is ignored when httpRule body is empty + assertThat(request.getRequestMessage()).isEqualTo("y3"); + assertThat(request.hasNested()).isFalse(); + } + + @Test + void testNested() { + var request = buildRequest( + null, + null, + Map.of( + "some_message", new String[] {"x1"}, + "requestMessage", new String[] {"y1"}, + "nested.some_message", new String[] {"x2"}, + "nested.requestMessage", new String[] {"y2"}, + "nested.nested.some_message", new String[] {"x3"}, + "nested.nested.repeated_string", new String[] {"a3", "b3"})); + + assertThat(request.getSomeMessage()).isEqualTo("x1"); + assertThat(request.getRequestMessage()).isEqualTo("y1"); + assertThat(request.hasNested()).isTrue(); + assertThat(request.getNested().getSomeMessage()).isEqualTo("x2"); + assertThat(request.getNested().getRequestMessage()).isEqualTo("y2"); + assertThat(request.getNested().hasNested()).isTrue(); + assertThat(request.getNested().getNested().getSomeMessage()).isEqualTo("x3"); + assertThat(request.getNested().getNested().getRepeatedStringList()).containsExactly("a3", "b3"); + } + + @Test + void testRepeated() { + var request = buildRequest( + null, + null, + Map.of( + "repeated_message.some_message", new String[] {"x2"}, + "repeated_message.requestMessage", new String[] {"y2"}, + "repeated_string", new String[] {"v1", "v2"})); + + assertThat(request.getRepeatedMessageList()).isEmpty(); + assertThat(request.getRepeatedStringList()).containsExactly("v1", "v2"); + + // test empty array + request = buildRequest(null, null, Map.of("repeated_string", new String[] {})); + + assertThat(request.getRepeatedMessageList()).isEmpty(); + assertThat(request.getRepeatedStringList()).isEmpty(); + } + + @Test + void testEnum() { + // use string + testEnumParsing("V1", transcoding.TranscoderTest.SimpleRequest.Enum.V1); + testEnumParsing("V2", transcoding.TranscoderTest.SimpleRequest.Enum.V2); + testEnumParsing(" ", transcoding.TranscoderTest.SimpleRequest.Enum.ENUM_UNSPECIFIED); + assertThatCode(() -> testEnumParsing("NON", transcoding.TranscoderTest.SimpleRequest.Enum.ENUM_UNSPECIFIED)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Can't parse enum value 'NON' for field 'enum'"); + + // use number + testEnumParsing("0", transcoding.TranscoderTest.SimpleRequest.Enum.ENUM_UNSPECIFIED); + testEnumParsing("1", transcoding.TranscoderTest.SimpleRequest.Enum.V1); + testEnumParsing("2", transcoding.TranscoderTest.SimpleRequest.Enum.V2); + assertThatCode(() -> testEnumParsing("3", transcoding.TranscoderTest.SimpleRequest.Enum.ENUM_UNSPECIFIED)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Can't parse enum value '3' for field 'enum'"); + } + + @Test + void testComplexBody() { + var body = + """ + { + "requestMessage": "Hi", + "some_message": "Hi", + "nested": { + "requestMessage": "Hi", + "some_message": "Hi", + "nested": { + "requestMessage": "Hi", + "some_message": "Hi", + "repeated_string": ["a", "b"] + } + }, + "repeated_string": ["a", "b"], + "repeated_message": [ + { + "requestMessage": "Hi", + "some_message": "Hi" + }, + { + "requestMessage": "Hi", + "some_message": "Hi" + } + ], + "enum": "V1", + "int32_wrapper": 1 + }"""; + + var request = buildRequest( + null, body, null, HttpRule.newBuilder().setBody("*").build()); + + assertThat(request.getRequestMessage()).isEqualTo("Hi"); + assertThat(request.getSomeMessage()).isEqualTo("Hi"); + assertThat(request.hasNested()).isTrue(); + assertThat(request.getNested().getRequestMessage()).isEqualTo("Hi"); + assertThat(request.getNested().getSomeMessage()).isEqualTo("Hi"); + assertThat(request.getNested().hasNested()).isTrue(); + assertThat(request.getNested().getNested().getRequestMessage()).isEqualTo("Hi"); + assertThat(request.getNested().getNested().getSomeMessage()).isEqualTo("Hi"); + assertThat(request.getNested().getNested().getRepeatedStringList()).containsExactly("a", "b"); + assertThat(request.getRepeatedStringList()).containsExactly("a", "b"); + assertThat(request.getRepeatedMessageList()).hasSize(2); + assertThat(request.getRepeatedMessage(0).getRequestMessage()).isEqualTo("Hi"); + assertThat(request.getRepeatedMessage(0).getSomeMessage()).isEqualTo("Hi"); + assertThat(request.getRepeatedMessage(1).getRequestMessage()).isEqualTo("Hi"); + assertThat(request.getRepeatedMessage(1).getSomeMessage()).isEqualTo("Hi"); + assertThat(request.getEnum()).isEqualTo(transcoding.TranscoderTest.SimpleRequest.Enum.V1); + assertThat(request.getInt32Wrapper().getValue()).isEqualTo(1); + } + + private static transcoding.TranscoderTest.SimpleRequest buildRequest( + Map pathVariables, String body, Map parameterMap) { + return buildRequest(pathVariables, body, parameterMap, HttpRule.getDefaultInstance()); + } + + @SneakyThrows + private static transcoding.TranscoderTest.SimpleRequest buildRequest( + Map pathVariables, String body, Map parameterMap, HttpRule httpRule) { + Transcoder transcoder = Transcoder.create( + new Transcoder.Variable(body != null ? body.getBytes(UTF_8) : null, parameterMap, pathVariables)); + + // body is empty, body is ignored + var builder = transcoding.TranscoderTest.SimpleRequest.newBuilder(); + transcoder.into(builder, httpRule); + return builder.build(); + } + + private static void testEnumParsing(String enumValue, transcoding.TranscoderTest.SimpleRequest.Enum expectedEnum) { + var request = buildRequest(null, null, Map.of("enum", new String[] {enumValue})); + + assertThat(request.getEnum()).isEqualTo(expectedEnum); + } +} diff --git a/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/ProtoUtilTest.java b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/UtilTest.java similarity index 67% rename from grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/ProtoUtilTest.java rename to grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/UtilTest.java index e1ba2d18..a6553892 100644 --- a/grpc-extensions/grpc-json-transcoder/src/test/java/com/freemanan/starter/grpc/extensions/jsontranscoder/util/ProtoUtilTest.java +++ b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/UtilTest.java @@ -1,17 +1,21 @@ -package com.freemanan.starter.grpc.extensions.jsontranscoder.util; +package grpcstarter.extensions.transcoding; -import static com.freemanan.starter.grpc.extensions.jsontranscoder.util.ProtoUtil.isSimpleValueMessage; +import static grpcstarter.extensions.transcoding.Util.isSimpleValueMessage; +import static grpcstarter.extensions.transcoding.Util.snakeToPascal; import static org.assertj.core.api.Assertions.assertThat; import com.google.protobuf.BoolValue; import com.google.protobuf.ByteString; import com.google.protobuf.BytesValue; +import com.google.protobuf.Descriptors; import com.google.protobuf.DoubleValue; +import com.google.protobuf.Empty; import com.google.protobuf.FloatValue; import com.google.protobuf.Int32Value; import com.google.protobuf.Int64Value; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.ListValue; +import com.google.protobuf.Message; import com.google.protobuf.NullValue; import com.google.protobuf.StringValue; import com.google.protobuf.Struct; @@ -19,10 +23,18 @@ import com.google.protobuf.UInt64Value; import com.google.protobuf.Value; import com.google.protobuf.util.JsonFormat; +import io.grpc.testing.protobuf.SimpleRequest; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; +import transcoding.TranscoderTest; -class ProtoUtilTest { +/** + * {@link Util} tester. + */ +class UtilTest { + /** + * {@link Util#isSimpleValueMessage(Message)} + */ @Test void testSimpleValue() { assertThat(isSimpleValueMessage(StringValue.of(""))).isTrue(); @@ -112,4 +124,54 @@ void testSimpleValueParse2Message() throws InvalidProtocolBufferException { assertThat(printer.print(valueBuilder.build())).isEqualTo("1.0"); } + + /** + * {@link Util#snakeToPascal(String)} + */ + @Test + void testSnakeToPascal() { + assertThat(snakeToPascal("snake_case")).isEqualTo("SnakeCase"); + assertThat(snakeToPascal("s_s")).isEqualTo("SS"); + assertThat(snakeToPascal("s")).isEqualTo("S"); + assertThat(snakeToPascal("Ss")).isEqualTo("Ss"); + assertThat(snakeToPascal("SS")).isEqualTo("SS"); + assertThat(snakeToPascal("Ss_ss")).isEqualTo("SsSs"); + assertThat(snakeToPascal("SsSs")).isEqualTo("SsSs"); + assertThat(snakeToPascal("ssSs")).isEqualTo("SsSs"); + } + + /** + * {@link Util#getClassName(Descriptors.Descriptor)} + */ + @Test + void testGetClassName() { + var descriptor = TranscoderTest.UseSubMessageRequestRpcRequest.SubMessage.getDescriptor(); + assertThat(Util.getClassName(descriptor)).isEqualTo("UseSubMessageRequestRpcRequest$SubMessage"); + + descriptor = TranscoderTest.UseSubMessageRequestRpcRequest.getDescriptor(); + assertThat(Util.getClassName(descriptor)).isEqualTo("UseSubMessageRequestRpcRequest"); + } + + /** + * {@link Util#getDefaultMessage(Descriptors.Descriptor)} + */ + @Test + void testGetDefaultMessage() { + var descriptor = TranscoderTest.UseSubMessageRequestRpcRequest.SubMessage.getDescriptor(); + assertThat(Util.getDefaultMessage(descriptor)) + .isEqualTo(TranscoderTest.UseSubMessageRequestRpcRequest.SubMessage.getDefaultInstance()); + + descriptor = TranscoderTest.UseSubMessageRequestRpcRequest.getDescriptor(); + assertThat(Util.getDefaultMessage(descriptor)) + .isEqualTo(TranscoderTest.UseSubMessageRequestRpcRequest.getDefaultInstance()); + + descriptor = Empty.getDescriptor(); + assertThat(Util.getDefaultMessage(descriptor)).isEqualTo(Empty.getDefaultInstance()); + + descriptor = Int32Value.getDescriptor(); + assertThat(Util.getDefaultMessage(descriptor)).isEqualTo(Int32Value.getDefaultInstance()); + + descriptor = SimpleRequest.getDescriptor(); + assertThat(Util.getDefaultMessage(descriptor)).isEqualTo(SimpleRequest.getDefaultInstance()); + } } diff --git a/grpc-extensions/grpc-transcoding/src/test/proto/transcoder_test.proto b/grpc-extensions/grpc-transcoding/src/test/proto/transcoder_test.proto new file mode 100644 index 00000000..18a13ec7 --- /dev/null +++ b/grpc-extensions/grpc-transcoding/src/test/proto/transcoder_test.proto @@ -0,0 +1,77 @@ +syntax = "proto3"; + +import "google/api/annotations.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/empty.proto"; + +package transcoding; + +// A simple service for test. +service SimpleService { + // Simple unary RPC. + rpc UnaryRpc (SimpleRequest) returns (SimpleResponse) { + option (google.api.http) = { + post: "/v1/unaryrpc", + body: "*", + additional_bindings: { + get: "/v1/unaryrpc/{requestMessage=*}" + } + }; + } + + // Simple server-to-client streaming RPC. + rpc ServerStreamingRpc (SimpleRequest) returns (stream SimpleResponse) { + option (google.api.http) = { + get: "/v1/serverstreaming" + }; + } + + // Use another package in the request message. + rpc UseAnotherPackageRequestRpc (google.protobuf.Empty) returns (google.protobuf.StringValue) {} + + // Use sub message in the request message. + rpc UseSubMessageRequestRpc (UseSubMessageRequestRpcRequest.SubMessage) returns (UseSubMessageRequestRpcResponse.SubMessage) {} + +} + +// A simple request message type for test. +message SimpleRequest { + // An optional string message for test, camelCase naming. + string requestMessage = 1; + // Underline naming + string some_message = 2; + // Nested message + SimpleRequest nested = 3; + // Repeated string + repeated string repeated_string = 4; + // Repeated message + repeated SimpleRequest repeated_message = 5; + // Enum + Enum enum = 6; + // Wrappers + google.protobuf.Int32Value int32_wrapper = 7; + + enum Enum { + ENUM_UNSPECIFIED = 0; + V1 = 1; + V2 = 2; + } +} + +// A simple response message type for test. +message SimpleResponse { + // An optional string message for test. + string responseMessage = 1; +} + +message UseSubMessageRequestRpcRequest { + message SubMessage { + string message = 1; + } +} + +message UseSubMessageRequestRpcResponse { + message SubMessage { + string message = 1; + } +} diff --git a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationAutoConfiguration.java b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/GrpcValidationAutoConfiguration.java similarity index 93% rename from grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationAutoConfiguration.java rename to grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/GrpcValidationAutoConfiguration.java index ea173afd..3058e018 100644 --- a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationAutoConfiguration.java +++ b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/GrpcValidationAutoConfiguration.java @@ -1,10 +1,10 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import build.buf.protovalidate.Validator; -import com.freemanan.starter.grpc.client.ConditionOnGrpcClientEnabled; -import com.freemanan.starter.grpc.client.GrpcClientProperties; -import com.freemanan.starter.grpc.server.ConditionOnGrpcServerEnabled; -import com.freemanan.starter.grpc.server.GrpcServerProperties; +import grpcstarter.client.ConditionOnGrpcClientEnabled; +import grpcstarter.client.GrpcClientProperties; +import grpcstarter.server.ConditionOnGrpcServerEnabled; +import grpcstarter.server.GrpcServerProperties; import io.envoyproxy.pgv.ReflectiveValidatorIndex; import io.envoyproxy.pgv.ValidatorIndex; import io.envoyproxy.pgv.grpc.ValidatingClientInterceptor; diff --git a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationProperties.java b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/GrpcValidationProperties.java similarity index 96% rename from grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationProperties.java rename to grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/GrpcValidationProperties.java index 24752011..575222f0 100644 --- a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationProperties.java +++ b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/GrpcValidationProperties.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/OrderedValidatingClientInterceptor.java b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/OrderedValidatingClientInterceptor.java similarity index 89% rename from grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/OrderedValidatingClientInterceptor.java rename to grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/OrderedValidatingClientInterceptor.java index 797681eb..858cfeed 100644 --- a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/OrderedValidatingClientInterceptor.java +++ b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/OrderedValidatingClientInterceptor.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import io.envoyproxy.pgv.ValidatorIndex; import io.envoyproxy.pgv.grpc.ValidatingClientInterceptor; diff --git a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/OrderedValidatingServerInterceptor.java b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/OrderedValidatingServerInterceptor.java similarity index 89% rename from grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/OrderedValidatingServerInterceptor.java rename to grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/OrderedValidatingServerInterceptor.java index 5f3a44ad..ec4f8469 100644 --- a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/OrderedValidatingServerInterceptor.java +++ b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/OrderedValidatingServerInterceptor.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import io.envoyproxy.pgv.ValidatorIndex; import io.envoyproxy.pgv.grpc.ValidatingServerInterceptor; diff --git a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ProtoValidateClientInterceptor.java b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ProtoValidateClientInterceptor.java similarity index 85% rename from grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ProtoValidateClientInterceptor.java rename to grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ProtoValidateClientInterceptor.java index 94227a4f..58f70604 100644 --- a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ProtoValidateClientInterceptor.java +++ b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ProtoValidateClientInterceptor.java @@ -1,7 +1,7 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; -import static com.freemanan.starter.grpc.extensions.validation.ValidationExceptionUtil.asInternalException; -import static com.freemanan.starter.grpc.extensions.validation.ValidationExceptionUtil.asInvalidArgumentException; +import static grpcstarter.extensions.validation.ValidationExceptionUtil.asInternalException; +import static grpcstarter.extensions.validation.ValidationExceptionUtil.asInvalidArgumentException; import build.buf.protovalidate.ValidationResult; import build.buf.protovalidate.Validator; diff --git a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ProtoValidateServerInterceptor.java b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ProtoValidateServerInterceptor.java similarity index 93% rename from grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ProtoValidateServerInterceptor.java rename to grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ProtoValidateServerInterceptor.java index ce2e0f20..eadec089 100644 --- a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ProtoValidateServerInterceptor.java +++ b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ProtoValidateServerInterceptor.java @@ -1,6 +1,6 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; -import static com.freemanan.starter.grpc.extensions.validation.ValidationExceptionUtil.asInvalidArgumentException; +import static grpcstarter.extensions.validation.ValidationExceptionUtil.asInvalidArgumentException; import build.buf.protovalidate.ValidationResult; import build.buf.protovalidate.Validator; diff --git a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ValidationExceptionUtil.java b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ValidationExceptionUtil.java similarity index 94% rename from grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ValidationExceptionUtil.java rename to grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ValidationExceptionUtil.java index fe420dfc..9103ec47 100644 --- a/grpc-extensions/grpc-validation/src/main/java/com/freemanan/starter/grpc/extensions/validation/ValidationExceptionUtil.java +++ b/grpc-extensions/grpc-validation/src/main/java/grpcstarter/extensions/validation/ValidationExceptionUtil.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import build.buf.protovalidate.exceptions.ValidationException; import build.buf.validate.Violation; @@ -21,7 +21,7 @@ class ValidationExceptionUtil { * @return {@link StatusRuntimeException} */ public static StatusRuntimeException asInternalException(ValidationException ex) { - return new StatusRuntimeException(Status.INTERNAL.withDescription(ex.getLocalizedMessage())); + return new StatusRuntimeException(Status.INTERNAL.withDescription(ex.getMessage())); } /** diff --git a/grpc-extensions/grpc-validation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grpc-extensions/grpc-validation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 4ce616d7..e8bf6719 100644 --- a/grpc-extensions/grpc-validation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/grpc-extensions/grpc-validation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1 @@ -com.freemanan.starter.grpc.extensions.validation.GrpcValidationAutoConfiguration +grpcstarter.extensions.validation.GrpcValidationAutoConfiguration diff --git a/grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationAutoConfigurationTest.java b/grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/GrpcValidationAutoConfigurationTest.java similarity index 98% rename from grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationAutoConfigurationTest.java rename to grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/GrpcValidationAutoConfigurationTest.java index 2911bc50..ef3dd6b7 100644 --- a/grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/GrpcValidationAutoConfigurationTest.java +++ b/grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/GrpcValidationAutoConfigurationTest.java @@ -1,4 +1,4 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import static com.freemanan.cr.core.anno.Verb.EXCLUDE; import static org.assertj.core.api.Assertions.assertThat; diff --git a/grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationClientDisabledIT.java b/grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationClientDisabledIT.java similarity index 91% rename from grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationClientDisabledIT.java rename to grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationClientDisabledIT.java index fb3f78a4..45f0941f 100644 --- a/grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationClientDisabledIT.java +++ b/grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationClientDisabledIT.java @@ -1,12 +1,12 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import static org.assertj.core.api.Assertions.assertThatCode; -import com.freemanan.starter.grpc.extensions.test.InProcessName; -import com.freemanan.starter.grpc.extensions.test.StubUtil; import com.freemanan.validation.v1.Foo; import com.freemanan.validation.v1.FooServiceGrpc; import com.freemanan.validation.v1.GetFooRequest; +import grpcstarter.extensions.test.InProcessName; +import grpcstarter.extensions.test.StubUtil; import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; import org.junit.jupiter.api.Test; diff --git a/grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationClientServerDisabledIT.java b/grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationClientServerDisabledIT.java similarity index 90% rename from grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationClientServerDisabledIT.java rename to grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationClientServerDisabledIT.java index 8788f7cf..519884e9 100644 --- a/grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationClientServerDisabledIT.java +++ b/grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationClientServerDisabledIT.java @@ -1,12 +1,12 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import static org.assertj.core.api.Assertions.assertThatCode; -import com.freemanan.starter.grpc.extensions.test.InProcessName; -import com.freemanan.starter.grpc.extensions.test.StubUtil; import com.freemanan.validation.v1.Foo; import com.freemanan.validation.v1.FooServiceGrpc; import com.freemanan.validation.v1.GetFooRequest; +import grpcstarter.extensions.test.InProcessName; +import grpcstarter.extensions.test.StubUtil; import io.grpc.stub.StreamObserver; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; diff --git a/grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationIT.java b/grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationIT.java similarity index 92% rename from grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationIT.java rename to grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationIT.java index 1e4e9bd9..e8b715a9 100644 --- a/grpc-extensions/grpc-validation/src/test/java/com/freemanan/starter/grpc/extensions/validation/PgvValidationIT.java +++ b/grpc-extensions/grpc-validation/src/test/java/grpcstarter/extensions/validation/PgvValidationIT.java @@ -1,13 +1,13 @@ -package com.freemanan.starter.grpc.extensions.validation; +package grpcstarter.extensions.validation; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; -import com.freemanan.starter.grpc.extensions.test.InProcessName; -import com.freemanan.starter.grpc.extensions.test.StubUtil; import com.freemanan.validation.v1.Foo; import com.freemanan.validation.v1.FooServiceGrpc; import com.freemanan.validation.v1.GetFooRequest; +import grpcstarter.extensions.test.InProcessName; +import grpcstarter.extensions.test.StubUtil; import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; import org.junit.jupiter.api.Test; diff --git a/grpc-starter-dependencies/build.gradle b/grpc-starter-dependencies/build.gradle index 3c9ecd36..f878187c 100644 --- a/grpc-starter-dependencies/build.gradle +++ b/grpc-starter-dependencies/build.gradle @@ -23,10 +23,10 @@ dependencies { api(project(":grpc-boot-autoconfigure:grpc-server-boot-autoconfigure")) // extensions - api(project(":grpc-extensions:grpc-json-transcoder")) api(project(":grpc-extensions:grpc-metrics")) api(project(":grpc-extensions:grpc-test")) api(project(":grpc-extensions:grpc-tracing")) + api(project(":grpc-extensions:grpc-transcoding")) api(project(":grpc-extensions:grpc-validation")) // starters @@ -37,12 +37,9 @@ dependencies { api(project(":grpc-starters:grpc-starter-protovalidate")) api(project(":grpc-starters:grpc-starter-test")) api(project(":grpc-starters:grpc-starter-tracing")) + api(project(":grpc-starters:grpc-starter-transcoding-webflux")) + api(project(":grpc-starters:grpc-starter-transcoding-webmvc")) api(project(":grpc-starters:grpc-starter-validation")) - api(project(":grpc-starters:grpc-starter-web")) - api(project(":grpc-starters:grpc-starter-webflux")) - - // sample api - api(project(":examples:grpc-sample-api")) } api(platform("io.grpc:grpc-bom:${grpcVersion}")) diff --git a/grpc-starters/grpc-starter-metrics/build.gradle b/grpc-starters/grpc-starter-metrics/build.gradle index 14992313..4054e808 100644 --- a/grpc-starters/grpc-starter-metrics/build.gradle +++ b/grpc-starters/grpc-starter-metrics/build.gradle @@ -1,5 +1,6 @@ dependencies { api(project(":grpc-extensions:grpc-metrics")) + api("org.springframework.boot:spring-boot-starter-actuator") optionalSupportApi("org.springframework.boot:spring-boot-starter-aop") diff --git a/grpc-starters/grpc-starter-tracing/build.gradle b/grpc-starters/grpc-starter-tracing/build.gradle index f608af81..15bec0e4 100644 --- a/grpc-starters/grpc-starter-tracing/build.gradle +++ b/grpc-starters/grpc-starter-tracing/build.gradle @@ -1,5 +1,7 @@ dependencies { api(project(":grpc-extensions:grpc-tracing")) + api("org.springframework.boot:spring-boot-starter-actuator") + api("io.micrometer:micrometer-tracing") optionalSupportApi("io.micrometer:micrometer-tracing-bridge-brave") optionalSupportApi("io.micrometer:micrometer-tracing-bridge-otel") diff --git a/grpc-starters/grpc-starter-transcoding-webflux/build.gradle b/grpc-starters/grpc-starter-transcoding-webflux/build.gradle new file mode 100644 index 00000000..91019d89 --- /dev/null +++ b/grpc-starters/grpc-starter-transcoding-webflux/build.gradle @@ -0,0 +1,6 @@ +dependencies { + api(project(":grpc-extensions:grpc-transcoding")) + api("org.springframework.boot:spring-boot-starter-webflux") +} + +apply from: "${rootDir}/gradle/deploy.gradle" diff --git a/grpc-starters/grpc-starter-web/build.gradle b/grpc-starters/grpc-starter-transcoding-webmvc/build.gradle similarity index 68% rename from grpc-starters/grpc-starter-web/build.gradle rename to grpc-starters/grpc-starter-transcoding-webmvc/build.gradle index 067142af..a81e078b 100644 --- a/grpc-starters/grpc-starter-web/build.gradle +++ b/grpc-starters/grpc-starter-transcoding-webmvc/build.gradle @@ -1,5 +1,5 @@ dependencies { - api(project(":grpc-extensions:grpc-json-transcoder")) + api(project(":grpc-extensions:grpc-transcoding")) api("org.springframework.boot:spring-boot-starter-web") } diff --git a/grpc-starters/grpc-starter-webflux/build.gradle b/grpc-starters/grpc-starter-webflux/build.gradle deleted file mode 100644 index cc9c85ab..00000000 --- a/grpc-starters/grpc-starter-webflux/build.gradle +++ /dev/null @@ -1,12 +0,0 @@ -dependencies { - // Do not use shaded netty when using webflux, - // because they both use netty and it will increase the size of the package (has two versions of netty). - api(project(":grpc-extensions:grpc-json-transcoder")) - api("io.grpc:grpc-netty") { - // using the netty version of spring-boot-starter-webflux - exclude(group: "io.netty") - } - api("org.springframework.boot:spring-boot-starter-webflux") -} - -apply from: "${rootDir}/gradle/deploy.gradle" diff --git a/settings.gradle b/settings.gradle index b3b5f7cc..10df8789 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,21 +8,21 @@ pluginManagement { rootProject.name = 'grpc-starter' -// core autoconfigure +// core autoconfigure, order by name include(":grpc-boot-autoconfigure:grpc-client-boot-autoconfigure") include(":grpc-boot-autoconfigure:grpc-server-boot-autoconfigure") -// extensions -include(":grpc-extensions:grpc-json-transcoder") +// extensions, order by name include(":grpc-extensions:grpc-metrics") -include(":grpc-extensions:grpc-tracing") include(":grpc-extensions:grpc-test") +include(":grpc-extensions:grpc-tracing") +include(":grpc-extensions:grpc-transcoding") include(":grpc-extensions:grpc-validation") // bom include(":grpc-starter-dependencies") -// starters +// starters, order by name include(":grpc-starters:grpc-boot-starter") include(":grpc-starters:grpc-client-boot-starter") include(":grpc-starters:grpc-server-boot-starter") @@ -30,19 +30,25 @@ include(":grpc-starters:grpc-starter-metrics") include(":grpc-starters:grpc-starter-protovalidate") include(":grpc-starters:grpc-starter-test") include(":grpc-starters:grpc-starter-tracing") +include(":grpc-starters:grpc-starter-transcoding-webflux") +include(":grpc-starters:grpc-starter-transcoding-webmvc") include(":grpc-starters:grpc-starter-validation") -include(":grpc-starters:grpc-starter-web") -include(":grpc-starters:grpc-starter-webflux") -// examples +// examples, order by name include(":examples:grpc-sample-api") -include(":examples:json-transcoder:webflux") -include(":examples:json-transcoder:webmvc") include(":examples:metrics") +include(":examples:multi-module:api") +include(":examples:multi-module:server") include(":examples:proto-validate") include(":examples:quick-start") include(":examples:refresh") include(":examples:tls") include(":examples:tracing") -include(":examples:user:user-api") -include(":examples:user:user-server") +include(":examples:transcoding:webflux") +include(":examples:transcoding:webmvc") + +java.util.Optional.of(new File("${rootDir}/.git/hooks")).filter { it.exists() && it.isDirectory() }.ifPresent { + new File("${rootDir}/.githooks").eachFile(groovy.io.FileType.FILES) { + java.nio.file.Files.copy(it.toPath(), new File("${rootDir}/.git/hooks", it.name).toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING) + } +}