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 <[email protected]>
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());
}
}