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 3875249322 ISIS-3295: fixes post-construct not called, when viewmodel 
new-ed up programmatically
3875249322 is described below

commit 3875249322ab308921be2724845a4cf00a95c1ac
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Fri Nov 25 09:39:32 2022 +0100

    ISIS-3295: fixes post-construct not called, when viewmodel new-ed up
    programmatically
---
 .../applib/services/factory/FactoryService.java    |  2 +-
 .../facets/object/viewmodel/ViewModelFacet.java    |  7 +++
 .../object/viewmodel/ViewModelFacetAbstract.java   | 12 +++-
 .../factory/FactoryServiceDefault.java             | 68 ++++++++++++++--------
 4 files changed, 61 insertions(+), 28 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/factory/FactoryService.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/factory/FactoryService.java
index 499833b7a4..81dee2ddc6 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/services/factory/FactoryService.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/factory/FactoryService.java
@@ -154,7 +154,7 @@ public interface FactoryService {
      * with injection points resolved,
      * post-construct called
      * and defaults applied.
-     * @param domainClass - must be a <i>Spring</i> managed type
+     * @param domainClass - must NOT be a <i>Spring</i> managed type
      * @throws IllegalArgumentException if domainClass is a <i>Spring</i> 
managed type,
      *      or not recognized by the meta-model
      * @apiNote forces the domainClass to be added to the meta-model if not 
already
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
index 73f8bc30ca..dc74b4778f 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
@@ -20,6 +20,8 @@ package 
org.apache.causeway.core.metamodel.facets.object.viewmodel;
 
 import java.util.Optional;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.causeway.applib.annotation.Nature;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
 import org.apache.causeway.core.metamodel.facetapi.Facet;
@@ -54,4 +56,9 @@ public interface ViewModelFacet extends Facet {
      */
     Bookmark serializeToBookmark(ManagedObject managedObject);
 
+    /**
+     * For given view-model pojo resolves injection points, then calls 
post-construct method(s) if any.
+     */
+    void initialize(@Nullable Object pojo);
+
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/viewmodel/ViewModelFacetAbstract.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/viewmodel/ViewModelFacetAbstract.java
index 9ad17cf8c0..ddc2b2e157 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/viewmodel/ViewModelFacetAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/viewmodel/ViewModelFacetAbstract.java
@@ -21,6 +21,8 @@ package 
org.apache.causeway.core.metamodel.facets.object.viewmodel;
 import java.lang.reflect.Method;
 import java.util.Optional;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.causeway.applib.services.bookmark.Bookmark;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.core.metamodel.commons.CanonicalInvoker;
@@ -74,11 +76,17 @@ implements ViewModelFacet {
                 ? createViewmodel(spec)
                 : createViewmodel(spec, bookmark);
 
-        getServiceInjector().injectServicesInto(viewModel.getPojo());
-        invokePostConstructMethod(viewModel.getPojo());
+        initialize(viewModel.getPojo());
         return viewModel;
     }
 
+    @Override
+    public final void initialize(final @Nullable Object pojo) {
+        if(pojo==null) return;
+        getServiceInjector().injectServicesInto(pojo);
+        invokePostConstructMethod(pojo);
+    }
+
     /**
      * Create default viewmodel instance (without any {@link Bookmark} 
available).
      */
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/factory/FactoryServiceDefault.java
 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/factory/FactoryServiceDefault.java
index 37535df515..4a56c4a41a 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/factory/FactoryServiceDefault.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/factory/FactoryServiceDefault.java
@@ -61,7 +61,7 @@ public class FactoryServiceDefault implements FactoryService {
 
     @Override
     public <T> T getOrCreate(final @NonNull Class<T> requiredType) {
-        val spec = loadSpec(requiredType);
+        val spec = loadSpecElseFail(requiredType);
         if(spec.isInjectable()) {
             return get(requiredType);
         }
@@ -77,19 +77,19 @@ public class FactoryServiceDefault implements 
FactoryService {
 
     @Override
     public <T> T detachedEntity(final @NonNull Class<T> domainClass) {
-        val entitySpec = loadSpec(domainClass);
+        val entitySpec = loadSpecElseFail(domainClass);
         if(!entitySpec.isEntity()) {
             throw _Exceptions.illegalArgument("Class '%s' is not an entity", 
domainClass.getName());
         }
-        return _Casts.uncheckedCast(createObject(entitySpec));
+        return createObject(domainClass, entitySpec);
     }
 
     @Override
     public <T> T detachedEntity(final @NonNull T entityPojo) {
         val entityClass = entityPojo.getClass();
-        val spec = loadSpec(entityClass);
+        val spec = loadSpecElseFail(entityClass);
         if(!spec.isEntity()) {
-            throw _Exceptions.illegalArgument("Type '%s' is not recogniced as 
an entity type by the framework.",
+            throw _Exceptions.illegalArgument("Type '%s' is not recognized as 
an entity type by the framework.",
                     entityClass);
         }        
objectLifecyclePublisher().onPostCreate(ManagedObject.entity(spec, entityPojo, 
Optional.empty()));
         return entityPojo;
@@ -97,7 +97,7 @@ public class FactoryServiceDefault implements FactoryService {
 
     @Override
     public <T> T mixin(final @NonNull Class<T> mixinClass, final @NonNull 
Object mixee) {
-        val mixinSpec = loadSpec(mixinClass);
+        val mixinSpec = loadSpecElseFail(mixinClass);
         val mixinFacet = mixinSpec.getFacet(MixinFacet.class);
         if(mixinFacet == null) {
             throw _Exceptions.illegalArgument("Class '%s' is not a mixin",
@@ -114,49 +114,67 @@ public class FactoryServiceDefault implements 
FactoryService {
     @Override
     public <T> T viewModel(final @NonNull T viewModelPojo) {
         val viewModelClass = viewModelPojo.getClass();
-        val spec = loadSpec(viewModelClass);
+        val spec = loadSpecElseFail(viewModelClass);
         if(!spec.isViewModel()) {
-            throw _Exceptions.illegalArgument("Type '%s' is not recogniced as 
a ViewModel by the framework.",
+            throw _Exceptions.illegalArgument("Type '%s' is not recognized as 
a ViewModel by the framework.",
                     viewModelClass);
         }
+        spec.viewmodelFacetElseFail().initialize(viewModelPojo);
         objectLifecyclePublisher().onPostCreate(ManagedObject.viewmodel(spec, 
viewModelPojo, Optional.empty()));
         return viewModelPojo;
     }
 
     @Override
     public <T> T viewModel(final @NonNull Class<T> viewModelClass, final 
@Nullable Bookmark bookmark) {
-        val spec = loadSpec(viewModelClass);
-        if(!spec.isViewModel()) {
-            throw _Exceptions.illegalArgument("Type '%s' is not recogniced as 
a ViewModel by the framework.",
-                    viewModelClass);
-        }
-        val viewModelFacet = spec.viewmodelFacetElseFail();
-        val viewModel = viewModelFacet.instantiate(spec, 
Optional.ofNullable(bookmark));
-        objectLifecyclePublisher().onPostCreate(viewModel);
-        return _Casts.uncheckedCast(viewModel.getPojo());
+        val spec = loadSpecElseFail(viewModelClass);
+        return createViewModelElseFail(viewModelClass, spec, 
Optional.ofNullable(bookmark));
     }
 
     @Override
     public <T> T create(final @NonNull Class<T> domainClass) {
-        val spec = loadSpec(domainClass);
-
+        val spec = loadSpecElseFail(domainClass);
         if(spec.isInjectable()) {
             throw _Exceptions.illegalArgument(
-                    "Class '%s' is managed by IoC container, use get() 
instead", domainClass.getName());
+                    "Class '%s' is managed by Spring, use get() instead", 
domainClass.getName());
         }
-        return _Casts.uncheckedCast(createObject(spec));
+        if(spec.isViewModel()) {
+            return createViewModelElseFail(domainClass, spec, 
Optional.empty());
+        }
+        if(spec.isEntity()) {
+            return detachedEntity(domainClass);
+        }
+        // fallback to generic object creation
+        return createObject(domainClass, spec);
     }
 
     // -- HELPER
 
-    private ObjectSpecification loadSpec(final @NonNull Class<?> type) {
+    private ObjectSpecification loadSpecElseFail(final @NonNull Class<?> type) 
{
         return specificationLoader.specForTypeElseFail(type);
     }
 
-    private Object createObject(final ObjectSpecification spec) {
-        // already handles injection and publishing
+    /** handles injection, post-construct and publishing */
+    private <T> T createViewModelElseFail(
+            final @NonNull Class<T> viewModelClass,
+            final @NonNull ObjectSpecification objectSpecification,
+            final @NonNull Optional<Bookmark> bookmarkIfAny) {
+        return Optional.of(objectSpecification)
+        .filter(ObjectSpecification::isViewModel)
+        .<T>map(spec->{
+            val viewModel = spec.viewmodelFacetElseFail().instantiate(spec, 
bookmarkIfAny);
+            objectLifecyclePublisher().onPostCreate(viewModel);
+            return _Casts.uncheckedCast(viewModel.getPojo());
+        })
+        .orElseThrow(()->_Exceptions.illegalArgument("Type '%s' is not 
recognized as a ViewModel by the framework.",
+                viewModelClass));
+    }
+
+    /** handles injection and publishing, but probably not post-construct */
+    private <T> T createObject(
+            final @NonNull Class<?> type,
+            final @NonNull ObjectSpecification spec) {
         val domainObject = spec.createObject();
-        return domainObject.getPojo();
+        return _Casts.uncheckedCast(domainObject.getPojo());
     }
 
 }

Reply via email to