fix: set locking to VaadinContext instead of ServletContext (#13962)
Description
Potential solutions (I did not really think these through):
Lock on vaadin context in getCachedIndexHtmlDocument to avoid locking in another order. Seems quite fragile and there might be other similar cases here and there. Use the same object for locking in all cases. Can't see why we really need to synchronize on different ones for these operations
The same object - VaadinContext is used for locking.
Fixes #13962
Type of change
- [x] Bugfix
- [ ] Feature
Checklist
- [x] I have read the contribution guide: https://vaadin.com/docs/latest/guide/contributing/overview/
- [x] I have added a description following the guideline.
- [x] The issue is created in the corresponding repository and I have referenced it.
- [ ] I have added tests to ensure my change is effective and works as intended.
- [x] New and existing tests are passing locally with my change.
- [x] I have performed self-review and corrected misspellings.
Additional for Feature type of change
- [ ] Enhancement / new feature was discussed in a corresponding GitHub issue and Acceptance Criteria were created.
Unit Test Results
955 files ± 0 955 suites ±0 58m 2s :stopwatch: + 4m 6s 6 082 tests ± 0 6 028 :heavy_check_mark: ± 0 54 :zzz: ±0 0 :x: ±0 6 348 runs +11 6 286 :heavy_check_mark: +11 62 :zzz: ±0 0 :x: ±0
Results for commit 91118421. ± Comparison against base commit dc00ef1a.
:recycle: This comment has been updated with latest results.
Is VaadinServletContext a singleton? Otherwise locking will have no effect
Is
VaadinServletContexta singleton? Otherwise locking will have no effect
@Artur- indeed, so why to lock on VaadinContext in FeatureFlags if they call setAttributes which already locks on ServletContext?
The locking in FeatureFlags looks wrong. It wants to lock to avoid creating FeatureFlagsWrapper multiple times. The normal pattern for that would be something like
FeatureFlagsWrapper attribute = context.getAttribute(FeatureFlagsWrapper.class);
if (attribute == null) {
synchronized (FeatureFlags.class) {
attribute = context.getAttribute(FeatureFlagsWrapper.class);
if (attribute == null) {
// create it
}
}
}
return attribute.getFeatureFlags();
There is no need to lock on anything external as only FeatureFlags is creating the wrapper.
The simpler version which locks every time, and might be good enough in FeatureFlags would be
synchronized (FeatureFlags.class) {
FeatureFlagsWrapper attribute = context.getAttribute(FeatureFlagsWrapper.class);
if (attribute == null) {
// create it
}
}
return attribute.getFeatureFlags();







