Skip to content

Commit 0d3ed7f

Browse files
committed
Fixes eclipse-ee4j#4264 - AsyncInvocationinverceptors not properly created for each request
Signed-off-by: David Kral <david.k.kral@oracle.com>
1 parent 7c67bae commit 0d3ed7f

File tree

5 files changed

+43
-33
lines changed

5 files changed

+43
-33
lines changed

ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ExecutorServiceWrapper.java

+12-6
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@
3535
*/
3636
class ExecutorServiceWrapper implements ExecutorService {
3737

38+
//
39+
static final ThreadLocal<List<AsyncInvocationInterceptor>> asyncInterceptors = new ThreadLocal<>();
40+
3841
private final ExecutorService wrapped;
39-
private final List<AsyncInvocationInterceptor> asyncInterceptors;
4042

41-
ExecutorServiceWrapper(ExecutorService wrapped,
42-
List<AsyncInvocationInterceptor> asyncInterceptors) {
43+
ExecutorServiceWrapper(ExecutorService wrapped) {
4344
this.wrapped = wrapped;
44-
this.asyncInterceptors = asyncInterceptors;
4545
}
4646

4747
@Override
@@ -112,15 +112,21 @@ public void execute(Runnable command) {
112112
}
113113

114114
private <T> Callable<T> wrap(Callable<T> task) {
115+
List<AsyncInvocationInterceptor> asyncInvocationInterceptors = asyncInterceptors.get();
115116
return () -> {
116-
asyncInterceptors.forEach(AsyncInvocationInterceptor::applyContext);
117+
if (asyncInvocationInterceptors != null) {
118+
asyncInvocationInterceptors.forEach(AsyncInvocationInterceptor::applyContext);
119+
}
117120
return task.call();
118121
};
119122
}
120123

121124
private Runnable wrap(Runnable task) {
125+
List<AsyncInvocationInterceptor> asyncInvocationInterceptors = asyncInterceptors.get();
122126
return () -> {
123-
asyncInterceptors.forEach(AsyncInvocationInterceptor::applyContext);
127+
if (asyncInvocationInterceptors != null) {
128+
asyncInvocationInterceptors.forEach(AsyncInvocationInterceptor::applyContext);
129+
}
124130
task.run();
125131
};
126132
}

ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java

+14-13
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
3939
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
4040
import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptor;
41+
import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptorFactory;
4142
import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;
4243
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
4344
import org.glassfish.jersey.client.inject.ParameterUpdater;
@@ -64,7 +65,7 @@ class InterfaceModel {
6465
private final CreationalContext<?> creationalContext;
6566

6667
private final List<ClientHeaderParamModel> clientHeaders;
67-
private final List<AsyncInvocationInterceptor> asyncInterceptors;
68+
private final List<AsyncInvocationInterceptorFactory> asyncInterceptorFactories;
6869
private final Set<ResponseExceptionMapper> responseExceptionMappers;
6970
private final Set<ParamConverterProvider> paramConverterProviders;
7071
private final Set<Annotation> interceptorAnnotations;
@@ -73,23 +74,23 @@ class InterfaceModel {
7374
/**
7475
* Creates new model based on interface class. Interface is parsed according to specific annotations.
7576
*
76-
* @param restClientClass interface class
77-
* @param responseExceptionMappers registered exception mappers
78-
* @param paramConverterProviders registered parameter providers
79-
* @param asyncInterceptors async interceptors
77+
* @param restClientClass interface class
78+
* @param responseExceptionMappers registered exception mappers
79+
* @param paramConverterProviders registered parameter providers
80+
* @param asyncInterceptorFactories async interceptor factories
8081
* @param injectionManager
8182
* @return new model instance
8283
*/
8384
static InterfaceModel from(Class<?> restClientClass,
8485
Set<ResponseExceptionMapper> responseExceptionMappers,
8586
Set<ParamConverterProvider> paramConverterProviders,
86-
List<AsyncInvocationInterceptor> asyncInterceptors,
87+
List<AsyncInvocationInterceptorFactory> asyncInterceptorFactories,
8788
InjectionManager injectionManager,
8889
BeanManager beanManager) {
8990
return new Builder(restClientClass,
9091
responseExceptionMappers,
9192
paramConverterProviders,
92-
asyncInterceptors,
93+
asyncInterceptorFactories,
9394
injectionManager,
9495
beanManager).build();
9596
}
@@ -106,7 +107,7 @@ private InterfaceModel(Builder builder) {
106107
this.paramConverterProviders = builder.paramConverterProviders;
107108
this.interceptorAnnotations = builder.interceptorAnnotations;
108109
this.creationalContext = builder.creationalContext;
109-
this.asyncInterceptors = builder.asyncInterceptors;
110+
this.asyncInterceptorFactories = builder.asyncInterceptorFactories;
110111
this.beanManager = builder.beanManager;
111112
}
112113

@@ -169,8 +170,8 @@ List<ClientHeaderParamModel> getClientHeaders() {
169170
*
170171
* @return registered async interceptors
171172
*/
172-
List<AsyncInvocationInterceptor> getAsyncInterceptors() {
173-
return asyncInterceptors;
173+
List<AsyncInvocationInterceptorFactory> getAsyncInterceptorFactories() {
174+
return asyncInterceptorFactories;
174175
}
175176

176177
/**
@@ -251,22 +252,22 @@ private static class Builder {
251252
private ClientHeadersFactory clientHeadersFactory;
252253
private CreationalContext<?> creationalContext;
253254
private List<ClientHeaderParamModel> clientHeaders;
254-
private List<AsyncInvocationInterceptor> asyncInterceptors;
255+
private List<AsyncInvocationInterceptorFactory> asyncInterceptorFactories;
255256
private Set<ResponseExceptionMapper> responseExceptionMappers;
256257
private Set<ParamConverterProvider> paramConverterProviders;
257258
private Set<Annotation> interceptorAnnotations;
258259

259260
private Builder(Class<?> restClientClass,
260261
Set<ResponseExceptionMapper> responseExceptionMappers,
261262
Set<ParamConverterProvider> paramConverterProviders,
262-
List<AsyncInvocationInterceptor> asyncInterceptors,
263+
List<AsyncInvocationInterceptorFactory> asyncInterceptorFactories,
263264
InjectionManager injectionManager,
264265
BeanManager beanManager) {
265266
this.injectionManager = injectionManager;
266267
this.restClientClass = restClientClass;
267268
this.responseExceptionMappers = responseExceptionMappers;
268269
this.paramConverterProviders = paramConverterProviders;
269-
this.asyncInterceptors = asyncInterceptors;
270+
this.asyncInterceptorFactories = asyncInterceptorFactories;
270271
this.beanManager = beanManager;
271272
filterAllInterceptorAnnotations();
272273
}

ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java

+12-3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import org.eclipse.microprofile.rest.client.RestClientDefinitionException;
7070
import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
7171
import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptor;
72+
import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptorFactory;
7273
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
7374

7475
/**
@@ -121,7 +122,7 @@ private MethodModel(Builder builder) {
121122
subResourceModel = RestClientModel.from(returnType.getRawType(),
122123
interfaceModel.getResponseExceptionMappers(),
123124
interfaceModel.getParamConverterProviders(),
124-
interfaceModel.getAsyncInterceptors(),
125+
interfaceModel.getAsyncInterceptorFactories(),
125126
interfaceModel.getInjectionManager(),
126127
interfaceModel.getBeanManager());
127128
} else {
@@ -243,6 +244,14 @@ private CompletableFuture asynchronousCall(Invocation.Builder builder,
243244
Object entity,
244245
Method method,
245246
MultivaluedMap<String, Object> customHeaders) {
247+
248+
//AsyncInterceptors initialization
249+
List<AsyncInvocationInterceptor> asyncInterceptors = interfaceModel.getAsyncInterceptorFactories().stream()
250+
.map(AsyncInvocationInterceptorFactory::newInterceptor)
251+
.collect(Collectors.toList());
252+
asyncInterceptors.forEach(AsyncInvocationInterceptor::prepareContext);
253+
ExecutorServiceWrapper.asyncInterceptors.set(asyncInterceptors);
254+
246255
CompletableFuture<Object> result = new CompletableFuture<>();
247256
Future<Response> theFuture;
248257
if (entity != null
@@ -255,7 +264,7 @@ private CompletableFuture asynchronousCall(Invocation.Builder builder,
255264

256265
CompletableFuture<Response> completableFuture = (CompletableFuture<Response>) theFuture;
257266
completableFuture.thenAccept(response -> {
258-
interfaceModel.getAsyncInterceptors().forEach(AsyncInvocationInterceptor::removeContext);
267+
asyncInterceptors.forEach(AsyncInvocationInterceptor::removeContext);
259268
try {
260269
evaluateResponse(response, method);
261270
if (returnType.getType().equals(Void.class)) {
@@ -269,7 +278,7 @@ private CompletableFuture asynchronousCall(Invocation.Builder builder,
269278
result.completeExceptionally(e);
270279
}
271280
}).exceptionally(throwable -> {
272-
interfaceModel.getAsyncInterceptors().forEach(AsyncInvocationInterceptor::removeContext);
281+
asyncInterceptors.forEach(AsyncInvocationInterceptor::removeContext);
273282
result.completeExceptionally(throwable);
274283
return null;
275284
});

ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java

+2-8
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,7 @@ public <T> T build(Class<T> interfaceClass) throws IllegalStateException, RestCl
154154
//We need to check first if default exception mapper was not disabled by property on builder.
155155
registerExceptionMapper();
156156

157-
//AsyncInterceptors initialization
158-
List<AsyncInvocationInterceptor> asyncInterceptors = asyncInterceptorFactories.stream()
159-
.map(AsyncInvocationInterceptorFactory::newInterceptor)
160-
.collect(Collectors.toList());
161-
asyncInterceptors.forEach(AsyncInvocationInterceptor::prepareContext);
162-
163-
clientBuilder.executorService(new ExecutorServiceWrapper(executorService.get(), asyncInterceptors));
157+
clientBuilder.executorService(new ExecutorServiceWrapper(executorService.get()));
164158

165159
if (null != sslContext) {
166160
clientBuilder.sslContext(sslContext);
@@ -187,7 +181,7 @@ public <T> T build(Class<T> interfaceClass) throws IllegalStateException, RestCl
187181
RestClientModel restClientModel = RestClientModel.from(interfaceClass,
188182
responseExceptionMappers,
189183
paramConverterProviders,
190-
asyncInterceptors,
184+
asyncInterceptorFactories,
191185
injectionManagerExposer.injectionManager,
192186
CdiUtil.getBeanManager());
193187

ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientModel.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import javax.ws.rs.client.WebTarget;
2929
import javax.ws.rs.ext.ParamConverterProvider;
3030

31-
import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptor;
31+
import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptorFactory;
3232
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
3333
import org.glassfish.jersey.internal.inject.InjectionManager;
3434

@@ -56,13 +56,13 @@ class RestClientModel {
5656
static RestClientModel from(Class<?> restClientClass,
5757
Set<ResponseExceptionMapper> responseExceptionMappers,
5858
Set<ParamConverterProvider> paramConverterProviders,
59-
List<AsyncInvocationInterceptor> asyncInterceptors,
59+
List<AsyncInvocationInterceptorFactory> asyncInterceptorFactories,
6060
InjectionManager injectionManager,
6161
BeanManager beanManager) {
6262
InterfaceModel interfaceModel = InterfaceModel.from(restClientClass,
6363
responseExceptionMappers,
6464
paramConverterProviders,
65-
asyncInterceptors,
65+
asyncInterceptorFactories,
6666
injectionManager,
6767
beanManager);
6868
return new Builder()

0 commit comments

Comments
 (0)