You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2023/09/20 12:55:39 UTC

[causeway] branch CAUSEWAY-3593 created (now 8993dbb174)

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

danhaywood pushed a change to branch CAUSEWAY-3593
in repository https://gitbox.apache.org/repos/asf/causeway.git


      at 8993dbb174 CAUSEWAY-3593: adds refiner for MaxLengthJpaColumnAnnotationFacetFactory also

This branch includes the following new commits:

     new e422a22aac CAUSEWAY-3593: makes JPA-specific facet factories mirror JDO
     new 8993dbb174 CAUSEWAY-3593: adds refiner for MaxLengthJpaColumnAnnotationFacetFactory also

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[causeway] 02/02: CAUSEWAY-3593: adds refiner for MaxLengthJpaColumnAnnotationFacetFactory also

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-3593
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 8993dbb1748bcb5bba7937a779dbe831ae302830
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Wed Sep 20 13:55:35 2023 +0100

    CAUSEWAY-3593: adds refiner for MaxLengthJpaColumnAnnotationFacetFactory also
    
    and makes consistent other JDO/JPA classes from prev commit
---
 ...romXxxColumnAnnotationMetaModelRefinerUtil.java |  1 +
 ...romXxxColumnAnnotationMetaModelRefinerUtil.java |  1 +
 ...omXxxColumnAnnotationMetaModelRefinerUtil.java} | 16 +++++------
 ...DecimalFromJdoColumnAnnotationFacetFactory.java | 13 +++++----
 ...ndatoryFromJdoColumnAnnotationFacetFactory.java | 13 ++++-----
 ...xLengthFromJdoColumnAnnotationFacetFactory.java | 33 +++++-----------------
 ...DecimalFromJpaColumnAnnotationFacetFactory.java |  5 ++--
 ...ndatoryFromJpaColumnAnnotationFacetFactory.java |  7 ++---
 ...xLengthFromJpaColumnAnnotationFacetFactory.java | 20 +++++++++----
 9 files changed, 48 insertions(+), 61 deletions(-)

diff --git a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil.java b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil.java
index ebb90f58d6..0e600923a7 100644
--- a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil.java
+++ b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil.java
@@ -9,6 +9,7 @@ import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure
 
 @UtilityClass
 public class BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil {
+
     public static void validateBigDecimalValueFacet(final ObjectAssociation association) {
 
         association.lookupFacet(MaxTotalDigitsFacet.class)
diff --git a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java
index 76da577ad8..312cd89fad 100644
--- a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java
+++ b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java
@@ -8,6 +8,7 @@ import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure
 
 @UtilityClass
 public class MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil {
+
     public static void validateMandatoryFacet(final ObjectAssociation association) {
 
         association.lookupFacet(MandatoryFacet.class)
diff --git a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MaxLengthFromXxxColumnAnnotationMetaModelRefinerUtil.java
similarity index 56%
copy from persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java
copy to persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MaxLengthFromXxxColumnAnnotationMetaModelRefinerUtil.java
index 76da577ad8..dfcf3251ac 100644
--- a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java
+++ b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MaxLengthFromXxxColumnAnnotationMetaModelRefinerUtil.java
@@ -2,26 +2,24 @@ package org.apache.causeway.persistence.commons.metamodel.facets.prop.column;
 
 import lombok.experimental.UtilityClass;
 
-import org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet;
+import org.apache.causeway.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure;
 
 @UtilityClass
-public class MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil {
-    public static void validateMandatoryFacet(final ObjectAssociation association) {
-
-        association.lookupFacet(MandatoryFacet.class)
-        .map(MandatoryFacet::getSharedFacetRankingElseFail)
+public class MaxLengthFromXxxColumnAnnotationMetaModelRefinerUtil {
+    public static void validateMaxLengthFacet(ObjectAssociation association) {
+        association.lookupFacet(MaxLengthFacet.class)
+        .map(MaxLengthFacet::getSharedFacetRankingElseFail)
         .ifPresent(facetRanking->facetRanking
-                .visitTopRankPairsSemanticDiffering(MandatoryFacet.class, (a, b)->{
+                .visitTopRankPairsSemanticDiffering(MaxLengthFacet.class, (a, b)->{
 
                     ValidationFailure.raiseFormatted(
                             association,
-                            "%s: inconsistent Mandatory/Optional semantics specified in %s and %s.",
+                            "%s: inconsistent MaxLength semantics specified in %s and %s.",
                             association.getFeatureIdentifier().toString(),
                             a.getClass().getSimpleName(),
                             b.getClass().getSimpleName());
                 }));
-
     }
 }
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactory.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactory.java
index 10882eddb2..e2ef62282a 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactory.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactory.java
@@ -69,18 +69,19 @@ implements MetaModelRefiner {
 
     @Override
     public void refineProgrammingModel(final ProgrammingModel programmingModel) {
-        programmingModel.addValidatorSkipManagedBeans(spec->{
+        programmingModel.addValidatorSkipManagedBeans(objectSpec->{
 
             // only consider persistent entities
-            final JdoPersistenceCapableFacet pcFacet = spec.getFacet(JdoPersistenceCapableFacet.class);
+            final JdoPersistenceCapableFacet pcFacet = objectSpec.getFacet(JdoPersistenceCapableFacet.class);
             if(pcFacet==null || pcFacet.getIdentityType() == IdentityType.NONDURABLE) {
                 return;
             }
 
-            spec.streamProperties(MixedIn.EXCLUDED)
-            // skip checks if annotated with JDO @NotPersistent
-            .filter(association->!association.containsNonFallbackFacet(JdoNotPersistentFacet.class))
-            .forEach(BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil::validateBigDecimalValueFacet);
+            objectSpec
+                    .streamProperties(MixedIn.EXCLUDED)
+                    // skip checks if annotated with JDO @NotPersistent
+                    .filter(association->!association.containsNonFallbackFacet(JdoNotPersistentFacet.class))
+                    .forEach(BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil::validateBigDecimalValueFacet);
 
         });
     }
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
index e48052e83b..127346607a 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
@@ -136,14 +136,11 @@ implements MetaModelRefiner {
                 return;
             }
 
-            final Stream<ObjectAssociation> associations = objectSpec
-                    .streamAssociations(MixedIn.EXCLUDED)
-                    .filter(ObjectAssociation.Predicates.PROPERTIES);
-
-            associations
-            // skip checks if annotated with JDO @NotPersistent
-            .filter(association->!association.containsNonFallbackFacet(JdoNotPersistentFacet.class))
-            .forEach(MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil::validateMandatoryFacet);
+            objectSpec
+                    .streamProperties(MixedIn.EXCLUDED)
+                    // skip checks if annotated with JDO @NotPersistent
+                    .filter(association->!association.containsNonFallbackFacet(JdoNotPersistentFacet.class))
+                    .forEach(MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil::validateMandatoryFacet);
 
         });
     }
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFromJdoColumnAnnotationFacetFactory.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFromJdoColumnAnnotationFacetFactory.java
index c8fbd6ea96..4785fc487f 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFromJdoColumnAnnotationFacetFactory.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFromJdoColumnAnnotationFacetFactory.java
@@ -29,11 +29,10 @@ import org.apache.causeway.core.metamodel.facetapi.FacetUtil;
 import org.apache.causeway.core.metamodel.facetapi.FeatureType;
 import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
 import org.apache.causeway.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.causeway.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
 import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
 import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure;
+import org.apache.causeway.persistence.commons.metamodel.facets.prop.column.MaxLengthFromXxxColumnAnnotationMetaModelRefinerUtil;
 import org.apache.causeway.persistence.jdo.provider.entities.JdoFacetContext;
 import org.apache.causeway.persistence.jdo.provider.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
 import org.apache.causeway.persistence.jdo.provider.metamodel.facets.prop.notpersistent.JdoNotPersistentFacet;
@@ -75,35 +74,17 @@ implements MetaModelRefiner {
     @Override
     public void refineProgrammingModel(final ProgrammingModel programmingModel) {
         programmingModel.addValidatorSkipManagedBeans(objectSpec->{
+
             final JdoPersistenceCapableFacet pcFacet = objectSpec.getFacet(JdoPersistenceCapableFacet.class);
             if(pcFacet==null || pcFacet.getIdentityType() == IdentityType.NONDURABLE) {
                 return;
             }
 
-            final Stream<ObjectAssociation> associations = objectSpec
-                    .streamAssociations(MixedIn.EXCLUDED)
-                    .filter(ObjectAssociation.Predicates.PROPERTIES);
-
-            associations.forEach(association->{
-                // skip checks if annotated with JDO @NotPersistent
-                if(association.containsNonFallbackFacet(JdoNotPersistentFacet.class)) {
-                    return;
-                }
-
-                association.lookupFacet(MaxLengthFacet.class)
-                .map(MaxLengthFacet::getSharedFacetRankingElseFail)
-                .ifPresent(facetRanking->facetRanking
-                        .visitTopRankPairsSemanticDiffering(MaxLengthFacet.class, (a, b)->{
-
-                            ValidationFailure.raiseFormatted(
-                                    association,
-                                    "%s: inconsistent MaxLength semantics specified in %s and %s.",
-                                    association.getFeatureIdentifier().toString(),
-                                    a.getClass().getSimpleName(),
-                                    b.getClass().getSimpleName());
-                        }));
-
-            });
+            objectSpec
+                    .streamProperties(MixedIn.EXCLUDED)
+                    // skip checks if annotated with JDO @NotPersistent
+                    .filter(association->!association.containsNonFallbackFacet(JdoNotPersistentFacet.class))
+                    .forEach(MaxLengthFromXxxColumnAnnotationMetaModelRefinerUtil::validateMaxLengthFacet);
         });
     }
 
diff --git a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/BigDecimalFromJpaColumnAnnotationFacetFactory.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/BigDecimalFromJpaColumnAnnotationFacetFactory.java
index f79bda9c7d..bed0b2a311 100644
--- a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/BigDecimalFromJpaColumnAnnotationFacetFactory.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/BigDecimalFromJpaColumnAnnotationFacetFactory.java
@@ -66,9 +66,10 @@ implements MetaModelRefiner {
 
     @Override
     public void refineProgrammingModel(final ProgrammingModel programmingModel) {
-        programmingModel.addValidatorSkipManagedBeans(spec->{
+        programmingModel.addValidatorSkipManagedBeans(objectSpec->{
 
-            spec.streamProperties(MixedIn.EXCLUDED)
+            objectSpec
+                    .streamProperties(MixedIn.EXCLUDED)
                     .forEach(BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil::validateBigDecimalValueFacet);
 
         });
diff --git a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java
index 94597ac206..0040f88d9a 100644
--- a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java
@@ -73,11 +73,8 @@ implements MetaModelRefiner {
     public void refineProgrammingModel(final ProgrammingModel programmingModel) {
         programmingModel.addValidatorSkipManagedBeans(objectSpec->{
 
-            final Stream<ObjectAssociation> associations = objectSpec
-                    .streamAssociations(MixedIn.EXCLUDED)
-                    .filter(ObjectAssociation.Predicates.PROPERTIES);
-
-            associations
+            objectSpec
+                    .streamProperties(MixedIn.EXCLUDED)
                     .forEach(MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil::validateMandatoryFacet);
 
         });
diff --git a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFromJpaColumnAnnotationFacetFactory.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFromJpaColumnAnnotationFacetFactory.java
index 5df9e0cf0d..3efa4ca5c6 100644
--- a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFromJpaColumnAnnotationFacetFactory.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFromJpaColumnAnnotationFacetFactory.java
@@ -18,8 +18,6 @@
  */
 package org.apache.causeway.persistence.jpa.metamodel.facets.prop.column;
 
-import java.util.stream.Stream;
-
 import javax.persistence.Column;
 
 import org.apache.causeway.core.metamodel.context.MetaModelContext;
@@ -27,16 +25,18 @@ import org.apache.causeway.core.metamodel.facetapi.FacetUtil;
 import org.apache.causeway.core.metamodel.facetapi.FeatureType;
 import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
 import org.apache.causeway.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.causeway.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
 import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
 import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure;
+import org.apache.causeway.persistence.commons.metamodel.facets.prop.column.MaxLengthFromXxxColumnAnnotationMetaModelRefinerUtil;
 
 import lombok.val;
 
+import java.util.stream.Stream;
+
 public class MaxLengthFromJpaColumnAnnotationFacetFactory
-extends FacetFactoryAbstract {
+extends FacetFactoryAbstract
+implements MetaModelRefiner {
 
     public MaxLengthFromJpaColumnAnnotationFacetFactory(final MetaModelContext mmc) {
         super(mmc, FeatureType.PROPERTIES_ONLY);
@@ -61,4 +61,14 @@ extends FacetFactoryAbstract {
                 .create(jdoColumnIfAny, facetHolder));
     }
 
+    @Override
+    public void refineProgrammingModel(final ProgrammingModel programmingModel) {
+        programmingModel.addValidatorSkipManagedBeans(objectSpec->{
+
+            objectSpec
+                    .streamProperties(MixedIn.EXCLUDED)
+                    .forEach(MaxLengthFromXxxColumnAnnotationMetaModelRefinerUtil::validateMaxLengthFacet);
+        });
+    }
+
 }


[causeway] 01/02: CAUSEWAY-3593: makes JPA-specific facet factories mirror JDO

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-3593
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit e422a22aacf8b3280b8b496c7d2c91bdd66e6f08
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Wed Sep 20 13:48:06 2023 +0100

    CAUSEWAY-3593: makes JPA-specific facet factories mirror JDO
    
    for BigDecimalFrom{Jdo/Jpa}ColumnAnnotationFacetFactory
    for MandatoryFrom{Jdo/Jpa}ColumnAnnotationFacetFactory
---
 persistence/commons/src/main/java/module-info.java |   1 +
 ...romXxxColumnAnnotationMetaModelRefinerUtil.java |  40 +++++++
 ...romXxxColumnAnnotationMetaModelRefinerUtil.java |  27 +++++
 persistence/jdo/metamodel/pom.xml                  |  31 +++--
 .../jdo/metamodel/src/main/java/module-info.java   |   1 +
 .../jdo/metamodel/JdoProgrammingModel.java         |   8 +-
 ...BigDecimalFromColumnAnnotationFacetFactory.java | 131 ---------------------
 ...DecimalFromJdoColumnAnnotationFacetFactory.java |  88 ++++++++++++++
 ...toryFacetFromAbsenceOfJdoColumnAnnotation.java} |   4 +-
 ... => MandatoryFacetFromJdoColumnAnnotation.java} |   4 +-
 ...datoryFromJdoColumnAnnotationFacetFactory.java} |  81 +++++++------
 ...ctionalDigitsFacetFromJdoColumnAnnotation.java} |  25 +---
 .../MaxLengthFacetFromJdoColumnAnnotation.java     |   2 +-
 ...xLengthFromJdoColumnAnnotationFacetFactory.java |  16 +--
 ...ctionalDigitsFacetFromJdoColumnAnnotation.java} |  30 ++---
 .../metamodel/facets/prop/column/_ColumnUtil.java  |  93 ---------------
 ...malFromJdoColumnAnnotationFacetFactoryTest.java |   6 +-
 ...oryFromJdoColumnAnnotationFacetFactoryTest.java |  20 ++--
 persistence/jpa/metamodel/pom.xml                  |  29 +++--
 .../jpa/metamodel/src/main/java/module-info.java   |   1 +
 .../jpa/metamodel/JpaProgrammingModel.java         |   3 +
 ...DecimalFromJpaColumnAnnotationFacetFactory.java |  17 ++-
 ...ndatoryFromJpaColumnAnnotationFacetFactory.java |  24 +++-
 ...actionalDigitsFacetFromJpaColumnAnnotation.java |  10 +-
 .../MaxLengthFacetFromJpaColumnAnnotation.java}    |  24 ++--
 ...LengthFromJpaColumnAnnotationFacetFactory.java} |  40 +++----
 26 files changed, 350 insertions(+), 406 deletions(-)

diff --git a/persistence/commons/src/main/java/module-info.java b/persistence/commons/src/main/java/module-info.java
index dc127a51db..981355e018 100644
--- a/persistence/commons/src/main/java/module-info.java
+++ b/persistence/commons/src/main/java/module-info.java
@@ -19,6 +19,7 @@
 module org.apache.causeway.persistence.commons {
     exports org.apache.causeway.persistence.jpa.integration.changetracking;
     exports org.apache.causeway.persistence.commons;
+    exports org.apache.causeway.persistence.commons.metamodel.facets.prop.column;
 
     requires java.annotation;
     requires java.desktop;
diff --git a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil.java b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil.java
new file mode 100644
index 0000000000..ebb90f58d6
--- /dev/null
+++ b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil.java
@@ -0,0 +1,40 @@
+package org.apache.causeway.persistence.commons.metamodel.facets.prop.column;
+
+import lombok.experimental.UtilityClass;
+
+import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MaxFractionalDigitsFacet;
+import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MaxTotalDigitsFacet;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure;
+
+@UtilityClass
+public class BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil {
+    public static void validateBigDecimalValueFacet(final ObjectAssociation association) {
+
+        association.lookupFacet(MaxTotalDigitsFacet.class)
+        .map(MaxTotalDigitsFacet::getSharedFacetRankingElseFail)
+        .ifPresent(facetRanking->facetRanking
+                .visitTopRankPairsSemanticDiffering(MaxTotalDigitsFacet.class, (a, b)->{
+
+                    ValidationFailure.raiseFormatted(
+                            association,
+                            "%s: inconsistent MaxTotalDigits semantics specified in %s and %s.",
+                            association.getFeatureIdentifier().toString(),
+                            a.getClass().getSimpleName(),
+                            b.getClass().getSimpleName());
+                }));
+
+        association.lookupFacet(MaxFractionalDigitsFacet.class)
+        .map(MaxFractionalDigitsFacet::getSharedFacetRankingElseFail)
+        .ifPresent(facetRanking->facetRanking
+                .visitTopRankPairsSemanticDiffering(MaxFractionalDigitsFacet.class, (a, b)->{
+
+                    ValidationFailure.raiseFormatted(
+                            association,
+                            "%s: inconsistent MaxFractionalDigits semantics specified in %s and %s.",
+                            association.getFeatureIdentifier().toString(),
+                            a.getClass().getSimpleName(),
+                            b.getClass().getSimpleName());
+                }));
+    }
+}
diff --git a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java
new file mode 100644
index 0000000000..76da577ad8
--- /dev/null
+++ b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/metamodel/facets/prop/column/MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil.java
@@ -0,0 +1,27 @@
+package org.apache.causeway.persistence.commons.metamodel.facets.prop.column;
+
+import lombok.experimental.UtilityClass;
+
+import org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure;
+
+@UtilityClass
+public class MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil {
+    public static void validateMandatoryFacet(final ObjectAssociation association) {
+
+        association.lookupFacet(MandatoryFacet.class)
+        .map(MandatoryFacet::getSharedFacetRankingElseFail)
+        .ifPresent(facetRanking->facetRanking
+                .visitTopRankPairsSemanticDiffering(MandatoryFacet.class, (a, b)->{
+
+                    ValidationFailure.raiseFormatted(
+                            association,
+                            "%s: inconsistent Mandatory/Optional semantics specified in %s and %s.",
+                            association.getFeatureIdentifier().toString(),
+                            a.getClass().getSimpleName(),
+                            b.getClass().getSimpleName());
+                }));
+
+    }
+}
diff --git a/persistence/jdo/metamodel/pom.xml b/persistence/jdo/metamodel/pom.xml
index f3a4586718..bd37c2ac39 100644
--- a/persistence/jdo/metamodel/pom.xml
+++ b/persistence/jdo/metamodel/pom.xml
@@ -1,13 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- 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 
+<!-- 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. -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
@@ -37,26 +37,31 @@
 			<groupId>org.apache.causeway.persistence</groupId>
 			<artifactId>causeway-persistence-jdo-applib</artifactId>
 		</dependency>
-		
+
 		<dependency>
 			<groupId>org.apache.causeway.persistence</groupId>
 			<artifactId>causeway-persistence-jdo-provider</artifactId>
 		</dependency>
 
-		<dependency>
+        <dependency>
+            <groupId>org.apache.causeway.persistence</groupId>
+            <artifactId>causeway-persistence-commons</artifactId>
+        </dependency>
+
+        <dependency>
 			<groupId>org.apache.causeway.core</groupId>
 			<artifactId>causeway-core-runtime</artifactId>
 		</dependency>
 
 		<!-- TESTING -->
-		
+
         <dependency>
             <groupId>org.apache.causeway.core</groupId>
             <artifactId>causeway-core-internaltestsupport</artifactId>
             <scope>test</scope>
         </dependency>
 
-	</dependencies>
+    </dependencies>
 
 
 </project>
\ No newline at end of file
diff --git a/persistence/jdo/metamodel/src/main/java/module-info.java b/persistence/jdo/metamodel/src/main/java/module-info.java
index c820846749..f7748fa6d0 100644
--- a/persistence/jdo/metamodel/src/main/java/module-info.java
+++ b/persistence/jdo/metamodel/src/main/java/module-info.java
@@ -28,6 +28,7 @@ module org.apache.causeway.persistence.jdo.metamodel {
     requires javax.jdo;
     requires org.apache.causeway.security.api;
     requires org.datanucleus.store.rdbms;
+    requires org.apache.causeway.persistence.commons;
 
     exports org.apache.causeway.persistence.jdo.metamodel;
     exports org.apache.causeway.persistence.jdo.metamodel.facets.object.persistencecapable;
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/JdoProgrammingModel.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/JdoProgrammingModel.java
index 9ec479f00a..483c62e633 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/JdoProgrammingModel.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/JdoProgrammingModel.java
@@ -36,8 +36,8 @@ import org.apache.causeway.persistence.jdo.metamodel.facets.object.datastoreiden
 import org.apache.causeway.persistence.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacetFactory;
 import org.apache.causeway.persistence.jdo.metamodel.facets.object.query.JdoQueryAnnotationFacetFactory;
 import org.apache.causeway.persistence.jdo.metamodel.facets.object.version.JdoVersionAnnotationFacetFactory;
-import org.apache.causeway.persistence.jdo.metamodel.facets.prop.column.BigDecimalFromColumnAnnotationFacetFactory;
-import org.apache.causeway.persistence.jdo.metamodel.facets.prop.column.MandatoryFromColumnAnnotationFacetFactory;
+import org.apache.causeway.persistence.jdo.metamodel.facets.prop.column.BigDecimalFromJdoColumnAnnotationFacetFactory;
+import org.apache.causeway.persistence.jdo.metamodel.facets.prop.column.MandatoryFromJdoColumnAnnotationFacetFactory;
 import org.apache.causeway.persistence.jdo.metamodel.facets.prop.column.MaxLengthFromJdoColumnAnnotationFacetFactory;
 import org.apache.causeway.persistence.jdo.metamodel.facets.prop.notpersistent.JdoNotPersistentAnnotationFacetFactory;
 import org.apache.causeway.persistence.jdo.metamodel.facets.prop.primarykey.JdoPrimaryKeyAnnotationFacetFactory;
@@ -82,12 +82,12 @@ public class JdoProgrammingModel implements MetaModelRefiner {
 
         pm.addFactory(step2, new JdoQueryAnnotationFacetFactory(mmc, jdoFacetContext), Marker.JDO);
 
-        pm.addFactory(step2, new BigDecimalFromColumnAnnotationFacetFactory(mmc), Marker.JDO);
+        pm.addFactory(step2, new BigDecimalFromJdoColumnAnnotationFacetFactory(mmc), Marker.JDO);
         pm.addFactory(step2, new MaxLengthFromJdoColumnAnnotationFacetFactory(mmc), Marker.JDO);
         // must appear after JdoPrimaryKeyAnnotationFacetFactory (above)
         // and also MandatoryFacetOnPropertyMandatoryAnnotationFactory
         // and also PropertyAnnotationFactory
-        pm.addFactory(step2, new MandatoryFromColumnAnnotationFacetFactory(mmc, jdoFacetContext), Marker.JDO);
+        pm.addFactory(step2, new MandatoryFromJdoColumnAnnotationFacetFactory(mmc, jdoFacetContext), Marker.JDO);
 
 
         // -- validators
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromColumnAnnotationFacetFactory.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromColumnAnnotationFacetFactory.java
deleted file mode 100644
index 158fcb9693..0000000000
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromColumnAnnotationFacetFactory.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *  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.causeway.persistence.jdo.metamodel.facets.prop.column;
-
-import java.math.BigDecimal;
-
-import javax.inject.Inject;
-import javax.jdo.annotations.IdentityType;
-
-import org.apache.causeway.core.metamodel.context.MetaModelContext;
-import org.apache.causeway.core.metamodel.facetapi.FeatureType;
-import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
-import org.apache.causeway.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.causeway.core.metamodel.facets.FacetedMethod;
-import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MaxFractionalDigitsFacet;
-import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MaxTotalDigitsFacet;
-import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
-import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
-import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure;
-import org.apache.causeway.persistence.jdo.provider.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
-import org.apache.causeway.persistence.jdo.provider.metamodel.facets.prop.notpersistent.JdoNotPersistentFacet;
-
-public class BigDecimalFromColumnAnnotationFacetFactory
-extends FacetFactoryAbstract
-implements MetaModelRefiner {
-
-    @Inject
-    public BigDecimalFromColumnAnnotationFacetFactory(final MetaModelContext mmc) {
-        super(mmc, FeatureType.PROPERTIES_ONLY);
-    }
-
-    @Override
-    public void process(final ProcessMethodContext processMethodContext) {
-
-        if(BigDecimal.class != processMethodContext.getMethod().getReturnType()) {
-            return;
-        }
-
-        final FacetedMethod holder = processMethodContext.getFacetHolder();
-
-        _ColumnUtil.processColumnAnnotations(processMethodContext,
-                jdoColumnIfAny->{
-                    addFacetIfPresent(
-                            MaxTotalDigitsFacetFromJdoColumnAnnotation
-                            .createJdo(jdoColumnIfAny, holder));
-
-                    addFacetIfPresent(
-                            MaxFractionalDigitsFacetFromJdoColumn
-                            .createJdo(jdoColumnIfAny, holder));
-                },
-                jpaColumnIfAny->{
-                    addFacetIfPresent(
-                            MaxTotalDigitsFacetFromJdoColumnAnnotation
-                            .createJpa(jpaColumnIfAny, holder));
-
-                    addFacetIfPresent(
-                            MaxFractionalDigitsFacetFromJdoColumn
-                            .createJpa(jpaColumnIfAny, holder));
-                });
-
-    }
-
-    @Override
-    public void refineProgrammingModel(final ProgrammingModel programmingModel) {
-        programmingModel.addValidatorSkipManagedBeans(spec->{
-
-            // only consider persistent entities
-            final JdoPersistenceCapableFacet pcFacet = spec.getFacet(JdoPersistenceCapableFacet.class);
-            if(pcFacet==null || pcFacet.getIdentityType() == IdentityType.NONDURABLE) {
-                return;
-            }
-
-            spec.streamProperties(MixedIn.EXCLUDED)
-            // skip checks if annotated with JDO @NotPersistent
-            .filter(association->!association.containsNonFallbackFacet(JdoNotPersistentFacet.class))
-            .forEach(association->{
-                validateBigDecimalValueFacet(association);
-            });
-
-        });
-    }
-
-    private static void validateBigDecimalValueFacet(final ObjectAssociation association) {
-
-        association.lookupFacet(MaxTotalDigitsFacet.class)
-        .map(MaxTotalDigitsFacet::getSharedFacetRankingElseFail)
-        .ifPresent(facetRanking->facetRanking
-                .visitTopRankPairsSemanticDiffering(MaxTotalDigitsFacet.class, (a, b)->{
-
-                    ValidationFailure.raiseFormatted(
-                            association,
-                            "%s: inconsistent MaxTotalDigits semantics specified in %s and %s.",
-                            association.getFeatureIdentifier().toString(),
-                            a.getClass().getSimpleName(),
-                            b.getClass().getSimpleName());
-                }));
-
-        association.lookupFacet(MaxFractionalDigitsFacet.class)
-        .map(MaxFractionalDigitsFacet::getSharedFacetRankingElseFail)
-        .ifPresent(facetRanking->facetRanking
-                .visitTopRankPairsSemanticDiffering(MaxFractionalDigitsFacet.class, (a, b)->{
-
-                    ValidationFailure.raiseFormatted(
-                            association,
-                            "%s: inconsistent MaxFractionalDigits semantics specified in %s and %s.",
-                            association.getFeatureIdentifier().toString(),
-                            a.getClass().getSimpleName(),
-                            b.getClass().getSimpleName());
-                }));
-
-    }
-
-
-}
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactory.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactory.java
new file mode 100644
index 0000000000..10882eddb2
--- /dev/null
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactory.java
@@ -0,0 +1,88 @@
+/*
+ *  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.causeway.persistence.jdo.metamodel.facets.prop.column;
+
+import lombok.val;
+
+import java.math.BigDecimal;
+
+import javax.inject.Inject;
+import javax.jdo.annotations.Column;
+import javax.jdo.annotations.IdentityType;
+
+import org.apache.causeway.core.metamodel.context.MetaModelContext;
+import org.apache.causeway.core.metamodel.facetapi.FeatureType;
+import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
+import org.apache.causeway.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.causeway.core.metamodel.facets.FacetedMethod;
+import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
+import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
+import org.apache.causeway.persistence.commons.metamodel.facets.prop.column.BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil;
+import org.apache.causeway.persistence.jdo.provider.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
+import org.apache.causeway.persistence.jdo.provider.metamodel.facets.prop.notpersistent.JdoNotPersistentFacet;
+
+public class BigDecimalFromJdoColumnAnnotationFacetFactory
+extends FacetFactoryAbstract
+implements MetaModelRefiner {
+
+    @Inject
+    public BigDecimalFromJdoColumnAnnotationFacetFactory(final MetaModelContext mmc) {
+        super(mmc, FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+
+        if(BigDecimal.class != processMethodContext.getMethod().getReturnType()) {
+            return;
+        }
+
+        final FacetedMethod holder = processMethodContext.getFacetHolder();
+
+        val jdoColumnIfAny = processMethodContext.synthesizeOnMethod(Column.class);
+
+        addFacetIfPresent(
+                MaxTotalDigitsFacetFromJdoColumnAnnotation
+                .createJdo(jdoColumnIfAny, holder));
+
+        addFacetIfPresent(
+                MaxFractionalDigitsFacetFromJdoColumnAnnotation
+                .create(jdoColumnIfAny, holder));
+
+    }
+
+    @Override
+    public void refineProgrammingModel(final ProgrammingModel programmingModel) {
+        programmingModel.addValidatorSkipManagedBeans(spec->{
+
+            // only consider persistent entities
+            final JdoPersistenceCapableFacet pcFacet = spec.getFacet(JdoPersistenceCapableFacet.class);
+            if(pcFacet==null || pcFacet.getIdentityType() == IdentityType.NONDURABLE) {
+                return;
+            }
+
+            spec.streamProperties(MixedIn.EXCLUDED)
+            // skip checks if annotated with JDO @NotPersistent
+            .filter(association->!association.containsNonFallbackFacet(JdoNotPersistentFacet.class))
+            .forEach(BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil::validateBigDecimalValueFacet);
+
+        });
+    }
+
+}
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromAbsenceOfColumnAnnotation.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromAbsenceOfJdoColumnAnnotation.java
similarity index 91%
rename from persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromAbsenceOfColumnAnnotation.java
rename to persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromAbsenceOfJdoColumnAnnotation.java
index 985adbec7f..7c7c324497 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromAbsenceOfColumnAnnotation.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromAbsenceOfJdoColumnAnnotation.java
@@ -24,10 +24,10 @@ import org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.Mandatory
 /**
  * Inferred from absence of an <tt>@Column</tt> method.
  */
-public class MandatoryFacetFromAbsenceOfColumnAnnotation
+public class MandatoryFacetFromAbsenceOfJdoColumnAnnotation
 extends MandatoryFacetAbstract {
 
-    public MandatoryFacetFromAbsenceOfColumnAnnotation(
+    public MandatoryFacetFromAbsenceOfJdoColumnAnnotation(
             final Semantics semantics, final FacetHolder holder, final Precedence precedence) {
         super(semantics, holder, precedence);
     }
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromColumnAnnotation.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromJdoColumnAnnotation.java
similarity index 92%
rename from persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromColumnAnnotation.java
rename to persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromJdoColumnAnnotation.java
index 5e159b19db..fdb271f6ca 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromColumnAnnotation.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFacetFromJdoColumnAnnotation.java
@@ -24,10 +24,10 @@ import org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.Mandatory
 /**
  * Inferred from presence of an <tt>@Column</tt> annotation.
  */
-public class MandatoryFacetFromColumnAnnotation
+public class MandatoryFacetFromJdoColumnAnnotation
 extends MandatoryFacetAbstract {
 
-    public MandatoryFacetFromColumnAnnotation(
+    public MandatoryFacetFromJdoColumnAnnotation(
             final Semantics semantics, final FacetHolder holder) {
         super(semantics, holder);
     }
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromColumnAnnotationFacetFactory.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
similarity index 68%
rename from persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromColumnAnnotationFacetFactory.java
rename to persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
index 8bbdd0b0e8..e48052e83b 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromColumnAnnotationFacetFactory.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
@@ -18,11 +18,16 @@
  */
 package org.apache.causeway.persistence.jdo.metamodel.facets.prop.column;
 
+import lombok.val;
+
+import java.util.Optional;
 import java.util.stream.Stream;
 
 import javax.inject.Inject;
+import javax.jdo.annotations.Column;
 import javax.jdo.annotations.IdentityType;
 
+import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.core.metamodel.context.MetaModelContext;
 import org.apache.causeway.core.metamodel.facetapi.Facet.Precedence;
 import org.apache.causeway.core.metamodel.facetapi.FacetUtil;
@@ -35,21 +40,21 @@ import org.apache.causeway.core.metamodel.facets.properties.property.mandatory.M
 import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
 import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure;
+import org.apache.causeway.persistence.commons.metamodel.facets.prop.column.MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil;
 import org.apache.causeway.persistence.jdo.metamodel.facets.prop.primarykey.MandatoryFacetFromJdoPrimaryKeyAnnotation;
 import org.apache.causeway.persistence.jdo.provider.entities.JdoFacetContext;
 import org.apache.causeway.persistence.jdo.provider.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
 import org.apache.causeway.persistence.jdo.provider.metamodel.facets.prop.notpersistent.JdoNotPersistentFacet;
 
 
-public class MandatoryFromColumnAnnotationFacetFactory
+public class MandatoryFromJdoColumnAnnotationFacetFactory
 extends FacetFactoryAbstract
 implements MetaModelRefiner {
 
     private final JdoFacetContext jdoFacetContext;
 
     @Inject
-    public MandatoryFromColumnAnnotationFacetFactory(
+    public MandatoryFromJdoColumnAnnotationFacetFactory(
             final MetaModelContext mmc,
             final JdoFacetContext jdoFacetContext) {
         super(mmc, FeatureType.PROPERTIES_ONLY);
@@ -82,23 +87,46 @@ implements MetaModelRefiner {
             }
         }
 
-        _ColumnUtil.inferSemantics(processMethodContext,
-                semanticsWhileColumnPresent->{
-                    FacetUtil.addFacet(
-                            new MandatoryFacetFromColumnAnnotation(semanticsWhileColumnPresent, holder));
-                },
-                semanticsWhileColumnAbsent->{
-                    FacetUtil.addFacet(
-                            new MandatoryFacetFromAbsenceOfColumnAnnotation(
-                                    semanticsWhileColumnAbsent,
-                                    holder,
-                                    semanticsWhileColumnAbsent.isRequired()
-                                        ? Precedence.DEFAULT
-                                        : Precedence.INFERRED));
-                });
+        val jdoColumnIfAny = processMethodContext.synthesizeOnMethod(javax.jdo.annotations.Column.class);
+        MandatoryFacet.Semantics semantics = inferSemantics(processMethodContext, jdoColumnIfAny);
+        if(jdoColumnIfAny.isPresent()) {
+            FacetUtil.addFacet(
+                    new MandatoryFacetFromJdoColumnAnnotation(semantics, holder));
+        } else {
+            FacetUtil.addFacet(
+                    new MandatoryFacetFromAbsenceOfJdoColumnAnnotation(
+                            semantics,
+                            holder,
+                            semantics.isRequired()
+                                    ? Precedence.DEFAULT
+                                    : Precedence.INFERRED));
+        }
 
     }
 
+    static MandatoryFacet.Semantics inferSemantics(
+            final ProcessMethodContext processMethodContext,
+            final Optional<Column> columnIfAny) {
+
+        final String allowsNull = columnIfAny.isPresent()
+                ? columnIfAny.get().allowsNull()
+                : null;
+
+        if(_Strings.isNotEmpty(allowsNull)) {
+            // if miss-spelled, then DN assumes is not-nullable
+            return MandatoryFacet.Semantics.required(!"true".equalsIgnoreCase(allowsNull.trim()));
+        }
+
+        final Class<?> returnType = processMethodContext.getMethod().getReturnType();
+        // per JDO spec
+        return returnType != null
+                && returnType.isPrimitive()
+                ? MandatoryFacet.Semantics.REQUIRED
+                : MandatoryFacet.Semantics.OPTIONAL;
+
+    }
+
+
     @Override
     public void refineProgrammingModel(final ProgrammingModel programmingModel) {
         programmingModel.addValidatorSkipManagedBeans(objectSpec->{
@@ -115,26 +143,9 @@ implements MetaModelRefiner {
             associations
             // skip checks if annotated with JDO @NotPersistent
             .filter(association->!association.containsNonFallbackFacet(JdoNotPersistentFacet.class))
-            .forEach(association->validateMandatoryFacet(association));
+            .forEach(MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil::validateMandatoryFacet);
 
         });
     }
 
-    private static void validateMandatoryFacet(final ObjectAssociation association) {
-
-        association.lookupFacet(MandatoryFacet.class)
-        .map(MandatoryFacet::getSharedFacetRankingElseFail)
-        .ifPresent(facetRanking->facetRanking
-                .visitTopRankPairsSemanticDiffering(MandatoryFacet.class, (a, b)->{
-
-                    ValidationFailure.raiseFormatted(
-                            association,
-                            "%s: inconsistent Mandatory/Optional semantics specified in %s and %s.",
-                            association.getFeatureIdentifier().toString(),
-                            a.getClass().getSimpleName(),
-                            b.getClass().getSimpleName());
-                }));
-
-    }
-
 }
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumn.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumnAnnotation.java
similarity index 69%
copy from persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumn.java
copy to persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumnAnnotation.java
index b150bef8cd..a20e3eb613 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumn.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumnAnnotation.java
@@ -26,37 +26,24 @@ import org.apache.causeway.core.metamodel.facetapi.FacetHolder;
 import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MaxFractionalDigitsFacet;
 import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MaxFractionalDigitsFacetAbstract;
 
-public class MaxFractionalDigitsFacetFromJdoColumn
+public class MaxFractionalDigitsFacetFromJdoColumnAnnotation
 extends MaxFractionalDigitsFacetAbstract {
 
-    public static Optional<MaxFractionalDigitsFacet> createJdo(
+    public static Optional<MaxFractionalDigitsFacet> create(
             final Optional<Column> jdoColumnIfAny,
             final FacetHolder holder) {
 
         return jdoColumnIfAny
                 .filter(jdoColumn->jdoColumn.scale()>=0)
                 .map(jdoColumn->{
-                    return new MaxFractionalDigitsFacetFromJdoColumn(
+                    return new MaxFractionalDigitsFacetFromJdoColumnAnnotation(
                             jdoColumn.scale(), holder);
                 });
     }
 
-    public static Optional<MaxFractionalDigitsFacet> createJpa(
-            final Optional<javax.persistence.Column> jdoColumnIfAny,
-            final FacetHolder holder) {
-
-        return jdoColumnIfAny
-                .filter(jdoColumn->jdoColumn.scale()>=0)
-                .map(jdoColumn->{
-                    return new MaxFractionalDigitsFacetFromJdoColumn(
-                            jdoColumn.scale(), holder);
-                });
+    private MaxFractionalDigitsFacetFromJdoColumnAnnotation(
+            final int scale, final FacetHolder holder) {
+        super(scale, holder);
     }
 
-    private MaxFractionalDigitsFacetFromJdoColumn(
-            final int maxFractionalDigits, final FacetHolder holder) {
-        super(maxFractionalDigits, holder);
-    }
-
-
 }
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFacetFromJdoColumnAnnotation.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFacetFromJdoColumnAnnotation.java
index 4ca01d5fbb..5dfb363f84 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFacetFromJdoColumnAnnotation.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFacetFromJdoColumnAnnotation.java
@@ -29,7 +29,7 @@ import org.apache.causeway.core.metamodel.facets.objectvalue.maxlen.MaxLengthFac
 public class MaxLengthFacetFromJdoColumnAnnotation
 extends MaxLengthFacetAbstract {
 
-    public static Optional<MaxLengthFacet> createJdo(
+    public static Optional<MaxLengthFacet> create(
             final Optional<Column> jdoColumnIfAny,
             final FacetHolder holder) {
 
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFromJdoColumnAnnotationFacetFactory.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFromJdoColumnAnnotationFacetFactory.java
index 6d330e0c19..c8fbd6ea96 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFromJdoColumnAnnotationFacetFactory.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFromJdoColumnAnnotationFacetFactory.java
@@ -21,6 +21,7 @@ package org.apache.causeway.persistence.jdo.metamodel.facets.prop.column;
 import java.util.stream.Stream;
 
 import javax.inject.Inject;
+import javax.jdo.annotations.Column;
 import javax.jdo.annotations.IdentityType;
 
 import org.apache.causeway.core.metamodel.context.MetaModelContext;
@@ -64,18 +65,11 @@ implements MetaModelRefiner {
 
         val facetHolder = processMethodContext.getFacetHolder();
 
-        _ColumnUtil.processColumnAnnotations(processMethodContext,
-                jdoColumnIfAny->{
-                    FacetUtil.addFacetIfPresent(
-                            MaxTotalDigitsFacetFromJdoColumnAnnotation
-                            .createJdo(jdoColumnIfAny, facetHolder));
-                },
-                jpaColumnIfAny->{
-                    FacetUtil.addFacetIfPresent(
-                            MaxTotalDigitsFacetFromJdoColumnAnnotation
-                            .createJpa(jpaColumnIfAny, facetHolder));
-                });
+        val jdoColumnIfAny = processMethodContext.synthesizeOnMethod(Column.class);
 
+        FacetUtil.addFacetIfPresent(
+                MaxLengthFacetFromJdoColumnAnnotation
+                .create(jdoColumnIfAny, facetHolder));
     }
 
     @Override
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumn.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MinFractionalDigitsFacetFromJdoColumnAnnotation.java
similarity index 61%
rename from persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumn.java
rename to persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MinFractionalDigitsFacetFromJdoColumnAnnotation.java
index b150bef8cd..faf1ea497f 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJdoColumn.java
+++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MinFractionalDigitsFacetFromJdoColumnAnnotation.java
@@ -23,39 +23,27 @@ import java.util.Optional;
 import javax.jdo.annotations.Column;
 
 import org.apache.causeway.core.metamodel.facetapi.FacetHolder;
-import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MaxFractionalDigitsFacet;
-import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MaxFractionalDigitsFacetAbstract;
+import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MinFractionalDigitsFacet;
+import org.apache.causeway.core.metamodel.facets.objectvalue.digits.MinFractionalDigitsFacetAbstract;
 
-public class MaxFractionalDigitsFacetFromJdoColumn
-extends MaxFractionalDigitsFacetAbstract {
+public class MinFractionalDigitsFacetFromJdoColumnAnnotation
+extends MinFractionalDigitsFacetAbstract {
 
-    public static Optional<MaxFractionalDigitsFacet> createJdo(
+    public static Optional<MinFractionalDigitsFacet> create(
             final Optional<Column> jdoColumnIfAny,
             final FacetHolder holder) {
 
         return jdoColumnIfAny
                 .filter(jdoColumn->jdoColumn.scale()>=0)
                 .map(jdoColumn->{
-                    return new MaxFractionalDigitsFacetFromJdoColumn(
+                    return new MinFractionalDigitsFacetFromJdoColumnAnnotation(
                             jdoColumn.scale(), holder);
                 });
     }
 
-    public static Optional<MaxFractionalDigitsFacet> createJpa(
-            final Optional<javax.persistence.Column> jdoColumnIfAny,
-            final FacetHolder holder) {
-
-        return jdoColumnIfAny
-                .filter(jdoColumn->jdoColumn.scale()>=0)
-                .map(jdoColumn->{
-                    return new MaxFractionalDigitsFacetFromJdoColumn(
-                            jdoColumn.scale(), holder);
-                });
-    }
-
-    private MaxFractionalDigitsFacetFromJdoColumn(
-            final int maxFractionalDigits, final FacetHolder holder) {
-        super(maxFractionalDigits, holder);
+    private MinFractionalDigitsFacetFromJdoColumnAnnotation(
+            final int scale, final FacetHolder holder) {
+        super(scale, holder);
     }
 
 
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/_ColumnUtil.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/_ColumnUtil.java
deleted file mode 100644
index 89b95503a5..0000000000
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/_ColumnUtil.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.causeway.persistence.jdo.metamodel.facets.prop.column;
-
-import java.util.Optional;
-import java.util.function.Consumer;
-
-import javax.jdo.annotations.Column;
-
-import org.apache.causeway.commons.internal.base._Strings;
-import org.apache.causeway.core.metamodel.facets.FacetFactory.ProcessMethodContext;
-import org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet.Semantics;
-
-import lombok.val;
-import lombok.experimental.UtilityClass;
-
-@UtilityClass
-class _ColumnUtil {
-
-    void processColumnAnnotations(final ProcessMethodContext processMethodContext,
-            final Consumer<Optional<javax.jdo.annotations.Column>> onJdoColumn,
-            final Consumer<Optional<javax.persistence.Column>> onJpaColumn) {
-
-        val jdoColumnIfAny = processMethodContext.synthesizeOnMethod(javax.jdo.annotations.Column.class);
-        if(jdoColumnIfAny.isPresent()) {
-            onJdoColumn.accept(jdoColumnIfAny);
-        } else {
-            val jpaColumnIfAny = processMethodContext.synthesizeOnMethod(javax.persistence.Column.class);
-            if(jpaColumnIfAny.isPresent()) {
-                onJpaColumn.accept(jpaColumnIfAny);
-            }
-        }
-
-    }
-
-    void inferSemantics(final ProcessMethodContext processMethodContext,
-            final Consumer<Semantics> onColumnPresent,
-            final Consumer<Semantics> onColumnNotPresent) {
-        val jdoColumnIfAny = processMethodContext.synthesizeOnMethod(javax.jdo.annotations.Column.class);
-        if(jdoColumnIfAny.isPresent()) {
-            onColumnPresent.accept(inferSemantics(processMethodContext, jdoColumnIfAny));
-            return;
-        }
-        val jpaColumnIfAny = processMethodContext.synthesizeOnMethod(javax.persistence.Column.class);
-        if(jpaColumnIfAny.isPresent()) {
-            onColumnPresent.accept(Semantics.required(!jpaColumnIfAny.get().nullable()));
-            return;
-        }
-        onColumnNotPresent.accept(inferSemantics(processMethodContext, Optional.empty()));
-    }
-
-    // -- HELPER
-
-    private Semantics inferSemantics(
-            final ProcessMethodContext processMethodContext,
-            final Optional<Column> columnIfAny) {
-
-        final String allowsNull = columnIfAny.isPresent()
-                ? columnIfAny.get().allowsNull()
-                : null;
-
-        if(_Strings.isNotEmpty(allowsNull)) {
-            // if miss-spelled, then DN assumes is not-nullable
-            return Semantics.required(!"true".equalsIgnoreCase(allowsNull.trim()));
-        }
-
-        final Class<?> returnType = processMethodContext.getMethod().getReturnType();
-        // per JDO spec
-        return returnType != null
-                && returnType.isPrimitive()
-            ? Semantics.REQUIRED
-            : Semantics.OPTIONAL;
-
-    }
-
-}
diff --git a/persistence/jdo/metamodel/src/test/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactoryTest.java b/persistence/jdo/metamodel/src/test/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactoryTest.java
index 15e135aa5b..bc28d1ab06 100644
--- a/persistence/jdo/metamodel/src/test/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactoryTest.java
+++ b/persistence/jdo/metamodel/src/test/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/BigDecimalFromJdoColumnAnnotationFacetFactoryTest.java
@@ -38,14 +38,14 @@ import lombok.val;
 class BigDecimalFromJdoColumnAnnotationFacetFactoryTest
 extends AbstractFacetFactoryTest {
 
-    private BigDecimalFromColumnAnnotationFacetFactory facetFactory;
+    private BigDecimalFromJdoColumnAnnotationFacetFactory facetFactory;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
         val mmc = MetaModelContext_forTesting.buildDefault();
-        facetFactory = new BigDecimalFromColumnAnnotationFacetFactory(mmc);
+        facetFactory = new BigDecimalFromJdoColumnAnnotationFacetFactory(mmc);
     }
 
     @Override
@@ -115,7 +115,7 @@ extends AbstractFacetFactoryTest {
         if(maxFractionalDigits>=0) {
             final MaxFractionalDigitsFacet facet = facetedMethod.getFacet(MaxFractionalDigitsFacet.class);
             assertNotNull(facet);
-            assertTrue(facet instanceof MaxFractionalDigitsFacetFromJdoColumn);
+            assertTrue(facet instanceof MaxFractionalDigitsFacetFromJdoColumnAnnotation);
             assertThat(facet.getMaxFractionalDigits(), is(maxFractionalDigits));
         } else {
             assertNull(facetedMethod.getFacet(MaxFractionalDigitsFacet.class));
diff --git a/persistence/jdo/metamodel/src/test/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactoryTest.java b/persistence/jdo/metamodel/src/test/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactoryTest.java
index 4d9d3199dd..440bf3f65c 100644
--- a/persistence/jdo/metamodel/src/test/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactoryTest.java
+++ b/persistence/jdo/metamodel/src/test/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactoryTest.java
@@ -34,14 +34,14 @@ import lombok.val;
 class MandatoryFromJdoColumnAnnotationFacetFactoryTest
 extends AbstractFacetFactoryTest {
 
-    private MandatoryFromColumnAnnotationFacetFactory facetFactory;
+    private MandatoryFromJdoColumnAnnotationFacetFactory facetFactory;
     private Class<?> cls;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
-        facetFactory = new MandatoryFromColumnAnnotationFacetFactory(metaModelContext, jdoFacetContext);
+        facetFactory = new MandatoryFromJdoColumnAnnotationFacetFactory(metaModelContext, jdoFacetContext);
         cls = SimpleObjectWithColumnAllowsNullAnnotations.class;
     }
 
@@ -67,7 +67,7 @@ extends AbstractFacetFactoryTest {
 
         final MandatoryFacet facet = facetedMethod.getFacet(MandatoryFacet.class);
         assertNotNull(facet);
-        assertTrue(facet instanceof MandatoryFacetFromAbsenceOfColumnAnnotation);
+        assertTrue(facet instanceof MandatoryFacetFromAbsenceOfJdoColumnAnnotation);
         assertThat(facet.getSemantics().isOptional(), is(false));
     }
 
@@ -78,7 +78,7 @@ extends AbstractFacetFactoryTest {
 
         final MandatoryFacet facet = facetedMethod.getFacet(MandatoryFacet.class);
         assertNotNull(facet);
-        assertTrue(facet instanceof MandatoryFacetFromColumnAnnotation);
+        assertTrue(facet instanceof MandatoryFacetFromJdoColumnAnnotation);
         assertThat(facet.getSemantics().isOptional(), is(false));
     }
 
@@ -89,7 +89,7 @@ extends AbstractFacetFactoryTest {
 
         final MandatoryFacet facet = facetedMethod.getFacet(MandatoryFacet.class);
         assertNotNull(facet);
-        assertTrue(facet instanceof MandatoryFacetFromColumnAnnotation);
+        assertTrue(facet instanceof MandatoryFacetFromJdoColumnAnnotation);
         assertThat(facet.getSemantics().isOptional(), is(false));
     }
 
@@ -100,7 +100,7 @@ extends AbstractFacetFactoryTest {
 
         final MandatoryFacet facet = facetedMethod.getFacet(MandatoryFacet.class);
         assertNotNull(facet);
-        assertTrue(facet instanceof MandatoryFacetFromColumnAnnotation);
+        assertTrue(facet instanceof MandatoryFacetFromJdoColumnAnnotation);
         assertThat(facet.getSemantics().isOptional(), is(true));
     }
 
@@ -111,7 +111,7 @@ extends AbstractFacetFactoryTest {
 
         final MandatoryFacet facet = facetedMethod.getFacet(MandatoryFacet.class);
         assertNotNull(facet);
-        assertTrue(facet instanceof MandatoryFacetFromAbsenceOfColumnAnnotation);
+        assertTrue(facet instanceof MandatoryFacetFromAbsenceOfJdoColumnAnnotation);
         assertThat(facet.getSemantics().isOptional(), is(true));
     }
 
@@ -122,7 +122,7 @@ extends AbstractFacetFactoryTest {
 
         final MandatoryFacet facet = facetedMethod.getFacet(MandatoryFacet.class);
         assertNotNull(facet);
-        assertTrue(facet instanceof MandatoryFacetFromColumnAnnotation);
+        assertTrue(facet instanceof MandatoryFacetFromJdoColumnAnnotation);
         assertThat(facet.getSemantics().isOptional(), is(true));
     }
 
@@ -133,7 +133,7 @@ extends AbstractFacetFactoryTest {
 
         final MandatoryFacet facet = facetedMethod.getFacet(MandatoryFacet.class);
         assertNotNull(facet);
-        assertTrue(facet instanceof MandatoryFacetFromColumnAnnotation);
+        assertTrue(facet instanceof MandatoryFacetFromJdoColumnAnnotation);
         assertThat(facet.getSemantics().isOptional(), is(false));
     }
 
@@ -144,7 +144,7 @@ extends AbstractFacetFactoryTest {
 
         final MandatoryFacet facet = facetedMethod.getFacet(MandatoryFacet.class);
         assertNotNull(facet);
-        assertTrue(facet instanceof MandatoryFacetFromColumnAnnotation);
+        assertTrue(facet instanceof MandatoryFacetFromJdoColumnAnnotation);
         assertThat(facet.getSemantics().isOptional(), is(true));
     }
 
diff --git a/persistence/jpa/metamodel/pom.xml b/persistence/jpa/metamodel/pom.xml
index e97a9d63d1..9f782b171c 100644
--- a/persistence/jpa/metamodel/pom.xml
+++ b/persistence/jpa/metamodel/pom.xml
@@ -1,13 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- 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 
+<!-- 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. -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
@@ -37,14 +37,19 @@
 			<groupId>org.apache.causeway.persistence</groupId>
 			<artifactId>causeway-persistence-jpa-applib</artifactId>
 		</dependency>
-		
-		<dependency>
+
+        <dependency>
+            <groupId>org.apache.causeway.persistence</groupId>
+            <artifactId>causeway-persistence-commons</artifactId>
+        </dependency>
+
+        <dependency>
 			<groupId>org.apache.causeway.core</groupId>
 			<artifactId>causeway-core-runtime</artifactId>
 		</dependency>
 
 		<!-- TESTING -->
-		
+
         <dependency>
             <groupId>org.apache.causeway.core</groupId>
             <artifactId>causeway-core-internaltestsupport</artifactId>
diff --git a/persistence/jpa/metamodel/src/main/java/module-info.java b/persistence/jpa/metamodel/src/main/java/module-info.java
index ad5d858e20..950bebd715 100644
--- a/persistence/jpa/metamodel/src/main/java/module-info.java
+++ b/persistence/jpa/metamodel/src/main/java/module-info.java
@@ -32,4 +32,5 @@ module org.apache.causeway.persistence.jpa.metamodel {
     requires org.apache.causeway.core.runtime;
     requires org.apache.causeway.persistence.jpa.applib;
     requires spring.context;
+    requires org.apache.causeway.persistence.commons;
 }
\ No newline at end of file
diff --git a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/JpaProgrammingModel.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/JpaProgrammingModel.java
index 138b6f190a..a01d47ce50 100644
--- a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/JpaProgrammingModel.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/JpaProgrammingModel.java
@@ -18,6 +18,8 @@
  */
 package org.apache.causeway.persistence.jpa.metamodel;
 
+import org.apache.causeway.persistence.jpa.metamodel.facets.prop.column.MaxLengthFromJpaColumnAnnotationFacetFactory;
+
 import org.springframework.stereotype.Component;
 
 import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
@@ -45,6 +47,7 @@ public class JpaProgrammingModel implements MetaModelRefiner {
         pm.addFactory(step, new JpaTransientAnnotationFacetFactory(mmc), Marker.JPA);
         pm.addFactory(step, new MandatoryFromJpaColumnAnnotationFacetFactory(mmc), Marker.JPA);
         pm.addFactory(step, new BigDecimalFromJpaColumnAnnotationFacetFactory(mmc), Marker.JPA);
+        pm.addFactory(step, new MaxLengthFromJpaColumnAnnotationFacetFactory(mmc), Marker.JPA);
 
     }
 
diff --git a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/BigDecimalFromJpaColumnAnnotationFacetFactory.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/BigDecimalFromJpaColumnAnnotationFacetFactory.java
index 583b32b06e..f79bda9c7d 100644
--- a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/BigDecimalFromJpaColumnAnnotationFacetFactory.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/BigDecimalFromJpaColumnAnnotationFacetFactory.java
@@ -25,13 +25,18 @@ import javax.persistence.Column;
 
 import org.apache.causeway.core.metamodel.context.MetaModelContext;
 import org.apache.causeway.core.metamodel.facetapi.FeatureType;
+import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
 import org.apache.causeway.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.causeway.core.metamodel.facets.FacetedMethod;
+import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
+import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
+import org.apache.causeway.persistence.commons.metamodel.facets.prop.column.BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil;
 
 import lombok.val;
 
 public class BigDecimalFromJpaColumnAnnotationFacetFactory
-extends FacetFactoryAbstract {
+extends FacetFactoryAbstract
+implements MetaModelRefiner {
 
     @Inject
     public BigDecimalFromJpaColumnAnnotationFacetFactory(final MetaModelContext mmc) {
@@ -59,4 +64,14 @@ extends FacetFactoryAbstract {
 
     }
 
+    @Override
+    public void refineProgrammingModel(final ProgrammingModel programmingModel) {
+        programmingModel.addValidatorSkipManagedBeans(spec->{
+
+            spec.streamProperties(MixedIn.EXCLUDED)
+                    .forEach(BigDecimalFromXxxColumnAnnotationMetaModelRefinerUtil::validateBigDecimalValueFacet);
+
+        });
+    }
+
 }
diff --git a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java
index e24ef5951a..94597ac206 100644
--- a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java
@@ -19,6 +19,7 @@
 package org.apache.causeway.persistence.jpa.metamodel.facets.prop.column;
 
 import java.util.Optional;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.persistence.Column;
@@ -27,13 +28,19 @@ import javax.persistence.JoinColumn;
 import org.apache.causeway.core.metamodel.context.MetaModelContext;
 import org.apache.causeway.core.metamodel.facetapi.FacetUtil;
 import org.apache.causeway.core.metamodel.facetapi.FeatureType;
+import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
 import org.apache.causeway.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet.Semantics;
+import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
+import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.causeway.persistence.commons.metamodel.facets.prop.column.MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil;
 
 import lombok.val;
 
 public class MandatoryFromJpaColumnAnnotationFacetFactory
-extends FacetFactoryAbstract {
+extends FacetFactoryAbstract
+implements MetaModelRefiner {
 
     @Inject
     public MandatoryFromJpaColumnAnnotationFacetFactory(final MetaModelContext mmc) {
@@ -43,8 +50,6 @@ extends FacetFactoryAbstract {
     @Override
     public void process(final ProcessMethodContext processMethodContext) {
 
-        //val cls = processMethodContext.getCls();
-
         final Optional<Boolean> nullable1 = processMethodContext.synthesizeOnMethod(JoinColumn.class)
                 .map(JoinColumn::nullable);
 
@@ -64,5 +69,18 @@ extends FacetFactoryAbstract {
                 new MandatoryFacetFromJpaColumnAnnotation(semantics, facetHolder));
     }
 
+    @Override
+    public void refineProgrammingModel(final ProgrammingModel programmingModel) {
+        programmingModel.addValidatorSkipManagedBeans(objectSpec->{
+
+            final Stream<ObjectAssociation> associations = objectSpec
+                    .streamAssociations(MixedIn.EXCLUDED)
+                    .filter(ObjectAssociation.Predicates.PROPERTIES);
+
+            associations
+                    .forEach(MandatoryFromXxxColumnAnnotationMetaModelRefinerUtil::validateMandatoryFacet);
+
+        });
+    }
 
 }
diff --git a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJpaColumnAnnotation.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJpaColumnAnnotation.java
index 84b3677ced..38a994625b 100644
--- a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJpaColumnAnnotation.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxFractionalDigitsFacetFromJpaColumnAnnotation.java
@@ -35,15 +35,13 @@ extends MaxFractionalDigitsFacetAbstract {
 
          return jpaColumnIfAny
          .filter(jpaColumn->jpaColumn.scale()>=0)
-         .map(jdoColumn->{
-             return new MaxFractionalDigitsFacetFromJpaColumnAnnotation(
-                     jdoColumn.scale(), holder);
-         });
+         .map(jdoColumn-> new MaxFractionalDigitsFacetFromJpaColumnAnnotation(
+                 jdoColumn.scale(), holder));
     }
 
     private MaxFractionalDigitsFacetFromJpaColumnAnnotation(
-            final int maxFractionalDigits, final FacetHolder holder) {
-        super(maxFractionalDigits, holder);
+            final int scale, final FacetHolder holder) {
+        super(scale, holder);
     }
 
 }
diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFacetFromJdoColumnAnnotation.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFacetFromJpaColumnAnnotation.java
similarity index 66%
copy from persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFacetFromJdoColumnAnnotation.java
copy to persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFacetFromJpaColumnAnnotation.java
index 4ca01d5fbb..028fb62a71 100644
--- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/prop/column/MaxLengthFacetFromJdoColumnAnnotation.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFacetFromJpaColumnAnnotation.java
@@ -16,40 +16,30 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.persistence.jdo.metamodel.facets.prop.column;
+package org.apache.causeway.persistence.jpa.metamodel.facets.prop.column;
 
 import java.util.Optional;
 
-import javax.jdo.annotations.Column;
+import javax.persistence.Column;
 
 import org.apache.causeway.core.metamodel.facetapi.FacetHolder;
 import org.apache.causeway.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
 import org.apache.causeway.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacetAbstract;
 
-public class MaxLengthFacetFromJdoColumnAnnotation
+public class MaxLengthFacetFromJpaColumnAnnotation
 extends MaxLengthFacetAbstract {
 
-    public static Optional<MaxLengthFacet> createJdo(
-            final Optional<Column> jdoColumnIfAny,
-            final FacetHolder holder) {
-
-        return jdoColumnIfAny
-        .map(jdoColumn->
-            new MaxLengthFacetFromJdoColumnAnnotation(
-                    jdoColumn.length(), holder));
-    }
-
-    public static Optional<MaxLengthFacet> createJpa(
-            final Optional<javax.persistence.Column> jpaColumnIfAny,
+    public static Optional<MaxLengthFacet> create(
+            final Optional<Column> jpaColumnIfAny,
             final FacetHolder holder) {
 
         return jpaColumnIfAny
         .map(jdoColumn->
-            new MaxLengthFacetFromJdoColumnAnnotation(
+            new MaxLengthFacetFromJpaColumnAnnotation(
                     jdoColumn.length(), holder));
     }
 
-    private MaxLengthFacetFromJdoColumnAnnotation(
+    private MaxLengthFacetFromJpaColumnAnnotation(
             final int maxLength, final FacetHolder holder) {
         super(maxLength, holder);
     }
diff --git a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFromJpaColumnAnnotationFacetFactory.java
similarity index 59%
copy from persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java
copy to persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFromJpaColumnAnnotationFacetFactory.java
index e24ef5951a..5df9e0cf0d 100644
--- a/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MandatoryFromJpaColumnAnnotationFacetFactory.java
+++ b/persistence/jpa/metamodel/src/main/java/org/apache/causeway/persistence/jpa/metamodel/facets/prop/column/MaxLengthFromJpaColumnAnnotationFacetFactory.java
@@ -18,51 +18,47 @@
  */
 package org.apache.causeway.persistence.jpa.metamodel.facets.prop.column;
 
-import java.util.Optional;
+import java.util.stream.Stream;
 
-import javax.inject.Inject;
 import javax.persistence.Column;
-import javax.persistence.JoinColumn;
 
 import org.apache.causeway.core.metamodel.context.MetaModelContext;
 import org.apache.causeway.core.metamodel.facetapi.FacetUtil;
 import org.apache.causeway.core.metamodel.facetapi.FeatureType;
+import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
 import org.apache.causeway.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet.Semantics;
+import org.apache.causeway.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
+import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
+import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure;
 
 import lombok.val;
 
-public class MandatoryFromJpaColumnAnnotationFacetFactory
+public class MaxLengthFromJpaColumnAnnotationFacetFactory
 extends FacetFactoryAbstract {
 
-    @Inject
-    public MandatoryFromJpaColumnAnnotationFacetFactory(final MetaModelContext mmc) {
+    public MaxLengthFromJpaColumnAnnotationFacetFactory(final MetaModelContext mmc) {
         super(mmc, FeatureType.PROPERTIES_ONLY);
     }
 
     @Override
     public void process(final ProcessMethodContext processMethodContext) {
 
-        //val cls = processMethodContext.getCls();
+        // only applies to JDO entities; ignore any view models
+        final Class<?> cls = processMethodContext.getCls();
 
-        final Optional<Boolean> nullable1 = processMethodContext.synthesizeOnMethod(JoinColumn.class)
-                .map(JoinColumn::nullable);
-
-        final Optional<Boolean> nullable2 = processMethodContext.synthesizeOnMethod(Column.class)
-                .map(Column::nullable);
-
-        if(!nullable1.isPresent()
-                && !nullable2.isPresent()) {
+        if(String.class != processMethodContext.getMethod().getReturnType()) {
             return;
         }
 
-        val nullable = nullable1.orElseGet(nullable2::get);
-        val semantics = Semantics.required(!nullable);
-
         val facetHolder = processMethodContext.getFacetHolder();
-        FacetUtil.addFacet(
-                new MandatoryFacetFromJpaColumnAnnotation(semantics, facetHolder));
-    }
 
+        val jdoColumnIfAny = processMethodContext.synthesizeOnMethod(Column.class);
+
+        FacetUtil.addFacetIfPresent(
+                MaxLengthFacetFromJpaColumnAnnotation
+                .create(jdoColumnIfAny, facetHolder));
+    }
 
 }