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/10/11 19:04:01 UTC

git commit: ISIS-401: concurrency checking in bulk actions

Updated Branches:
  refs/heads/master bda2045b3 -> b717f39f0


ISIS-401: concurrency checking in bulk actions

If user A and user B both check a row, then user A updates that row then
user B updates that row, then show warning to user B and refresh list.

In addition:
- renamed MyAjaxFallback* -> IsisAjaxFallback*
- moved some Functions and Matchers into nester static classes of Oid
  and ObjectAdapterMemento


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

Branch: refs/heads/master
Commit: b717f39f0f3f60e9f53a02378ee0cce3566ed88a
Parents: bda2045
Author: Dan Haywood <da...@apache.org>
Authored: Fri Oct 11 18:03:49 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Oct 11 18:03:49 2013 +0100

----------------------------------------------------------------------
 .../wicket/model/common/SelectionHandler.java   |  17 +--
 .../model/mementos/ObjectAdapterMemento.java    | 105 +++++++++++++++++++
 .../model/models/EntityCollectionModel.java     |   4 +-
 .../wicket/model/util/MementoFunctions.java     |  84 +++++++--------
 .../model/util/ObjectAdapterFunctions.java      |  32 +++---
 .../viewer/wicket/model/util/OidMatchers.java   |  40 +++----
 .../ajaxtable/BulkActionsLinkFactory.java       |  99 +++++++++++++----
 .../CollectionContentsAsAjaxTablePanel.java     |  36 ++++++-
 .../ajaxtable/IsisAjaxFallbackDataTable.java    |  53 ++++++++++
 .../IsisAjaxFallbackHeadersToolbar.java         |  73 +++++++++++++
 .../MyAjaxFallbackDefaultDataTable.java         |  53 ----------
 .../ajaxtable/MyAjaxFallbackHeadersToolbar.java |  73 -------------
 .../columns/ObjectAdapterToggleboxColumn.java   |  21 +++-
 .../entity/EntityActionLinkFactory.java         |  12 ++-
 .../isis/core/metamodel/adapter/oid/Oid.java    |  42 ++++++++
 15 files changed, 489 insertions(+), 255 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java
index 3193fa8..dfecf23 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java
@@ -22,20 +22,23 @@ package org.apache.isis.viewer.wicket.model.common;
 import java.io.Serializable;
 
 import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 
 /**
  * Decouples the mechanism for selecting entities returned in collections.
  */
 public interface SelectionHandler extends Serializable {
 
-    /**
-     * The entity that has been selected.
-     * 
-     * @param context
-     *            TODO
-     */
-    void onSelected(Component context, ObjectAdapter selectedAdapter);
+    void onSelected(
+            Component context, ObjectAdapter selectedAdapter,
+            AjaxRequestTarget ajaxRequestTarget);
+
+    void onConcurrencyException(
+            Component context, ObjectAdapter selectedAdapter, 
+            ConcurrencyException ex,
+            AjaxRequestTarget ajaxRequestTarget);
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
index af0dc41..f7b4e0c 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
@@ -22,6 +22,8 @@ package org.apache.isis.viewer.wicket.model.mementos;
 import java.io.Serializable;
 import java.util.List;
 
+import com.google.common.base.Function;
+
 import org.apache.isis.core.commons.ensure.Ensure;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
@@ -33,6 +35,10 @@ import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
 import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.core.runtime.memento.Memento;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
@@ -347,6 +353,105 @@ public class ObjectAdapterMemento implements Serializable {
 
 
     //////////////////////////////////////////////////
+    // Functions
+    //////////////////////////////////////////////////
+    
+    
+    public final static class Functions {
+
+        private Functions() {
+        }
+
+        public static Function<ObjectSpecification, ObjectSpecId> fromSpec() {
+            return new Function<ObjectSpecification, ObjectSpecId>() {
+
+                @Override
+                public ObjectSpecId apply(final ObjectSpecification from) {
+                    return from.getSpecId();
+                }
+            };
+        }
+
+        public static Function<OneToOneAssociation, PropertyMemento> fromProperty() {
+            return new Function<OneToOneAssociation, PropertyMemento>() {
+                @Override
+                public PropertyMemento apply(final OneToOneAssociation from) {
+                    return new PropertyMemento(from);
+                }
+            };
+        }
+
+        public static Function<OneToManyAssociation, CollectionMemento> fromCollection() {
+            return new Function<OneToManyAssociation, CollectionMemento>() {
+                @Override
+                public CollectionMemento apply(final OneToManyAssociation from) {
+                    return new CollectionMemento(from);
+                }
+            };
+        }
+
+        public static Function<ObjectAction, ActionMemento> fromAction() {
+            return new Function<ObjectAction, ActionMemento>() {
+                @Override
+                public ActionMemento apply(final ObjectAction from) {
+                    return new ActionMemento(from);
+                }
+            };
+        }
+
+        public static Function<ObjectActionParameter, ActionParameterMemento> fromActionParameter() {
+            return new Function<ObjectActionParameter, ActionParameterMemento>() {
+                @Override
+                public ActionParameterMemento apply(final ObjectActionParameter from) {
+                    return new ActionParameterMemento(from);
+                }
+            };
+        }
+
+        public static Function<Object, ObjectAdapterMemento> fromPojo(final AdapterManager adapterManager) {
+            return new Function<Object, ObjectAdapterMemento>() {
+                @Override
+                public ObjectAdapterMemento apply(final Object pojo) {
+                    final ObjectAdapter adapter = adapterManager.adapterFor(pojo);
+                    return ObjectAdapterMemento.createOrNull(adapter);
+                }
+            };
+        }
+
+        public static Function<ObjectAdapter, ObjectAdapterMemento> fromAdapter() {
+            return new Function<ObjectAdapter, ObjectAdapterMemento>() {
+                @Override
+                public ObjectAdapterMemento apply(final ObjectAdapter adapter) {
+                    return ObjectAdapterMemento.createOrNull(adapter);
+                }
+            };
+        }
+
+
+        public static Function<ObjectAdapterMemento, ObjectAdapter> fromMemento(final ConcurrencyChecking concurrencyChecking) {
+            return new Function<ObjectAdapterMemento, ObjectAdapter>() {
+                @Override
+                public ObjectAdapter apply(final ObjectAdapterMemento from) {
+                    return from.getObjectAdapter(concurrencyChecking);
+                }
+            };
+        }
+
+        public static Function<ObjectAdapter, ObjectAdapterMemento> toMemento() {
+            return new Function<ObjectAdapter, ObjectAdapterMemento>() {
+
+                @Override
+                public ObjectAdapterMemento apply(ObjectAdapter from) {
+                    return ObjectAdapterMemento.createOrNull(from);
+                }
+                
+            };
+        }
+
+    }
+
+    
+    //////////////////////////////////////////////////
     // Dependencies (from context)
     //////////////////////////////////////////////////
     

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
index 0f21696..74f479d 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
@@ -73,12 +73,12 @@ public class EntityCollectionModel extends ModelAbstract<List<ObjectAdapter>> im
         STANDALONE {
             @Override
             List<ObjectAdapter> load(final EntityCollectionModel entityCollectionModel) {
-                return Lists.transform(entityCollectionModel.mementoList, ObjectAdapterFunctions.fromMemento());
+                return Lists.transform(entityCollectionModel.mementoList, ObjectAdapterMemento.Functions.fromMemento(ConcurrencyChecking.NO_CHECK));
             }
 
             @Override
             void setObject(EntityCollectionModel entityCollectionModel, List<ObjectAdapter> list) {
-                entityCollectionModel.mementoList = Lists.newArrayList(Lists.transform(list, ObjectAdapterFunctions.toMemento()));
+                entityCollectionModel.mementoList = Lists.newArrayList(Lists.transform(list, ObjectAdapterMemento.Functions.toMemento()));
             }
 
             @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java
index 2358e0c..45cfd33 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java
@@ -36,75 +36,69 @@ import org.apache.isis.viewer.wicket.model.mementos.CollectionMemento;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
 
+/**
+ * @deprecated - use {@link ObjectAdapterMemento.Functions}
+ */
+@Deprecated
 public final class MementoFunctions {
 
     private MementoFunctions() {
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
     public static Function<ObjectSpecification, ObjectSpecId> fromSpec() {
-        return new Function<ObjectSpecification, ObjectSpecId>() {
-
-            @Override
-            public ObjectSpecId apply(final ObjectSpecification from) {
-                return from.getSpecId();
-            }
-        };
+        return ObjectAdapterMemento.Functions.fromSpec();
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
     public static Function<OneToOneAssociation, PropertyMemento> fromProperty() {
-        return new Function<OneToOneAssociation, PropertyMemento>() {
-            @Override
-            public PropertyMemento apply(final OneToOneAssociation from) {
-                return new PropertyMemento(from);
-            }
-        };
+        return ObjectAdapterMemento.Functions.fromProperty();
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
     public static Function<OneToManyAssociation, CollectionMemento> fromCollection() {
-        return new Function<OneToManyAssociation, CollectionMemento>() {
-            @Override
-            public CollectionMemento apply(final OneToManyAssociation from) {
-                return new CollectionMemento(from);
-            }
-        };
+        return ObjectAdapterMemento.Functions.fromCollection();
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
     public static Function<ObjectAction, ActionMemento> fromAction() {
-        return new Function<ObjectAction, ActionMemento>() {
-            @Override
-            public ActionMemento apply(final ObjectAction from) {
-                return new ActionMemento(from);
-            }
-        };
+        return ObjectAdapterMemento.Functions.fromAction();
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
     public static Function<ObjectActionParameter, ActionParameterMemento> fromActionParameter() {
-        return new Function<ObjectActionParameter, ActionParameterMemento>() {
-            @Override
-            public ActionParameterMemento apply(final ObjectActionParameter from) {
-                return new ActionParameterMemento(from);
-            }
-        };
+        return ObjectAdapterMemento.Functions.fromActionParameter();
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
     public static Function<Object, ObjectAdapterMemento> fromPojo(final AdapterManager adapterManager) {
-        return new Function<Object, ObjectAdapterMemento>() {
-            @Override
-            public ObjectAdapterMemento apply(final Object pojo) {
-                final ObjectAdapter adapter = adapterManager.adapterFor(pojo);
-                return ObjectAdapterMemento.createOrNull(adapter);
-            }
-        };
+        return ObjectAdapterMemento.Functions.fromPojo(adapterManager);
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
     public static Function<ObjectAdapter, ObjectAdapterMemento> fromAdapter() {
-        return new Function<ObjectAdapter, ObjectAdapterMemento>() {
-            @Override
-            public ObjectAdapterMemento apply(final ObjectAdapter adapter) {
-                return ObjectAdapterMemento.createOrNull(adapter);
-            }
-        };
+        return ObjectAdapterMemento.Functions.fromAdapter();
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java
index 72f1230..7700e04 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java
@@ -26,37 +26,37 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 
+/**
+ * @deprecated - use {@link ObjectAdapter.Functions} or {@link ObjectAdapterMemento.Functions}
+ */
+@Deprecated
 public final class ObjectAdapterFunctions {
 
     private ObjectAdapterFunctions() {
     }
 
     /**
-     * Use {@link ObjectAdapter.Functions}
+     * @deprecated - use {@link ObjectAdapter.Functions}
      */
     @Deprecated
     public static Function<Object, ObjectAdapter> fromPojo(final AdapterManager adapterManager) {
         return ObjectAdapter.Functions.adapterForUsing(adapterManager);
     }
 
-    public static Function<ObjectAdapterMemento, ObjectAdapter> fromMemento() {
-        return new Function<ObjectAdapterMemento, ObjectAdapter>() {
-            @Override
-            public ObjectAdapter apply(final ObjectAdapterMemento from) {
-                return from.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
-            }
-        };
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<ObjectAdapterMemento, ObjectAdapter> fromMemento(final ConcurrencyChecking concurrencyChecking) {
+        return ObjectAdapterMemento.Functions.fromMemento(concurrencyChecking);
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
     public static Function<ObjectAdapter, ObjectAdapterMemento> toMemento() {
-        return new Function<ObjectAdapter, ObjectAdapterMemento>() {
-
-            @Override
-            public ObjectAdapterMemento apply(ObjectAdapter from) {
-                return ObjectAdapterMemento.createOrNull(from);
-            }
-            
-        };
+        return ObjectAdapterMemento.Functions.toMemento();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.java
index ed77526..7904a35 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.java
@@ -19,45 +19,33 @@
 
 package org.apache.isis.viewer.wicket.model.util;
 
-import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
 
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
 
+/**
+ * @deprecated - use {@link Oid.Matchers}
+ */
+@Deprecated
 public final class OidMatchers {
 
     private OidMatchers() {
     }
 
+    /**
+     * @deprecated - use {@link Oid.Matchers}
+     */
+    @Deprecated
     public static Matcher<Oid> isTransient() {
-        return new TypeSafeMatcher<Oid>() {
-
-            @Override
-            public boolean matchesSafely(final Oid item) {
-                return item.isTransient();
-            }
-
-            @Override
-            public void describeTo(final Description description) {
-                description.appendText("is transient");
-            }
-        };
+        return Oid.Matchers.isTransient();
     }
 
+    /**
+     * @deprecated - use {@link Oid.Matchers}
+     */
+    @Deprecated
     public static Matcher<Oid> isPersistent() {
-        return new TypeSafeMatcher<Oid>() {
-
-            @Override
-            public boolean matchesSafely(final Oid item) {
-                return !item.isTransient();
-            }
-
-            @Override
-            public void describeTo(final Description description) {
-                description.appendText("is persistent");
-            }
-        };
+        return Oid.Matchers.isPersistent();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
index e750c5c..cc3e1d4 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
@@ -28,15 +28,21 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
+import org.apache.wicket.Session;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
 import org.apache.wicket.markup.html.link.AbstractLink;
 import org.apache.wicket.markup.html.link.Link;
 
 import org.apache.isis.applib.annotation.Bulk;
 import org.apache.isis.applib.annotation.Bulk.InteractionContext;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
+import org.apache.isis.core.commons.authentication.MessageBroker;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ActionMemento;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
@@ -49,6 +55,7 @@ import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFa
 import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
 
 final class BulkActionsLinkFactory implements CssMenuLinkFactory {
+    
     private static final long serialVersionUID = 1L;
     private final EntityCollectionModel model;
     
@@ -70,38 +77,69 @@ final class BulkActionsLinkFactory implements CssMenuLinkFactory {
             @Override
             public void onClick() {
                 final ObjectAction objectAction = actionMemento.getAction();
+                final ConcurrencyChecking concurrencyChecking = 
+                        ConcurrencyChecking.concurrencyCheckingFor(objectAction.getSemantics());
 
                 try {
                     final List<ObjectAdapterMemento> toggleMementosList = model.getToggleMementosList();
-                    
-                    // REVIEW: have disabled concurrency checking here...
-                    final Iterable<ObjectAdapter> toggledAdapters = Iterables.transform(toggleMementosList, ObjectAdapterFunctions.fromMemento());
+
+                    final Iterable<ObjectAdapter> toggledAdapters = 
+                            Iterables.transform(toggleMementosList, ObjectAdapterMemento.Functions.fromMemento(concurrencyChecking));
                     
                     final List<Object> domainObjects = Lists.newArrayList(Iterables.transform(toggledAdapters, ObjectAdapter.Functions.getObject()));
-                    final Bulk.InteractionContext interactionContext = new Bulk.InteractionContext(domainObjects);
-                    Bulk.InteractionContext.current.set(interactionContext);
                     
-                    int i=0;
-                    for(final ObjectAdapter adapter : toggledAdapters) {
-    
-                        int numParameters = objectAction.getParameterCount();
-                        if(numParameters != 0) {
-                            return;
+                    try {
+                        final Bulk.InteractionContext interactionContext = new Bulk.InteractionContext(domainObjects);
+                        Bulk.InteractionContext.current.set(interactionContext);
+                        int i=0;
+                        for(final ObjectAdapter adapter : toggledAdapters) {
+        
+                            int numParameters = objectAction.getParameterCount();
+                            if(numParameters != 0) {
+                                return;
+                            }
+                            interactionContext.setIndex(i++);
+                            objectAction.execute(adapter, new ObjectAdapter[]{});
                         }
-                        interactionContext.setIndex(i++);
-                        objectAction.execute(adapter, new ObjectAdapter[]{});
+                    } finally {
+                        Bulk.InteractionContext.current.set(null);
                     }
-                } finally {
-                    Bulk.InteractionContext.current.set(null);
-                }
-                
-                model.clearToggleMementosList();
-                final ActionModel actionModelHint = model.getActionModelHint();
-                if(actionModelHint != null) {
-                    ObjectAdapter resultAdapter = actionModelHint.getObject();
-                    model.setObjectList(resultAdapter);
-                } else {
+                    
+                    model.clearToggleMementosList();
+                    final ActionModel actionModelHint = model.getActionModelHint();
+                    if(actionModelHint != null) {
+                        ObjectAdapter resultAdapter = actionModelHint.getObject();
+                        model.setObjectList(resultAdapter);
+                    } else {
+                        model.setObject(persistentAdaptersWithin(model.getObject()));
+                    }
+
+                } catch(final ConcurrencyException ex) {
+                    
+                    // resync with the objectstore
+                    final List<ObjectAdapterMemento> toggleMementosList = Lists.newArrayList(model.getToggleMementosList());
+                    for (ObjectAdapterMemento oam : toggleMementosList) {
+                        // just requesting the adapter will sync the OAM's version with the objectstore
+                        oam.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+                    }
+                    
+                    // discard any adapters that might have been deleted
                     model.setObject(persistentAdaptersWithin(model.getObject()));
+                    
+                    // attempt to preserve the toggled adapters
+                    final List<ObjectAdapter> adapters = model.getObject();
+                    model.clearToggleMementosList();
+                    for (ObjectAdapterMemento oam : toggleMementosList) {
+                        final ObjectAdapter objectAdapter = oam.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+                        if(adapters.contains(objectAdapter)) {
+                            // in case it has been deleted...
+                            model.toggleSelectionOn(objectAdapter);
+                        }
+                    }
+                    
+                    // display a warning to the user so that they know that the action wasn't performed
+                    getMessageBroker().addWarning(ex.getMessage());
+                    return;
                 }
             }
 
@@ -122,4 +160,19 @@ final class BulkActionsLinkFactory implements CssMenuLinkFactory {
 
         return new LinkAndLabel(link, objectAction.getName(), null, false, explorationOrPrototype, actionIdentifier, cssClass);
     }
+    
+    
+    ///////////////////////////////////////////////////////
+    // Dependencies (from context)
+    ///////////////////////////////////////////////////////
+
+    public AuthenticationSession getAuthenticationSession() {
+        final AuthenticationSessionProvider asa = (AuthenticationSessionProvider) Session.get();
+        return asa.getAuthenticationSession();
+    }
+
+    protected MessageBroker getMessageBroker() {
+        return getAuthenticationSession().getMessageBroker();
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
index 5117132..134344b 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
@@ -28,15 +28,21 @@ import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 
 import org.apache.wicket.Component;
+import org.apache.wicket.Session;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
 import org.apache.wicket.model.Model;
 
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.filter.Filter;
 import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
+import org.apache.isis.core.commons.authentication.MessageBroker;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.facets.hide.HiddenFacet;
@@ -93,7 +99,7 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         addPropertyColumnsIfRequired(columns);
 
         final SortableDataProvider<ObjectAdapter,String> dataProvider = new CollectionContentsSortableDataProvider(model);
-        dataTable = new MyAjaxFallbackDefaultDataTable<ObjectAdapter,String>(ID_TABLE, columns, dataProvider, model.getPageSize());
+        dataTable = new IsisAjaxFallbackDataTable<ObjectAdapter,String>(ID_TABLE, columns, dataProvider, model.getPageSize());
 
         buildEntityActionsGui(bulkActions);
 
@@ -101,8 +107,8 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
     }
     
     private void addToggleboxColumnIfRequired(final List<IColumn<ObjectAdapter,String>> columns, List<ObjectAction> bulkActions) {
-        final EntityCollectionModel model = getModel();
-        if(bulkActions.isEmpty() || model.isParented()) {
+        final EntityCollectionModel entityCollectionModel = getModel();
+        if(bulkActions.isEmpty() || entityCollectionModel.isParented()) {
             return;
         }
         
@@ -111,8 +117,24 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
             private static final long serialVersionUID = 1L;
 
             @Override
-            public void onSelected(final Component context, final ObjectAdapter selectedAdapter) {
-                model.toggleSelectionOn(selectedAdapter);
+            public void onSelected(
+                    final Component context, final ObjectAdapter selectedAdapter,
+                    AjaxRequestTarget ajaxRequestTarget) {
+                entityCollectionModel.toggleSelectionOn(selectedAdapter);
+            }
+
+            @Override
+            public void onConcurrencyException(
+                    final Component context, ObjectAdapter selectedAdapter, 
+                    ConcurrencyException ex,
+                    AjaxRequestTarget ajaxRequestTarget) {
+                
+                // this causes the row to be repainted
+                // but it isn't possible (yet) to raise any warning
+                // because that only gets flushed on page refresh.
+                //
+                // perhaps something to tackle in a separate ticket....
+                ajaxRequestTarget.add(dataTable);
             }
         }));
     }
@@ -247,4 +269,8 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         return settings;
     }
 
+    protected MessageBroker getMessageBroker() {
+        return getAuthenticationSession().getMessageBroker();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java
new file mode 100644
index 0000000..e1b9c14
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java
@@ -0,0 +1,53 @@
+/*
+ *  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.components.collectioncontents.ajaxtable;
+
+import java.util.List;
+
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxNavigationToolbar;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.NoRecordsToolbar;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.OddEvenItem;
+import org.apache.wicket.model.IModel;
+
+public class IsisAjaxFallbackDataTable<T, S> extends DataTable<T, S>
+{
+    private static final long serialVersionUID = 1L;
+
+    public IsisAjaxFallbackDataTable(final String id, final List<? extends IColumn<T, S>> columns,
+        final ISortableDataProvider<T, S> dataProvider, final int rowsPerPage)
+    {
+        super(id, columns, dataProvider, rowsPerPage);
+        setOutputMarkupId(true);
+        setVersioned(false);
+        addTopToolbar(new IsisAjaxFallbackHeadersToolbar<S>(this, dataProvider));
+        addBottomToolbar(new AjaxNavigationToolbar(this));
+        addBottomToolbar(new NoRecordsToolbar(this));
+    }
+
+    @Override
+    protected Item<T> newRowItem(final String id, final int index, final IModel<T> model)
+    {
+        return new OddEvenItem<T>(id, index, model);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java
new file mode 100644
index 0000000..e59e388
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java
@@ -0,0 +1,73 @@
+/**
+ *  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.components.collectioncontents.ajaxtable;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.IAjaxCallListener;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.sort.AjaxFallbackOrderByBorder;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackHeadersToolbar;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+
+
+/**
+ * Adapted from Wicket's own {@link AjaxFallbackHeadersToolbar}.
+ */
+public class IsisAjaxFallbackHeadersToolbar<S> extends MyHeadersToolbar<S>
+{
+    private static final long serialVersionUID = 1L;
+
+    public IsisAjaxFallbackHeadersToolbar(final DataTable<?, S> table, final ISortStateLocator<S> stateLocator)
+    {
+        super(table, stateLocator);
+        table.setOutputMarkupId(true);
+    }
+
+    @Override
+    protected WebMarkupContainer newSortableHeader(final String borderId, final S property,
+        final ISortStateLocator<S> locator)
+    {
+        return new AjaxFallbackOrderByBorder<S>(borderId, property, locator, getAjaxCallListener())
+        {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onAjaxClick(final AjaxRequestTarget target)
+            {
+                target.add(getTable());
+            }
+
+            @Override
+            protected void onSortChanged()
+            {
+                super.onSortChanged();
+                getTable().setCurrentPage(0);
+            }
+        };
+    }
+
+    /**
+     * Returns a decorator that will be used to decorate ajax links used in sortable headers
+     * 
+     * @return decorator or null for none
+     */
+    protected IAjaxCallListener getAjaxCallListener()
+    {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/MyAjaxFallbackDefaultDataTable.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/MyAjaxFallbackDefaultDataTable.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/MyAjaxFallbackDefaultDataTable.java
deleted file mode 100644
index 91ca852..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/MyAjaxFallbackDefaultDataTable.java
+++ /dev/null
@@ -1,53 +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.viewer.wicket.ui.components.collectioncontents.ajaxtable;
-
-import java.util.List;
-
-import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxNavigationToolbar;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.NoRecordsToolbar;
-import org.apache.wicket.markup.repeater.Item;
-import org.apache.wicket.markup.repeater.OddEvenItem;
-import org.apache.wicket.model.IModel;
-
-public class MyAjaxFallbackDefaultDataTable<T, S> extends DataTable<T, S>
-{
-    private static final long serialVersionUID = 1L;
-
-    public MyAjaxFallbackDefaultDataTable(final String id, final List<? extends IColumn<T, S>> columns,
-        final ISortableDataProvider<T, S> dataProvider, final int rowsPerPage)
-    {
-        super(id, columns, dataProvider, rowsPerPage);
-        setOutputMarkupId(true);
-        setVersioned(false);
-        addTopToolbar(new MyAjaxFallbackHeadersToolbar<S>(this, dataProvider));
-        addBottomToolbar(new AjaxNavigationToolbar(this));
-        addBottomToolbar(new NoRecordsToolbar(this));
-    }
-
-    @Override
-    protected Item<T> newRowItem(final String id, final int index, final IModel<T> model)
-    {
-        return new OddEvenItem<T>(id, index, model);
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/MyAjaxFallbackHeadersToolbar.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/MyAjaxFallbackHeadersToolbar.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/MyAjaxFallbackHeadersToolbar.java
deleted file mode 100644
index e14c496..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/MyAjaxFallbackHeadersToolbar.java
+++ /dev/null
@@ -1,73 +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.viewer.wicket.ui.components.collectioncontents.ajaxtable;
-
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.attributes.IAjaxCallListener;
-import org.apache.wicket.extensions.ajax.markup.html.repeater.data.sort.AjaxFallbackOrderByBorder;
-import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackHeadersToolbar;
-import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-
-
-/**
- * Adapted from Wicket's own {@link AjaxFallbackHeadersToolbar}.
- */
-public class MyAjaxFallbackHeadersToolbar<S> extends MyHeadersToolbar<S>
-{
-    private static final long serialVersionUID = 1L;
-
-    public MyAjaxFallbackHeadersToolbar(final DataTable<?, S> table, final ISortStateLocator<S> stateLocator)
-    {
-        super(table, stateLocator);
-        table.setOutputMarkupId(true);
-    }
-
-    @Override
-    protected WebMarkupContainer newSortableHeader(final String borderId, final S property,
-        final ISortStateLocator<S> locator)
-    {
-        return new AjaxFallbackOrderByBorder<S>(borderId, property, locator, getAjaxCallListener())
-        {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected void onAjaxClick(final AjaxRequestTarget target)
-            {
-                target.add(getTable());
-            }
-
-            @Override
-            protected void onSortChanged()
-            {
-                super.onSortChanged();
-                getTable().setCurrentPage(0);
-            }
-        };
-    }
-
-    /**
-     * Returns a decorator that will be used to decorate ajax links used in sortable headers
-     * 
-     * @return decorator or null for none
-     */
-    protected IAjaxCallListener getAjaxCallListener()
-    {
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java
index 8ce2cfc..bf63837 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java
@@ -24,13 +24,18 @@ import java.util.List;
 import com.google.common.collect.Lists;
 
 import org.apache.wicket.Component;
+import org.apache.wicket.Session;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.model.IModel;
 
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
+import org.apache.isis.core.commons.authentication.MessageBroker;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 import org.apache.isis.viewer.wicket.model.common.SelectionHandler;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.components.widgets.checkbox.ContainedToggleboxPanel;
@@ -70,13 +75,23 @@ public final class ObjectAdapterToggleboxColumn extends ColumnAbstract<ObjectAda
             private static final long serialVersionUID = 1L;
             @Override
             public void onSubmit(AjaxRequestTarget target) {
-                final EntityModel o = (EntityModel) rowModel;
-                final ObjectAdapter selectedAdapter = o.load(ConcurrencyChecking.NO_CHECK);
-                handler.onSelected(this, selectedAdapter);
+                final EntityModel entityModel = (EntityModel) rowModel;
+                ObjectAdapter selectedAdapter = null;
+                try {
+                    selectedAdapter = entityModel.load(ConcurrencyChecking.CHECK);
+                    handler.onSelected(this, selectedAdapter, target);
+                } catch(ConcurrencyException ex) {
+
+                    // should work second time, because the previous attempt will have updated the OAM's OIDs version.
+                    selectedAdapter = entityModel.load(ConcurrencyChecking.CHECK);
+                    handler.onConcurrencyException(this, selectedAdapter, ex, target);
+                }
             }
         };
         rowToggles.add(toggle);
         toggle.setOutputMarkupId(true);
         cellItem.add(toggle);
     }
+
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
index 89cb386..6690ced 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
@@ -99,14 +99,22 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
         }
     }
 
+    /**
+     * Creates a link to the {@link ActionPage} (ie the {@link PageClassRegistry registered page} for 
+     * {@link PageType#ACTION action}s) with the appropriate {@link PageParameters} to either render the action's
+     * parameter form (if it takes arguments) or to invoke the action directly.
+     * 
+     * <p>
+     * If the action's {@link ObjectAction#getSemantics() semantics} are {@link ActionSemantics.Of#SAFE safe}, then
+     * concurrency checking is disabled; otherwise it is enforced.
+     */
     private AbstractLink createLinkForPersistent(final String linkId, final ObjectAdapterMemento adapterMemento, final ObjectAction action) {
         final ObjectAdapter adapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
         final ObjectAdapter contextAdapter = entityModel.getObject();
 
         // use the action semantics to determine whether invoking this action will require a concurrency check or not
         // if it's "safe", then we'll just continue without any checking. 
-        final ConcurrencyChecking concurrencyChecking = 
-                action.getSemantics() == ActionSemantics.Of.SAFE? ConcurrencyChecking.NO_CHECK: ConcurrencyChecking.CHECK;
+        final ConcurrencyChecking concurrencyChecking = ConcurrencyChecking.concurrencyCheckingFor(action.getSemantics());
         final PageParameters pageParameters = ActionModel.createPageParameters(adapter, action, contextAdapter, ActionModel.SingleResultsMode.REDIRECT, concurrencyChecking);
         final Class<? extends Page> pageClass = getPageClassRegistry().getPageClass(PageType.ACTION);
         return Links.newBookmarkablePageLink(linkId, pageParameters, pageClass);

http://git-wip-us.apache.org/repos/asf/isis/blob/b717f39f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/Oid.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/Oid.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/Oid.java
index dd4501d..d7687ba 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/Oid.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/Oid.java
@@ -19,6 +19,10 @@
 
 package org.apache.isis.core.metamodel.adapter.oid;
 
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
 import org.apache.isis.applib.annotation.Value;
 import org.apache.isis.core.commons.encoding.Encodable;
 import org.apache.isis.core.metamodel.adapter.version.Version;
@@ -82,5 +86,43 @@ public interface Oid extends Encodable {
         }
     }
 
+
+    public final static class Matchers {
+
+        private Matchers() {
+        }
+
+        public static Matcher<Oid> isTransient() {
+            return new TypeSafeMatcher<Oid>() {
+
+                @Override
+                public boolean matchesSafely(final Oid item) {
+                    return item.isTransient();
+                }
+
+                @Override
+                public void describeTo(final Description description) {
+                    description.appendText("is transient");
+                }
+            };
+        }
+
+        public static Matcher<Oid> isPersistent() {
+            return new TypeSafeMatcher<Oid>() {
+
+                @Override
+                public boolean matchesSafely(final Oid item) {
+                    return !item.isTransient();
+                }
+
+                @Override
+                public void describeTo(final Description description) {
+                    description.appendText("is persistent");
+                }
+            };
+        }
+
+    }
+
     
 }