Skip to content

Conversation

@CMD137
Copy link

@CMD137 CMD137 commented Jan 22, 2026

What does this PR do?

This PR adds the Thread-Specific Storage design pattern implementation to the repository, addressing issue #3225.

Thread-Specific Storage is a concurrency design pattern where each thread retains its own isolated instance of shared data, preventing concurrency issues by eliminating the need for synchronization mechanisms.

Implementation Details:

  • UserContext: Represents the thread-specific object that stores user-related information (in this case, userId)
  • UserContextProxy: Acts as a proxy that manages the ThreadLocal storage, providing methods to set, get, and clear thread-specific data
  • RequestHandler: Simulates an application thread that processes requests, demonstrating how thread-local storage can be used during request processing
  • App: Demonstrates the pattern with concurrent request processing for multiple users

Key Features:

  • Implements proper thread isolation using ThreadLocal<T> to store per-thread data.
  • Includes proper cleanup mechanism to prevent memory leaks.
  • Demonstrates a realistic use case of maintaining user context across different stages of request processing.
  • Includes comprehensive unit tests covering single-threaded and multi-threaded scenarios.
  • Comprehensive README with UML diagrams, explanations, and usage examples.

Files Added:

  • Source code in src/main/java/com/iluwatar/threadspecificstorage/
  • Test suite in src/test/java/com/iluwatar/threadspecificstorage/
  • Detailed README with pattern explanation and examples
  • Maven configuration in pom.xml

The implementation follows the repository's coding standards and includes thorough documentation and tests to verify behavior in multi-threaded scenarios.

@github-actions
Copy link

github-actions bot commented Jan 22, 2026

PR Summary

Implements the Thread-Specific Storage (thread-local) design pattern to provide per-thread isolation of shared data. Introduces UserContext, UserContextProxy, RequestHandler, and an App demo, along with unit tests and documentation. Adds a dedicated Maven module thread-specific-storage including UML diagrams and README to explain usage, benefits, and cleanup to prevent memory leaks. Addresses concurrency patterns in issue #3225.

Changes

File Summary
pom.xml Adds new module thread-specific-storage to the parent Maven project to build the Thread-Specific Storage pattern module.
thread-specific-storage/README.md New README documenting the Thread-Specific Storage pattern, its usage, design, and a concrete Java example.
thread-specific-storage/etc/ThreadSpecificStorageUML.png New architecture diagram image for the Thread-Specific Storage pattern.
thread-specific-storage/etc/thread-specific-storage.urm.puml PlantUML script outlining the Thread-Specific Storage components and their relationships.
thread-specific-storage/pom.xml New Maven module pom for the Thread-Specific Storage module with dependencies and build setup.
thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java Demo application entry point showing concurrent request processing with per-thread user context.
thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java Request processing logic that parses a token, stores user context in a ThreadLocal via UserContextProxy, and demonstrates cleanup.
thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContext.java Data object representing per-thread user context (userId).
thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContextProxy.java ThreadLocal-based proxy to set, get, and clear UserContext per thread.
thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java Test for App.main() ensuring thread-started output contains expected logs.
thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/RequestHandlerTest.java Tests validating that RequestHandler stores the user context and clears it after processing.
thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextProxyTest.java Tests for thread-local storage behavior: set/get/clear and thread isolation.
thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextTest.java Tests for UserContext constructors, getters/setters, and toString/hashCode.

autogenerated by presubmit.ai

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🚨 Pull request needs attention.

Review Summary

Commits Considered (1)
  • 23f22a3: Add Thread-Specific Storage design pattern
Files Processed (13)
  • pom.xml (1 hunk)
  • thread-specific-storage/README.md (1 hunk)
  • thread-specific-storage/etc/ThreadSpecificStorageUML.png (0 hunks)
  • thread-specific-storage/etc/thread-specific-storage.urm.puml (1 hunk)
  • thread-specific-storage/pom.xml (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContext.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContextProxy.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/RequestHandlerTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextProxyTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextTest.java (1 hunk)
Actionable Comments (2)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [27-27]

    bug: "Logger usage inconsistent with Lombok setup"

  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextProxyTest.java [50-60]

    possible bug: "Assertions inside worker thread won't fail the test reliably; capture exceptions and assert after join"

Skipped Comments (3)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContextProxy.java [18-18]

    maintainability: "Static accessor methods suggest singleton-like usage; prefer instance-based API"

  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java [23-37]

    possible bug: "Test fragility: use thread join instead of sleep"

  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java [31-33]

    readability: "Test-check relies on logger output in stdout; ensure logback config prints to stdout or adjust test"

* 4. Finally, clear thread-local to prevent memory leak.
*/
public void process() {
LOGGER.info("Start handling request with token: {}", token);

Choose a reason for hiding this comment

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

LOGGER is not defined when using Lombok @slf4j. Lombok generates a 'log' field. This will fail to compile. Replace with log.info(...).

Comment on lines 50 to 60
void testThreadIsolation() throws InterruptedException {
UserContext context1 = new UserContext(123L);
UserContext context2 = new UserContext(456L);
UserContextProxy.set(context1);
// Create another thread to set different context
Thread thread = new Thread(() -> {
UserContextProxy.set(context2);
UserContext threadContext = UserContextProxy.get();
assertNotNull(threadContext);
assertEquals(456L, threadContext.getUserId());
});

Choose a reason for hiding this comment

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

Thread thread = new Thread(() -> {
UserContextProxy.set(context2);
UserContext threadContext = UserContextProxy.get();
assertNotNull(threadContext);
assertEquals(456L, threadContext.getUserId());
});
thread.start();
thread.join();

Run 'mvn spotless:apply' to fix these violations.
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🚨 Pull request needs attention.

Review Summary

Commits Considered (1)
  • 5d8581a: fixed:pom.xml
    Run 'mvn spotless:apply' to fix these violations.
Files Processed (8)
  • pom.xml (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContextProxy.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/RequestHandlerTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextProxyTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextTest.java (1 hunk)
Actionable Comments (1)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [25-25]

    best_practice: "Replace LOGGER with the Lombok-provided log"

Skipped Comments (3)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [38-38]

    possible bug: "Possible NPE when retrieving from thread-local storage"

  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java [33-34]

    maintainability: "Incorrect System.out restoration in test"

  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java [23-23]

    enhancement: "Improve test synchronization"

* clear thread-local to prevent memory leak.
*/
public void process() {
LOGGER.info("Start handling request with token: {}", token);

Choose a reason for hiding this comment

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

Use the Lombok-provided log field for SLF4J logging instead of the undefined LOGGER; Lombok's @slf4j exposes a 'log' instance.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

LGTM!

Review Summary

Commits Considered (1)
  • 6cfccc0: Merge branch 'master' into Thread-Specific-Storage
Files Processed (1)
  • pom.xml (1 hunk)
Actionable Comments (0)
Skipped Comments (5)
  • pom.xml [235-235]

    maintainability: "Add module to multi-module build"

  • pom.xml [235-235]

    readability: "Module naming and alignment"

  • pom.xml [235-235]

    best_practice: "ThreadLocal cleanup and memory leaks"

  • pom.xml [235-235]

    enhancement: "Tests coverage for thread scenarios"

  • pom.xml [235-235]

    readability: "Documentation and README"

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

LGTM!

Review Summary

Commits Considered (1)
  • 34cc03f: fix: address Sonar security hotspots for Random usage and e.printStackTrace()
Files Processed (2)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java (1 hunk)
Actionable Comments (0)
Skipped Comments (4)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java [41-41]

    best practice: "Use Lombok-provided logger instance."

  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [4-4]

    maintainability: "Remove unused import."

  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [26-26]

    best practice: "Use Lombok-provided logger."

  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [42-42]

    best practice: "Use Lombok-provided logger."

Run 'mvn spotless:apply'(remove unused import)
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🚨 Pull request needs attention.

Review Summary

Commits Considered (1)
  • 106f06d: fixed:
    Run 'mvn spotless:apply'(remove unused import)
Files Processed (1)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java (1 hunk)
Actionable Comments (2)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [25-25]

    best_practice: "Use Lombok-provided logger and redaction"

  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [38-38]

    possible bug: "Potential null dereference in thread-local access"

Skipped Comments (1)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [41-41]

    best_practice: "Use Lombok-provided logger"

* clear thread-local to prevent memory leak.
*/
public void process() {
LOGGER.info("Start handling request with token: {}", token);

Choose a reason for hiding this comment

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

Replace LOGGER with log to align with Lombok @slf4j; also avoid logging the raw token to prevent sensitive information exposure.

Thread.sleep(200);

// Step 3: Retrieve userId later in the request flow
Long retrievedId = contextProxy.get().getUserId();

Choose a reason for hiding this comment

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

contextProxy.get() may return null; guard against NullPointerException when retrieving userId.

Refactor Thread-Specific Storage pattern implementation to address Sonar issues: remove unnecessary instantiation, add private constructor, use diamond operator, and update tests.
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

LGTM!

Review Summary

Commits Considered (1)
  • d3a8041: fixed:
    Refactor Thread-Specific Storage pattern implementation to address Sonar issues: remove unnecessary instantiation, add private constructor, use diamond operator, and update tests.
Files Processed (6)
  • thread-specific-storage/pom.xml (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContextProxy.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/RequestHandlerTest.java (1 hunk)
Actionable Comments (0)
Skipped Comments (4)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java [38-38]

    bug: "Fix Lombok logging instance"

  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [26-26]

    readability: "Replace LOGGER with Lombok log and sanitize logs"

  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java [17-18]

    maintainability: "Restore System.out correctly in tests"

  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java [23-28]

    test: "Test stability for multi-thread output capturing"

update uml and README.md
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

LGTM!

Review Summary

Commits Considered (8)
  • c110258: Trigger CI rerun
  • 1bc4edd: fixed:
    update uml and README.md
  • d3a8041: fixed:
    Refactor Thread-Specific Storage pattern implementation to address Sonar issues: remove unnecessary instantiation, add private constructor, use diamond operator, and update tests.
  • 106f06d: fixed:
    Run 'mvn spotless:apply'(remove unused import)
  • 34cc03f: fix: address Sonar security hotspots for Random usage and e.printStackTrace()
  • 6cfccc0: Merge branch 'master' into Thread-Specific-Storage
  • 5d8581a: fixed:pom.xml
    Run 'mvn spotless:apply' to fix these violations.
  • 23f22a3: Add Thread-Specific Storage design pattern
Files Processed (13)
  • pom.xml (1 hunk)
  • thread-specific-storage/README.md (1 hunk)
  • thread-specific-storage/etc/ThreadSpecificStorageUML.png (0 hunks)
  • thread-specific-storage/etc/thread-specific-storage.urm.puml (1 hunk)
  • thread-specific-storage/pom.xml (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContext.java (1 hunk)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/UserContextProxy.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/RequestHandlerTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextProxyTest.java (1 hunk)
  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/UserContextTest.java (1 hunk)
Actionable Comments (0)
Skipped Comments (3)
  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/RequestHandler.java [26-26]

    best_practice: "Use Lombok-provided logger and avoid exposing token"

  • thread-specific-storage/src/main/java/com/iluwatar/threadspecificstorage/App.java [39-41]

    best_practice: "Replace logger with Lombok's 'log' instance"

  • thread-specific-storage/src/test/java/com/iluwatar/threadspecificstorage/AppTest.java [21-27]

    readability: "Testing sink mismatch: stdout capture vs. logging"

@CMD137
Copy link
Author

CMD137 commented Jan 23, 2026

CI may fail due to the AI Reviewer workflow (missing LLM_API_KEY and required type field).
The issue was resolved by manually triggering a CI rerun:
After executing git commit --allow-empty -m "Trigger CI rerun" and git push, the CI pipeline completed successfully.

@sonarqubecloud
Copy link

@CMD137
Copy link
Author

CMD137 commented Jan 23, 2026

Hi @iluwatar ,

This PR adds the Thread-Specific Storage design pattern implementation.
All checks have passed (build, tests, and SonarQube Quality Gate), and there are no merge conflicts.

Please review at your convenience. The PR is ready to merge.

Thanks! 🙏

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.

1 participant