From 214f9117681cd6b55ec80205647cd2badc0c0029 Mon Sep 17 00:00:00 2001 From: seal90 <578935869@qq.com> Date: Sat, 12 Apr 2025 15:04:18 +0800 Subject: [PATCH 1/3] add grpc client autowired Signed-off-by: seal90 <578935869@qq.com> --- .../dapr-spring-boot-autoconfigure/pom.xml | 6 + .../client/DaprInvokeAutoConfiguration.java | 21 ++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../dapr-spring-boot-starter/pom.xml | 5 + dapr-spring/dapr-spring-invoke/pom.xml | 25 ++ .../client/DaprGrpcBeanPostProcessor.java | 234 ++++++++++++++++++ .../invoke/grpc/client/DaprGrpcClient.java | 71 ++++++ dapr-spring/pom.xml | 1 + spring-boot-examples/consumer-app/pom.xml | 11 + .../invoke/grpc/HelloWorldController.java | 22 ++ spring-boot-examples/grpc-lib/pom.xml | 106 ++++++++ .../grpc-lib/src/main/proto/helloworld.proto | 23 ++ spring-boot-examples/pom.xml | 7 +- spring-boot-examples/producer-app/pom.xml | 16 ++ .../invoke/grpc/HelloWorldProducer.java | 19 ++ 15 files changed, 567 insertions(+), 1 deletion(-) create mode 100644 dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprInvokeAutoConfiguration.java create mode 100644 dapr-spring/dapr-spring-invoke/pom.xml create mode 100644 dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java create mode 100644 dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcClient.java create mode 100644 spring-boot-examples/consumer-app/src/main/java/io/dapr/springboot/examples/consumer/invoke/grpc/HelloWorldController.java create mode 100644 spring-boot-examples/grpc-lib/pom.xml create mode 100644 spring-boot-examples/grpc-lib/src/main/proto/helloworld.proto create mode 100644 spring-boot-examples/producer-app/src/main/java/io/dapr/springboot/examples/producer/invoke/grpc/HelloWorldProducer.java diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/pom.xml b/dapr-spring/dapr-spring-boot-autoconfigure/pom.xml index 3eca526528..cd8c2c6487 100644 --- a/dapr-spring/dapr-spring-boot-autoconfigure/pom.xml +++ b/dapr-spring/dapr-spring-boot-autoconfigure/pom.xml @@ -21,6 +21,12 @@ ${project.parent.version} true + + io.dapr.spring + dapr-spring-invoke + ${project.parent.version} + true + io.dapr.spring dapr-spring-messaging diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprInvokeAutoConfiguration.java b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprInvokeAutoConfiguration.java new file mode 100644 index 0000000000..42df54e5a0 --- /dev/null +++ b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprInvokeAutoConfiguration.java @@ -0,0 +1,21 @@ +package io.dapr.spring.boot.autoconfigure.client; + +import io.dapr.spring.invoke.grpc.client.DaprGrpcBeanPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; + +@AutoConfiguration +@AutoConfigureAfter(DaprClientAutoConfiguration.class) +public class DaprInvokeAutoConfiguration { + + @Bean + @ConditionalOnProperty(name = "dapr.invoke.grpc.client.daprGrpcClient.enabled", havingValue = "true", + matchIfMissing = true) + static DaprGrpcBeanPostProcessor daprGrpcClientBeanPostProcessor( + final ApplicationContext applicationContext) { + return new DaprGrpcBeanPostProcessor(applicationContext); + } +} diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index b583e70bfb..dc9b51d577 100644 --- a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ io.dapr.spring.boot.autoconfigure.client.DaprClientAutoConfiguration +io.dapr.spring.boot.autoconfigure.client.DaprInvokeAutoConfiguration diff --git a/dapr-spring/dapr-spring-boot-starters/dapr-spring-boot-starter/pom.xml b/dapr-spring/dapr-spring-boot-starters/dapr-spring-boot-starter/pom.xml index 623040b378..7ee3207676 100644 --- a/dapr-spring/dapr-spring-boot-starters/dapr-spring-boot-starter/pom.xml +++ b/dapr-spring/dapr-spring-boot-starters/dapr-spring-boot-starter/pom.xml @@ -35,6 +35,11 @@ dapr-spring-data ${project.parent.version} + + io.dapr.spring + dapr-spring-invoke + ${project.parent.version} + io.dapr.spring dapr-spring-messaging diff --git a/dapr-spring/dapr-spring-invoke/pom.xml b/dapr-spring/dapr-spring-invoke/pom.xml new file mode 100644 index 0000000000..19a3d5ca1b --- /dev/null +++ b/dapr-spring/dapr-spring-invoke/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + + io.dapr.spring + dapr-spring-parent + 0.15.0-SNAPSHOT + + + dapr-spring-invoke + dapr-spring-invoke + Dapr Spring Invoke + jar + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + + + + diff --git a/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java b/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java new file mode 100644 index 0000000000..f631779994 --- /dev/null +++ b/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java @@ -0,0 +1,234 @@ +package io.dapr.spring.invoke.grpc.client; + +import com.google.common.collect.Lists; +import io.dapr.client.DaprClient; +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientInterceptor; +import io.grpc.ClientInterceptors; +import io.grpc.stub.AbstractAsyncStub; +import io.grpc.stub.AbstractStub; +import org.springframework.beans.BeanInstantiationException; +import org.springframework.beans.BeansException; +import org.springframework.beans.InvalidPropertyException; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Parameter; +import java.util.List; + +import static java.util.Objects.requireNonNull; + +/** + * Handlers Dapr gRPC client in spring boot. + * Searches for fields and methods in beans that are annotated with {@link DaprGrpcClient} and sets them. + * + * @author seal90 (578935869@qq.com) + */ +public class DaprGrpcBeanPostProcessor implements BeanPostProcessor { + + private final ApplicationContext applicationContext; + + private DaprClient daprClient; + + public DaprGrpcBeanPostProcessor(ApplicationContext applicationContext) { + this.applicationContext = requireNonNull(applicationContext, "applicationContext"); + } + + @Override + public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException { + processDaprGprcClients(bean); + + return bean; + } + + /** + * Process Dapr gRPC client in bean. + * @param bean The bean to process. + */ + private void processDaprGprcClients(final Object bean) { + Class clazz = bean.getClass(); + do { + processDaprGprcClientFields(clazz, bean); + clazz = clazz.getSuperclass(); + } while (clazz != null); + } + + /** + * Process DaprGrpcClient annotation in bean. + * @param clazz The class to process. + * @param bean The bean to process. + */ + private void processDaprGprcClientFields(final Class clazz, final Object bean) { + for (final Field field : clazz.getDeclaredFields()) { + final DaprGrpcClient annotation = AnnotationUtils.findAnnotation(field, DaprGrpcClient.class); + if (annotation != null) { + ReflectionUtils.makeAccessible(field); + ReflectionUtils.setField(field, bean, processDaprGrpcClientPoint(field, field.getType(), annotation)); + } + } + } + + /** + * Processes DaprGrpcClient announce and computes the appropriate value for the injection. + * + * @param The type to be injected for the given injection point. + * @param injectionTarget The target member for the injection. + * @param injectionType The class that should injected type. + * @param annotation The DaprGrpcClient annotation instance. + * @return The value to be injected for the given injection point. + */ + private T processDaprGrpcClientPoint(final Member injectionTarget, final Class injectionType, + final DaprGrpcClient annotation) { + final String name = annotation.value(); + + final List interceptors = interceptorsFromAnnotation(annotation); + if (annotation.sortInterceptors()) { + interceptors.sort(AnnotationAwareOrderComparator.INSTANCE); + } + + return valueForMember(name, injectionTarget, injectionType, interceptors); + } + + /** + * Processes DaprGrpcClient announce with Channel or AbstractStub type. + * + * @param The type of the instance to be injected. + * @param The type of the AbstractStub implement class. + * @param name The name of target service name. + * @param injectionTarget The target member for the injection. + * @param injectionType The class that should injected type. + * @param interceptors The interceptors defined on DaprGrpcClient. + * @return The value that matches the type of the given field. + * @throws BeansException If the value of the field could not be created or the type of the field is unsupported. + */ + protected > T valueForMember(final String name, final Member injectionTarget, + final Class injectionType, + final List interceptors) + throws BeansException { + if (Channel.class.equals(injectionType)) { + Channel channel = getDaprClient().newGrpcStub(name, DaprGrpcBeanPostProcessor::newStub).getChannel(); + channel = ClientInterceptors.interceptForward(channel, interceptors); + return injectionType.cast(channel); + } else if (AbstractStub.class.isAssignableFrom(injectionType)) { + @SuppressWarnings("unchecked") + ST stub = getDaprClient().newGrpcStub(name, (daprChannel -> + createStub((Class)injectionType.asSubclass(AbstractStub.class), daprChannel))); + stub = stub.withInterceptors(interceptors.toArray(new ClientInterceptor[0])); + return injectionType.cast(stub); + } else { + if (injectionTarget != null) { + throw new InvalidPropertyException(injectionTarget.getDeclaringClass(), injectionTarget.getName(), + "Unsupported type " + injectionType.getName()); + } else { + throw new BeanInstantiationException(injectionType, "Unsupported grpc stub or channel type"); + } + } + } + + /** + * Create a new stub by stubType and channel. + * + * @param stubClass The stub class that needs to be created. + * @param channel The gRPC channel associated with the created stub, passed as a parameter to the stub factory. + * @return A newly created gRPC stub. + */ + private > T createStub(final Class stubClass, final Channel channel) { + try { + // Search for public static *Grpc#new*Stub(Channel) + final Class declaringClass = stubClass.getDeclaringClass(); + if (declaringClass != null) { + for (final Method method : declaringClass.getMethods()) { + final String name = method.getName(); + final int modifiers = method.getModifiers(); + final Parameter[] parameters = method.getParameters(); + if (name.startsWith("new") && name.endsWith("Stub") + && Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) + && method.getReturnType().isAssignableFrom(stubClass) + && parameters.length == 1 + && Channel.class.equals(parameters[0].getType())) { + return stubClass.cast(method.invoke(null, channel)); + } + } + } + + // Search for a public constructor *Stub(Channel) + final Constructor constructor = stubClass.getConstructor(Channel.class); + return constructor.newInstance(channel); + } catch (final Exception e) { + throw new BeanInstantiationException(stubClass, "Failed to create gRPC client", e); + } + } + + /** + * Create a new stub by stubType and channel. + * + * @param channel The grpc channel. + * @return The transparent stub instance. + */ + private static DaprTransparentStub newStub(final Channel channel) { + AbstractStub.StubFactory factory = new AbstractStub.StubFactory() { + public DaprTransparentStub newStub(final Channel channel, final CallOptions callOptions) { + return new DaprTransparentStub(channel, callOptions); + } + }; + return DaprTransparentStub.newStub(factory, channel); + } + + /** + * A transparent stub that for DaprClient get channel. + */ + private static class DaprTransparentStub extends AbstractAsyncStub { + private DaprTransparentStub(final Channel channel, final CallOptions callOptions) { + super(channel, callOptions); + } + + protected DaprTransparentStub build(final Channel channel, final CallOptions callOptions) { + return new DaprTransparentStub(channel, callOptions); + } + } + + /** + * Gets or creates the {@link ClientInterceptor}s that are referenced in the given annotation. + * + * @param annotation The annotation to get the interceptors for. + * @return A list containing the interceptors for the given annotation. + * @throws BeansException If the referenced interceptors weren't found or could not be created. + */ + protected List interceptorsFromAnnotation(final DaprGrpcClient annotation) throws BeansException { + final List list = Lists.newArrayList(); + for (final Class interceptorClass : annotation.interceptors()) { + final ClientInterceptor clientInterceptor; + if (this.applicationContext.getBeanNamesForType(interceptorClass).length > 0) { + clientInterceptor = this.applicationContext.getBean(interceptorClass); + } else { + try { + clientInterceptor = interceptorClass.getConstructor().newInstance(); + } catch (final Exception e) { + throw new BeanCreationException("Failed to create interceptor instance", e); + } + } + list.add(clientInterceptor); + } + for (final String interceptorName : annotation.interceptorNames()) { + list.add(this.applicationContext.getBean(interceptorName, ClientInterceptor.class)); + } + return list; + } + + private DaprClient getDaprClient() { + if (this.daprClient == null) { + this.daprClient = this.applicationContext.getBean(DaprClient.class); + } + return this.daprClient; + } +} diff --git a/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcClient.java b/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcClient.java new file mode 100644 index 0000000000..427fa9329b --- /dev/null +++ b/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcClient.java @@ -0,0 +1,71 @@ +package io.dapr.spring.invoke.grpc.client; + +import io.grpc.Channel; +import io.grpc.ClientInterceptor; +import io.grpc.stub.AbstractStub; +import org.springframework.beans.factory.annotation.Autowired; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation for fields of type {@link Channel} or subclasses of {@link AbstractStub}/gRPC client services. + * + *

+ * Note: Fields that are annotated with this annotation should NOT be annotated with + * {@link Autowired} (conflict). + *

+ * + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface DaprGrpcClient { + + /** + * The name of the target service. The channel use DaprClient's grpc channel. + * + *

+ * Example: @DaprGrpcClient("exampleService") <-> + * {@code headers.put(Metadata.Key.of("dapr-app-id", Metadata.ASCII_STRING_MARSHALLER), name); } + *

+ * + * @return The name of the target service. + */ + String value(); + + /** + * A list of {@link ClientInterceptor} classes that should be used with this client in addition to the globally + * defined ones. If a bean of the given type exists, it will be used; otherwise a new instance of that class will be + * created via no-args constructor. + * + * @return A list of ClientInterceptor classes that should be used. + */ + Class[] interceptors() default {}; + + /** + * A list of {@link ClientInterceptor} beans that should be used with this client in addition to the globally + * defined ones. + * + * @return A list of ClientInterceptor beans that should be used. + */ + String[] interceptorNames() default {}; + + /** + * Whether the custom ClientInterceptor defined by interceptors and interceptorNames should be sorted. + * + *

+ * Sorted by + * {@code interceptors.sort(AnnotationAwareOrderComparator.INSTANCE)} + *

+ * + * + * @return True, if the custom interceptors will be sorted. False otherwise. + */ + boolean sortInterceptors() default false; +} diff --git a/dapr-spring/pom.xml b/dapr-spring/pom.xml index fe4ebaa172..820c8a5765 100644 --- a/dapr-spring/pom.xml +++ b/dapr-spring/pom.xml @@ -19,6 +19,7 @@ dapr-spring-data + dapr-spring-invoke dapr-spring-messaging dapr-spring-workflows dapr-spring-boot-autoconfigure diff --git a/spring-boot-examples/consumer-app/pom.xml b/spring-boot-examples/consumer-app/pom.xml index b2e2d09406..9e50f21888 100644 --- a/spring-boot-examples/consumer-app/pom.xml +++ b/spring-boot-examples/consumer-app/pom.xml @@ -13,6 +13,10 @@ Spring Boot, Testcontainers and Dapr Integration Examples :: Consumer App + + io.dapr + grpc-lib + org.springframework.boot spring-boot-starter-web @@ -62,6 +66,13 @@ org.springframework.boot spring-boot-maven-plugin + + + + repackage + + + org.apache.maven.plugins diff --git a/spring-boot-examples/consumer-app/src/main/java/io/dapr/springboot/examples/consumer/invoke/grpc/HelloWorldController.java b/spring-boot-examples/consumer-app/src/main/java/io/dapr/springboot/examples/consumer/invoke/grpc/HelloWorldController.java new file mode 100644 index 0000000000..c109d38383 --- /dev/null +++ b/spring-boot-examples/consumer-app/src/main/java/io/dapr/springboot/examples/consumer/invoke/grpc/HelloWorldController.java @@ -0,0 +1,22 @@ +package io.dapr.springboot.examples.consumer.invoke.grpc; + +import io.dapr.examples.DaprExamplesProtos; +import io.dapr.examples.HelloWorldGrpc; +import io.dapr.spring.invoke.grpc.client.DaprGrpcClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloWorldController { + + @DaprGrpcClient("producer-app") + private HelloWorldGrpc.HelloWorldBlockingStub blockingStub; + + @RequestMapping("/hello") + public String sayHello(@RequestParam("name") String name) { + DaprExamplesProtos.HelloRequest request = DaprExamplesProtos.HelloRequest.newBuilder().setName(name).build(); + DaprExamplesProtos.HelloReply reply = blockingStub.sayHello(request); + return reply.getMessage(); + } +} diff --git a/spring-boot-examples/grpc-lib/pom.xml b/spring-boot-examples/grpc-lib/pom.xml new file mode 100644 index 0000000000..2e469c98e1 --- /dev/null +++ b/spring-boot-examples/grpc-lib/pom.xml @@ -0,0 +1,106 @@ + + + 4.0.0 + + io.dapr + spring-boot-examples + 0.15.0-SNAPSHOT + + + grpc-lib + grpc-lib + protobuf files + + + ${project.build.directory}/generated-sources + ${project.basedir}/src/main/proto + + + + + io.grpc + grpc-protobuf + ${grpc.version} + + + io.grpc + grpc-stub + ${grpc.version} + + + io.grpc + grpc-api + ${grpc.version} + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + com.google.protobuf + protobuf-java-util + ${protobuf.version} + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + + + + com.github.os72 + protoc-jar-maven-plugin + 3.11.4 + + + generate-sources + + run + + + ${protobuf.version} + inputs + direct + true + + ${protobuf.input.directory} + + + + java + ${protobuf.output.directory} + + + grpc-java + ${protobuf.output.directory} + io.grpc:protoc-gen-grpc-java:${grpc.version} + + + + + + + + org.apache.maven.plugins + maven-site-plugin + + true + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + true + + + + + + diff --git a/spring-boot-examples/grpc-lib/src/main/proto/helloworld.proto b/spring-boot-examples/grpc-lib/src/main/proto/helloworld.proto new file mode 100644 index 0000000000..d5c37bae13 --- /dev/null +++ b/spring-boot-examples/grpc-lib/src/main/proto/helloworld.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +package daprexamples; + +option java_outer_classname = "DaprExamplesProtos"; +option java_package = "io.dapr.examples"; + +// User Code definitions +service HelloWorld { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} + +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} \ No newline at end of file diff --git a/spring-boot-examples/pom.xml b/spring-boot-examples/pom.xml index 75a32364f7..958ae89caa 100644 --- a/spring-boot-examples/pom.xml +++ b/spring-boot-examples/pom.xml @@ -19,6 +19,7 @@ + grpc-lib producer-app consumer-app @@ -30,7 +31,11 @@ spring-boot-dependencies ${springboot.version} pom - import + import + + io.dapr + grpc-lib + 0.15.0-SNAPSHOT diff --git a/spring-boot-examples/producer-app/pom.xml b/spring-boot-examples/producer-app/pom.xml index b9ab6fcbfa..2f952c316e 100644 --- a/spring-boot-examples/producer-app/pom.xml +++ b/spring-boot-examples/producer-app/pom.xml @@ -14,6 +14,10 @@ Spring Boot, Testcontainers and Dapr Integration Examples :: Producer App + + io.dapr + grpc-lib + org.springframework.boot spring-boot-starter-actuator @@ -30,6 +34,11 @@ io.dapr.spring dapr-spring-boot-starter + + net.devh + grpc-server-spring-boot-starter + 3.1.0.RELEASE + io.dapr.spring dapr-spring-boot-starter-test @@ -57,6 +66,13 @@ org.springframework.boot spring-boot-maven-plugin + + + + repackage + + + org.apache.maven.plugins diff --git a/spring-boot-examples/producer-app/src/main/java/io/dapr/springboot/examples/producer/invoke/grpc/HelloWorldProducer.java b/spring-boot-examples/producer-app/src/main/java/io/dapr/springboot/examples/producer/invoke/grpc/HelloWorldProducer.java new file mode 100644 index 0000000000..dd3d4e6aa4 --- /dev/null +++ b/spring-boot-examples/producer-app/src/main/java/io/dapr/springboot/examples/producer/invoke/grpc/HelloWorldProducer.java @@ -0,0 +1,19 @@ +package io.dapr.springboot.examples.producer.invoke.grpc; + +import io.dapr.examples.HelloWorldGrpc; +import net.devh.boot.grpc.server.service.GrpcService; +import org.springframework.stereotype.Service; + +@GrpcService +public class HelloWorldProducer extends HelloWorldGrpc.HelloWorldImplBase { + + @Override + public void sayHello(io.dapr.examples.DaprExamplesProtos.HelloRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.dapr.examples.DaprExamplesProtos.HelloReply reply = io.dapr.examples.DaprExamplesProtos.HelloReply.newBuilder() + .setMessage("Hello " + request.getName()) + .build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } +} From d6f59dc6273bd79d29dd12dde6f39f09bac21361 Mon Sep 17 00:00:00 2001 From: seal90 <578935869@qq.com> Date: Sat, 12 Apr 2025 15:59:15 +0800 Subject: [PATCH 2/3] fix spotbugs warn Signed-off-by: seal90 <578935869@qq.com> --- .../consumer/invoke/grpc/HelloWorldController.java | 4 ++-- .../grpc-lib/src/main/proto/helloworld.proto | 2 +- .../producer/invoke/grpc/HelloWorldProducer.java | 9 ++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/spring-boot-examples/consumer-app/src/main/java/io/dapr/springboot/examples/consumer/invoke/grpc/HelloWorldController.java b/spring-boot-examples/consumer-app/src/main/java/io/dapr/springboot/examples/consumer/invoke/grpc/HelloWorldController.java index c109d38383..e0ff69aad8 100644 --- a/spring-boot-examples/consumer-app/src/main/java/io/dapr/springboot/examples/consumer/invoke/grpc/HelloWorldController.java +++ b/spring-boot-examples/consumer-app/src/main/java/io/dapr/springboot/examples/consumer/invoke/grpc/HelloWorldController.java @@ -1,7 +1,7 @@ package io.dapr.springboot.examples.consumer.invoke.grpc; -import io.dapr.examples.DaprExamplesProtos; -import io.dapr.examples.HelloWorldGrpc; +import io.dapr.springboot.examples.DaprExamplesProtos; +import io.dapr.springboot.examples.HelloWorldGrpc; import io.dapr.spring.invoke.grpc.client.DaprGrpcClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; diff --git a/spring-boot-examples/grpc-lib/src/main/proto/helloworld.proto b/spring-boot-examples/grpc-lib/src/main/proto/helloworld.proto index d5c37bae13..df5502640c 100644 --- a/spring-boot-examples/grpc-lib/src/main/proto/helloworld.proto +++ b/spring-boot-examples/grpc-lib/src/main/proto/helloworld.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package daprexamples; option java_outer_classname = "DaprExamplesProtos"; -option java_package = "io.dapr.examples"; +option java_package = "io.dapr.springboot.examples"; // User Code definitions service HelloWorld { diff --git a/spring-boot-examples/producer-app/src/main/java/io/dapr/springboot/examples/producer/invoke/grpc/HelloWorldProducer.java b/spring-boot-examples/producer-app/src/main/java/io/dapr/springboot/examples/producer/invoke/grpc/HelloWorldProducer.java index dd3d4e6aa4..7ac6c7262f 100644 --- a/spring-boot-examples/producer-app/src/main/java/io/dapr/springboot/examples/producer/invoke/grpc/HelloWorldProducer.java +++ b/spring-boot-examples/producer-app/src/main/java/io/dapr/springboot/examples/producer/invoke/grpc/HelloWorldProducer.java @@ -1,16 +1,15 @@ package io.dapr.springboot.examples.producer.invoke.grpc; -import io.dapr.examples.HelloWorldGrpc; +import io.dapr.springboot.examples.HelloWorldGrpc; import net.devh.boot.grpc.server.service.GrpcService; -import org.springframework.stereotype.Service; @GrpcService public class HelloWorldProducer extends HelloWorldGrpc.HelloWorldImplBase { @Override - public void sayHello(io.dapr.examples.DaprExamplesProtos.HelloRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.dapr.examples.DaprExamplesProtos.HelloReply reply = io.dapr.examples.DaprExamplesProtos.HelloReply.newBuilder() + public void sayHello(io.dapr.springboot.examples.DaprExamplesProtos.HelloRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.dapr.springboot.examples.DaprExamplesProtos.HelloReply reply = io.dapr.springboot.examples.DaprExamplesProtos.HelloReply.newBuilder() .setMessage("Hello " + request.getName()) .build(); responseObserver.onNext(reply); From e6b3b43128db84efe223103a2353c2c8346feb59 Mon Sep 17 00:00:00 2001 From: seal90 <578935869@qq.com> Date: Sat, 12 Apr 2025 16:17:29 +0800 Subject: [PATCH 3/3] delete author Signed-off-by: seal90 <578935869@qq.com> --- .../spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java b/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java index f631779994..50859621fc 100644 --- a/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java +++ b/dapr-spring/dapr-spring-invoke/src/main/java/io/dapr/spring/invoke/grpc/client/DaprGrpcBeanPostProcessor.java @@ -32,7 +32,6 @@ * Handlers Dapr gRPC client in spring boot. * Searches for fields and methods in beans that are annotated with {@link DaprGrpcClient} and sets them. * - * @author seal90 (578935869@qq.com) */ public class DaprGrpcBeanPostProcessor implements BeanPostProcessor {