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 2020/01/21 13:04:32 UTC

[isis] branch master updated: ISIS-2270: polishing FactoryService#get

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 4d6e3ed  ISIS-2270: polishing FactoryService#get
4d6e3ed is described below

commit 4d6e3ed63fb8c7f21a6b12ba89d3cecb20c83150
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Jan 21 14:04:24 2020 +0100

    ISIS-2270: polishing FactoryService#get
    
    - possibly shared or independent but required to resolvable uniquely
---
 .../isis/applib/services/factory/FactoryService.java    | 10 ++++++----
 .../core/commons/internal/exceptions/_Exceptions.java   | 17 +++++++++--------
 .../isis/core/commons/internal/ioc/IocContainer.java    | 11 +++++++++++
 .../commons/internal/ioc/spring/IocContainerSpring.java | 11 +++++++++++
 .../isis/core/metamodel/commons/ClassExtensions.java    |  5 +++++
 .../recreatable/RecreatableObjectFacetAbstract.java     | 10 +++++++++-
 .../runtimeservices/factory/FactoryServiceDefault.java  |  5 +++--
 .../demoapp/dom/actions/assoc/AssociatedActionMenu.java |  2 +-
 8 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/factory/FactoryService.java b/api/applib/src/main/java/org/apache/isis/applib/services/factory/FactoryService.java
index 2f4ec09..f13919e 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/factory/FactoryService.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/factory/FactoryService.java
@@ -24,18 +24,22 @@ import java.util.NoSuchElementException;
 import javax.annotation.Nullable;
 
 import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.core.commons.exceptions.IsisException;
 
 public interface FactoryService {
 
     /**
-     * Gets an instance of the specified {@code requiredType}, with injection points resolved 
+     * Gets an instance (possibly shared or independent) of the specified {@code requiredType}, 
+     * with injection points resolved 
      * and any life-cycle callback processed.
      * 
      * @param <T>
      * @param requiredType
-     * @return (non-null), if ambiguous picks the first best matching
+     * @return (non-null), an instance of {@code requiredType}, if available and unique
+     * (i.e. not multiple candidates found with none marked as primary)
      * 
      * @throws NoSuchElementException if result is empty
+     * @throws IsisException if instance creation failed
      * 
      * @apiNote does not force the requiredType to be added to the meta-model
      * 
@@ -57,7 +61,6 @@ public interface FactoryService {
      * @param viewModelClass
      * @param mementoStr - ignored if {@code null}
      * @since 2.0
-     * @apiNote EXPERIMENTAL
      */
     <T> T viewModel(Class<T> viewModelClass, @Nullable String mementoStr);
 
@@ -65,7 +68,6 @@ public interface FactoryService {
      * Creates a new ViewModel instance 
      * @param viewModelClass
      * @since 2.0
-     * @apiNote EXPERIMENTAL
      */
     default <T> T viewModel(Class<T> viewModelClass) {
         return viewModel(viewModelClass, /*mementoStr*/null);
diff --git a/core/commons/src/main/java/org/apache/isis/core/commons/internal/exceptions/_Exceptions.java b/core/commons/src/main/java/org/apache/isis/core/commons/internal/exceptions/_Exceptions.java
index 2563b62..fd1f314 100644
--- a/core/commons/src/main/java/org/apache/isis/core/commons/internal/exceptions/_Exceptions.java
+++ b/core/commons/src/main/java/org/apache/isis/core/commons/internal/exceptions/_Exceptions.java
@@ -31,6 +31,7 @@ import java.util.stream.Stream;
 
 import javax.annotation.Nullable;
 
+import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.internal.base._NullSafe;
 import org.apache.isis.core.commons.internal.base._Strings;
 import org.apache.isis.core.commons.internal.base._With;
@@ -108,20 +109,20 @@ public final class _Exceptions {
 
     // -- UNRECOVERABLE
     
-    public static RuntimeException unrecoverable(Throwable cause) {
-        return new RuntimeException("unrecoverable error: with cause ...", cause);
+    public static IsisException unrecoverable(Throwable cause) {
+        return new IsisException("unrecoverable error: with cause ...", cause);
     }
 
-    public static RuntimeException unrecoverable(String msg) {
-        return new RuntimeException(String.format("unrecoverable error: '%s'", msg));
+    public static IsisException unrecoverable(String msg) {
+        return new IsisException(String.format("unrecoverable error: '%s'", msg));
     }
 
-    public static RuntimeException unrecoverable(String msg, Throwable cause) {
-        return new RuntimeException(String.format("unrecoverable error: '%s' with cause ...", msg), cause);
+    public static IsisException unrecoverable(String msg, Throwable cause) {
+        return new IsisException(String.format("unrecoverable error: '%s' with cause ...", msg), cause);
     }
     
-    public static RuntimeException unrecoverableFormatted(String format, Object ...args) {
-        return new RuntimeException(String.format("unrecoverable error: '%s'", 
+    public static IsisException unrecoverableFormatted(String format, Object ...args) {
+        return new IsisException(String.format("unrecoverable error: '%s'", 
                 String.format(format, args)));
     }
     
diff --git a/core/commons/src/main/java/org/apache/isis/core/commons/internal/ioc/IocContainer.java b/core/commons/src/main/java/org/apache/isis/core/commons/internal/ioc/IocContainer.java
index a37ce0c..46d6f6f 100644
--- a/core/commons/src/main/java/org/apache/isis/core/commons/internal/ioc/IocContainer.java
+++ b/core/commons/src/main/java/org/apache/isis/core/commons/internal/ioc/IocContainer.java
@@ -27,6 +27,7 @@ import java.util.stream.Stream;
 import javax.annotation.Nullable;
 
 import org.apache.isis.core.commons.collections.Can;
+import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.internal.exceptions._Exceptions;
 
 /**
@@ -40,6 +41,16 @@ public interface IocContainer {
 
     Optional<?> lookupById(final String id);
 
+    /**
+     * Return an instance (possibly shared or independent) of the object managed by the IoC container.
+     * @param <T>
+     * @param requiredType
+     * @return an instance of the bean, or null if not available or not unique
+     * (i.e. multiple candidates found with none marked as primary)
+     * @throws IsisException if instance creation failed
+     */
+    <T> Optional<T> get(Class<T> requiredType);    
+    
     <T> Can<T> select(Class<T> requiredType);
     
     <T> Can<T> select(Class<T> requiredType, Set<Annotation> qualifiersRequired);
diff --git a/core/commons/src/main/java/org/apache/isis/core/commons/internal/ioc/spring/IocContainerSpring.java b/core/commons/src/main/java/org/apache/isis/core/commons/internal/ioc/spring/IocContainerSpring.java
index bfda14e..61a05f6 100644
--- a/core/commons/src/main/java/org/apache/isis/core/commons/internal/ioc/spring/IocContainerSpring.java
+++ b/core/commons/src/main/java/org/apache/isis/core/commons/internal/ioc/spring/IocContainerSpring.java
@@ -31,6 +31,7 @@ import org.springframework.core.ResolvableType;
 import org.apache.isis.core.commons.collections.Can;
 import org.apache.isis.core.commons.internal.base._NullSafe;
 import org.apache.isis.core.commons.internal.collections._Sets;
+import org.apache.isis.core.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.commons.internal.ioc.IocContainer;
 import org.apache.isis.core.commons.internal.ioc.ManagedBeanAdapter;
 import org.apache.isis.core.commons.internal.base._With;
@@ -50,6 +51,16 @@ public class IocContainerSpring implements IocContainer {
     @NonNull private final ApplicationContext springContext;
 
     @Override
+    public <T> Optional<T> get(Class<T> requiredType) {
+        val provider = springContext.getBeanProvider(requiredType);
+        try {
+            return Optional.ofNullable(provider.getIfUnique());
+        } catch (Exception cause) {
+            throw _Exceptions.unrecoverable("Failed to create an instance of type " + requiredType, cause);
+        }
+    }
+    
+    @Override
     public Stream<ManagedBeanAdapter> streamAllBeans() {
 
         val context = springContext;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/ClassExtensions.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/ClassExtensions.java
index 587951b..d586240 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/ClassExtensions.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/ClassExtensions.java
@@ -26,6 +26,7 @@ import java.lang.reflect.Modifier;
 import java.net.URL;
 
 import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.internal._Constants;
 import org.apache.isis.core.commons.internal.collections._Lists;
 import org.apache.isis.core.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.commons.internal.resources._Resources;
@@ -38,6 +39,10 @@ public final class ClassExtensions {
     private ClassExtensions() {
     }
 
+    public static Object newInstance(final Class<?> type) {
+        return ClassExtensions.newInstance(type, _Constants.emptyClasses, _Constants.emptyObjects);
+    }
+    
     public static Object newInstance(final Class<?> extendee, final Class<?> constructorParamType, final Object constructorArg) {
         return ClassExtensions.newInstance(extendee, new Class[] { constructorParamType }, new Object[] { constructorArg });
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
index f838cde..70f9758 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
@@ -23,6 +23,8 @@ import java.lang.reflect.Method;
 import java.util.Map;
 
 import org.apache.isis.applib.ViewModel;
+import org.apache.isis.core.commons.internal.base._Strings;
+import org.apache.isis.core.metamodel.commons.ClassExtensions;
 import org.apache.isis.core.metamodel.commons.MethodExtensions;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
@@ -31,6 +33,8 @@ import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
 import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
 import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault;
 
+import lombok.val;
+
 public abstract class RecreatableObjectFacetAbstract extends FacetAbstract implements ViewModelFacet {
 
     private final PostConstructMethodCache postConstructMethodCache;
@@ -81,7 +85,11 @@ public abstract class RecreatableObjectFacetAbstract extends FacetAbstract imple
         if (getRecreationMechanism() == RecreationMechanism.INITIALIZES) {
             throw new IllegalStateException("This view model instantiates rather than initializes");
         }
-        final Object viewModelPojo = doInstantiate(viewModelClass, mementoStr);
+        
+        val viewModelPojo = _Strings.isNullOrEmpty(mementoStr)
+                ? ClassExtensions.newInstance(viewModelClass)
+                : doInstantiate(viewModelClass, mementoStr);
+                
         getServiceInjector().injectServicesInto(viewModelPojo);
         invokePostConstructMethod(viewModelPojo);
         return viewModelPojo;
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/factory/FactoryServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/factory/FactoryServiceDefault.java
index ec76f6a..139020a 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/factory/FactoryServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/factory/FactoryServiceDefault.java
@@ -62,8 +62,9 @@ public class FactoryServiceDefault implements FactoryService {
 
     @Override
     public <T> T get(final Class<T> requiredType) {
-        val candidates = isisSystemEnvironment.getIocContainer().select(requiredType);
-        return candidates.getFirstOrFail();
+        return isisSystemEnvironment.getIocContainer()
+                .get(requiredType)
+                .orElseThrow(_Exceptions::noSuchElement);
     }
 
     @Override
diff --git a/examples/demo/src/main/java/demoapp/dom/actions/assoc/AssociatedActionMenu.java b/examples/demo/src/main/java/demoapp/dom/actions/assoc/AssociatedActionMenu.java
index 370279e..3460247 100644
--- a/examples/demo/src/main/java/demoapp/dom/actions/assoc/AssociatedActionMenu.java
+++ b/examples/demo/src/main/java/demoapp/dom/actions/assoc/AssociatedActionMenu.java
@@ -38,7 +38,7 @@ public class AssociatedActionMenu {
     @Action
     @ActionLayout(cssClassFa="fa-bolt")
     public AssociatedActionDemo associatedActions(){
-        val demo = factoryService.instantiate(AssociatedActionDemo.class);
+        val demo = factoryService.viewModel(AssociatedActionDemo.class);
         demo.initDefaults();
         return demo;
     }