-
Notifications
You must be signed in to change notification settings - Fork 864
Extra annotation for gRPC clients/stubs integration with spring context #580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extra annotation for gRPC clients/stubs integration with spring context #580
Conversation
I really like the idea of your change, but IMO the /**
* Annotation that can be added to `@Configuration` classes to create GrpcClient beans in the ApplicationContext.
*/
@Target(CLASS)
@Repeatable
public @interface GrpcClientBean {
/** The type of the bean to create. */
Class<?> clazz();
/** The name of the bean to create. If empty, a name will be generated automatically based on the bean class and the client name. */
String beanName() default "";
/** The client definition used to create the bean. */
GrpcClient definition();
} (Not sure about the property names yet) Usage: @Configuration
@GrpcClientBean(clazz = SimpleServiceStub.class, definition = @GrpcClient("foobar"))
public class GrpcBeanConfig {
MyAnotherExternalBean myExternalBean(SimpleServiceStub foobarSimpleServiceStub) {
return new MyAnotherExternalBean (foobarSimpleServiceStub);
}
} I'm not sure whether we should add a |
See also https://github.com/yidongnan/grpc-spring-boot-starter/issues/463 |
I thought about this problem. It seems to me that a good solution would be to declare the bean name as Unfortunately, this idea has failed.
That is why "soft" registration of the bean is proposed with try catch and only warn. Without this, indeed, even in the examples of unit tests, it was clear that about 50% would break without proper softness. It seems to me that this solution should not break anything in existing projects, and tests confirm this, while allowing you to use all the advantages of
To be honest, I don't like this solution, because for me all the beauty of this project is in 1 simple annotation that will do everything for you, then we will have more and more. On the other hand, we will be sure that nothing will break. |
After some debugging I managed to get it to work. In my case I either forgot to update one of the two I modified the code a bit to make it easier to debug: final String beanName = annotation.value() + injectionType.getSimpleName();
// final String beanName = Introspector.decapitalize(injectionType.getSimpleName());
try {
final ConfigurableListableBeanFactory beanFactory =
((ConfigurableApplicationContext) this.applicationContext).getBeanFactory();
final Set<String> names = Sets.newHashSet(beanFactory.getBeanNamesIterator());
beanFactory.registerSingleton(beanName, value);
final Set<String> names2 = Sets.newHashSet(beanFactory.getBeanNamesIterator());
names2.removeAll(names);
log.warn("New Names: {}", names2);
this.applicationContext.getAutowireCapableBeanFactory().autowireBean(value);
} catch (final Exception e) {
log.warn("Could not register and autowire bean: {}", beanName, e);
} IMO distinguishing them by client name is a requirement, especially since the following is potentially frequently used (especially if spread over multiple classes/libraries): @GrpcClient("test")
TestServiceGrpc.TestServiceBlockingStub blockingStub;
@GrpcClient("fallback")
TestServiceGrpc.TestServiceBlockingStub fallbackBlockingStub;
You are right. Your soft registration does not break any existing code, but it writes plenty of warnings to the logs.
Thanks for sharing your opinion. I summarized the benefits of each variant below, please comment, if I forgot something. Pro OneForAll: @GrpcClient("client")
private MyStub myStub;
Pro ExtraAnnotation: @GrpcClientBean(clazz = MyStub.class, definition = @GrpcClient("client"))
From this summary, I still prefer the ExtraAnnotation variant, but that's just my opinion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I consulted with @Shinigami92 and we came to the conclusion, that the unambiguity of the bean definition is more important than having only a single annotation for all.
Please change your PR to create an extra annotation for grpc clients/stubs that will be added to the application context.
Thank you very much for the research after reanalysis, the solution with additional annotation looks better for me now. I`ll start ASAP on this week Before starting, I propose to have your agreement with solution, that we should add annotation, which add to the context a bean /**
* Annotation that can be added to `@Configuration` classes to create GrpcClient beans in the ApplicationContext.
*/
@Target(CLASS)
@Repeatable
public @interface GrpcClientBean {
/** The type of the bean to create. */
Class<?> clazz();
/** The name of the bean to create. If empty, a name will be generated automatically based on the bean class and the client name. */
String beanName() default "";
/** The client definition used to create the bean. */
GrpcClient definition();
} But there are several questions that are not entirely clear to me:
|
Awesome. No need to rush though. Have a nice weekend!
I'm not sure about that. Will the beans get autowired if not called?
No, IMO the existing post processor is a good match for it -> Add this new feature to it.
That's a good question. My first thought was we should check for the
IMO we should not add any additional limitations on these, so it will be possible to to have both Any suggestions regarding field names? I'm really not sure which names would be best.
|
I think that simple and concise names just awesome. So |
…ntext registration
@ST-DDT would you be so kind to code review again? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, I have just some small suggestions regarding the code readability.
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
…ecessary dependency
@ST-DDT would you be so kind to final review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, for the delay with the review. I'm currently quite busy so I can only do a fast pass. I hope that I have more time next weekend.
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Final review before merge. 👍
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
...utoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java
Outdated
Show resolved
Hide resolved
Co-authored-by: ST-DDT <[email protected]>
Co-authored-by: ST-DDT <[email protected]>
Co-authored-by: ST-DDT <[email protected]>
Co-authored-by: ST-DDT <[email protected]>
Co-authored-by: ST-DDT <[email protected]>
Co-authored-by: ST-DDT <[email protected]>
Co-authored-by: ST-DDT <[email protected]>
…oot/grpc/client/inject/GrpcClientBeanPostProcessor.java Co-authored-by: ST-DDT <[email protected]>
…oot/grpc/client/inject/GrpcClientBeanPostProcessor.java Co-authored-by: ST-DDT <[email protected]>
@ST-DDT it seems that we have a flaky test - MetricCollectingInterceptorTest > testMetricsFailedCall() failed in different builds with just md changes:
Have I to commit something to rerun build or there is more another "handy" way? |
I am aware of that test, I already improved it multiple times to "fail less", but the error still prevails and I'm not sure why. Currently I get a ~1% chance of a failure in my local builds. Sometimes I suspect that it only happens at specific times.
I have a re-run button in travis, that I can use to execute the checks again. Not sure, whether you have it as well.
Feel free to have a try (once this one is merged). |
Thanks for your contribution! |
Please try do move the It looks like I need to improve the initialization/bean declaration order somehow. EDIT: Please try removing |
Context
Closes #463
There is a rather inconvenient problem described in https://github.com/yidongnan/grpc-spring-boot-starter/issues/463
@GrpcClient
is not a@Bean
, so we are encouraged to wrap it in a standard bean creation for quality of life.TO BE
TO DO
@Autowired
and@Qualifier
are available for method and field injection