Skip to content

[Spring] Share application context #1848

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

Merged
merged 12 commits into from
Dec 21, 2019
Merged

[Spring] Share application context #1848

merged 12 commits into from
Dec 21, 2019

Conversation

dom54
Copy link
Contributor

@dom54 dom54 commented Dec 20, 2019

When executing Cucumber in parallel in combination with cucumber-spring users would often encounter a cryptic error message: No qualifying bean of type 'Steps' available: expected single matching bean but found 1 (#1823).

This was initially fixed by ensuring that the Spring application context was not shared between threads (#1153, #1148). This however has the downside that the application context is not shared with JUnit tests either (#1583) and comes at significant performance penalty (#1846).

The root cause however was a race condition in DefaultListableBeanFactory.registerBeanDefinition(String beanName, BeanDefinition beanDefinition). There is a check to see if the definition already exists. If it does not exist, it replaces the bean definition in a ConcurrentHashMap (in a synchronized block as well) but then adds the bean name to a list without checking if it already exists.

By synchronizing inside SpringFactory.start we prevent concurrent modification of the application context by cucumber-spring This in turn makes it possible to share the application context between threads and with JUnit tests.

Fixes: #1846
Fixes: #1583
Closes: #1848
Closes: #1582

@dom54
Copy link
Contributor Author

dom54 commented Dec 20, 2019

making this the default - share context between all threads

@@ -26,8 +26,6 @@
import java.util.Set;

import static io.cucumber.spring.CucumberTestContext.SCOPE_CUCUMBER_GLUE;
import static io.cucumber.spring.FixBootstrapUtils.createBootstrapContext;
import static io.cucumber.spring.FixBootstrapUtils.resolveTestContextBootstrapper;
Copy link
Contributor

Choose a reason for hiding this comment

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

Removed the FixBootstrapUtils. Wasn't needed any more.

} else {
if (beanFactory == null) {
beanFactory = createFallbackContext();
synchronized (monitor) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Replaced the SpringFactory.class with monitor. The class is accessible by any one. And while I don't expect any one to use it to synchronize on it, there also no need to do so.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also explained the why of it all.


@Test
void test() {
@RepeatedTest(100)
Copy link
Contributor

Choose a reason for hiding this comment

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

We're running 100 repetitions with 100 concurrent scenarios. Should tone this down a bit for CI but good enough.

Copy link
Contributor

Choose a reason for hiding this comment

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

[INFO] Cucumber-JVM: Spring ............................... SUCCESS [02:12 min]

🤣

@mpkorstanje mpkorstanje changed the title [1846] Fixing thread safety when beanFactory is shared between threads [Spring] Safely share application context between scenarios Dec 21, 2019
@mpkorstanje mpkorstanje changed the title [Spring] Safely share application context between scenarios [Spring] Safely share application context Dec 21, 2019
@mpkorstanje
Copy link
Contributor

To keep the history readable PRs are squashed when merging. I've drafted a commit message in your original description of the PR. You should be able to edit it.

@dom54
Copy link
Contributor Author

dom54 commented Dec 21, 2019

looks good to me

@mpkorstanje mpkorstanje changed the title [Spring] Safely share application context [Spring] Share application context Dec 21, 2019
@mpkorstanje mpkorstanje merged commit 06f26a0 into cucumber:master Dec 21, 2019
@aslakhellesoy
Copy link
Contributor

Hi @dom54,

Thanks for your making your first contribution to Cucumber, and welcome to the Cucumber committers team! You can now push directly to this repo and all other repos under the cucumber organization! 🍾

In return for this generous offer we hope you will:

  • ✅ Continue to use branches and pull requests. When someone on the core team approves a pull request (yours or someone else's), you're welcome to merge it yourself.
  • 💚 Commit to setting a good example by following and upholding our code of conduct in your interactions with other collaborators and users.
  • 💬 Join the community Slack channel to meet the rest of the team and make yourself at home.
  • ℹ️ Don't feel obliged to help, just do what you can if you have the time and the energy.
  • 🙋 Ask if you need anything. We're looking for feedback about how to make the project more welcoming, so please tell us!

On behalf of the Cucumber core team,
Aslak Hellesøy
Creator of Cucumber

@mpkorstanje
Copy link
Contributor

mpkorstanje commented Dec 21, 2019

Aright then we're done! Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants