Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,15 @@ protected BasePushNotificationSender() {

@Inject
public BasePushNotificationSender(PushNotificationConfigStore configStore) {
this.httpClient = A2AHttpClientFactory.create();
// Make sure the TCCL is one of the platform ones before the ServiceLoader
// in A2AHttpClientFactory's static initializer
ClassLoader originalTccl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(BasePushNotificationSender.class.getClassLoader());
this.httpClient = A2AHttpClientFactory.create();
} finally {
Thread.currentThread().setContextClassLoader(originalTccl);
}
Comment on lines +61 to +67
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

This TCCL (Thread Context Class Loader) swap is fragile because it depends on the initialization order of A2AHttpClientFactory. Since the factory's PROVIDERS list is initialized in a static block, this logic only works if BasePushNotificationSender is the first class to trigger the factory's loading. If another component accesses the factory first without this TCCL swap, the factory will be initialized with an empty provider list and remain broken for the life of the application. The service discovery should be made robust within A2AHttpClientFactory itself, for example by using ServiceLoader.load(A2AHttpClientProvider.class, A2AHttpClientProvider.class.getClassLoader()) to ensure the providers are always found regardless of the current thread's context.

this.configStore = configStore;
}

Expand Down