You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/12/06 17:21:54 UTC

[2/4] git commit: ISIS-486, ISIS-624, ISIS-625, ISIS-626: modal dialogs, @Digits, MMV error handling

ISIS-486, ISIS-624, ISIS-625, ISIS-626: modal dialogs, @Digits, MMV error handling

ISIS-486: improvements to modal dialog
- now correctly displays feedback error on conversion exception when tab out
- to reduce flicker, waits 250ms before performing veil transition

ISIS-624: removed @Decimal, replaced with @Digits (bringing in JSR-349 beanval 1.1 dependency)

ISIS-625: New MmvErrorPage to display any detected metamodel validation errors

ISIS-626: Built-in ExceptionRecognizer implementation for PagedExpiredException.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/7d81325f
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/7d81325f
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/7d81325f

Branch: refs/heads/master
Commit: 7d81325f491a30bcc28f18155e81de226c70ec5f
Parents: ee0910c
Author: Dan Haywood <da...@apache.org>
Authored: Fri Dec 6 15:00:56 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Dec 6 15:00:56 2013 +0000

----------------------------------------------------------------------
 ...ivedFromJdoColumnAnnotationFacetFactory.java | 128 +++++++++++++++--
 ...toryFromJdoColumnAnnotationFacetFactory.java |  78 ++++++-----
 .../wicket/viewer/IsisWicketApplication.java    |  52 ++++++-
 .../wicket/WebRequestCycleForIsis.java          |  48 +++++--
 .../actions/ActionParametersFormPanel.java      |  11 +-
 .../scalars/ScalarModelSubscriber.java          |   2 +
 .../components/scalars/ScalarPanelAbstract.java |   9 ++
 .../jdkmath/BigDecimalConverterWithScale.java   |   1 +
 .../ui/pages/jquery.isis.wicket.viewer.js       |  24 +++-
 .../wicket/ui/pages/mmverror/MmvErrorPage.css   |  63 +++++++++
 .../wicket/ui/pages/mmverror/MmvErrorPage.html  |  63 +++++++++
 .../wicket/ui/pages/mmverror/MmvErrorPage.java  | 139 +++++++++++++++++++
 core/applib/pom.xml                             |   4 +
 .../apache/isis/applib/annotation/Decimal.java  |  45 ------
 .../validator/MetaModelInvalidException.java    |  26 ++--
 .../validator/ValidationFailures.java           |  11 +-
 ...lFacetForParameterFromDecimalAnnotation.java |  50 -------
 ...erivedFromDecimalAnnotationFacetFactory.java |  70 ----------
 ...eterFromJavaxValidationDigitsAnnotation.java |  50 +++++++
 ...omJavaxValidationAnnotationFacetFactory.java |  67 +++++++++
 ...alFacetForPropertyFromDecimalAnnotation.java |  51 -------
 ...erivedFromDecimalAnnotationFacetFactory.java |  63 ---------
 ...ertyFromJavaxValidationDigitsAnnotation.java |  51 +++++++
 ...edFromJavaxValidationDigitsFacetFactory.java |  59 ++++++++
 .../value/bigdecimal/BigDecimalValueFacet.java  |  22 +++
 .../dflt/ProgrammingModelFacetsJava5.java       |   8 +-
 .../BigDecimalAnnotationFacetFactoryTest.java   |  82 -----------
 ...idationDigitsAnnotationFacetFactoryTest.java |  83 +++++++++++
 core/pom.xml                                    |   5 +
 .../dom/src/main/java/dom/todo/ToDoItem.java    |  23 +--
 30 files changed, 927 insertions(+), 461 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/BigDecimalDerivedFromJdoColumnAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/BigDecimalDerivedFromJdoColumnAnnotationFacetFactory.java b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/BigDecimalDerivedFromJdoColumnAnnotationFacetFactory.java
index a5ff082..3d51140 100644
--- a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/BigDecimalDerivedFromJdoColumnAnnotationFacetFactory.java
+++ b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/BigDecimalDerivedFromJdoColumnAnnotationFacetFactory.java
@@ -19,19 +19,36 @@
 package org.apache.isis.objectstore.jdo.metamodel.facets.prop.column;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 import javax.jdo.annotations.Column;
+import javax.jdo.annotations.IdentityType;
 
+import com.google.common.base.Objects;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner;
 import org.apache.isis.core.metamodel.facets.Annotations;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.mandatory.MandatoryFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting;
+import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor;
+import org.apache.isis.core.progmodel.facets.properties.javaxvaldigits.BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation;
 import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
 import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueSemanticsProvider;
+import org.apache.isis.objectstore.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
+import org.apache.isis.objectstore.jdo.metamodel.facets.prop.notpersistent.JdoNotPersistentFacet;
 
 
-public class BigDecimalDerivedFromJdoColumnAnnotationFacetFactory extends FacetFactoryAbstract {
+public class BigDecimalDerivedFromJdoColumnAnnotationFacetFactory extends FacetFactoryAbstract implements MetaModelValidatorRefiner {
 
     private static final int DEFAULT_LENGTH = BigDecimalValueSemanticsProvider.DEFAULT_LENGTH;
     private static final int DEFAULT_SCALE = BigDecimalValueSemanticsProvider.DEFAULT_SCALE;
@@ -43,27 +60,108 @@ public class BigDecimalDerivedFromJdoColumnAnnotationFacetFactory extends FacetF
     @Override
     public void process(final ProcessMethodContext processMethodContext) {
 
-        final Column annotation = Annotations.getAnnotation(processMethodContext.getMethod(), Column.class);
-
         if(BigDecimal.class != processMethodContext.getMethod().getReturnType()) {
             return;
-        } 
-        final BigDecimalValueFacet facet;
-        final FacetedMethod holder = processMethodContext.getFacetHolder();
+        }
         
-        if (annotation == null) {
-            facet = new BigDecimalFacetFallback(holder);
-        } else {
-            facet = new BigDecimalFacetDerivedFromJdoColumn(
-                            holder, 
-                            valueElseDefault(annotation.length(), DEFAULT_LENGTH), 
-                            valueElseDefault(annotation.scale(), DEFAULT_SCALE));
+        final FacetedMethod holder = processMethodContext.getFacetHolder();
+
+        // obtain the existing facet's length and scale, to use as defaults if none are specified on the @Column
+        // this will mean a metamodel validation exception will only be fired later (see #refineMetaModelValidator)
+        // if there was an *explicit* value defined on the @Column annotation that is incompatible with existing.
+        Integer existingLength = null;
+        Integer existingScale = null;
+        BigDecimalValueFacet existingFacet = (BigDecimalValueFacet) holder.getFacet(BigDecimalValueFacet.class);
+        if(existingFacet != null && !existingFacet.isNoop()) {
+            existingLength = existingFacet.getLength();
+            existingScale = existingFacet.getScale();
         }
+        final Column annotation = Annotations.getAnnotation(processMethodContext.getMethod(), Column.class);
+        final BigDecimalValueFacet facet = annotation == null 
+                ? new BigDecimalFacetFallback(holder) 
+                : new BigDecimalFacetDerivedFromJdoColumn(
+                        holder, 
+                        valueElseDefaults(annotation.length(), existingLength, DEFAULT_LENGTH), 
+                        valueElseDefaults(annotation.scale(), existingScale, DEFAULT_SCALE));
+                
+        // any existing BigDecimalValueFacets, eg from the @javax.validation.constraints.Digits annotation, will be
+        // chained to this facet as the 'underlying'.  We check they are compatible in the #refineMetaModelValidator, below.
         FacetUtil.addFacet(facet);
     }
 
-    private final static Integer valueElseDefault(final int value, final int defaultValue) {
-        return value != -1? value: defaultValue;
+    private final static Integer valueElseDefaults(final int value, final Integer underlying, int defaultVal) {
+        return value != -1
+                ? value
+                : underlying != null
+                    ? underlying
+                    : defaultVal;
+    }
+
+
+    @Override
+    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
+        metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor()));
+    }
+
+    private Visitor newValidatorVisitor() {
+        return new MetaModelValidatorVisiting.Visitor() {
+
+            @Override
+            public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
+                validate(objectSpec, validationFailures);
+                return true;
+            }
+
+            private void validate(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
+                
+                // only consider persistent entities
+                final JdoPersistenceCapableFacet pcFacet = objectSpec.getFacet(JdoPersistenceCapableFacet.class);
+                if(pcFacet==null || pcFacet.getIdentityType() == IdentityType.NONDURABLE) {
+                    return;
+                }
+                
+                final List<ObjectAssociation> associations = objectSpec.getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES);
+                for (ObjectAssociation association : associations) {
+                    
+                    // skip checks if annotated with JDO @NotPersistent
+                    if(association.containsDoOpFacet(JdoNotPersistentFacet.class)) {
+                        return;
+                    }
+                    
+                    validateBigDecimalValueFacet(association, validationFailures);
+                }
+            }
+
+            private void validateBigDecimalValueFacet(ObjectAssociation association, ValidationFailures validationFailures) {
+                BigDecimalValueFacet facet = association.getFacet(BigDecimalValueFacet.class);
+                if(facet == null) {
+                    return;
+                }
+                
+                BigDecimalValueFacet underlying = (BigDecimalValueFacet) facet.getUnderlyingFacet();
+                if(underlying == null) {
+                    return;
+                } 
+                
+                if(facet instanceof BigDecimalFacetDerivedFromJdoColumn) {
+                    
+                    if(underlying instanceof BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation) {
+
+                        if(notNullButNotEqual(facet.getLength(), underlying.getLength())) {
+                            validationFailures.add("%s: @javax.jdo.annotations.Column(length=...) different from @javax.validation.constraint.Digits(...); should equal the sum of its integer and fraction attributes", association.getIdentifier().toClassAndNameIdentityString());
+                        }
+    
+                        if(notNullButNotEqual(facet.getScale(), underlying.getScale())) {
+                            validationFailures.add("%s: @javax.jdo.annotations.Column(scale=...) different from @javax.validation.constraint.Digits(fraction=...)", association.getIdentifier().toClassAndNameIdentityString());
+                        }
+                    }
+                }
+            }
+
+            private boolean notNullButNotEqual(Integer x, Integer y) {
+                return x != null && y != null && !x.equals(y);
+            }
+        };
     }
 
     

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
index 19f76f4..0c74ea8 100644
--- a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
+++ b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
@@ -135,48 +135,52 @@ public class MandatoryFromJdoColumnAnnotationFacetFactory extends FacetFactoryAb
                         return;
                     }
                     
-                    MandatoryFacet facet = association.getFacet(MandatoryFacet.class);
+                    validateMandatoryFacet(association, validationFailures);
+                }
+            }
+
+            private void validateMandatoryFacet(ObjectAssociation association, ValidationFailures validationFailures) {
+                MandatoryFacet facet = association.getFacet(MandatoryFacet.class);
 
-                    MandatoryFacet underlying = (MandatoryFacet) facet.getUnderlyingFacet();
-                    if(underlying == null) {
-                        continue;
+                MandatoryFacet underlying = (MandatoryFacet) facet.getUnderlyingFacet();
+                if(underlying == null) {
+                    return;
+                } 
+                
+                if(facet instanceof MandatoryFacetDerivedFromJdoColumn) {
+
+                    if(association.isNotPersisted()) {
+                        validationFailures.add("%s: @javax.jdo.annotations.Column found on non-persisted property; please remove)", association.getIdentifier().toClassAndNameIdentityString());
+                        return;
                     }
 
-                    if(facet instanceof MandatoryFacetDerivedFromJdoColumn) {
-
-                        if(association.isNotPersisted()) {
-                            validationFailures.add("%s: @javax.jdo.annotations.Column found on non-persisted property; please remove)", association.getIdentifier().toClassAndNameIdentityString());
-                            continue;
-                        }
-
-                        if(underlying.isInvertedSemantics() == facet.isInvertedSemantics()) {
-                            continue;
-                        }
-                        
-                        if(underlying.isInvertedSemantics()) {
-                            // ie @Optional
-                            validationFailures.add("%s: incompatible usage of Isis' @Optional annotation and @javax.jdo.annotations.Column; use just @javax.jdo.annotations.Column(allowNulls=\"...\")", association.getIdentifier().toClassAndNameIdentityString());
-                        } else {
-                            validationFailures.add("%s: incompatible Isis' default of required/optional properties vs JDO; add @javax.jdo.annotations.Column(allowNulls=\"...\")", association.getIdentifier().toClassAndNameIdentityString());
-                        }
+                    if(underlying.isInvertedSemantics() == facet.isInvertedSemantics()) {
+                        return;
                     }
                     
-                    if(facet instanceof MandatoryFacetInferredFromAbsenceOfJdoColumn) {
-                        
-                        if(association.isNotPersisted()) {
-                            // nothing to do.
-                            continue;
-                        }
-
-                        if(underlying.isInvertedSemantics() == facet.isInvertedSemantics()) {
-                            continue;
-                        }
-                        if(underlying.isInvertedSemantics()) {
-                            // ie @Optional
-                            validationFailures.add("%s: incompatible usage of Isis' @Optional annotation and @javax.jdo.annotations.Column; use just @javax.jdo.annotations.Column(allowNulls=\"...\")", association.getIdentifier().toClassAndNameIdentityString());
-                        } else {
-                            validationFailures.add("%s: incompatible default handling of required/optional properties between Isis and JDO; add @javax.jdo.annotations.Column(allowsNull=\"...\")", association.getIdentifier().toClassAndNameIdentityString());
-                        }
+                    if(underlying.isInvertedSemantics()) {
+                        // ie @Optional
+                        validationFailures.add("%s: incompatible usage of Isis' @Optional annotation and @javax.jdo.annotations.Column; use just @javax.jdo.annotations.Column(allowNulls=\"...\")", association.getIdentifier().toClassAndNameIdentityString());
+                    } else {
+                        validationFailures.add("%s: incompatible Isis' default of required/optional properties vs JDO; add @javax.jdo.annotations.Column(allowNulls=\"...\")", association.getIdentifier().toClassAndNameIdentityString());
+                    }
+                }
+                
+                if(facet instanceof MandatoryFacetInferredFromAbsenceOfJdoColumn) {
+                    
+                    if(association.isNotPersisted()) {
+                        // nothing to do.
+                        return;
+                    }
+
+                    if(underlying.isInvertedSemantics() == facet.isInvertedSemantics()) {
+                        return;
+                    }
+                    if(underlying.isInvertedSemantics()) {
+                        // ie @Optional
+                        validationFailures.add("%s: incompatible usage of Isis' @Optional annotation and @javax.jdo.annotations.Column; use just @javax.jdo.annotations.Column(allowNulls=\"...\")", association.getIdentifier().toClassAndNameIdentityString());
+                    } else {
+                        validationFailures.add("%s: incompatible default handling of required/optional properties between Isis and JDO; add @javax.jdo.annotations.Column(allowsNull=\"...\")", association.getIdentifier().toClassAndNameIdentityString());
                     }
                 }
             }

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index 9090864..4b75e8b 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.viewer.wicket.viewer;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -28,7 +29,9 @@ import java.util.Set;
 import javax.servlet.ServletContext;
 
 import com.google.common.base.Function;
+import com.google.common.base.Throwables;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.inject.Guice;
 import com.google.inject.Inject;
@@ -68,6 +71,7 @@ import org.apache.isis.core.commons.resource.ResourceStreamSourceContextLoaderCl
 import org.apache.isis.core.commons.resource.ResourceStreamSourceCurrentClassClassPath;
 import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelInvalidException;
 import org.apache.isis.core.runtime.logging.IsisLoggingConfigurer;
 import org.apache.isis.core.runtime.runner.IsisInjectModule;
 import org.apache.isis.core.runtime.system.DeploymentType;
@@ -197,6 +201,8 @@ public class IsisWicketApplication extends AuthenticatedWebApplication implement
     private boolean determiningDeploymentType;
     private DeploymentTypeWicketAbstract deploymentType;
 
+    private final List<String> validationErrors = Lists.newArrayList();
+
 
     // /////////////////////////////////////////////////
     // constructor, init
@@ -259,12 +265,51 @@ public class IsisWicketApplication extends AuthenticatedWebApplication implement
             mountPage("/action/${objectOid}/${actionOwningSpec}/${actionId}/${actionType}/#{actionArgs}", PageType.ACTION_PROMPT);
             
         } catch(RuntimeException ex) {
-            // because Wicket's handling in its WicketFilter (that calls this method) does not log the exception.
-            LOG.error("Failed to initialize", ex);
-            throw ex;
+            List<MetaModelInvalidException> mmies = Lists.newArrayList(
+                    Iterables.filter(Throwables.getCausalChain(ex), MetaModelInvalidException.class));
+            if(!mmies.isEmpty()) {
+                final MetaModelInvalidException mmie = mmies.get(0);
+                log("");
+                logBanner();
+                log("");
+                validationErrors.addAll(mmie.getValidationErrors());
+                for (String validationError : validationErrors) {
+                    logError(validationError);
+                }
+                log("");
+                log("Please inspect the above messages and correct your domain model.");
+                log("");
+                logBanner();
+                log("");
+            } else {
+                // because Wicket's handling in its WicketFilter (that calls this method) does not log the exception.
+                LOG.error("Failed to initialize", ex);
+                throw ex;
+            }
         }
     }
 
+    /**
+     * The validation errors, if any, that occurred on {@link #init() startup}.
+     */
+    public List<String> getValidationErrors() {
+        return validationErrors;
+    }
+    
+    private void logError(String validationError) {
+        log(validationError);
+    }
+
+    private static void logBanner() {
+        String msg = "################################################ ISIS METAMODEL VALIDATION ERRORS ################################################################";
+        log(msg);
+    }
+
+    private static void log(String msg) {
+        System.err.println(msg);
+        LOG.error(msg);
+    }
+
     private void mountPage(final String mountPath, final PageType pageType) {
         final Class<? extends Page> pageClass = this.pageClassRegistry.getPageClass(pageType);
         mount(new MountedMapper(mountPath, pageClass));
@@ -325,6 +370,7 @@ public class IsisWicketApplication extends AuthenticatedWebApplication implement
                 }
              };
 
+
     private Set<CssResourceReference> cssResourceReferencesForAllComponents() {
         Collection<ComponentFactory> componentFactories = getComponentFactoryRegistry().listComponentFactories();
         return Sets.newLinkedHashSet(

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
index 26dfca7..2460f78 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
@@ -19,24 +19,29 @@
 
 package org.apache.isis.viewer.wicket.viewer.integration.wicket;
 
-import java.util.Collections;
 import java.util.List;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
 import org.apache.wicket.RestartResponseException;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
 import org.apache.wicket.core.request.handler.PageProvider;
 import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
 import org.apache.wicket.core.request.handler.RenderPageRequestHandler.RedirectPolicy;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.protocol.http.PageExpiredException;
 import org.apache.wicket.protocol.http.WebSession;
 import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.component.IRequestablePage;
 import org.apache.wicket.request.cycle.AbstractRequestCycleListener;
 import org.apache.wicket.request.cycle.RequestCycle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerComposite;
+import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerForType;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.runtime.system.context.IsisContext;
@@ -45,6 +50,8 @@ import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
 import org.apache.isis.viewer.wicket.ui.errors.ExceptionModel;
 import org.apache.isis.viewer.wicket.ui.pages.error.ErrorPage;
 import org.apache.isis.viewer.wicket.ui.pages.login.WicketSignInPage;
+import org.apache.isis.viewer.wicket.ui.pages.mmverror.MmvErrorPage;
+import org.apache.isis.viewer.wicket.viewer.IsisWicketApplication;
 
 /**
  * Isis-specific implementation of the Wicket's {@link WebRequestCycle},
@@ -105,7 +112,10 @@ public class WebRequestCycleForIsis extends AbstractRequestCycleListener {
                         return;
                     }
                 }
-                throw new RestartResponseException(errorPageProviderFor(ex), RedirectPolicy.ALWAYS_REDIRECT);
+                
+                // shouldn't return null given that we're in a session ...
+                PageProvider errorPageProvider = errorPageProviderFor(ex);
+                throw new RestartResponseException(errorPageProvider, RedirectPolicy.ALWAYS_REDIRECT);
             }
         }
     }
@@ -129,18 +139,40 @@ public class WebRequestCycleForIsis extends AbstractRequestCycleListener {
 
     @Override
     public IRequestHandler onException(RequestCycle cycle, Exception ex) {
-        return new RenderPageRequestHandler(errorPageProviderFor(ex), RedirectPolicy.ALWAYS_REDIRECT);
+        PageProvider errorPageProvider = errorPageProviderFor(ex);
+        // avoid infinite redirect loops
+        RedirectPolicy redirectPolicy = ex instanceof PageExpiredException? RedirectPolicy.NEVER_REDIRECT: RedirectPolicy.ALWAYS_REDIRECT;
+        return errorPageProvider != null 
+                ? new RenderPageRequestHandler(errorPageProvider, redirectPolicy)
+                : null;
     }
 
     protected PageProvider errorPageProviderFor(Exception ex) {
-        return new PageProvider(errorPageFor(ex));
+        IRequestablePage errorPage = errorPageFor(ex);
+        return errorPage != null? new PageProvider(errorPage): null;
     }
 
+    // special case handling for PageExpiredException, otherwise infinite loop
+    private final static ExceptionRecognizerForType pageExpiredExceptionRecognizer = 
+            new ExceptionRecognizerForType(PageExpiredException.class, new Function<String,String>(){
+                @Override
+                public String apply(String input) {
+                    return "Requested page is no longer available. Please navigate back to the home page or select an object from the bookmark bar.";
+                }
+            });
+
     protected IRequestablePage errorPageFor(Exception ex) {
-        List<ExceptionRecognizer> exceptionRecognizers = Collections.emptyList();
+        List<ExceptionRecognizer> exceptionRecognizers = Lists.newArrayList();
+        exceptionRecognizers.add(pageExpiredExceptionRecognizer);
+
         if(inIsisSession()) {
-            exceptionRecognizers = getServicesInjector().lookupServices(ExceptionRecognizer.class);
+            exceptionRecognizers.addAll(getServicesInjector().lookupServices(ExceptionRecognizer.class));
         } else {
+            List<String> validationErrors = IsisWicketApplication.get().getValidationErrors();
+            if(!validationErrors.isEmpty()) {
+                return new MmvErrorPage(Model.ofList(validationErrors));
+            }
+            // not sure whether this can ever happen now...
             LOG.warn("Unable to obtain exceptionRecognizers (no session), will be treated as unrecognized exception");
         }
         String recognizedMessageIfAny = new ExceptionRecognizerComposite(exceptionRecognizers).recognize(ex);

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
index 6858d79..d713589 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
@@ -263,7 +263,16 @@ public class ActionParametersFormPanel extends PanelAbstract<ActionModel> {
                 getAuthenticationSession().getMessageBroker().addWarning(ex.getMessage());
                 return;
             }
-            
+            target.add(this);
+        }
+        
+        @Override
+        public void onError(AjaxRequestTarget target, ScalarModelProvider provider) {
+            if(provider instanceof Component) {
+                // ensure that any feedback error associated with the providing component is shown.
+                target.add((Component)provider); 
+            }
         }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarModelSubscriber.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarModelSubscriber.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarModelSubscriber.java
index 88b9a7c..647d903 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarModelSubscriber.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarModelSubscriber.java
@@ -24,4 +24,6 @@ public interface ScalarModelSubscriber {
 
     void onUpdate(AjaxRequestTarget target, ScalarModelProvider provider);
 
+    void onError(AjaxRequestTarget target, ScalarModelProvider provider);
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
index 898da32..b5ab758 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
@@ -201,6 +201,15 @@ public abstract class ScalarPanelAbstract extends PanelAbstract<ScalarModel> imp
                         subscriber.onUpdate(target, ScalarPanelAbstract.this);
                     }
                 }
+                
+                @Override
+                protected void onError(AjaxRequestTarget target, RuntimeException e) {
+                    super.onError(target, e);
+                    for (ScalarModelSubscriber subscriber : subscribers) {
+                        subscriber.onError(target, ScalarPanelAbstract.this);
+                    }
+
+                }
             });
         }
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java
index 095a817..b93b185 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java
@@ -79,6 +79,7 @@ class BigDecimalConverterWithScale extends BigDecimalConverter {
     
     @Override
     public BigDecimal convertToObject(String valueStr, Locale locale) throws ConversionException {
+
         DecimalFormat numberFormat = (DecimalFormat) getNumberFormat(locale);
         char groupingSeparator = numberFormat.getDecimalFormatSymbols().getGroupingSeparator();
         

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js
index 5f564b3..c3039da 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js
@@ -18,24 +18,38 @@
  */
 $(document).ready(function() {
 
+    var timeoutId;
+    
     isisShowVeil = function() {
         $("#veil").stop().show();
     }
-    isisFadeInVeil = function() {
+    isisFadeInVeil = function(attributes, jqxhr, settings) {
+        /*
         $("#veil").fadeIn(750);
+        */
+        var activeEl = attributes.currentTarget.activeElement;
+        timeoutId = setTimeout(function() {
+            $("#veil").fadeIn(750);
+        }, 250);
+        
     }
-    isisHideVeil = function() {
-        $("#veil").stop().hide();
+    isisHideVeil = function(attributes, jqXHR, settings) {
+        if(timeoutId) {
+            clearTimeout(timeoutId);
+            timeoutId = null;
+        } else {
+            $("#veil").stop().hide();
+        }
     }
 
     /* for modal dialogs */
     Wicket.Event.subscribe(
             '/ajax/call/beforeSend', function(attributes, jqXHR, settings) {
-                isisFadeInVeil();
+                isisFadeInVeil(attributes, jqXHR, settings);
             });
     Wicket.Event.subscribe(
             '/ajax/call/complete', function(attributes, jqXHR, settings) {
-                isisHideVeil();
+                isisHideVeil(attributes, jqXHR, settings);
             });
     
 

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.css
new file mode 100644
index 0000000..bd982b8
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.css
@@ -0,0 +1,63 @@
+/*
+ *  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.
+ */
+
+
+#header .applicationName {
+	display:none;
+}
+ 
+
+.mmvErrorPage .mainMessage {
+	margin-top: 550px;
+}
+
+
+ .validationErrorsPanel .errorInfo {
+    margin-left: 50px;
+    margin-right: 50px;
+    padding-top: 50px;
+}
+
+
+.validationErrorsPanel .mainMessage {
+    background:#FFFFFF;
+    border-radius:4px;
+    -moz-border-radius:4px;
+    -webkit-border-radius:4px;
+    padding: 15px;
+    display: block;
+    text-align:center;
+    font-size:1.2em;
+}
+
+ .validationErrorsPanel .errorDetail {
+    margin-top: 30px; 
+}
+
+
+
+.validationErrorsPanel ul {
+	list-style: initial;
+	padding: 10px;
+	margin-left: 20px;
+}
+
+.validationErrorsPanel li {
+    padding: 5px;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.html
new file mode 100644
index 0000000..f4818ca
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.html
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<!--
+  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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
+      xml:lang="en"  
+      lang="en">
+	<head>
+		<title wicket:id="pageTitle"></title>
+		<wicket:link>
+			<link href="../cssreset.css" rel="stylesheet" type="text/css"/>
+			<link href="MmvErrorPage.css" rel="stylesheet" />
+			<link href="../PageAbstract.css" rel="stylesheet" />
+		</wicket:link>
+	</head>
+	<body>
+		<div id="container">
+        
+			<div class="headerContainer">
+				<div id="header">
+					<h1>
+                        <span wicket:id="applicationName" class="applicationName">[application name]</span>
+                    </h1>
+				</div>
+				<div class="clear"/>
+			</div>
+
+            <div id="body">
+                <div class="validationErrorsPanel">
+                    <div class="errorInfo clear">
+                        <span class="mainMessage">The application failed to start due to a number of metamodel validation errors.</span>
+                        <div class="errorDetail">
+                            <ul>
+                                <li wicket:id="error">
+                                    <span wicket:id="errorMessage">[error message]</span>
+                                </li>
+                            </ul>
+                        </div>
+                    </div>
+                </div>
+                <div class="clear"/>
+            </div>
+
+	    </div>
+	</body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.java
new file mode 100644
index 0000000..47856c3
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/mmverror/MmvErrorPage.java
@@ -0,0 +1,139 @@
+/*
+ *  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.isis.viewer.wicket.ui.pages.mmverror;
+
+import java.util.List;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.markup.head.CssReferenceHeaderItem;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;
+import org.apache.wicket.markup.head.PriorityHeaderItem;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.IModel;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+
+/**
+ * Boilerplate, pick up our HTML and CSS.
+ */
+public class MmvErrorPage extends WebPage {
+    
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_PAGE_TITLE = "pageTitle";
+    private static final String ID_APPLICATION_NAME = "applicationName";
+
+    /**
+     * {@link Inject}ed when {@link #init() initialized}.
+     */
+    @Inject
+    @Named("applicationName")
+    private String applicationName;
+
+    /**
+     * {@link Inject}ed when {@link #init() initialized}.
+     */
+    @Inject
+    @Named("applicationCss")
+    private String applicationCss;
+    
+    /**
+     * {@link Inject}ed when {@link #init() initialized}.
+     */
+    @Inject
+    @Named("applicationJs")
+    private String applicationJs;
+
+    private static final String ID_ERROR = "error";
+    private static final String ID_ERROR_MESSAGE = "errorMessage";
+
+    public MmvErrorPage(final IModel<List<? extends String>> model) {
+        super(model);
+        addPageTitle();
+        addApplicationName();
+        addValidationErrors();
+    }
+
+    @SuppressWarnings("unchecked")
+    private IModel<List<? extends String>> getModel() {
+        return (IModel<List<? extends String>>) getDefaultModel();
+    }
+
+    private MarkupContainer addPageTitle() {
+        return add(new Label(ID_PAGE_TITLE, applicationName));
+    }
+
+    private void addApplicationName() {
+        add(new Label(ID_APPLICATION_NAME, applicationName));
+    }
+
+    private void addValidationErrors() {
+        class ValidationErrorListView extends ListView<String> {
+            
+            private static final long serialVersionUID = 1L;
+            private final String idLine;
+
+            public ValidationErrorListView(String id, String idLine, final IModel<List<? extends String>> model) {
+                super(id, model);
+                this.idLine = idLine;
+            }
+
+            @Override
+            protected void populateItem(ListItem<String> item) {
+                final String validationError = item.getModelObject();
+                item.add(new Label(idLine, validationError));
+            }
+        }
+        add(new ValidationErrorListView(ID_ERROR, ID_ERROR_MESSAGE, getModel()));
+    }
+
+    @Override
+    public void renderHead(IHeaderResponse response) {
+        super.renderHead(response);
+        response.render(new PriorityHeaderItem(JavaScriptHeaderItem.forReference(Application.get().getJavaScriptLibrarySettings().getJQueryReference())));
+        
+        if(applicationCss != null) {
+            response.render(CssReferenceHeaderItem.forUrl(applicationCss));
+        }
+        if(applicationJs != null) {
+            response.render(JavaScriptReferenceHeaderItem.forUrl(applicationJs));
+        }
+    }
+
+ 
+    // ///////////////////////////////////////////////////
+    // System components
+    // ///////////////////////////////////////////////////
+
+    protected IsisConfiguration getConfiguration() {
+        return IsisContext.getConfiguration();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/applib/pom.xml
----------------------------------------------------------------------
diff --git a/core/applib/pom.xml b/core/applib/pom.xml
index 4850dd0..c79682d 100644
--- a/core/applib/pom.xml
+++ b/core/applib/pom.xml
@@ -91,6 +91,10 @@
             <groupId>org.apache.geronimo.specs</groupId>
             <artifactId>geronimo-atinject_1.0_spec</artifactId>
         </dependency>
+        <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation-api</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.isis.core</groupId>

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/applib/src/main/java/org/apache/isis/applib/annotation/Decimal.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Decimal.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Decimal.java
deleted file mode 100644
index e4f6320..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Decimal.java
+++ /dev/null
@@ -1,45 +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.isis.applib.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * The length and scale for a decimal value.
- * 
- * <p>
- * If using the JDO object store, then the <tt>@Column</tt> annotation should usually be used to indicate
- * length (precision) and scale of properties.  However, the <tt>@Column</tt> annotation is not, of course, valid for 
- * action parameters.  This annotation is therefore of use for action parameters whose value is intended to be
- * compatible with JDO-annotated properties.  If the <tt>@Column</tt> and {@link Decimal} annotations are both
- * present on a property, then they must be compatible (and Isis' metamodel validator will flag up any 
- * incompatibility). 
- */
-@Inherited
-@Target({ ElementType.METHOD, ElementType.PARAMETER })
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Decimal {
-    int length() default -1;
-    int scale() default -1;
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelInvalidException.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelInvalidException.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelInvalidException.java
index 3a7992b..0209fe1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelInvalidException.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelInvalidException.java
@@ -19,23 +19,31 @@
 
 package org.apache.isis.core.metamodel.specloader.validator;
 
+import java.util.Set;
+
 public class MetaModelInvalidException extends IllegalStateException {
 
     private static final long serialVersionUID = 1L;
+    private final Set<String> validationErrors;
 
-    public MetaModelInvalidException() {
+    public MetaModelInvalidException(Set<String> validationErrors) {
+        super(concatenate(validationErrors));
+        this.validationErrors = validationErrors;
     }
-
-    public MetaModelInvalidException(final String s) {
-        super(s);
+    
+    public Set<String> getValidationErrors() {
+        return validationErrors;
     }
 
-    public MetaModelInvalidException(final Throwable cause) {
-        super(cause);
-    }
+    // //////////////////////////////////////
 
-    public MetaModelInvalidException(final String message, final Throwable cause) {
-        super(message, cause);
+    private static String concatenate(Set<String> messages) {
+        final StringBuilder buf = new StringBuilder();
+        int i=0;
+        for (String message : messages) {
+            buf.append(++i).append(": ").append(message).append("\n");
+        }
+        return buf.toString();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/ValidationFailures.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/ValidationFailures.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/ValidationFailures.java
index a7fae1b..87080ec 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/ValidationFailures.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/ValidationFailures.java
@@ -37,7 +37,7 @@ public final class ValidationFailures implements Iterable<String> {
         if (!occurred()) {
             return;
         }
-        throw new MetaModelInvalidException(getMessagesBuf());
+        throw new MetaModelInvalidException(messages);
     }
 
     public boolean occurred() {
@@ -48,15 +48,6 @@ public final class ValidationFailures implements Iterable<String> {
         return Collections.unmodifiableSet(messages);
     }
 
-    private String getMessagesBuf() {
-        final StringBuilder buf = new StringBuilder();
-        int i=0;
-        for (String message : messages) {
-            buf.append(++i).append(": ").append(message).append("\n");
-        }
-        return buf.toString();
-    }
-
     public int getNumberOfMessages() {
         return messages.size();
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/decimal/BigDecimalFacetForParameterFromDecimalAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/decimal/BigDecimalFacetForParameterFromDecimalAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/decimal/BigDecimalFacetForParameterFromDecimalAnnotation.java
deleted file mode 100644
index 6d1e474..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/decimal/BigDecimalFacetForParameterFromDecimalAnnotation.java
+++ /dev/null
@@ -1,50 +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.isis.core.progmodel.facets.param.decimal;
-
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
-
-public class BigDecimalFacetForParameterFromDecimalAnnotation extends FacetAbstract implements BigDecimalValueFacet {
-
-    private final Integer length;
-    private final Integer scale;
-
-    public static Class<? extends Facet> type() {
-        return BigDecimalValueFacet.class;
-    }
-
-    public BigDecimalFacetForParameterFromDecimalAnnotation(final FacetHolder holder, final Integer length, final Integer scale) {
-        super(BigDecimalFacetForParameterFromDecimalAnnotation.type(), holder, Derivation.NOT_DERIVED);
-        this.length = length;
-        this.scale = scale;
-    }
-
-    @Override
-    public Integer getLength() {
-        return length;
-    }
-
-    @Override
-    public Integer getScale() {
-        return scale;
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/decimal/BigDecimalForParameterDerivedFromDecimalAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/decimal/BigDecimalForParameterDerivedFromDecimalAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/decimal/BigDecimalForParameterDerivedFromDecimalAnnotationFacetFactory.java
deleted file mode 100644
index 6bb37fc..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/decimal/BigDecimalForParameterDerivedFromDecimalAnnotationFacetFactory.java
+++ /dev/null
@@ -1,70 +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.isis.core.progmodel.facets.param.decimal;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-
-import org.apache.isis.applib.annotation.Decimal;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facetapi.FacetUtil;
-import org.apache.isis.core.metamodel.facetapi.FeatureType;
-import org.apache.isis.core.metamodel.facets.Annotations;
-import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
-import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueSemanticsProvider;
-
-public class BigDecimalForParameterDerivedFromDecimalAnnotationFacetFactory extends FacetFactoryAbstract {
-
-    private static final int DEFAULT_LENGTH = BigDecimalValueSemanticsProvider.DEFAULT_LENGTH;
-    private static final int DEFAULT_SCALE = BigDecimalValueSemanticsProvider.DEFAULT_SCALE;
-
-    public BigDecimalForParameterDerivedFromDecimalAnnotationFacetFactory() {
-        super(FeatureType.PARAMETERS_ONLY);
-    }
-
-    @Override
-    public void processParams(ProcessParameterContext processParameterContext) {
-
-        final Method method = processParameterContext.getMethod();
-        final int paramNum = processParameterContext.getParamNum();
-        
-        final Annotation[] parameterAnnotations = Annotations.getParameterAnnotations(method)[paramNum];
-
-        for (final Annotation parameterAnnotation : parameterAnnotations) {
-            if (parameterAnnotation instanceof Decimal) {
-                FacetUtil.addFacet(create((Decimal) parameterAnnotation, processParameterContext.getFacetHolder()));
-                return;
-            }
-        }
-    }
-
-    private BigDecimalValueFacet create(final Decimal annotation, final FacetHolder holder) {
-        return annotation == null ? null : 
-            new BigDecimalFacetForParameterFromDecimalAnnotation(
-                    holder, 
-                    valueElseDefault(annotation.length(), DEFAULT_LENGTH), 
-                    valueElseDefault(annotation.scale(), DEFAULT_SCALE));
-    }
-
-    private static Integer valueElseDefault(final int value, final int defaultValue) {
-        return value != -1? value: defaultValue;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/javaxvaldigits/BigDecimalFacetForParameterFromJavaxValidationDigitsAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/javaxvaldigits/BigDecimalFacetForParameterFromJavaxValidationDigitsAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/javaxvaldigits/BigDecimalFacetForParameterFromJavaxValidationDigitsAnnotation.java
new file mode 100644
index 0000000..d204c02
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/javaxvaldigits/BigDecimalFacetForParameterFromJavaxValidationDigitsAnnotation.java
@@ -0,0 +1,50 @@
+/*
+ *  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.isis.core.progmodel.facets.param.javaxvaldigits;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
+
+public class BigDecimalFacetForParameterFromJavaxValidationDigitsAnnotation extends FacetAbstract implements BigDecimalValueFacet {
+
+    private final Integer length;
+    private final Integer scale;
+
+    public static Class<? extends Facet> type() {
+        return BigDecimalValueFacet.class;
+    }
+
+    public BigDecimalFacetForParameterFromJavaxValidationDigitsAnnotation(final FacetHolder holder, final Integer length, final Integer scale) {
+        super(BigDecimalFacetForParameterFromJavaxValidationDigitsAnnotation.type(), holder, Derivation.NOT_DERIVED);
+        this.length = length;
+        this.scale = scale;
+    }
+
+    @Override
+    public Integer getLength() {
+        return length;
+    }
+
+    @Override
+    public Integer getScale() {
+        return scale;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/javaxvaldigits/BigDecimalForParameterDerivedFromJavaxValidationAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/javaxvaldigits/BigDecimalForParameterDerivedFromJavaxValidationAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/javaxvaldigits/BigDecimalForParameterDerivedFromJavaxValidationAnnotationFacetFactory.java
new file mode 100644
index 0000000..5c1d050
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/javaxvaldigits/BigDecimalForParameterDerivedFromJavaxValidationAnnotationFacetFactory.java
@@ -0,0 +1,67 @@
+/*
+ *  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.isis.core.progmodel.facets.param.javaxvaldigits;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+
+import javax.validation.constraints.Digits;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
+
+public class BigDecimalForParameterDerivedFromJavaxValidationAnnotationFacetFactory extends FacetFactoryAbstract {
+
+    public BigDecimalForParameterDerivedFromJavaxValidationAnnotationFacetFactory() {
+        super(FeatureType.PARAMETERS_ONLY);
+    }
+
+    @Override
+    public void processParams(ProcessParameterContext processParameterContext) {
+
+        final Method method = processParameterContext.getMethod();
+        final int paramNum = processParameterContext.getParamNum();
+        
+        if(BigDecimal.class != method.getParameterTypes()[paramNum]) {
+            return;
+        }
+        final Annotation[] parameterAnnotations = Annotations.getParameterAnnotations(method)[paramNum];
+
+        for (final Annotation parameterAnnotation : parameterAnnotations) {
+            if (parameterAnnotation instanceof Digits) {
+                Digits digitsAnnotation = (Digits) parameterAnnotation;
+                FacetUtil.addFacet(create(digitsAnnotation, processParameterContext.getFacetHolder()));
+                return;
+            }
+        }
+    }
+
+    private BigDecimalValueFacet create(final Digits annotation, final FacetHolder holder) {
+        final int length = annotation.integer() + annotation.fraction();
+        final int scale = annotation.fraction();
+        return annotation == null ? null : 
+            new BigDecimalFacetForParameterFromJavaxValidationDigitsAnnotation(holder, length, scale);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/decimal/BigDecimalFacetForPropertyFromDecimalAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/decimal/BigDecimalFacetForPropertyFromDecimalAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/decimal/BigDecimalFacetForPropertyFromDecimalAnnotation.java
deleted file mode 100644
index 1b743bd..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/decimal/BigDecimalFacetForPropertyFromDecimalAnnotation.java
+++ /dev/null
@@ -1,51 +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.isis.core.progmodel.facets.properties.decimal;
-
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
-
-
-public class BigDecimalFacetForPropertyFromDecimalAnnotation extends FacetAbstract implements BigDecimalValueFacet {
-
-    private final Integer length;
-    private final Integer scale;
-
-    public static Class<? extends Facet> type() {
-        return BigDecimalValueFacet.class;
-    }
-
-    public BigDecimalFacetForPropertyFromDecimalAnnotation(final FacetHolder holder, final Integer length, final Integer scale) {
-        super(BigDecimalFacetForPropertyFromDecimalAnnotation.type(), holder, Derivation.NOT_DERIVED);
-        this.length = length;
-        this.scale = scale;
-    }
-
-    @Override
-    public Integer getLength() {
-        return length;
-    }
-
-    @Override
-    public Integer getScale() {
-        return scale;
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/decimal/BigDecimalForPropertyDerivedFromDecimalAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/decimal/BigDecimalForPropertyDerivedFromDecimalAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/decimal/BigDecimalForPropertyDerivedFromDecimalAnnotationFacetFactory.java
deleted file mode 100644
index affa82f..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/decimal/BigDecimalForPropertyDerivedFromDecimalAnnotationFacetFactory.java
+++ /dev/null
@@ -1,63 +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.isis.core.progmodel.facets.properties.decimal;
-
-import java.math.BigDecimal;
-
-import org.apache.isis.applib.annotation.Decimal;
-import org.apache.isis.core.metamodel.facetapi.FacetUtil;
-import org.apache.isis.core.metamodel.facetapi.FeatureType;
-import org.apache.isis.core.metamodel.facets.Annotations;
-import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.isis.core.metamodel.facets.FacetedMethod;
-import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
-import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueSemanticsProvider;
-
-public class BigDecimalForPropertyDerivedFromDecimalAnnotationFacetFactory extends FacetFactoryAbstract {
-
-    private static final int DEFAULT_LENGTH = BigDecimalValueSemanticsProvider.DEFAULT_LENGTH;
-    private static final int DEFAULT_SCALE = BigDecimalValueSemanticsProvider.DEFAULT_SCALE;
-
-    public BigDecimalForPropertyDerivedFromDecimalAnnotationFacetFactory() {
-        super(FeatureType.PROPERTIES_ONLY);
-    }
-
-    @Override
-    public void process(final ProcessMethodContext processMethodContext) {
-
-        final Decimal annotation = Annotations.getAnnotation(processMethodContext.getMethod(), Decimal.class);
-
-        if(BigDecimal.class != processMethodContext.getMethod().getReturnType()) {
-            return;
-        } 
-        final BigDecimalValueFacet facet;
-        final FacetedMethod holder = processMethodContext.getFacetHolder();
-        
-        if (annotation == null) {
-            return;
-        }
-        facet = new BigDecimalFacetForPropertyFromDecimalAnnotation(holder, valueElseDefault(annotation.length(), DEFAULT_LENGTH), valueElseDefault(annotation.scale(), DEFAULT_SCALE));
-        FacetUtil.addFacet(facet);
-    }
-
-    Integer valueElseDefault(final int value, final int defaultValue) {
-        return value != -1? value: defaultValue;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/javaxvaldigits/BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/javaxvaldigits/BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/javaxvaldigits/BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation.java
new file mode 100644
index 0000000..404a160
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/javaxvaldigits/BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation.java
@@ -0,0 +1,51 @@
+/*
+ *  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.isis.core.progmodel.facets.properties.javaxvaldigits;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
+
+
+public class BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation extends FacetAbstract implements BigDecimalValueFacet {
+
+    private final int length;
+    private final int scale;
+
+    public static Class<? extends Facet> type() {
+        return BigDecimalValueFacet.class;
+    }
+
+    public BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation(final FacetHolder holder, final Integer length, final Integer scale) {
+        super(BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation.type(), holder, Derivation.NOT_DERIVED);
+        this.length = length;
+        this.scale = scale;
+    }
+
+    @Override
+    public Integer getLength() {
+        return length;
+    }
+
+    @Override
+    public Integer getScale() {
+        return scale;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/javaxvaldigits/BigDecimalForPropertyDerivedFromJavaxValidationDigitsFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/javaxvaldigits/BigDecimalForPropertyDerivedFromJavaxValidationDigitsFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/javaxvaldigits/BigDecimalForPropertyDerivedFromJavaxValidationDigitsFacetFactory.java
new file mode 100644
index 0000000..88dae81
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/javaxvaldigits/BigDecimalForPropertyDerivedFromJavaxValidationDigitsFacetFactory.java
@@ -0,0 +1,59 @@
+/*
+ *  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.isis.core.progmodel.facets.properties.javaxvaldigits;
+
+import java.math.BigDecimal;
+
+import javax.validation.constraints.Digits;
+
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.progmodel.facets.value.bigdecimal.BigDecimalValueFacet;
+
+public class BigDecimalForPropertyDerivedFromJavaxValidationDigitsFacetFactory extends FacetFactoryAbstract {
+
+    public BigDecimalForPropertyDerivedFromJavaxValidationDigitsFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+
+        if (BigDecimal.class != processMethodContext.getMethod().getReturnType()) {
+            return;
+        }
+
+        final Digits annotation = Annotations.getAnnotation(processMethodContext.getMethod(), Digits.class);
+        if (annotation == null) {
+            return;
+        }
+        FacetUtil.addFacet(create(processMethodContext, annotation));
+    }
+
+    private BigDecimalValueFacet create(final ProcessMethodContext processMethodContext, final Digits annotation) {
+        final FacetedMethod holder = processMethodContext.getFacetHolder();
+        final int length = annotation.integer() + annotation.fraction();
+        final int scale = annotation.fraction();
+        return new BigDecimalFacetForPropertyFromJavaxValidationDigitsAnnotation(holder, length, scale);
+    }    
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/bigdecimal/BigDecimalValueFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/bigdecimal/BigDecimalValueFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/bigdecimal/BigDecimalValueFacet.java
index 710d4c1..7388f7b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/bigdecimal/BigDecimalValueFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/bigdecimal/BigDecimalValueFacet.java
@@ -23,8 +23,30 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
 
 public interface BigDecimalValueFacet extends Facet {
 
+    /**
+     * Maximum length of digits for this decimal.
+     * 
+     * <p>
+     * For example:
+     * <ul>
+     * <li><tt>12345.789</tt> has a length of 8 (and a {@link #getScale() scale} of 3)</li>
+     * <li><tt>12345</tt> has a length of 5 (and {@link #getScale() scale} of 0)</li>
+     * <li><tt>12345.0</tt> has a length of 6 (and {@link #getScale() scale} of 1)</li>
+     * </ul>
+     */
     Integer getLength();
     
+    /**
+     * The number of digits to the right of the decimal place (fractional part) for this decimal.
+     * 
+     * <p>
+     * For example:
+     * <ul>
+     * <li><tt>12345.789</tt> has scale of 3 (and a {@link #getLength() length} of 8)</li>
+     * <li><tt>12345</tt> has a scale of 0 (and a {@link #getLength() length} of 5)</li>
+     * <li><tt>12345.0</tt> has a scale of 1 (and a {@link #getLength() length} of 6)</li>
+     * </ul>
+     */
     Integer getScale();
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/7d81325f/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index 03c3694..b8c6967 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -132,10 +132,10 @@ import org.apache.isis.core.progmodel.facets.param.autocomplete.ActionParameterA
 import org.apache.isis.core.progmodel.facets.param.choices.enums.ParameterChoicesFacetDerivedFromChoicesFacetFacetFactory;
 import org.apache.isis.core.progmodel.facets.param.choices.method.ActionChoicesFacetFactory;
 import org.apache.isis.core.progmodel.facets.param.choices.methodnum.ActionParameterChoicesFacetFactory;
-import org.apache.isis.core.progmodel.facets.param.decimal.BigDecimalForParameterDerivedFromDecimalAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.param.defaults.fromtype.ParameterDefaultDerivedFromTypeFacetFactory;
 import org.apache.isis.core.progmodel.facets.param.defaults.methodnum.ActionParameterDefaultsFacetFactory;
 import org.apache.isis.core.progmodel.facets.param.describedas.annotation.DescribedAsAnnotationOnParameterFacetFactory;
+import org.apache.isis.core.progmodel.facets.param.javaxvaldigits.BigDecimalForParameterDerivedFromJavaxValidationAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.param.mandatory.annotation.OptionalAnnotationForParameterFacetFactory;
 import org.apache.isis.core.progmodel.facets.param.mandatory.dflt.MandatoryDefaultForParametersFacetFactory;
 import org.apache.isis.core.progmodel.facets.param.multiline.annotation.MultiLineAnnotationOnParameterFacetFactory;
@@ -151,11 +151,11 @@ import org.apache.isis.core.progmodel.facets.properties.accessor.PropertyAccesso
 import org.apache.isis.core.progmodel.facets.properties.autocomplete.PropertyAutoCompleteFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.choices.enums.PropertyChoicesFacetDerivedFromChoicesFacetFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.choices.method.PropertyChoicesFacetFactory;
-import org.apache.isis.core.progmodel.facets.properties.decimal.BigDecimalForPropertyDerivedFromDecimalAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.defaults.fromtype.PropertyDefaultDerivedFromTypeFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.defaults.method.PropertyDefaultFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.disabled.fromimmutable.DisabledFacetForPropertyDerivedFromImmutableTypeFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.event.PostsPropertyChangedEventAnnotationFacetFactory;
+import org.apache.isis.core.progmodel.facets.properties.javaxvaldigits.BigDecimalForPropertyDerivedFromJavaxValidationDigitsFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.mandatory.annotation.MandatoryAnnotationForPropertyFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.mandatory.annotation.OptionalAnnotationForPropertyFacetFactory;
 import org.apache.isis.core.progmodel.facets.properties.mandatory.dflt.MandatoryDefaultForPropertiesFacetFactory;
@@ -333,8 +333,8 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         addFactory(DescribedAsOnMemberFacetFactory.class);
         addFactory(DescribedAsAnnotationOnParameterFacetFactory.class);
         
-        addFactory(BigDecimalForParameterDerivedFromDecimalAnnotationFacetFactory.class);
-        addFactory(BigDecimalForPropertyDerivedFromDecimalAnnotationFacetFactory.class);
+        addFactory(BigDecimalForParameterDerivedFromJavaxValidationAnnotationFacetFactory.class);
+        addFactory(BigDecimalForPropertyDerivedFromJavaxValidationDigitsFacetFactory.class);
 
         addFactory(DisabledFacetFactory.class);
         addFactory(EncodableAnnotationFacetFactory.class);