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 2017/05/15 07:36:12 UTC

[12/12] isis git commit: ISIS-1613: stuff

ISIS-1613: stuff


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

Branch: refs/heads/ISIS-1613
Commit: 054e07c0b217fc81a41360a6964868cf30ad245e
Parents: 3448973
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat May 13 06:38:29 2017 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Mon May 15 08:35:41 2017 +0100

----------------------------------------------------------------------
 .../applib/layout/component/component.xsd       |   1 +
 .../apache/isis/applib/annotation/Property.java |  13 +-
 .../isis/applib/annotation/PropertyLayout.java  |  25 ++
 .../layout/component/PropertyLayoutData.java    |  12 +
 .../metamodel/adapter/mgr/AdapterManager.java   |  32 +-
 .../PropertyLayoutFacetFactory.java             |  17 +-
 ...hangingFacetForPropertyLayoutAnnotation.java |  41 +++
 .../UnchangingFacetForPropertyXml.java          |  42 +++
 ...gingFacetOnPropertyFromLayoutProperties.java |  49 +++
 .../renderunchanged/UnchangingFacet.java        |  30 ++
 .../UnchangingFacetAbstract.java                |  36 ++
 .../grid/GridSystemServiceAbstract.java         |   3 +
 core/viewer-wicket-impl/pom.xml                 |   6 +-
 .../wicket/viewer/IsisWicketApplication.java    |  33 ++
 .../model/mementos/ObjectAdapterMemento.java    |   2 +-
 .../viewer/wicket/model/models/ActionModel.java |  26 +-
 .../viewer/wicket/model/models/EntityModel.java |   5 +-
 .../wicket/model/models/FormExecutor.java       |   7 +-
 .../viewer/wicket/model/models/ScalarModel.java |  70 ++--
 .../entityactions/EntityActionLinkFactory.java  |  21 +-
 .../entityactions/LinkAndLabelUtil.java         |   7 +-
 .../actionmenu/serviceactions/CssMenuItem.java  |   4 +-
 .../ServiceActionLinkFactory.java               |   8 +-
 .../serviceactions/ServiceActionUtil.java       |  33 +-
 .../ui/components/actions/ActionPanel.java      |   7 +-
 .../actions/ActionParametersFormExecutor.java   | 239 +++-----------
 .../collection/bulk/BulkActionsLinkFactory.java |  19 +-
 .../property/FormExecutorAbstract.java          | 330 +++++++++++++++++++
 .../property/PropertyEditFormExecutor.java      | 235 +++----------
 .../components/property/PropertyEditPanel.java  |  18 +-
 .../property/PropertyEditPromptHeaderPanel.java |   4 +-
 .../components/scalars/ScalarPanelAbstract.java |   3 +-
 .../scalars/ScalarPanelAbstract2.java           |  54 +--
 .../scalars/ScalarPanelTextFieldAbstract.java   |   4 +-
 .../StandaloneCollectionPanel.java              |   2 +-
 .../widgets/linkandlabel/ActionLinkFactory.java |   3 +-
 .../linkandlabel/ActionLinkFactoryAbstract.java |   8 +-
 .../viewer/wicket/ui/pages/home/HomePage.java   |   5 +-
 .../ui/panels/PromptFormPanelAbstract.java      | 108 +++---
 39 files changed, 989 insertions(+), 573 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/adocs/documentation/src/main/asciidoc/applib/layout/component/component.xsd
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/applib/layout/component/component.xsd b/adocs/documentation/src/main/asciidoc/applib/layout/component/component.xsd
index a83d9dd..43603d7 100644
--- a/adocs/documentation/src/main/asciidoc/applib/layout/component/component.xsd
+++ b/adocs/documentation/src/main/asciidoc/applib/layout/component/component.xsd
@@ -75,6 +75,7 @@
 
     <xs:attribute name="renderedAsDayBefore" type="xs:boolean"/>
     <xs:attribute name="typicalLength" type="xs:int"/>
+    <xs:attribute name="unchanging" type="xs:boolean"/>
   </xs:complexType>
 
   <xs:complexType name="collection">

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
index 52cac59..d4377ee 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
@@ -19,14 +19,19 @@
 
 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;
+
+import javax.jdo.annotations.NotPersistent;
+
 import org.apache.isis.applib.services.eventbus.PropertyDomainEvent;
 import org.apache.isis.applib.spec.Specification;
 import org.apache.isis.applib.value.Blob;
 import org.apache.isis.applib.value.Clob;
 
-import javax.jdo.annotations.NotPersistent;
-import java.lang.annotation.*;
-
 /**
  * Domain semantics for domain object property.
  */
@@ -118,8 +123,6 @@ public @interface Property {
 
 
 
-
-
     /**
      * Whether the property edit should be published.
      *

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java
index dae0a20..e7d0328 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java
@@ -108,5 +108,30 @@ public @interface PropertyLayout {
      * The typical entry length of a field, use to determine the optimum width for display
      */
     int typicalLength() default -1;
+
+    /**
+     * Indicates that the value held by the property never changes over time, even when other properties of the object
+     * do change.
+     *
+     * <p>
+     *     Setting this attribute to <tt>true</tt> is used as a hint to the viewer to not redraw the property
+     *     after an AJAX update of some other property/ies of the object have changed.
+     *     This is primarily for performance, eg can improve the user experience when rendering PDFs/blobs.
+     * </p>
+     *
+     * <p>
+     *     Note that for this to work, the viewer will also ensure that none of the property's parent component
+     *     (such as a tab group panel) are re-rendered.
+     * </p>
+     *
+     * <p>
+     *     Design note: we considered implementing this an "immutable" flag on the {@link Property } annotation
+     *     (because this flag is typically appropriate for immutable/unchanging properties of a domain object).
+     *     However, we decided not to do that, on the basis that it might be interpreted as having a deeper impact
+     *     within the framework than simply a hint for rendering.
+     * </p>
+     */
+    boolean unchanging() default false;
+
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java
index 9388740..3e6cad5 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java
@@ -210,6 +210,18 @@ public class PropertyLayoutData
     }
 
 
+    private Boolean unchanging;
+
+    @XmlAttribute(required = false)
+    public Boolean getUnchanging() {
+        return unchanging;
+    }
+
+    public void setUnchanging(Boolean unchanging) {
+        this.unchanging = unchanging;
+    }
+
+
 
     private List<ActionLayoutData> actions = Lists.newArrayList();
 

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
index 334eb08..ffcc8c8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
@@ -72,7 +72,7 @@ public interface AdapterManager extends AdapterManagerBase {
         };
 
         /**
-         * Whether concurrency checking is currently disabled.
+         * Whether concurrency checking is currently enabled or disabled.
          */
         public static boolean isCurrentlyEnabled() {
             return concurrencyChecking.get().isChecking();
@@ -82,15 +82,37 @@ public interface AdapterManager extends AdapterManagerBase {
          * Allows a caller to temporarily disable concurrency checking for the current thread.
          */
         public static <T> T executeWithConcurrencyCheckingDisabled(final Callable<T> callable) {
-            final ConcurrencyChecking prior = ConcurrencyChecking.concurrencyChecking.get();
+            ConcurrencyChecking prior = null;
             try {
-                ConcurrencyChecking.concurrencyChecking.set(ConcurrencyChecking.NO_CHECK);
+                prior = disable();
                 return callable.call();
             } catch(Exception ex) {
                 throw new RuntimeException(ex);
             } finally {
-                ConcurrencyChecking.concurrencyChecking.set(prior);
+                reset(prior);
+            }
+        }
+
+        /**
+         * Recommended instead to call {@link #executeWithConcurrencyCheckingDisabled(Runnable)} or {@link #executeWithConcurrencyCheckingDisabled(Callable)}.
+         *
+         * <p>
+         *     If this method is used, then make sure to call {@link #reset(ConcurrencyChecking)} afterwards, using the value returned by this method.
+         * </p>
+         *
+         * @return the value of the {@link ConcurrencyChecking} thread-local prior to disabling it (to allow for nested calls).
+         */
+        public static ConcurrencyChecking disable() {
+            final ConcurrencyChecking prior = ConcurrencyChecking.concurrencyChecking.get();
+            ConcurrencyChecking.concurrencyChecking.set(ConcurrencyChecking.NO_CHECK);
+            return prior;
+        }
+
+        public static void reset(ConcurrencyChecking prior) {
+            if(prior == null) {
+                return;
             }
+            ConcurrencyChecking.concurrencyChecking.set(prior);
         }
 
         /**
@@ -99,7 +121,7 @@ public interface AdapterManager extends AdapterManagerBase {
         public static void executeWithConcurrencyCheckingDisabled(final Runnable runnable) {
             final ConcurrencyChecking prior = ConcurrencyChecking.concurrencyChecking.get();
             try {
-                ConcurrencyChecking.concurrencyChecking.set(ConcurrencyChecking.NO_CHECK);
+                disable();
                 runnable.run();
             } finally {
                 ConcurrencyChecking.concurrencyChecking.set(prior);

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/PropertyLayoutFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/PropertyLayoutFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/PropertyLayoutFacetFactory.java
index 985395e..229a7c4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/PropertyLayoutFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/PropertyLayoutFacetFactory.java
@@ -34,11 +34,12 @@ import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
 import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
+import org.apache.isis.core.metamodel.facets.object.promptStyle.PromptStyleFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.labelat.LabelAtFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.multiline.MultiLineFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.renderedadjusted.RenderedAdjustedFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
-import org.apache.isis.core.metamodel.facets.object.promptStyle.PromptStyleFacet;
+import org.apache.isis.core.metamodel.facets.properties.renderunchanged.UnchangingFacet;
 
 public class PropertyLayoutFacetFactory extends FacetFactoryAbstract implements ContributeeMemberFacetFactory {
 
@@ -70,6 +71,8 @@ public class PropertyLayoutFacetFactory extends FacetFactoryAbstract implements
         processRenderedAdjusted(holder, properties, propertyLayout);
 
         processTypicalLength(holder, properties, propertyLayout);
+
+        processUnchanging(holder, properties, propertyLayout);
     }
 
     void processCssClass(final FacetHolder holder, final Properties properties, final PropertyLayout propertyLayout) {
@@ -161,6 +164,18 @@ public class PropertyLayoutFacetFactory extends FacetFactoryAbstract implements
         FacetUtil.addFacet(typicalLengthFacet);
     }
 
+    void processUnchanging(
+            final FacetHolder holder,
+            final Properties properties,
+            final PropertyLayout propertyLayout) {
+        UnchangingFacet unchangingFacet = UnchangingFacetOnPropertyFromLayoutProperties
+                .create(properties, holder);
+        if(unchangingFacet == null) {
+            unchangingFacet = UnchangingFacetForPropertyLayoutAnnotation.create(propertyLayout, holder);
+        }
+        FacetUtil.addFacet(unchangingFacet);
+    }
+
     @Override
     public void process(ProcessContributeeMemberContext processMemberContext) {
         final FacetHolder holder = processMemberContext.getFacetHolder();

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetForPropertyLayoutAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetForPropertyLayoutAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetForPropertyLayoutAnnotation.java
new file mode 100644
index 0000000..f9f5142
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetForPropertyLayoutAnnotation.java
@@ -0,0 +1,41 @@
+/*
+ *  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.metamodel.facets.properties.propertylayout;
+
+import org.apache.isis.applib.annotation.PropertyLayout;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.properties.renderunchanged.UnchangingFacet;
+import org.apache.isis.core.metamodel.facets.properties.renderunchanged.UnchangingFacetAbstract;
+
+public class UnchangingFacetForPropertyLayoutAnnotation extends UnchangingFacetAbstract {
+
+    public static UnchangingFacet create(PropertyLayout propertyLayout, FacetHolder holder) {
+        if(propertyLayout == null) {
+            return null;
+        }
+        final boolean isUnchanging = propertyLayout.unchanging();
+        return new UnchangingFacetForPropertyLayoutAnnotation(isUnchanging, holder);
+    }
+
+    private UnchangingFacetForPropertyLayoutAnnotation(final boolean unchanging, FacetHolder holder) {
+        super(unchanging, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetForPropertyXml.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetForPropertyXml.java
new file mode 100644
index 0000000..07eb82a
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetForPropertyXml.java
@@ -0,0 +1,42 @@
+/*
+ *  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.metamodel.facets.properties.propertylayout;
+
+import org.apache.isis.applib.layout.component.PropertyLayoutData;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.properties.renderunchanged.UnchangingFacet;
+import org.apache.isis.core.metamodel.facets.properties.renderunchanged.UnchangingFacetAbstract;
+
+public class UnchangingFacetForPropertyXml extends UnchangingFacetAbstract {
+
+    public static UnchangingFacet create(final PropertyLayoutData propertyLayout, FacetHolder holder) {
+        if(propertyLayout == null) {
+            return null;
+        }
+        final Boolean unchanging = propertyLayout.getUnchanging();
+        final boolean isUnchanging = unchanging != null && unchanging;
+        return new UnchangingFacetForPropertyXml(isUnchanging, holder);
+    }
+
+    private UnchangingFacetForPropertyXml(final boolean unchanging, FacetHolder holder) {
+        super(unchanging, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetOnPropertyFromLayoutProperties.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetOnPropertyFromLayoutProperties.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetOnPropertyFromLayoutProperties.java
new file mode 100644
index 0000000..1e80ef1
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/UnchangingFacetOnPropertyFromLayoutProperties.java
@@ -0,0 +1,49 @@
+/*
+ *  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.metamodel.facets.properties.propertylayout;
+
+import java.util.Properties;
+
+import com.google.common.base.Strings;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.properties.renderunchanged.UnchangingFacet;
+import org.apache.isis.core.metamodel.facets.properties.renderunchanged.UnchangingFacetAbstract;
+
+public class UnchangingFacetOnPropertyFromLayoutProperties extends UnchangingFacetAbstract {
+
+    public static UnchangingFacet create(Properties properties, FacetHolder holder) {
+        final boolean isUnchanging = unchanging(properties);
+        return new UnchangingFacetOnPropertyFromLayoutProperties(isUnchanging, holder);
+    }
+
+    private UnchangingFacetOnPropertyFromLayoutProperties(final boolean isUnchanging, FacetHolder holder) {
+        super(isUnchanging, holder);
+    }
+
+    private static boolean unchanging(Properties properties) {
+        if(properties == null) {
+            return false;
+        }
+        String unchanging = Strings.emptyToNull(properties.getProperty("unchanging"));
+        return unchanging != null && Boolean.parseBoolean(unchanging);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/renderunchanged/UnchangingFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/renderunchanged/UnchangingFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/renderunchanged/UnchangingFacet.java
new file mode 100644
index 0000000..549b8d1
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/renderunchanged/UnchangingFacet.java
@@ -0,0 +1,30 @@
+/*
+ *  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.metamodel.facets.properties.renderunchanged;
+
+import org.apache.isis.core.metamodel.facets.SingleValueFacet;
+
+/**
+ * Whether a property should NOT be re-rendered (because it is unchanged) even if other properties of a domain object
+ * have changed.
+ */
+public interface UnchangingFacet extends SingleValueFacet<Boolean> {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/renderunchanged/UnchangingFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/renderunchanged/UnchangingFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/renderunchanged/UnchangingFacetAbstract.java
new file mode 100644
index 0000000..15d5f28
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/renderunchanged/UnchangingFacetAbstract.java
@@ -0,0 +1,36 @@
+/*
+ *  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.metamodel.facets.properties.renderunchanged;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
+
+public abstract class UnchangingFacetAbstract extends SingleValueFacetAbstract<Boolean> implements UnchangingFacet {
+
+    public static Class<? extends Facet> type() {
+        return UnchangingFacet.class;
+    }
+
+    public UnchangingFacetAbstract(final Boolean value, final FacetHolder holder) {
+        super(type(), value, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
index 344d1f1..c4baf66 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
@@ -103,6 +103,7 @@ import org.apache.isis.core.metamodel.facets.properties.propertylayout.NamedFace
 import org.apache.isis.core.metamodel.facets.properties.propertylayout.PromptStyleFacetForPropertyXml;
 import org.apache.isis.core.metamodel.facets.properties.propertylayout.RenderedAdjustedFacetForPropertyXml;
 import org.apache.isis.core.metamodel.facets.properties.propertylayout.TypicalLengthFacetForPropertyXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.UnchangingFacetForPropertyXml;
 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.ObjectAction;
@@ -316,6 +317,8 @@ public abstract class GridSystemServiceAbstract<G extends Grid> implements GridS
                         PromptStyleFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
                 FacetUtil.addOrReplaceFacet(
                         RenderedAdjustedFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+                FacetUtil.addOrReplaceFacet(
+                        UnchangingFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
                 FacetUtil.addOrReplaceFacet(TypicalLengthFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
 
                 // @MemberOrder#name based on owning property group, @MemberOrder#sequence monotonically increasing

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-impl/pom.xml
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-impl/pom.xml b/core/viewer-wicket-impl/pom.xml
index 4b7b325..2e3068a 100644
--- a/core/viewer-wicket-impl/pom.xml
+++ b/core/viewer-wicket-impl/pom.xml
@@ -94,6 +94,10 @@
 			<groupId>de.agilecoders.wicket</groupId>
 			<artifactId>wicket-bootstrap-core</artifactId>
 		</dependency>
-	</dependencies>
+        <dependency>
+            <groupId>org.apache.wicket</groupId>
+            <artifactId>wicket-core</artifactId>
+        </dependency>
+    </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index f86303e..2d41a93 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -35,11 +35,14 @@ import com.google.inject.Injector;
 import com.google.inject.Module;
 
 import org.apache.wicket.Application;
+import org.apache.wicket.Component;
 import org.apache.wicket.ConverterLocator;
 import org.apache.wicket.IConverterLocator;
 import org.apache.wicket.Page;
 import org.apache.wicket.RuntimeConfigurationType;
 import org.apache.wicket.SharedResources;
+import org.apache.wicket.application.IComponentOnAfterRenderListener;
+import org.apache.wicket.application.IComponentOnBeforeRenderListener;
 import org.apache.wicket.authentication.IAuthenticationStrategy;
 import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
@@ -66,6 +69,7 @@ import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.commons.config.IsisConfigurationDefault;
 import org.apache.isis.core.commons.configbuilder.IsisConfigurationBuilder;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelInvalidException;
 import org.apache.isis.core.runtime.logging.IsisLoggingConfigurer;
@@ -313,6 +317,10 @@ public class IsisWicketApplication
             @SuppressWarnings("unused")
             SharedResources sharedResources = getSharedResources();
 
+            final DisableConcurrencyCheckingOnRenderListener listenr = new DisableConcurrencyCheckingOnRenderListener();
+            getComponentPreOnBeforeRenderListeners().add(listenr);
+            getComponentOnAfterRenderListeners().add(listenr);
+            
             final MetaModelInvalidException mmie = IsisContext.getMetaModelInvalidExceptionIfAny();
             if(mmie != null) {
                 log(mmie.getValidationErrors());
@@ -870,4 +878,29 @@ public class IsisWicketApplication
         return settings;
     }
 
+    private static class DisableConcurrencyCheckingOnRenderListener
+            implements IComponentOnAfterRenderListener, IComponentOnBeforeRenderListener {
+
+        private static ThreadLocal<AdapterManager.ConcurrencyChecking> concurrencyChecking =
+                new ThreadLocal<AdapterManager.ConcurrencyChecking>() {
+                    protected AdapterManager.ConcurrencyChecking initialValue() {
+                        return null;
+                    }
+                };
+
+        @Override
+        public void onBeforeRender(final Component component) {
+            final AdapterManager.ConcurrencyChecking prior = AdapterManager.ConcurrencyChecking.disable();
+            concurrencyChecking.set(prior);
+        }
+
+        @Override
+        public void onAfterRender(final Component component) {
+            final AdapterManager.ConcurrencyChecking prior = DisableConcurrencyCheckingOnRenderListener.concurrencyChecking.get();
+            if(prior != null) {
+                AdapterManager.ConcurrencyChecking.reset(prior);
+            }
+            DisableConcurrencyCheckingOnRenderListener.concurrencyChecking.remove();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
index 3f2bc86..1b1c5c5 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
@@ -254,7 +254,7 @@ public class ObjectAdapterMemento implements Serializable {
 
             @Override
             public void resetVersion(
-                    ObjectAdapterMemento oam,
+                    final ObjectAdapterMemento oam,
                     final PersistenceSession persistenceSession,
                     final SpecificationLoader specificationLoader) {
                 // REVIEW: this may be redundant because recreateAdapter also guarantees the version will be reset.

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index f853ae2..f9a8240 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -114,15 +114,14 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> implements For
 
 
     /**
-     * @param objectAdapter
+     * @param entityModel
      * @param action
      * @return
      */
-    public static ActionModel create(final ObjectAdapter objectAdapter, final ObjectAction action) {
-        final ObjectAdapterMemento serviceMemento = ObjectAdapterMemento.Functions.fromAdapter().apply(objectAdapter);
+    public static ActionModel create(final EntityModel entityModel, final ObjectAction action) {
         final ActionMemento homePageActionMemento = ObjectAdapterMemento.Functions.fromAction().apply(action);
         final Mode mode = action.getParameterCount() > 0? Mode.PARAMETERS : Mode.RESULTS;
-        return new ActionModel(serviceMemento, homePageActionMemento, mode);
+        return new ActionModel(entityModel, homePageActionMemento, mode);
     }
 
     public static ActionModel createForPersistent(
@@ -270,7 +269,7 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> implements For
         return action.getParameterCount() > 0 ? Mode.PARAMETERS : Mode.RESULTS;
     }
 
-    private final ObjectAdapterMemento targetAdapterMemento;
+    private final EntityModel entityModel;
     private final ActionMemento actionMemento;
     private Mode actionMode;
 
@@ -281,7 +280,7 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> implements For
 
 
     private ActionModel(final PageParameters pageParameters, final SpecificationLoader specificationLoader) {
-        this(newObjectAdapterMementoFrom(pageParameters), newActionMementoFrom(pageParameters, specificationLoader), actionModeFrom(pageParameters,
+        this(newEntityModelFrom(pageParameters), newActionMementoFrom(pageParameters, specificationLoader), actionModeFrom(pageParameters,
                 specificationLoader));
 
         setArgumentsIfPossible(pageParameters);
@@ -309,12 +308,12 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> implements For
     }
 
 
-    private static ObjectAdapterMemento newObjectAdapterMementoFrom(final PageParameters pageParameters) {
+    private static EntityModel newEntityModelFrom(final PageParameters pageParameters) {
         final RootOid oid = oidFor(pageParameters);
         if(oid.isTransient()) {
             return null;
         } else {
-            return ObjectAdapterMemento.createPersistent(oid);
+            return new EntityModel(ObjectAdapterMemento.createPersistent(oid));
         }
     }
 
@@ -324,8 +323,8 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> implements For
     }
 
 
-    private ActionModel(final ObjectAdapterMemento adapterMemento, final ActionMemento actionMemento, final Mode actionMode) {
-        this.targetAdapterMemento = adapterMemento;
+    private ActionModel(final EntityModel entityModel, final ActionMemento actionMemento, final Mode actionMode) {
+        this.entityModel = entityModel;
         this.actionMemento = actionMemento;
         this.actionMode = actionMode;
     }
@@ -334,7 +333,7 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> implements For
      * Copy constructor, as called by {@link #copy()}.
      */
     private ActionModel(final ActionModel actionModel) {
-        this.targetAdapterMemento = actionModel.targetAdapterMemento;
+        this.entityModel = actionModel.entityModel;
         this.actionMemento = actionModel.actionMemento;
         this.actionMode = actionModel.actionMode;
         //this.actionPrompt = actionModel.actionPrompt;
@@ -438,7 +437,7 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> implements For
         final int i = apm.getNumber();
 		ActionArgumentModel actionArgumentModel = arguments.get(i);
         if (actionArgumentModel == null) {
-            actionArgumentModel = new ScalarModel(targetAdapterMemento, apm);
+            actionArgumentModel = new ScalarModel(entityModel, apm);
             final int number = actionArgumentModel.getParameterMemento().getNumber();
             arguments.put(number, actionArgumentModel);
         }
@@ -446,8 +445,7 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> implements For
     }
 
     public ObjectAdapter getTargetAdapter() {
-        return targetAdapterMemento.getObjectAdapter(getConcurrencyChecking(), getPersistenceSession(),
-                getSpecificationLoader());
+        return entityModel.load(getConcurrencyChecking());
     }
 
     protected ConcurrencyChecking getConcurrencyChecking() {

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
index 8b2bca3..1a25674 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
@@ -347,7 +347,8 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> implements UiH
      */
     @Override
     public ObjectAdapter load() {
-        return load(ConcurrencyChecking.CHECK);
+        final ObjectAdapter objectAdapter = load(ConcurrencyChecking.CHECK);
+        return objectAdapter;
     }
 
 
@@ -379,7 +380,7 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> implements UiH
     public ScalarModel getPropertyModel(final PropertyMemento pm) {
         ScalarModel scalarModel = propertyScalarModels.get(pm);
         if (scalarModel == null) {
-            scalarModel = new ScalarModel(getObjectAdapterMemento(), pm);
+            scalarModel = new ScalarModel(this, pm);
             if (isViewMode()) {
                 scalarModel.toViewMode();
             } else {

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/FormExecutor.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/FormExecutor.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/FormExecutor.java
index 2f33bbc..6eec674 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/FormExecutor.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/FormExecutor.java
@@ -24,6 +24,8 @@ import java.io.Serializable;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.form.Form;
 
+import org.apache.isis.applib.annotation.PromptStyle;
+
 /**
  * Passed through the {@link ActionModel} or {@link ScalarModel}, allowing
  * two different Wicket UI components (eg owning <code>ActionPanel</code> and
@@ -37,5 +39,8 @@ import org.apache.wicket.markup.html.form.Form;
  */
 public interface FormExecutor extends Serializable {
 
-    boolean executeAndProcessResults(AjaxRequestTarget target, Form<?> feedbackForm);
+    boolean executeAndProcessResults(
+            AjaxRequestTarget target,
+            Form<?> feedbackForm,
+            PromptStyle promptStyle);
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
index 209a4c9..112621c 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
@@ -92,15 +92,17 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
 
             @Override
             public String getLongName(final ScalarModel scalarModel) {
-                ObjectSpecId objectSpecId = scalarModel.parentObjectAdapterMemento.getObjectSpecId();
+
+                ObjectSpecId objectSpecId =
+                        scalarModel.getParentEntityModel().getTypeOfSpecification().getSpecId();
+
                 final String specShortName = SpecUtils.getSpecificationFor(objectSpecId, scalarModel.getSpecificationLoader()).getShortIdentifier();
                 return specShortName + "-" + scalarModel.getPropertyMemento().getProperty(scalarModel.getSpecificationLoader()).getId();
             }
 
             @Override
             public String disable(final ScalarModel scalarModel, final Where where) {
-                final ObjectAdapter parentAdapter = scalarModel.parentObjectAdapterMemento.getObjectAdapter(
-                        ConcurrencyChecking.CHECK, scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
                 final OneToOneAssociation property = scalarModel.getPropertyMemento().getProperty(scalarModel.getSpecificationLoader());
                 try {
                     final Consent usable = property.isUsable(parentAdapter, InteractionInitiatedBy.USER, where);
@@ -118,8 +120,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                     parseableFacet = property.getSpecification().getFacet(ParseableFacet.class);
                 }
                 try {
-                    final ObjectAdapter parentAdapter = scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK,
-                            scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+                    final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
                     final ObjectAdapter currentValue = property.get(parentAdapter, InteractionInitiatedBy.USER);
                     final ObjectAdapter proposedAdapter =
                             parseableFacet.parseTextEntry(currentValue, proposedPojoAsStr, InteractionInitiatedBy.USER);
@@ -137,8 +138,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
 
             @Override
             public String validate(final ScalarModel scalarModel, final ObjectAdapter proposedAdapter) {
-                final ObjectAdapter parentAdapter = scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK,
-                        scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
                 final OneToOneAssociation property = scalarModel.getPropertyMemento().getProperty(scalarModel.getSpecificationLoader());
                 try {
                     final Consent valid = property.isAssociationValid(parentAdapter, proposedAdapter,
@@ -176,8 +176,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                     final DeploymentCategory deploymentCategory) {
                 final PropertyMemento propertyMemento = scalarModel.getPropertyMemento();
                 final OneToOneAssociation property = propertyMemento.getProperty(scalarModel.getSpecificationLoader());
-                ObjectAdapter parentAdapter = scalarModel.parentObjectAdapterMemento
-                        .getObjectAdapter(ConcurrencyChecking.NO_CHECK, scalarModel.getPersistenceSession(),
+                ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load(ConcurrencyChecking.NO_CHECK);
                                 scalarModel.getSpecificationLoader());
                 final ObjectAdapter[] choices = property.getChoices(
                         parentAdapter,
@@ -202,8 +201,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                 final PropertyMemento propertyMemento = scalarModel.getPropertyMemento();
                 final OneToOneAssociation property = propertyMemento.getProperty(scalarModel.getSpecificationLoader());
                 final ObjectAdapter parentAdapter =
-                        scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK,
-                                scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+                        scalarModel.getParentEntityModel().load(ConcurrencyChecking.NO_CHECK);
                 final ObjectAdapter[] choices =
                         property.getAutoComplete(
                                 parentAdapter, searchArg,
@@ -226,7 +224,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
             
             @Override
             public void resetVersion(ScalarModel scalarModel) {
-                scalarModel.parentObjectAdapterMemento.resetVersion(scalarModel.getPersistenceSession(),
+                scalarModel.getParentObjectAdapterMemento().resetVersion(scalarModel.getPersistenceSession(),
                         scalarModel.getSpecificationLoader());
             }
 
@@ -278,9 +276,9 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
             @Override
             public void reset(ScalarModel scalarModel) {
                 final OneToOneAssociation property = scalarModel.propertyMemento.getProperty(scalarModel.getSpecificationLoader());
-                final ObjectAdapter parentAdapter =
-                        scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK,
-                                scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+
+                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
+
                 final ObjectAdapter associatedAdapter =
                         property.get(parentAdapter, InteractionInitiatedBy.USER);
                 scalarModel.setObject(associatedAdapter);
@@ -336,8 +334,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                 final ObjectActionParameter parameter = scalarModel.getParameterMemento().getActionParameter(
                         scalarModel.getSpecificationLoader());
                 try {
-                    final ObjectAdapter parentAdapter = scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK,
-                            scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+                    final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
                     final String invalidReasonIfAny = parameter.isValid(parentAdapter, proposedPojoAsStr,
                             InteractionInitiatedBy.USER
                     );
@@ -352,8 +349,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                 final ObjectActionParameter parameter = scalarModel.getParameterMemento().getActionParameter(
                         scalarModel.getSpecificationLoader());
                 try {
-                    final ObjectAdapter parentAdapter = scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK,
-                            scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+                    final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
                     final String invalidReasonIfAny = parameter.isValid(parentAdapter, proposedAdapter.getObject(),
                             InteractionInitiatedBy.USER
                     );
@@ -391,9 +387,9 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                     final DeploymentCategory deploymentCategory) {
                 final ActionParameterMemento parameterMemento = scalarModel.getParameterMemento();
                 final ObjectActionParameter actionParameter = parameterMemento.getActionParameter(scalarModel.getSpecificationLoader());
-                final ObjectAdapter parentAdapter =
-                        scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK,
-                                scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+
+                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
+
                 final ObjectAdapter[] choices =
                         actionParameter.getChoices(
                                 parentAdapter, argumentsIfAvailable,
@@ -417,8 +413,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                 final ObjectActionParameter actionParameter = parameterMemento.getActionParameter(scalarModel.getSpecificationLoader());
 
                 final ObjectAdapter parentAdapter =
-                        scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK,
-                                scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+                        scalarModel.getParentEntityModel().load(ConcurrencyChecking.NO_CHECK);
                 final ObjectAdapter[] choices = actionParameter.getAutoComplete(
                         parentAdapter, searchArg,
                         InteractionInitiatedBy.USER);
@@ -491,8 +486,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                 final ObjectActionParameter actionParameter = scalarModel.parameterMemento.getActionParameter(
                         scalarModel.getSpecificationLoader());
                 final ObjectAdapter parentAdapter =
-                        scalarModel.parentObjectAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK,
-                                scalarModel.getPersistenceSession(), scalarModel.getSpecificationLoader());
+                        scalarModel.getParentEntityModel().load(ConcurrencyChecking.NO_CHECK);
                 final ObjectAdapter defaultAdapter = actionParameter.getDefault(parentAdapter);
                 scalarModel.setObject(defaultAdapter);
             }
@@ -602,7 +596,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
 
     private final Kind kind;
     
-    private final ObjectAdapterMemento parentObjectAdapterMemento;
+    private final EntityModel parentEntityModel;
 
     @Override
     public ObjectAdapter load() {
@@ -629,9 +623,9 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
      * object, with the {@link #getObject() value of this model} to be default
      * value (if any) of that action parameter.
      */
-    public ScalarModel(final ObjectAdapterMemento parentObjectAdapterMemento, final ActionParameterMemento apm) {
+    public ScalarModel(final EntityModel parentEntityModel, final ActionParameterMemento apm) {
         this.kind = Kind.PARAMETER;
-        this.parentObjectAdapterMemento = parentObjectAdapterMemento;
+        this.parentEntityModel = parentEntityModel;
         this.parameterMemento = apm;
 
         init();
@@ -643,13 +637,13 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
      * {@link #getObject() value of this model} to be current value of the
      * property.
      */
-    public ScalarModel(final ObjectAdapterMemento parentObjectAdapterMemento, final PropertyMemento pm) {
+    public ScalarModel(final EntityModel parentEntityModel, final PropertyMemento pm) {
         this.kind = Kind.PROPERTY;
-        this.parentObjectAdapterMemento = parentObjectAdapterMemento;
+        this.parentEntityModel = parentEntityModel;
         this.propertyMemento = pm;
 
         init();
-        getAndStore(parentObjectAdapterMemento);
+        getAndStore(parentEntityModel);
         setMode(Mode.VIEW);
     }
 
@@ -661,11 +655,16 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
         kind.reset(this);
     }
 
+    public EntityModel getParentEntityModel() {
+        return parentEntityModel;
+    }
+
     public ObjectAdapterMemento getParentObjectAdapterMemento() {
-        return parentObjectAdapterMemento;
+        return parentEntityModel.getObjectAdapterMemento();
     }
 
-    private void getAndStore(final ObjectAdapterMemento parentAdapterMemento) {
+    private void getAndStore(final EntityModel parentEntityModel) {
+        final ObjectAdapterMemento parentAdapterMemento = parentEntityModel.getObjectAdapterMemento();
         final OneToOneAssociation property = propertyMemento.getProperty(getSpecificationLoader());
         final ObjectAdapter parentAdapter = parentAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK,
                 getPersistenceSession(), getSpecificationLoader());
@@ -942,8 +941,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
     public String getReasonInvalidIfAny() {
         final OneToOneAssociation property = getPropertyMemento().getProperty(getSpecificationLoader());
 
-        final ObjectAdapter adapter = getParentObjectAdapterMemento().getObjectAdapter(ConcurrencyChecking.CHECK,
-                getPersistenceSession(), getSpecificationLoader());
+        final ObjectAdapter adapter = getParentEntityModel().load();
 
         final ObjectAdapter associate = getObject();
 

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
index 000d4cf..a221530 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
@@ -19,6 +19,8 @@
 
 package org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions;
 
+import java.util.Objects;
+
 import org.apache.wicket.markup.html.link.AbstractLink;
 
 import org.apache.isis.applib.annotation.Where;
@@ -37,22 +39,25 @@ public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
 
     private static final long serialVersionUID = 1L;
 
-    @SuppressWarnings("unused")
-    private final EntityModel entityModel;
-
     public EntityActionLinkFactory(final EntityModel entityModel, final ScalarModel scalarModelForAssociationIfAny) {
-        super(scalarModelForAssociationIfAny);
-        this.entityModel = entityModel;
+        super(entityModel, scalarModelForAssociationIfAny);
     }
 
     @Override
     public LinkAndLabel newLink(
             final String linkId,
-            final ObjectAdapterMemento adapterMemento,
+            final EntityModel entityModel,
+            final ObjectAdapterMemento adapterMementoUnused,
             final ObjectAction action) {
 
+        final ObjectAdapterMemento adapterMemento = entityModel.getObjectAdapterMemento();
+
+        if(!Objects.equals(entityModel, this.entityModel)) {
+            throw new IllegalStateException("mismatch! " + entityModel + " vs " + this.entityModel);
+        }
+
         final ObjectAdapter objectAdapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK,
-                entityModel.getPersistenceSession(), entityModel.getSpecificationLoader());
+                this.entityModel.getPersistenceSession(), this.entityModel.getSpecificationLoader());
         
         final Boolean persistent = objectAdapter.representsPersistent();
         if (!persistent) {
@@ -71,7 +76,7 @@ public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
         }
 
         
-        final AbstractLink link = newLink(linkId, objectAdapter, action);
+        final AbstractLink link = newLink(linkId, objectAdapter, this.entityModel, action);
         
         final Consent usability =
                 action.isUsable(

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
index e983335..31d0925 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
@@ -48,8 +48,7 @@ public final class LinkAndLabelUtil {
             return Collections.emptyList();
         }
 
-        final ObjectAdapterMemento parentMemento = scalarModelForAssociation.getParentObjectAdapterMemento();
-        final EntityModel parentEntityModel = new EntityModel(parentMemento);
+        final EntityModel parentEntityModel = scalarModelForAssociation.getParentEntityModel();
 
         final ObjectAdapter parentAdapter = parentEntityModel.load(AdapterManager.ConcurrencyChecking.NO_CHECK);
 
@@ -81,13 +80,13 @@ public final class LinkAndLabelUtil {
         final ActionLinkFactory linkFactory = new EntityActionLinkFactory(parentEntityModel, scalarModelForAssociationIfAny);
         final String linkId = AdditionalLinksPanel.ID_ADDITIONAL_LINK;
 
-        final ObjectAdapterMemento adapterMemento = parentEntityModel.getObjectAdapterMemento();
+        final ObjectAdapterMemento parentAdapterMemento = parentEntityModel.getObjectAdapterMemento();
         return FluentIterable.from(actions)
                 .transform(new Function<ObjectAction, LinkAndLabel>() {
 
                     @Override
                     public LinkAndLabel apply(ObjectAction objectAction) {
-                        return linkFactory.newLink(linkId, adapterMemento, objectAction);
+                        return linkFactory.newLink(linkId, parentEntityModel, parentAdapterMemento, objectAction);
                     }
                 })
                 .filter(Predicates.<LinkAndLabel>notNull())

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
index 998c366..08ef32a 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
@@ -323,8 +323,8 @@ class CssMenuItem implements Serializable {
 
         // build the link
         final LinkAndLabel linkAndLabel = actionLinkFactory.newLink(
-                PageAbstract.ID_MENU_LINK, targetAdapterMemento, objectAction
-        );
+                PageAbstract.ID_MENU_LINK, null, targetAdapterMemento,
+                objectAction);
         if (linkAndLabel == null) {
             // can only get a null if invisible, so this should not happen given guard above
             return null;

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
index 89657be..0bbed3e 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
@@ -30,26 +30,28 @@ import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactoryAbstract;
 
 class ServiceActionLinkFactory extends ActionLinkFactoryAbstract {
 
     private static final long serialVersionUID = 1L;
 
-    ServiceActionLinkFactory() {
-        super(null);
+    ServiceActionLinkFactory(final EntityModel serviceEntityModel) {
+        super(serviceEntityModel, null);
     }
 
     @Override
     public LinkAndLabel newLink(
             final String linkId,
+            final EntityModel entityModel,
             final ObjectAdapterMemento adapterMemento,
             final ObjectAction action) {
         
         ObjectAdapter objectAdapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK,
                 getPersistenceSession(), getSpecificationLoader());
 
-        final AbstractLink link = newLink(linkId, objectAdapter, action);
+        final AbstractLink link = newLink(linkId, objectAdapter, entityModel, action);
 
         return newLinkAndLabel(objectAdapter, action, link, null);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
index 4931ea2..904e6ae 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
@@ -48,6 +48,7 @@ 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.ObjectAction;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.ServiceActionsModel;
 import org.apache.isis.viewer.wicket.ui.components.actionmenu.CssClassFaBehavior;
 import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactory;
@@ -59,7 +60,7 @@ public final class ServiceActionUtil {
 
     private ServiceActionUtil(){}
 
-    private final static ActionLinkFactory linkAndLabelFactory = new ServiceActionLinkFactory();
+
 
     static void addLeafItem(final CssMenuItem menuItem, final ListItem<CssMenuItem> listItem, final MarkupContainer parent) {
         Fragment leafItem;
@@ -172,14 +173,23 @@ public final class ServiceActionUtil {
         private final String serviceName;
         private final ObjectAdapter serviceAdapter;
         private final ObjectAdapterMemento serviceAdapterMemento;
+        private final EntityModel serviceEntityModel;
         private final ObjectAction objectAction;
+        private final ServiceActionLinkFactory linkAndLabelFactory;
+
         public boolean separator;
 
-        LogicalServiceAction(final String serviceName, final ObjectAdapter serviceAdapter, final ObjectAction objectAction) {
+        LogicalServiceAction(
+                final String serviceName,
+                final ObjectAdapter serviceAdapter,
+                final EntityModel serviceEntityModel,
+                final ObjectAction objectAction) {
             this.serviceName = serviceName;
             this.serviceAdapter = serviceAdapter;
             this.serviceAdapterMemento = ObjectAdapterMemento.createOrNull(serviceAdapter);
+            this.serviceEntityModel = serviceEntityModel;
             this.objectAction = objectAction;
+            this.linkAndLabelFactory = new ServiceActionLinkFactory(serviceEntityModel);
         }
         @Override
         public String toString() {
@@ -203,7 +213,7 @@ public final class ServiceActionUtil {
         // prune any service names that have no service actions
         serviceNamesInOrder.retainAll(serviceActionsByName.keySet());
 
-        return buildMenuItems(serviceNamesInOrder, serviceActionsByName, linkAndLabelFactory);
+        return buildMenuItems(serviceNamesInOrder, serviceActionsByName);
     }
 
     /**
@@ -211,8 +221,7 @@ public final class ServiceActionUtil {
      */
     private static List<CssMenuItem> buildMenuItems(
             final Set<String> serviceNamesInOrder,
-            final Map<String, List<LogicalServiceAction>> serviceActionsByName,
-            final ActionLinkFactory actionLinkFactory) {
+            final Map<String, List<LogicalServiceAction>> serviceActionsByName) {
 
         final List<CssMenuItem> menuItems = Lists.newArrayList();
         for (String serviceName : serviceNamesInOrder) {
@@ -227,7 +236,10 @@ public final class ServiceActionUtil {
                 final ObjectAdapterMemento serviceAdapterMemento = logicalServiceAction.serviceAdapterMemento;
                 final ObjectAction objectAction = logicalServiceAction.objectAction;
                 final boolean separator = logicalServiceAction.separator;
-                final CssMenuItem.Builder subMenuItemBuilder = serviceMenuItem.newSubMenuItem(serviceAdapterMemento, objectAction, separator, actionLinkFactory);
+                final ActionLinkFactory actionLinkFactory = logicalServiceAction.linkAndLabelFactory;
+
+                final CssMenuItem.Builder subMenuItemBuilder =
+                        serviceMenuItem.newSubMenuItem(serviceAdapterMemento, objectAction, separator, actionLinkFactory);
                 if (subMenuItemBuilder == null) {
                     // not visible
                     continue;
@@ -247,7 +259,11 @@ public final class ServiceActionUtil {
     /**
      * Spin through all object actions of the service adapter, and add to the provided List of {@link LogicalServiceAction}s.
      */
-    private static void collateServiceActions(final ObjectAdapter serviceAdapter, ActionType actionType, List<LogicalServiceAction> serviceActions) {
+    private static void collateServiceActions(
+            final ObjectAdapter serviceAdapter,
+            final ActionType actionType,
+            final List<LogicalServiceAction> serviceActions) {
+
         final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
 
         // skip if annotated to not be included in repository menu using @DomainService
@@ -275,7 +291,8 @@ public final class ServiceActionUtil {
             if(Strings.isNullOrEmpty(serviceName)){
                 serviceName = serviceSpec.getFacet(NamedFacet.class).value();
             }
-            serviceActions.add(new LogicalServiceAction(serviceName, serviceAdapter, objectAction));
+            final EntityModel serviceModel = new EntityModel(serviceAdapter);
+            serviceActions.add(new LogicalServiceAction(serviceName, serviceAdapter, serviceModel, objectAction));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
index a5a53b6..0ace71f 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
@@ -140,9 +140,10 @@ public class ActionPanel extends PanelAbstract<ActionModel> {
         return header;
     }
 
-    private void buildGuiForNoParameters(final ActionModel actionModel) {
+    private void buildGuiForNoParameters(final ActionModel formExecutor) {
 
-        boolean succeeded = actionModel.getFormExecutor().executeAndProcessResults(null, null);
+        boolean succeeded = formExecutor.getFormExecutor().executeAndProcessResults(null, null,
+                formExecutor.getPromptStyle());
         if(succeeded) {
             // nothing to do
         } else {
@@ -152,7 +153,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> {
             // (One way this can occur is if an event subscriber has a defect and throws an exception; in which case
             // the EventBus' exception handler will automatically veto.  This results in a growl message rather than
             // an error page, but is probably 'good enough').
-            final ObjectAdapter targetAdapter = actionModel.getTargetAdapter();
+            final ObjectAdapter targetAdapter = formExecutor.getTargetAdapter();
 
             ActionResultResponse resultResponse = ActionResultResponseType.OBJECT.interpretResult(this.getActionModel(), targetAdapter, null);
             resultResponse.getHandlingStrategy().handleResults(this, resultResponse, getIsisSessionFactory());

http://git-wip-us.apache.org/repos/asf/isis/blob/054e07c0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormExecutor.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormExecutor.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormExecutor.java
index d74cb1d..69d17e3 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormExecutor.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormExecutor.java
@@ -1,195 +1,81 @@
 package org.apache.isis.viewer.wicket.ui.components.actions;
 
-import java.util.List;
-
-import com.google.common.base.Throwables;
-
 import org.apache.wicket.MarkupContainer;
 import org.apache.wicket.Session;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.form.Form;
-
-import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.command.CommandContext;
-import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
-import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerComposite;
-import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.commons.authentication.MessageBroker;
+
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
-import org.apache.isis.core.metamodel.services.ServicesInjector;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
-import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
-import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
 import org.apache.isis.viewer.wicket.model.models.BookmarkableModel;
 import org.apache.isis.viewer.wicket.model.models.BookmarkedPagesModel;
-import org.apache.isis.viewer.wicket.model.models.FormExecutor;
-import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponse;
-import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponseHandlingStrategy;
 import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponseType;
+import org.apache.isis.viewer.wicket.ui.components.property.FormExecutorAbstract;
 import org.apache.isis.viewer.wicket.ui.pages.BookmarkedPagesModelProvider;
-import org.apache.isis.viewer.wicket.ui.util.Components;
 
-public class ActionParametersFormExecutor implements FormExecutor {
-
-    private final MarkupContainer panel;
-    private final ActionModel actionModel;
+public class ActionParametersFormExecutor extends FormExecutorAbstract<ActionModel> {
 
     public ActionParametersFormExecutor(final MarkupContainer panel, final ActionModel actionModel) {
-        this.panel = panel;
-        this.actionModel = actionModel;
+        super(panel, actionModel);
     }
 
-    private ActionPrompt actionPrompt;
-
-    /**
-     * @param feedbackForm - for feedback messages.
-     * @return
-     */
-    @Override
-    public boolean executeAndProcessResults(AjaxRequestTarget target, Form<?> feedbackForm) {
-
-        Components.permanentlyHide(panel, ComponentType.ENTITY_ICON_AND_TITLE);
-
-        ObjectAdapter targetAdapter = null;
-        try {
-            targetAdapter = actionModel.getTargetAdapter();
-
-            // no concurrency exception, so continue...
-            return executeActionOnTargetAndProcessResults(target, feedbackForm);
 
-        } catch (ConcurrencyException ex) {
-
-            // second attempt should succeed, because the Oid would have
-            // been updated in the attempt
-            if (targetAdapter == null) {
-                targetAdapter = actionModel.getTargetAdapter();
-            }
-
-            // forward onto the target page with the concurrency exception
-            ActionResultResponse resultResponse = ActionResultResponseType.OBJECT
-                    .interpretResult(actionModel, targetAdapter, ex);
-            resultResponse.getHandlingStrategy().handleResults(panel, resultResponse, getIsisSessionFactory());
-
-            getMessageBroker().addWarning(ex.getMessage());
-            return false;
-        }
+    protected ObjectAdapter obtainTargetAdapter() {
+        return model.getTargetAdapter();
     }
 
-    /**
-     * @param target
-     * @return whether to clear args or not (they aren't if there was a validation exception)
-     */
-    private boolean executeActionOnTargetAndProcessResults(
-            final AjaxRequestTarget target,
-            final Form<?> feedbackForm) {
-
-        // validate the action parameters (if any)
-        final String invalidReasonIfAny = actionModel.getReasonInvalidIfAny();
+    protected String getReasonInvalidIfAny() {
+        return model.getReasonInvalidIfAny();
+    }
 
-        if (invalidReasonIfAny != null) {
-            raiseWarning(target, feedbackForm, invalidReasonIfAny);
-            return false;
+    protected void onExecuteAndProcessResults(final AjaxRequestTarget target) {
+        if (model.isBookmarkable()) {
+            bookmarkPage(model);
         }
 
-        final CommandContext commandContext = getServicesInjector().lookupService(CommandContext.class);
-        final Command command;
-        if (commandContext != null) {
-            command = commandContext.getCommand();
-            command.setExecutor(Command.Executor.USER);
-        } else {
-            command = null;
+        if (actionPrompt != null) {
+            actionPrompt.closePrompt(target);
+            // cos will be reused next time, so mustn't cache em.
+            model.clearArguments();
         }
+    }
 
-        // the object store could raise an exception (eg uniqueness constraint)
-        // so we handle it here.
-        try {
-            // could be programmatic flushing, so must include in the try... finally
-            final ObjectAdapter resultAdapter = actionModel.executeHandlingApplicationExceptions();
-
-            // flush any queued changes, so concurrency or violation exceptions (if any)
-            // will be thrown here
-            getTransactionManager().flushTransaction();
-
-            ActionResultResponse resultResponse = ActionResultResponseType
-                    .determineAndInterpretResult(actionModel, target, resultAdapter);
-            resultResponse.getHandlingStrategy().handleResults(panel, resultResponse, getIsisSessionFactory());
-
-            if (actionModel.isBookmarkable()) {
-                bookmarkPage(actionModel);
-            }
-
-            if (actionPrompt != null) {
-                actionPrompt.closePrompt(target);
-                // cos will be reused next time, so mustn't cache em.
-                actionModel.clearArguments();
-            }
-
-            return true;
-
-        } catch (RuntimeException ex) {
-
-            String message = recognizeException(ex, target, feedbackForm);
-
-            if (message != null) {
-                // no need to add to message broker, should already have been added...
-
-                if (feedbackForm == null) {
-                    // forward on instead to void page
-                    // (otherwise, we'll have rendered an action parameters page
-                    // and so we'll be staying on that page)
-                    ActionResultResponseHandlingStrategy.REDIRECT_TO_VOID
-                            .handleResults(panel, null, getIsisSessionFactory());
-                }
-
-                return false;
-            }
-
-            // not handled, so capture and propagate
-            if (command != null) {
-                command.setException(Throwables.getStackTraceAsString(ex));
-            }
+    protected ObjectAdapter obtainResultAdapter() {
+        return model.executeHandlingApplicationExceptions();
+    }
 
-            throw ex;
-        }
+    protected void forwardOnConcurrencyException(
+            final ObjectAdapter targetAdapter,
+            final ConcurrencyException ex) {
+        ActionResultResponse resultResponse = ActionResultResponseType.OBJECT
+                .interpretResult(model, targetAdapter, ex);
+        resultResponse.getHandlingStrategy().handleResults(panel, resultResponse, getIsisSessionFactory());
     }
 
-    private String recognizeException(RuntimeException ex, AjaxRequestTarget target, Form<?> feedbackForm) {
+    protected void forwardOntoResult(
+            final ObjectAdapter resultAdapter,
+            final AjaxRequestTarget target) {
+        ActionResultResponse resultResponse = ActionResultResponseType
+                .determineAndInterpretResult(model, target, resultAdapter);
+        resultResponse.getHandlingStrategy().handleResults(panel, resultResponse, getIsisSessionFactory());
+    }
 
-        // REVIEW: this code is similar to stuff in EntityPropertiesForm, perhaps move up to superclass?
-        // REVIEW: similar code also in WebRequestCycleForIsis; combine?
+    ///////////////////////////////////////////////////////
 
-        // see if the exception is recognized as being a non-serious error
-        // (nb: similar code in WebRequestCycleForIsis, as a fallback)
-        List<ExceptionRecognizer> exceptionRecognizers = getServicesInjector()
-                .lookupServices(ExceptionRecognizer.class);
-        String recognizedErrorIfAny = new ExceptionRecognizerComposite(exceptionRecognizers).recognize(ex);
-        if (recognizedErrorIfAny != null) {
+    private BookmarkedPagesModel getBookmarkedPagesModel() {
+        BookmarkedPagesModelProvider application = (BookmarkedPagesModelProvider) getSession();
+        return application.getBookmarkedPagesModel();
+    }
 
-            // recognized
-            raiseWarning(target, feedbackForm, recognizedErrorIfAny);
+    Session getSession() {
+        return Session.get();
+    }
 
-            getTransactionManager().getCurrentTransaction().clearAbortCause();
 
-            // there's no need to abort the transaction, it will have already been done
-            // (in IsisTransactionManager#executeWithinTransaction(...)).
-        }
-        return recognizedErrorIfAny;
-    }
 
-    public void raiseWarning(AjaxRequestTarget target, Form<?> feedbackForm, String error) {
-        if (target != null && feedbackForm != null) {
-            target.add(feedbackForm);
-            feedbackForm.error(error);
-        } else {
-            getMessageBroker().addWarning(error);
-        }
-    }
+    private ActionPrompt actionPrompt;
 
     void setActionPrompt(final ActionPrompt actionPrompt) {
         this.actionPrompt = actionPrompt;
@@ -203,45 +89,4 @@ public class ActionParametersFormExecutor implements FormExecutor {
         getBookmarkedPagesModel().bookmarkPage(model);
     }
 
-    // ///////////////////////////////////////////////////////////////////
-    // Dependencies (from IsisContext)
-    // ///////////////////////////////////////////////////////////////////
-
-    protected PersistenceSession getPersistenceSession() {
-        return getIsisSessionFactory().getCurrentSession().getPersistenceSession();
-    }
-
-    protected ServicesInjector getServicesInjector() {
-        return getIsisSessionFactory().getServicesInjector();
-    }
-
-    protected SpecificationLoader getSpecificationLoader() {
-        return getIsisSessionFactory().getSpecificationLoader();
-    }
-
-    private IsisTransactionManager getTransactionManager() {
-        return getPersistenceSession().getTransactionManager();
-    }
-
-    private MessageBroker getMessageBroker() {
-        return getAuthenticationSession().getMessageBroker();
-    }
-
-    protected IsisSessionFactory getIsisSessionFactory() {
-        return IsisContext.getSessionFactory();
-    }
-
-    protected AuthenticationSession getAuthenticationSession() {
-        return getIsisSessionFactory().getCurrentSession().getAuthenticationSession();
-    }
-
-    private BookmarkedPagesModel getBookmarkedPagesModel() {
-        BookmarkedPagesModelProvider application = (BookmarkedPagesModelProvider) getSession();
-        return application.getBookmarkedPagesModel();
-    }
-
-    Session getSession() {
-        return Session.get();
-    }
-
 }