Resolve critical thread safety issues in format configurers#52
Resolve critical thread safety issues in format configurers#52
Conversation
Fixed three critical thread safety issues in format configurers: 1. **JsonSimpleConfigurer**: Removed shared JSONParser instance - JSONParser is not thread-safe and has no configuration options - Simplified to create new JSONParser() per load() call - Removed Supplier field/constructor (unnecessary complexity) 2. **YamlSnakeYamlConfigurer**: Removed shared Yaml instance - SnakeYAML Yaml class is not thread-safe per documentation - Changed to Supplier<Yaml> pattern with yaml.get() per call - Constructor accepts Supplier<Yaml> for custom configurations - Updated code style: private @Setter String (annotation between modifier/type) 3. **PropertiesConfigurer**: Fixed OrderedProperties ArrayList race - Changed from ArrayList to CopyOnWriteArrayList for orderedKeys - Prevents ConcurrentModificationException during iteration - Clone method updated to use CopyOnWriteArrayList 4. **FieldDeclaration**: Fixed FINAL_WARNS concurrency - Changed from HashSet to ConcurrentHashMap.newKeySet() - Prevents data corruption when multiple configs created concurrently Breaking changes: - JsonSimpleConfigurer(JSONParser) constructor removed - YamlSnakeYamlConfigurer(Yaml) now requires Supplier<Yaml> All other configurers retain setters for non-critical fields (commentPrefix, etc.) following "configure once, use many" pattern - no volatile needed.
PR Review: Thread Safety ImprovementsOverviewThis PR addresses critical thread safety issues across multiple format configurers. The changes are well-reasoned and follow proper concurrency patterns. Overall, this is a strong improvement to the codebase. ✅ Excellent Changes1. FieldDeclaration.java (core/src/main/java/eu/okaeri/configs/schema/FieldDeclaration.java:27)- private static final Set<String> FINAL_WARNS = new HashSet<>();
+ private static final Set<String> FINAL_WARNS = ConcurrentHashMap.newKeySet();Perfect fix. 2. JsonSimpleConfigurer.java (json-simple/src/main/java/eu/okaeri/configs/json/simple/JsonSimpleConfigurer.java:58)- return (Map<String, Object>) this.parser.parse(data, CONTAINER_FACTORY);
+ return (Map<String, Object>) new JSONParser().parse(data, CONTAINER_FACTORY);Correct approach. JSONParser has no configuration options and is not thread-safe. Creating a new instance per call is the right solution. The constructor/field removal is a good simplification. 3. YamlSnakeYamlConfigurer.java (yaml-snakeyaml/src/main/java/eu/okaeri/configs/yaml/snakeyaml/YamlSnakeYamlConfigurer.java:27,34,66,71)- private Yaml yaml;
+ private final Supplier<Yaml> yaml;
+ public YamlSnakeYamlConfigurer(@NonNull Supplier<Yaml> yaml) { ... }
+ this.yaml.get().load(inputStream)
+ this.yaml.get().dump(data)Well-designed solution. The
Code style improvement: Moving
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #52 +/- ##
============================================
- Coverage 82.76% 82.74% -0.02%
+ Complexity 1302 1301 -1
============================================
Files 93 93
Lines 4341 4336 -5
Branches 796 796
============================================
- Hits 3593 3588 -5
Misses 471 471
Partials 277 277 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code Review - PR #52: Thread Safety FixesSummaryThis PR addresses critical thread safety issues in format configurers and core components. The changes are technically sound and follow proper concurrency patterns. ✅ Approved Changes1. FieldDeclaration.java:27 - FINAL_WARNS Thread Safety- private static final Set<String> FINAL_WARNS = new HashSet<>();
+ private static final Set<String> FINAL_WARNS = ConcurrentHashMap.newKeySet();Verdict: ✅ Excellent fix
2. JsonSimpleConfigurer.java:58 - JSONParser Thread Safety- private JSONParser parser; // Removed field
- return (Map<String, Object>) this.parser.parse(data, CONTAINER_FACTORY);
+ return (Map<String, Object>) new JSONParser().parse(data, CONTAINER_FACTORY);Verdict: ✅ Correct approach
3. YamlSnakeYamlConfigurer.java - SnakeYAML Thread Safety- private Yaml yaml;
+ private final Supplier<Yaml> yaml;
// Constructor changes
- public YamlSnakeYamlConfigurer(@NonNull Yaml yaml) { this.yaml = yaml; }
+ public YamlSnakeYamlConfigurer(@NonNull Supplier<Yaml> yaml) { this.yaml = yaml; }
// Usage changes
- this.yaml.load(inputStream)
+ this.yaml.get().load(inputStream)Verdict: ✅ Well-designed solution
|
Fixed three critical thread safety issues in format configurers:
JsonSimpleConfigurer: Removed shared JSONParser instance
YamlSnakeYamlConfigurer: Removed shared Yaml instance
FieldDeclaration: Fixed FINAL_WARNS concurrency
Breaking changes:
All other configurers retain setters for non-critical fields (commentPrefix, etc.) following "configure once, use many" pattern - no volatile needed.