You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/11/30 12:42:28 UTC
[isis] branch v2 updated: ISIS-2039: introduces _CDI (internal API)
...
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/v2 by this push:
new b71b075 ISIS-2039: introduces _CDI (internal API) ...
b71b075 is described below
commit b71b0753e6ae34ad9ca8fa639fb0ce5f14fff8d9
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Nov 30 13:42:22 2018 +0100
ISIS-2039: introduces _CDI (internal API) ...
and allows for the ServicesInjector to also inject CDI managed beans
Task-Url: https://issues.apache.org/jira/browse/ISIS-2039
---
.../org/apache/isis/commons/internal/cdi/_CDI.java | 124 +++++++++++++++++++++
.../apache/isis/commons/internal/cdi/CDITest.java | 107 ++++++++++++++++++
.../internal/cdi/ValidQualifierForTesting.java | 17 +++
.../org/apache/isis/config/AppConfigLocator.java | 14 +--
.../core/metamodel/services/ServicesInjector.java | 6 +
5 files changed, 256 insertions(+), 12 deletions(-)
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/cdi/_CDI.java b/core/commons/src/main/java/org/apache/isis/commons/internal/cdi/_CDI.java
new file mode 100644
index 0000000..0e26c48
--- /dev/null
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/cdi/_CDI.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.commons.internal.cdi;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import javax.enterprise.inject.spi.CDI;
+import javax.inject.Qualifier;
+
+import org.apache.isis.commons.internal.base._NullSafe;
+
+/**
+ * <h1>- internal use only -</h1>
+ * <p>
+ * Framework internal CDI support.
+ * <p>
+ * <b>WARNING</b>: Do <b>NOT</b> use any of the classes provided by this package! <br/>
+ * These may be changed or removed without notice!
+ *
+ * @since 2.0.0-M2
+ */
+public final class _CDI {
+
+ /**
+ * Obtains a child Instance for the given required type and additional required qualifiers.
+ * @param subType
+ * @param qualifiers
+ * @return an optional, empty if passed two instances of the same qualifier type, or an
+ * instance of an annotation that is not a qualifier type
+ */
+ public static <T> Optional<T> getManagedBean(final Class<T> subType, List<Annotation> qualifiers) {
+ if(_NullSafe.isEmpty(qualifiers)) {
+ return getManagedBean(subType);
+ }
+
+ final Annotation[] _qualifiers = qualifiers.toArray(new Annotation[] {});
+
+ return cdi()
+ .map(cdi->tryGet(()->cdi.select(subType, _qualifiers)))
+ .map(instance->tryGet(instance::get));
+ }
+
+ /**
+ * Obtains a child Instance for the given required type and additional required qualifiers.
+ * @param subType
+ * @param qualifiers
+ * @return an optional, empty if passed two instances of the same qualifier type, or an
+ * instance of an annotation that is not a qualifier type
+ */
+ public static <T> Optional<T> getManagedBean(final Class<T> subType) {
+ return cdi()
+ .map(cdi->tryGet(()->cdi.select(subType)))
+ .map(instance->tryGet(instance::get));
+ }
+
+ /**
+ * Get the CDI instance that provides access to the current container.
+ * @return an optional
+ */
+ public static Optional<CDI<Object>> cdi() {
+ try {
+ CDI<Object> cdi = CDI.current();
+ return Optional.ofNullable(cdi);
+ } catch (Exception e) {
+ return Optional.empty();
+ }
+ }
+
+ /**
+ * Filters the input array into a collection, such that only annotations are retained,
+ * that are valid qualifiers for CDI.
+ * @param annotations
+ * @return non-null
+ */
+ public static List<Annotation> filterQualifiers(final Annotation[] annotations) {
+ return _NullSafe.stream(annotations)
+ .filter(_CDI::isQualifier)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * @param annotation
+ * @return whether or not the annotation is a valid qualifier for CDI
+ */
+ public static boolean isQualifier(Annotation annotation) {
+ if(annotation==null) {
+ return false;
+ }
+ return annotation.annotationType().getAnnotationsByType(Qualifier.class).length>0;
+ }
+
+ // -- HELPER
+
+ private _CDI() {}
+
+ private static <T> T tryGet(final Supplier<T> supplier) {
+ try {
+ return supplier.get();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+}
diff --git a/core/commons/src/test/java/org/apache/isis/commons/internal/cdi/CDITest.java b/core/commons/src/test/java/org/apache/isis/commons/internal/cdi/CDITest.java
new file mode 100644
index 0000000..6365071
--- /dev/null
+++ b/core/commons/src/test/java/org/apache/isis/commons/internal/cdi/CDITest.java
@@ -0,0 +1,107 @@
+package org.apache.isis.commons.internal.cdi;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.List;
+
+import javax.annotation.CheckForNull;
+import javax.inject.Inject;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class CDITest {
+
+ private Field stringField1;
+ private Field stringField2;
+ private Field stringField3;
+
+ @BeforeEach
+ void setUp() throws Exception {
+ stringField1 = Customer.class.getDeclaredField("stringField1");
+ stringField2 = Customer.class.getDeclaredField("stringField2");
+ stringField3 = Customer.class.getDeclaredField("stringField3");
+ }
+
+ @AfterEach
+ void tearDown() throws Exception {
+ }
+
+ // -- STAGED TEST CLASS
+
+ static class Customer {
+
+ @Inject
+ String stringField1;
+
+ @Inject @CheckForNull //arbitrary non qualifier
+ String stringField2;
+
+ @Inject @ValidQualifierForTesting
+ String stringField3;
+ }
+
+ // ---
+
+ @Test
+ void qualifierDetection() {
+
+ //when
+ ValidQualifierForTesting[] annotations = stringField3.getAnnotationsByType(ValidQualifierForTesting.class);
+
+ //then
+ assertNotNull(annotations);
+ assertEquals(1, annotations.length);
+
+ //when
+ ValidQualifierForTesting annotation = annotations[0];
+
+ //then
+ assertNotNull(annotation);
+ assertTrue(_CDI.isQualifier(annotation));
+
+ }
+
+
+ @Test
+ void noQualifier() {
+
+ //when
+ List<Annotation> qualifiers = _CDI.filterQualifiers(stringField1.getAnnotations());
+
+ //then
+ assertNotNull(qualifiers);
+ assertEquals(0, qualifiers.size());
+
+ }
+
+ @Test
+ void noQualifier_arbitraryAnnotation() {
+
+ //when
+ List<Annotation> qualifiers = _CDI.filterQualifiers(stringField2.getAnnotations());
+
+ //then
+ assertNotNull(qualifiers);
+ assertEquals(0, qualifiers.size());
+
+ }
+
+ @Test
+ void singleQualifier() {
+
+ //when
+ List<Annotation> qualifiers = _CDI.filterQualifiers(stringField3.getAnnotations());
+
+ //then
+ assertNotNull(qualifiers);
+ assertEquals(1, qualifiers.size());
+
+ }
+
+}
diff --git a/core/commons/src/test/java/org/apache/isis/commons/internal/cdi/ValidQualifierForTesting.java b/core/commons/src/test/java/org/apache/isis/commons/internal/cdi/ValidQualifierForTesting.java
new file mode 100644
index 0000000..32ac449
--- /dev/null
+++ b/core/commons/src/test/java/org/apache/isis/commons/internal/cdi/ValidQualifierForTesting.java
@@ -0,0 +1,17 @@
+package org.apache.isis.commons.internal.cdi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Qualifier
+@Retention(RUNTIME)
+@Target(FIELD)
+@interface ValidQualifierForTesting {
+
+
+}
diff --git a/core/config/src/main/java/org/apache/isis/config/AppConfigLocator.java b/core/config/src/main/java/org/apache/isis/config/AppConfigLocator.java
index 74e962d..0abdb01 100644
--- a/core/config/src/main/java/org/apache/isis/config/AppConfigLocator.java
+++ b/core/config/src/main/java/org/apache/isis/config/AppConfigLocator.java
@@ -1,12 +1,11 @@
package org.apache.isis.config;
-import javax.enterprise.inject.spi.CDI;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.isis.applib.AppManifest;
import org.apache.isis.commons.internal.base._Casts;
+import org.apache.isis.commons.internal.cdi._CDI;
import org.apache.isis.commons.internal.context._Context;
import org.apache.isis.commons.internal.context._Plugin;
import org.apache.isis.config.builder.IsisConfigurationBuilder;
@@ -50,16 +49,7 @@ public final class AppConfigLocator {
}
private static AppConfig lookupAppConfig_UsingCDI() {
- try {
- final CDI<Object> cdi = CDI.current();
- if(cdi==null) {
- return null;
- }
- return cdi.select(AppConfig.class).get();
- } catch (Exception e) {
- // ignore
- }
- return null;
+ return _CDI.getManagedBean(AppConfig.class).orElse(null);
}
private static AppConfig lookupAppConfig_UsingServiceLoader() {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
index 3644dd1..d7cfc36 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
@@ -37,6 +37,7 @@ import org.apache.isis.applib.services.registry.ServiceRegistry;
import org.apache.isis.commons.internal.base._Lazy;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.commons.internal.cdi._CDI;
import org.apache.isis.commons.internal.collections._Collections;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.commons.internal.collections._Multimaps;
@@ -332,6 +333,11 @@ public class ServicesInjector implements ApplicationScopedComponent, ServiceRegi
return;
}
}
+
+ // fallback and try CDI
+ _CDI.getManagedBean(typeToBeInjected, _CDI.filterQualifiers(field.getAnnotations()))
+ .ifPresent(bean->invokeInjectorField(field, object, bean));
+
}
private void autowireViaPrefixedMethods(