Skip to content

[Spring] Exception is thrown complaining about multiple matching beans with version 1.2.5 #1225

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

Closed
EugeneS30 opened this issue Sep 18, 2017 · 12 comments · Fixed by #1226
Closed

Comments

@EugeneS30
Copy link

In the process of transitioning from version Cucumber 1.1.8 to 1.2.5 I have ran into an issue where the below exception is thrown:

CucumberException No qualifying bean of type x is defined: expected single matching bean but found 2

I tried to dig a bit deeper and I see that the <T> T getInstance(final Class<T> type) method in SpringFactory class had changed and apparently is somehow responsible for that behavior.

I was able to replicate this behavior in a simple project which I uploaded to github and the link is below.

Cucumber Version: 1.2.5
Operating System and version: Windows 7
Link to your project: https://github.com/EugeneS30/cucumber-bean-defect-verification.git

@mpkorstanje
Copy link
Contributor

mpkorstanje commented Sep 18, 2017

It appears to be that CoffeeSteps twice is registered twice. Once because it has the @ContextHierarchy/@ContextConfiguration annotation and once because it inherits the @Component annotation. One causes the bean to be named functional.coffeeSteps while the other causes the bean to be named coffeeSteps.

I do believe Cucumber should be smart enough to handle this but I don't know how to achieve this yet.

For the time being though you can declare CoffeeSteps without the @Component declaration.

@ContextHierarchy({@ContextConfiguration("classpath:/cucumber.xml")})
public class CoffeeSteps {

@mpkorstanje
Copy link
Contributor

This bug is also present is 2.0.x.

@EugeneS30
Copy link
Author

@mpkorstanje Thanks for the analysis.
In my project though if I get rid of the @Component annotation, I will end up getting the Annotations differs on glue classes found exception.

So it looks like I can't solve one issue without triggering the other.

@brasmusson
Copy link
Contributor

@EugeneS30 If your only put the @ContextHierarchy/@ContextConfiguration annotations on classes that do not have the @Component annotation, it should work (Cucumber-JVM only need to find one glue classes with @ContextHierarchy/@ContextConfiguration).

@EugeneS30
Copy link
Author

EugeneS30 commented Sep 18, 2017

@brasmusson Hi, thanks for your input.

Yes, I have already tried different combinations but I always end up getting this error one way or another.

Initially I used a parent class BddGlue that was defining the @ContextHierarchy({@ContextConfiguration("classpath:/cucumber.xml")}) and all other classes inherited from it.

Now I removed this class to make things a bit clearer and annotated all the classes that used to inherit from it with:
@ContextHierarchy({@ContextConfiguration("classpath:/cucumber.xml")})

Most of these classes do not need to be annotated with @Component anyway but the only class that does need, is triggering the double bean creation issue. Even though this class is not even annotated with:
@ContextHierarchy({@ContextConfiguration("classpath:/cucumber.xml")}). It just has the @Component annotation.

@EugeneS30
Copy link
Author

@mpkorstanje @brasmusson Hi, I have just removed all double annotations so that all glue including classes only have @ContextHierarchy({@ContextConfiguration("classpath:/cucumber.xml")}) and do not have the @component annotation and I have few classes annotated with @component but no @ContextHierarchy({@ContextConfiguration("classpath:/cucumber.xml")}).

Even in such case I get the double bean exception for one of the classes annotated with @Component even though it does not have any other annotations.

@EugeneS30
Copy link
Author

Just an update. As a workaround I was able to avoid the exception by using @Primary annotation in addition to @Component.

@mpkorstanje
Copy link
Contributor

mpkorstanje commented Sep 18, 2017

I reckon the problem can be found at SpringFactory.java#L114

    @Override
    public void start() {
        if (stepClassWithSpringContext != null) {
            testContextManager = new CucumberTestContextManager(stepClassWithSpringContext);
        } else {
            if (beanFactory == null) {
                beanFactory = createFallbackContext();
            }
        }
        notifyContextManagerAboutTestClassStarted();
        if (beanFactory == null || isNewContextCreated()) {
            beanFactory = testContextManager.getBeanFactory();
            for (Class<?> stepClass : stepClasses) {
                registerStepClassBeanDefinition(beanFactory, stepClass);
            }
        }
        GlueCodeContext.getInstance().start();
}

All stepClasses are registered as bean definitions. The set of step classes may however also include the stepClassWithSpringContext when annotated with @Component. When annotated stepClassWithSpringContext will be registered as a bean when used to create the CucumberTestContextManager.

@mpkorstanje
Copy link
Contributor

mpkorstanje commented Sep 19, 2017

Unfortunately we can't resolve this by simply skipping the registration of stepClassWithSpringContext when it is already defined.

We can't detect duplicate registrations. Bean registration is done by name. This is the fully qualified name when the bean is registered through class path scanning by cucumber, but only the fqn minus the root scanning package when done by Spring.

I reckon the current code is correct. But we could improve it somewhat by throw an exception when @Component or related stereo types are detected.

@mpkorstanje @brasmusson Hi, I have just removed all double annotations so that all glue including classes only have @ContextHierarchy({@ContextConfiguration("classpath:/cucumber.xml")}) and do not have the @component annotation and I have few classes annotated with @component but no @ContextHierarchy({@ContextConfiguration("classpath:/cucumber.xml")}).
Even in such case I get the double bean exception for one of the classes annotated with @component even though it does not have any other annotations.

@EugeneS30 do you by any chance happen to have multiple component scans going on? If they're using different but related base packages all components will be registered twice with different names (fqn minus the root scanning package).

@EugeneS30
Copy link
Author

@mpkorstanje The project I am working on is dependent on few other modules where different cucumber.xml are defined. You reckon that could cause multiple components scan? Thanks

mpkorstanje added a commit that referenced this issue Sep 20, 2017
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
@mpkorstanje
Copy link
Contributor

@EugeneS30 possibly. You'd have to put a break poing at DefaultListableBeanFactory#registerBeanDefinition and see which beans are registered and where they came from.

mpkorstanje added a commit that referenced this issue Oct 11, 2017
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
mpkorstanje added a commit that referenced this issue Oct 11, 2017
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
mpkorstanje added a commit that referenced this issue Oct 11, 2017
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
mpkorstanje added a commit that referenced this issue Oct 11, 2017
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
mpkorstanje added a commit that referenced this issue Oct 11, 2017
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
mpkorstanje added a commit that referenced this issue Oct 11, 2017
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
@lock
Copy link

lock bot commented Oct 24, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Oct 24, 2018
mpkorstanje added a commit that referenced this issue Oct 4, 2019
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
mpkorstanje added a commit that referenced this issue Oct 4, 2019
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
mpkorstanje added a commit that referenced this issue Oct 4, 2019
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
mpkorstanje added a commit that referenced this issue Oct 4, 2019
…ponent

When step definitions are annotated with @component or other related
annotations they can be picked up by springs class path scanning. This
conflicts with cucumbers class path scanning and may result in
multiple bean definitions for the same class.

This problem is hard to understand and hard to trace. By making the
problem explicit and providing a clear instruction on how to resolve
this we can hopefully avoid future confusion.

The current implementation only checks the a subset of all annotations.
This will hopefully be sufficient.

Closes #1225
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants