Add MP Rest Client to jersey-bom
Simplify CDI Extension
The default injection can be solved by explicitly specifying qualifiers Default and Any
Prefer looking up BeanManager in JNDI
This aligns the behavior with DefaultBeanManagerProvider and also works better
in more complicated classloader constellations.
Support Boolean in PrimitiveValueOfInserter
Signed-off-by: Patrik Dudits <patrik.dudits@payara.fish>
diff --git a/bom/pom.xml b/bom/pom.xml
index a0bb9cd..f8ed3cc 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -249,6 +249,11 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mp-rest-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${project.version}</version>
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/inject/PrimitiveValueOfInserter.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/inject/PrimitiveValueOfInserter.java
index 9e1ccc8..9c8b33c 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/internal/inject/PrimitiveValueOfInserter.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/inject/PrimitiveValueOfInserter.java
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2010, 2017 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018 Payara Foundation and/or its affiliates.
+ * Copyright (c) 2018, 2019 Payara Foundation and/or its affiliates.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -26,9 +26,10 @@
* @author Paul Sandoz
* @author Marek Potociar (marek.potociar at oracle.com)
* @author Gaurav Gupta (gaurav.gupta@payara.fish)
+ * @author Patrik Dudits
*
*/
-final class PrimitiveValueOfInserter implements ParameterInserter<Number, String> {
+final class PrimitiveValueOfInserter implements ParameterInserter<Object, String> {
private final String parameter;
private final String defaultValue;
@@ -61,7 +62,7 @@
}
@Override
- public String insert(Number value) {
+ public String insert(Object value) {
if (value != null) {
return value.toString();
} else if (defaultValue != null) {
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java
index dad9c5e..35a19f5 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceModel.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -50,6 +51,7 @@
* Model of interface and its annotation.
*
* @author David Kral
+ * @author Patrik Dudits
*/
class InterfaceModel {
@@ -66,6 +68,7 @@
private final Set<ResponseExceptionMapper> responseExceptionMappers;
private final Set<ParamConverterProvider> paramConverterProviders;
private final Set<Annotation> interceptorAnnotations;
+ private final BeanManager beanManager;
/**
* Creates new model based on interface class. Interface is parsed according to specific annotations.
@@ -81,12 +84,14 @@
Set<ResponseExceptionMapper> responseExceptionMappers,
Set<ParamConverterProvider> paramConverterProviders,
List<AsyncInvocationInterceptor> asyncInterceptors,
- InjectionManager injectionManager) {
+ InjectionManager injectionManager,
+ BeanManager beanManager) {
return new Builder(restClientClass,
responseExceptionMappers,
paramConverterProviders,
asyncInterceptors,
- injectionManager)
+ injectionManager,
+ beanManager)
.pathValue(restClientClass.getAnnotation(Path.class))
.produces(restClientClass.getAnnotation(Produces.class))
.consumes(restClientClass.getAnnotation(Consumes.class))
@@ -108,6 +113,7 @@
this.interceptorAnnotations = builder.interceptorAnnotations;
this.creationalContext = builder.creationalContext;
this.asyncInterceptors = builder.asyncInterceptors;
+ this.beanManager = builder.beanManager;
}
/**
@@ -237,11 +243,16 @@
return arg;
}
+ BeanManager getBeanManager() {
+ return beanManager;
+ }
+
private static class Builder {
private final Class<?> restClientClass;
private final InjectionManager injectionManager;
+ private final BeanManager beanManager;
private String pathValue;
private String[] produces;
private String[] consumes;
@@ -257,30 +268,27 @@
Set<ResponseExceptionMapper> responseExceptionMappers,
Set<ParamConverterProvider> paramConverterProviders,
List<AsyncInvocationInterceptor> asyncInterceptors,
- InjectionManager injectionManager) {
+ InjectionManager injectionManager,
+ BeanManager beanManager) {
this.injectionManager = injectionManager;
this.restClientClass = restClientClass;
this.responseExceptionMappers = responseExceptionMappers;
this.paramConverterProviders = paramConverterProviders;
this.asyncInterceptors = asyncInterceptors;
+ this.beanManager = beanManager;
filterAllInterceptorAnnotations();
}
private void filterAllInterceptorAnnotations() {
creationalContext = null;
interceptorAnnotations = new HashSet<>();
- try {
- if (CDI.current() != null) {
- BeanManager beanManager = CDI.current().getBeanManager();
- creationalContext = beanManager.createCreationalContext(null);
- for (Annotation annotation : restClientClass.getAnnotations()) {
- if (beanManager.isInterceptorBinding(annotation.annotationType())) {
- interceptorAnnotations.add(annotation);
- }
+ if (beanManager != null) {
+ creationalContext = beanManager.createCreationalContext(null);
+ for (Annotation annotation : restClientClass.getAnnotations()) {
+ if (beanManager.isInterceptorBinding(annotation.annotationType())) {
+ interceptorAnnotations.add(annotation);
}
}
- } catch (IllegalStateException ignored) {
- //CDI not present. Ignore.
}
}
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
index 52079eb..e7a2925 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -39,7 +40,6 @@
import java.util.stream.Collectors;
import javax.enterprise.inject.spi.BeanManager;
-import javax.enterprise.inject.spi.CDI;
import javax.enterprise.inject.spi.InterceptionType;
import javax.enterprise.inject.spi.Interceptor;
import javax.json.JsonValue;
@@ -74,6 +74,7 @@
* Method model contains all information about method defined in rest client interface.
*
* @author David Kral
+ * @author Patrik Dudits
*/
class MethodModel {
@@ -127,7 +128,8 @@
interfaceModel.getResponseExceptionMappers(),
interfaceModel.getParamConverterProviders(),
interfaceModel.getAsyncInterceptors(),
- interfaceModel.getInjectionManager());
+ interfaceModel.getInjectionManager(),
+ interfaceModel.getBeanManager());
} else {
subResourceModel = null;
}
@@ -475,35 +477,31 @@
private void filterAllInterceptorAnnotations() {
invocationInterceptors = new ArrayList<>();
- try {
- if (CDI.current() != null) {
- Set<Annotation> interceptorAnnotations = new HashSet<>();
- BeanManager beanManager = CDI.current().getBeanManager();
- for (Annotation annotation : method.getAnnotations()) {
- if (beanManager.isInterceptorBinding(annotation.annotationType())) {
- interceptorAnnotations.add(annotation);
- }
- }
- interceptorAnnotations.addAll(interfaceModel.getInterceptorAnnotations());
- Annotation[] allInterceptorAnnotations = interceptorAnnotations.toArray(new Annotation[0]);
- if (allInterceptorAnnotations.length == 0) {
- return;
- }
- List<Interceptor<?>> interceptors = beanManager.resolveInterceptors(InterceptionType.AROUND_INVOKE,
- allInterceptorAnnotations);
- if (!interceptors.isEmpty()) {
- for (Interceptor<?> interceptor : interceptors) {
- Object interceptorInstance = beanManager.getReference(interceptor,
- interceptor.getBeanClass(),
- interfaceModel.getCreationalContext());
- invocationInterceptors.add(new InterceptorInvocationContext
- .InvocationInterceptor(interceptorInstance,
- interceptor));
- }
+ BeanManager beanManager = interfaceModel.getBeanManager();
+ if (beanManager != null) {
+ Set<Annotation> interceptorAnnotations = new HashSet<>();
+ for (Annotation annotation : method.getAnnotations()) {
+ if (beanManager.isInterceptorBinding(annotation.annotationType())) {
+ interceptorAnnotations.add(annotation);
}
}
- } catch (IllegalStateException ignored) {
- //CDI not present. Ignore.
+ interceptorAnnotations.addAll(interfaceModel.getInterceptorAnnotations());
+ Annotation[] allInterceptorAnnotations = interceptorAnnotations.toArray(new Annotation[0]);
+ if (allInterceptorAnnotations.length == 0) {
+ return;
+ }
+ List<Interceptor<?>> interceptors = beanManager.resolveInterceptors(InterceptionType.AROUND_INVOKE,
+ allInterceptorAnnotations);
+ if (!interceptors.isEmpty()) {
+ for (Interceptor<?> interceptor : interceptors) {
+ Object interceptorInstance = beanManager.getReference(interceptor,
+ interceptor.getBeanClass(),
+ interfaceModel.getCreationalContext());
+ invocationInterceptors.add(new InterceptorInvocationContext
+ .InvocationInterceptor(interceptorInstance,
+ interceptor));
+ }
+ }
}
}
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
index fadca0f..1d96c4b 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,6 +37,11 @@
import java.util.stream.Collectors;
import javax.annotation.Priority;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.CDI;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
import javax.ws.rs.Priorities;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
@@ -55,7 +61,6 @@
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
import org.eclipse.microprofile.rest.client.spi.RestClientListener;
import org.glassfish.jersey.client.Initializable;
-import org.glassfish.jersey.client.JerseyClient;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
import org.glassfish.jersey.internal.util.ReflectionHelper;
@@ -64,6 +69,7 @@
* Rest client builder implementation. Creates proxy instance of requested interface.
*
* @author David Kral
+ * @author Patrik Dudits
*/
public class RestClientBuilderImpl implements RestClientBuilder {
@@ -183,7 +189,8 @@
responseExceptionMappers,
paramConverterProviders,
asyncInterceptors,
- injectionManagerExposer.injectionManager);
+ injectionManagerExposer.injectionManager,
+ lookupBeanManager());
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
@@ -192,6 +199,31 @@
);
}
+ private BeanManager lookupBeanManager() {
+ Context initialContext = null;
+ try {
+ initialContext = new InitialContext();
+ return (BeanManager) initialContext.lookup("java:comp/BeanManager");
+ } catch (NamingException e) {
+ // no bean manager in JNDI
+ } finally {
+ if (initialContext != null) {
+ try {
+ initialContext.close();
+ } catch (NamingException e) {
+ }
+ }
+ }
+ try {
+ if (CDI.current() != null) {
+ return CDI.current().getBeanManager();
+ }
+ } catch (IllegalStateException e) {
+ // CDI unavailable
+ }
+ return null;
+ }
+
private void processConfigProviders(Class<?> restClientInterface, String[] providerArray) {
for (String provider : providerArray) {
Class<?> providerClass = AccessController.doPrivileged(ReflectionHelper.classForNamePA(provider));
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientExtension.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientExtension.java
index 05743a2..58fca82 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientExtension.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientExtension.java
@@ -72,63 +72,13 @@
}
/**
- * Iterates over all {@link ProcessInjectionPoint} to find only those annotated
- * with {@link RestClient} and configures their proper injection.
- *
- * @param pip processed injection point
- */
- public void collectClientProducer(@Observes ProcessInjectionPoint<?, ?> pip) {
- RestClient restClient = pip.getInjectionPoint().getAnnotated().getAnnotation(RestClient.class);
- if (restClient != null) {
- InjectionPoint ip = pip.getInjectionPoint();
- Class<?> type = (Class<?>) ip.getType();
-
- RestClientLiteral q = new RestClientLiteral(type);
-
- pip.configureInjectionPoint().addQualifier(q);
- }
- }
-
- /**
* Creates new producers based on collected interfaces.
*
* @param abd after bean discovery instance
* @param bm bean manager instance
*/
public void restClientRegistration(@Observes AfterBeanDiscovery abd, BeanManager bm) {
- interfaces.forEach(type -> abd.addBean(new RestClientProducer(new RestClientLiteral(type), type, bm)));
- interfaces.forEach(type -> abd.addBean(new RestClientProducer(null, type, bm)));
- }
-
- @Qualifier
- @Retention(RUNTIME)
- @Target({METHOD, FIELD})
- @interface MpRestClientQualifier {
-
- Class<?> interfaceType();
-
- }
-
- private static class RestClientLiteral extends AnnotationLiteral<MpRestClientQualifier> implements MpRestClientQualifier {
-
- private final Class<?> interfaceType;
-
- RestClientLiteral(Class<?> interfaceType) {
- this.interfaceType = interfaceType;
- }
-
- @Override
- public Class<?> interfaceType() {
- return interfaceType;
- }
-
- @Override
- public String toString() {
- return "RestClientLiteral{"
- + "interfaceType=" + interfaceType
- + '}';
- }
-
+ interfaces.forEach(type -> abd.addBean(new RestClientProducer(type, bm)));
}
}
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientModel.java
index 49d353c..4e81ca3 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientModel.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,6 +24,7 @@
import java.util.Map;
import java.util.Set;
+import javax.enterprise.inject.spi.BeanManager;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.ext.ParamConverterProvider;
@@ -34,6 +36,7 @@
* Model of the rest client interface.
*
* @author David Kral
+ * @author Patrik Dudits
*/
class RestClientModel {
@@ -54,12 +57,14 @@
Set<ResponseExceptionMapper> responseExceptionMappers,
Set<ParamConverterProvider> paramConverterProviders,
List<AsyncInvocationInterceptor> asyncInterceptors,
- InjectionManager injectionManager) {
+ InjectionManager injectionManager,
+ BeanManager beanManager) {
InterfaceModel interfaceModel = InterfaceModel.from(restClientClass,
responseExceptionMappers,
paramConverterProviders,
asyncInterceptors,
- injectionManager);
+ injectionManager,
+ beanManager);
return new Builder()
.interfaceModel(interfaceModel)
.methodModels(parseMethodModels(interfaceModel))
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
index 7c0c4b3..eb3acb9 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
@@ -32,12 +32,14 @@
import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.DeploymentException;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.PassivationCapable;
+import javax.enterprise.util.AnnotationLiteral;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
@@ -62,7 +64,6 @@
private static final String CONFIG_CONNECTION_TIMEOUT = "/mp-rest/connectTimeout";
private static final String CONFIG_READ_TIMEOUT = "/mp-rest/readTimeout";
- private final RestClientExtension.MpRestClientQualifier qualifier;
private final BeanManager beanManager;
private final Class<?> interfaceType;
private final Class<? extends Annotation> scope;
@@ -72,14 +73,11 @@
/**
* Creates new instance of RestClientProducer.
*
- * @param qualifier qualifier which defines rest client interface
* @param interfaceType rest client interface
* @param beanManager bean manager
*/
- RestClientProducer(RestClientExtension.MpRestClientQualifier qualifier,
- Class<?> interfaceType,
+ RestClientProducer(Class<?> interfaceType,
BeanManager beanManager) {
- this.qualifier = qualifier;
this.interfaceType = interfaceType;
this.beanManager = beanManager;
this.config = ConfigProvider.getConfig();
@@ -125,7 +123,8 @@
.ifPresent(aLong -> restClientBuilder.readTimeout(aLong, TimeUnit.MILLISECONDS));
return restClientBuilder.build(interfaceType);
} catch (MalformedURLException e) {
- throw new IllegalStateException("URL is not in valid format: " + baseUrl);
+ throw new IllegalStateException("URL is not in valid format for Rest interface " + interfaceType.getName()
+ + ": " + baseUrl);
}
}
@@ -140,11 +139,9 @@
@Override
public Set<Annotation> getQualifiers() {
- if (qualifier == null) {
- return Collections.singleton(Default.Literal.INSTANCE);
- }
Set<Annotation> annotations = new HashSet<>();
- annotations.add(qualifier);
+ annotations.add(new AnnotationLiteral<Default>() {});
+ annotations.add(new AnnotationLiteral<Any>() {});
annotations.add(RestClient.LITERAL);
return annotations;
}
@@ -156,10 +153,7 @@
@Override
public String getName() {
- if (qualifier == null) {
- return interfaceType.getName() + "RestClient";
- }
- return interfaceType.getName();
+ return interfaceType.getName() + "RestClient";
}
@Override
diff --git a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceValidationTest.java b/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceValidationTest.java
index a810399..2f1b4fd 100644
--- a/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceValidationTest.java
+++ b/ext/microprofile/mp-rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceValidationTest.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -29,7 +30,7 @@
@Test
public void testValidInterface() {
RestClientModel.from(CorrectInterface.class, new HashSet<>(), new HashSet<>(), new ArrayList<>(),
- null);
+ null, null);
}
-}
+}
\ No newline at end of file