Skip to content
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

Added resolving beans by type #695

Merged
merged 13 commits into from Jul 16, 2019
Merged

Added resolving beans by type #695

merged 13 commits into from Jul 16, 2019

Conversation

fatroom
Copy link
Member

@fatroom fatroom commented Jun 17, 2019

Description

Inject tracer by bean reference instead of name

Motivation and Context

Currently tracer bean is injected by name. This leads to incompatibility issues with tracing-lightstep-spring-boot-starter > 0.1.5
Instead of relying on bean name for plugin registration, I've changed to loading by type.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.

@zalando zalando deleted a comment Jun 17, 2019
@whiskeysierra
Copy link
Collaborator

I believe we have a couple of other places where this could be useful. Basically whenever we inject by name right now. Logbook comes to mind, e.g.

@fatroom
Copy link
Member Author

fatroom commented Jun 18, 2019

Another way that came into my mind: register factories in postProcessBeanDefinitionRegistry and afterwards configure them in postProcessBeanFactory. This seems to be the most API-friendly way of solving the problem, but will require a lot(?) of changes in initialisation

@whiskeysierra
Copy link
Collaborator

I believe we have a couple of other places where this could be useful. Basically whenever we inject by name right now. Logbook comes to mind, e.g.

And MeterRegistry.

Another way that came into my mind: register factories in postProcessBeanDefinitionRegistry and afterwards configure them in postProcessBeanFactory. This seems to be the most API-friendly way of solving the problem, but will require a lot(?) of changes in initialisation

We have two kinds of configuration. Some of them completely disable a bean and others really just configure it. So we would need to spread this across both.

@fatroom
Copy link
Member Author

fatroom commented Jun 18, 2019

I would propose following:

  • introduce properties for *PluginFactories
  • leave creation of the factories for the postProcessBeanDefinitionRegistry so we got all the beans registered during appropriate phases
  • setup the properties from the postProcessBeanFactory so we got type resolving available for us.

If this sounds fine for you I'll start working on implementation.

We have two kinds of configuration. Some of them completely disable a bean and others really just configure it. So we would need to spread this across both.

I don't get this point. What do you mean by two kinds of configuration? Any sample in the code?

@whiskeysierra
Copy link
Collaborator

I don't get this point. What do you mean by two kinds of configuration? Any sample in the code?

riptide.clients.example:
  tracing:
    enabled: true
    tags:
      peer.service: example-service

The enabled property dictates that the bean should be registered (or not, if set to false) while the rest (e.g. tags) is meant to configure the bean (in this case OpenTracingPlugin).

So the configuration affects both the registration and wiring of beans as well as the configuration of the properties of said beans.

@whiskeysierra
Copy link
Collaborator

If this sounds fine for you I'll start working on implementation.

Looking forward to some code to discuss this further! 🎉

@fatroom
Copy link
Member Author

fatroom commented Jun 19, 2019

While implementing a lot of factories, I just recognised that we don't actually require that. So there's a lot more simplified approach. I haven't changed yet the metricsRegistry yet, since it leads to broken tests, and I want to figure out reasons for this behaviour.

@zalando zalando deleted a comment Jun 19, 2019
@zalando zalando deleted a comment Jun 19, 2019
bd.getConstructorArgumentValues()
.getIndexedArgumentValues()
.values().stream()
.filter(holder -> arg.equals(holder.getValue()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That feels risky.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fatroom
Copy link
Member Author

fatroom commented Jun 19, 2019

So with moving away from fixed name strategy, appropriate bean resolving will happen based on primary annotation if available, or the last one in the found beans.
Still I believe this approach is better than relying on the "bean name never change" strategy, as we know that this is not the case.

@@ -40,7 +40,8 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry regis

@Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException {
// nothing to do
final DefaultRiptideConfigurer configurer = new DefaultRiptideConfigurer(beanFactory, Defaulting.withDefaults(properties));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defaulting.withDefaults(properties) can be done once in setEnvironment

@whiskeysierra
Copy link
Collaborator

👍

@fatroom
Copy link
Member Author

fatroom commented Jul 5, 2019

@whiskeysierra while I was describing the changes in migration guide, something struck in my mind. Afaik if multiple beans of the same type present in spring context, but no primary explicitly defined I think spring will fail the context init. But last time I saw this behaviour was somewhere during initial release of spring 4, and not sure if it's current one. Should we follow this behaviour as well here, instead of injection of the first random bean?

@whiskeysierra
Copy link
Collaborator

I believe Spring tries to fallback to injecting by name. If that fails is usually complains about non-unique beans. Ideally we would hand over all of this work to Spring.

@fatroom
Copy link
Member Author

fatroom commented Jul 5, 2019

Switched to default spring behaviour: try to find primary bean, if not found use resolve by name.

@whiskeysierra
Copy link
Collaborator

You're missing some code coverage there.

@whiskeysierra
Copy link
Collaborator

👍

@whiskeysierra whiskeysierra merged commit e04558e into zalando:master Jul 16, 2019
@fatroom fatroom mentioned this pull request Jul 16, 2019
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants