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 7638af5646 ISIS-3232: fail MM validation, if viewmodels have no
recreation strategy
7638af5646 is described below
commit 7638af5646de3e9d7250302fdffe5f87c8e04fc5
Author: Andi Huber <[email protected]>
AuthorDate: Thu Oct 6 07:52:42 2022 +0200
ISIS-3232: fail MM validation, if viewmodels have no recreation strategy
---
.../progmodel/ProgrammingModelConstants.java | 10 ++++++
.../facets/HasPostConstructMethodCache.java | 4 +--
.../object/viewmodel/ViewModelFacetAbstract.java | 2 +-
.../object/viewmodel/ViewModelFacetFactory.java | 39 +++++++++++++---------
.../metamodel/facets/MethodFinderUtilsTest.java | 11 ++----
5 files changed, 40 insertions(+), 26 deletions(-)
diff --git
a/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
b/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
index 22b2ac0b67..3975086aea 100644
---
a/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
+++
b/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
@@ -478,9 +478,19 @@ public final class ProgrammingModelConstants {
UNSATISFIED_DOMAIN_INCLUDE_SEMANTICS("${type}#${member}: "
+ "has synthesized (effective) annotation @Domain.Include, "
+ "is assumed to represent or support a property, collection
or action."),
+ VIEWMODEL_CONFLICTING_SERIALIZATION_STRATEGIES(
+ "${type}: has multiple incompatible annotations/interfaces
indicating that "
+ + "it is a recreatable object of some sort (${facetA} and
${facetB})"),
VIEWMODEL_MISSING_DESERIALIZING_CONSTRUCTOR(
"${type}: ViewModel contract violation: missing single
(String) arg constructor "
+ "(for de-serialization from memento string)."),
+ VIEWMODEL_MISSING_SERIALIZATION_STRATEGY( // draft: not used yet
+ "${type}: Missing ViewModel serialization strategy
encountered; "
+ + "for ViewModels one of those must be true: "
+ + "(1) implements the ViewModel interface, "
+ + "(2) implements Serializable, "
+ + "(3) uses JAXB semantics, "
+ + "(4) has explicit VIEW_MODEL nature via DomainObject
annotation."),
DOMAIN_OBJECT_INVALID_NAVIGABLE_PARENT("${type}: the object's
navigable parent must no be void, "
+ "plural, vetoed or a value-type; "
+ "yet the parent type '${parentType}' as discovered was
${parentTypeDeficiency}; "),
diff --git
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/HasPostConstructMethodCache.java
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/HasPostConstructMethodCache.java
index 5e0555595e..3d6389cacf 100644
---
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/HasPostConstructMethodCache.java
+++
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/HasPostConstructMethodCache.java
@@ -35,10 +35,10 @@ public interface HasPostConstructMethodCache {
MethodByClassMap getPostConstructMethodsCache();
- default Method postConstructMethodFor(final Object pojo) {
+ default Method postConstructMethodFor(final Class<?> domainObjectClass) {
return findAnnotatedMethod(
// @PostConstruct is allowed to appear on non-public methods
- MethodFinder.notNecessarilyPublic(pojo.getClass(),
MethodFinder.ANY_NAME)
+ MethodFinder.notNecessarilyPublic(domainObjectClass,
MethodFinder.ANY_NAME)
.withRequiredReturnType(void.class),
PostConstruct.class,
getPostConstructMethodsCache());
diff --git
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetAbstract.java
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetAbstract.java
index 9776e8ca8d..08770e07ff 100644
---
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetAbstract.java
+++
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetAbstract.java
@@ -95,7 +95,7 @@ implements ViewModelFacet {
@NonNull Bookmark bookmark);
private void invokePostConstructMethod(final Object viewModel) {
- final Method postConstructMethod =
postConstructMethodCache.postConstructMethodFor(viewModel);
+ final Method postConstructMethod =
postConstructMethodCache.postConstructMethodFor(viewModel.getClass());
if (postConstructMethod != null) {
CanonicalInvoker.invoke(postConstructMethod, viewModel);
}
diff --git
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetFactory.java
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetFactory.java
index e1462fecba..bb935d73df 100644
---
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetFactory.java
+++
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetFactory.java
@@ -18,9 +18,12 @@
*/
package org.apache.isis.core.metamodel.facets.object.viewmodel;
+import java.util.Map;
+
import javax.inject.Inject;
import javax.xml.bind.annotation.XmlRootElement;
+import org.apache.isis.core.config.progmodel.ProgrammingModelConstants;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.facetapi.FacetUtil;
import org.apache.isis.core.metamodel.facetapi.FeatureType;
@@ -90,22 +93,28 @@ implements
programmingModel.addVisitingValidatorSkipManagedBeans(objectSpec -> {
- objectSpec.lookupFacet(ViewModelFacet.class)
- .map(ViewModelFacet::getSharedFacetRankingElseFail)
- .ifPresent(facetRanking->facetRanking
- .visitTopRankPairsSemanticDiffering(ViewModelFacet.class,
(a, b)->{
-
- ValidationFailure.raiseFormatted(
- objectSpec,
- "%s: has multiple incompatible
annotations/interfaces indicating that " +
- "it is a recreatable object of
some sort (%s and %s)",
- objectSpec.getFullIdentifier(),
- a.getClass().getSimpleName(),
- b.getClass().getSimpleName());
-
-
- }));
+ // ensure concrete viewmodel types have a ViewModelFacet
+ if(!objectSpec.isAbstract()
+ && objectSpec.getBeanSort().isViewModel()
+ && !objectSpec.viewmodelFacet().isPresent()) {
+ ValidationFailure.raiseFormatted(objectSpec,
+
ProgrammingModelConstants.Validation.VIEWMODEL_MISSING_SERIALIZATION_STRATEGY
+
.getMessageForType(objectSpec.getCorrespondingClass().getName()));
+ }
+ objectSpec.viewmodelFacet()
+ .map(ViewModelFacet::getSharedFacetRankingElseFail)
+ .ifPresent(facetRanking->{
+ facetRanking
+ .visitTopRankPairsSemanticDiffering(ViewModelFacet.class, (a,
b)->{
+ ValidationFailure.raiseFormatted(objectSpec,
+
ProgrammingModelConstants.Validation.VIEWMODEL_CONFLICTING_SERIALIZATION_STRATEGIES
+ .getMessage(Map.of(
+ "type", objectSpec.getFullIdentifier(),
+ "facetA", a.getClass().getSimpleName(),
+ "facetB",
b.getClass().getSimpleName())));
+ });
+ });
});
}
diff --git
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/MethodFinderUtilsTest.java
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/MethodFinderUtilsTest.java
index 9fc9c43bcc..eb28b10a68 100644
---
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/MethodFinderUtilsTest.java
+++
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/MethodFinderUtilsTest.java
@@ -45,19 +45,14 @@ class MethodFinderUtilsTest {
@BeforeEach
public void setup() {
val methodByClassMap = new MethodByClassMap();
- this.hasPostConstructMethodCache = new HasPostConstructMethodCache() {
- @Override
- public MethodByClassMap getPostConstructMethodsCache() {
- return methodByClassMap;
- }
- };
+ this.hasPostConstructMethodCache = () -> methodByClassMap;
}
@Test
public void whenExists() throws Exception {
val cache = hasPostConstructMethodCache.getPostConstructMethodsCache();
- val method = hasPostConstructMethodCache.postConstructMethodFor(new
_TestDummies.WithPostConstruct());
+ val method =
hasPostConstructMethodCache.postConstructMethodFor(_TestDummies.WithPostConstruct.class);
assertThat(method, is(not(nullValue())));
final Optional<Method> actual =
cache.get(_TestDummies.WithPostConstruct.class);
@@ -70,7 +65,7 @@ class MethodFinderUtilsTest {
public void whenDoesNotExist() throws Exception {
val cache = hasPostConstructMethodCache.getPostConstructMethodsCache();
- val method = hasPostConstructMethodCache.postConstructMethodFor(new
NoPostConstruct());
+ val method =
hasPostConstructMethodCache.postConstructMethodFor(NoPostConstruct.class);
assertThat(method, is(nullValue()));
final Optional<Method> actual = cache.get(NoPostConstruct.class);