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

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 3d9246c  ISIS-2275: improve interfaces 
ObjectAction-/ObjectAssociationContainer
3d9246c is described below

commit 3d9246cdd3b240a6262ceb6bf44ed6f6c2ef0fb8
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Tue Feb 11 13:31:53 2020 +0100

    ISIS-2275: improve interfaces ObjectAction-/ObjectAssociationContainer
    
    wrap return values with Optional where appropriate
---
 .../isis/applib/layout/grid/GridAbstract.java      |  1 +
 .../services/grid/GridSystemServiceAbstract.java   | 61 +++++++++++-----------
 .../grid/bootstrap3/GridSystemServiceBS3.java      |  2 +-
 .../metamodel/MetaModelServiceDefault.java         |  2 +-
 .../core/metamodel/spec/ObjectSpecification.java   |  4 +-
 .../spec/feature/ObjectActionContainer.java        | 19 +++++--
 .../spec/feature/ObjectAssociationContainer.java   | 10 +++-
 .../specimpl/ObjectSpecificationAbstract.java      | 47 +++--------------
 .../specimpl/dflt/ObjectSpecificationDefault.java  | 17 +++---
 .../core/metamodel/util/snapshot/XmlSnapshot.java  | 11 ++--
 .../testspec/ObjectSpecificationStub.java          | 38 +++++++-------
 .../DomainModelTest_usingGoodDomain.java           | 12 ++---
 .../resources/DomainTypeResourceServerside.java    | 34 ++++++------
 .../resources/ObjectAdapterAccessHelper.java       | 46 ++++++----------
 .../wicket/model/mementos/ActionMemento.java       |  2 +-
 .../wicket/model/mementos/CollectionMemento.java   |  3 +-
 .../wicket/model/mementos/PropertyMemento.java     |  4 +-
 .../wicket/model/models/EntityCollectionModel.java |  2 +-
 .../serviceactions/ServiceActionUtil.java          |  2 +-
 .../CollectionContentsSortableDataProvider.java    | 14 ++---
 .../columns/ObjectAdapterPropertyColumn.java       |  2 +-
 .../components/entity/fieldset/PropertyGroup.java  | 35 ++++---------
 .../wicket/ui/components/layout/bs3/col/Col.java   | 11 ++--
 23 files changed, 167 insertions(+), 212 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/layout/grid/GridAbstract.java 
b/api/applib/src/main/java/org/apache/isis/applib/layout/grid/GridAbstract.java
index 5ebfa9d..6a1fdc1 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/layout/grid/GridAbstract.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/layout/grid/GridAbstract.java
@@ -98,6 +98,7 @@ public abstract class GridAbstract implements Grid {
     protected void traverseActions(
             final ActionLayoutDataOwner actionLayoutDataOwner,
             final GridAbstract.Visitor visitor) {
+        
         final List<ActionLayoutData> actionLayoutDatas = 
actionLayoutDataOwner.getActions();
         if(actionLayoutDatas == null) {
             return;
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 c9b961b..7cfb931 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
@@ -35,7 +35,6 @@ import org.apache.isis.applib.annotation.RenderDay;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.layout.component.ActionLayoutData;
 import org.apache.isis.applib.layout.component.CollectionLayoutData;
-import org.apache.isis.applib.layout.component.CssClassFaPosition;
 import org.apache.isis.applib.layout.component.DomainObjectLayoutData;
 import org.apache.isis.applib.layout.component.DomainObjectLayoutDataOwner;
 import org.apache.isis.applib.layout.component.FieldSet;
@@ -108,7 +107,6 @@ import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.TypicalLe
 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;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
@@ -396,42 +394,45 @@ implements GridSystemService<G> {
 
             @Override
             public void visit(final ActionLayoutData actionLayoutData) {
-                final ObjectAction objectAction = 
objectSpec.getObjectAction(actionLayoutData.getId());
-
-                setBookmarkingIfAny(actionLayoutData, objectAction);
-                setCssClassIfAny(actionLayoutData, objectAction);
-                setCssClassFaIfAny(actionLayoutData, objectAction);
-                setDescribedAsIfAny(actionLayoutData, objectAction);
-                setHiddenIfAny(actionLayoutData, objectAction);
-                setNamedIfAny(actionLayoutData, objectAction);
-                setActionPositionIfAny(actionLayoutData, objectAction);
+                objectSpec.getObjectAction(actionLayoutData.getId())
+                .ifPresent(objectAction->{
+                    setBookmarkingIfAny(actionLayoutData, objectAction);
+                    setCssClassIfAny(actionLayoutData, objectAction);
+                    setCssClassFaIfAny(actionLayoutData, objectAction);
+                    setDescribedAsIfAny(actionLayoutData, objectAction);
+                    setHiddenIfAny(actionLayoutData, objectAction);
+                    setNamedIfAny(actionLayoutData, objectAction);
+                    setActionPositionIfAny(actionLayoutData, objectAction);    
+                });
             }
 
             @Override
             public void visit(final CollectionLayoutData collectionLayoutData) 
{
-                final ObjectAssociation collection = 
objectSpec.getAssociation(collectionLayoutData.getId());
-
-                setCssClassIfAny(collectionLayoutData, collection);
-                setDefaultViewIfAny(collectionLayoutData, collection);
-                setDescribedAsIfAny(collectionLayoutData, collection);
-                setHiddenIfAny(collectionLayoutData, collection);
-                setNamedIfAny(collectionLayoutData, collection);
-                setPagedIfAny(collectionLayoutData, collection);
-                setSortedByIfAny(collectionLayoutData, collection);
+                objectSpec.getAssociation(collectionLayoutData.getId())
+                .ifPresent(collection->{
+                    setCssClassIfAny(collectionLayoutData, collection);
+                    setDefaultViewIfAny(collectionLayoutData, collection);
+                    setDescribedAsIfAny(collectionLayoutData, collection);
+                    setHiddenIfAny(collectionLayoutData, collection);
+                    setNamedIfAny(collectionLayoutData, collection);
+                    setPagedIfAny(collectionLayoutData, collection);
+                    setSortedByIfAny(collectionLayoutData, collection);    
+                });
             }
 
             @Override
             public void visit(final PropertyLayoutData propertyLayoutData) {
-                final ObjectAssociation property = 
objectSpec.getAssociation(propertyLayoutData.getId());
-
-                setCssClassIfAny(propertyLayoutData, property);
-                setDescribedAsIfAny(propertyLayoutData, property);
-                setHiddenIfAny(propertyLayoutData, property);
-                setNamedIfAny(propertyLayoutData, property);
-                setLabelPositionIfAny(propertyLayoutData, property);
-                setMultiLineIfAny(propertyLayoutData, property);
-                setRenderedAsDayBeforeIfAny(propertyLayoutData, property);
-                setTypicalLengthIfAny(propertyLayoutData, property);
+                objectSpec.getAssociation(propertyLayoutData.getId())
+                .ifPresent(property->{
+                    setCssClassIfAny(propertyLayoutData, property);
+                    setDescribedAsIfAny(propertyLayoutData, property);
+                    setHiddenIfAny(propertyLayoutData, property);
+                    setNamedIfAny(propertyLayoutData, property);
+                    setLabelPositionIfAny(propertyLayoutData, property);
+                    setMultiLineIfAny(propertyLayoutData, property);
+                    setRenderedAsDayBeforeIfAny(propertyLayoutData, property);
+                    setTypicalLengthIfAny(propertyLayoutData, property);    
+                });
             }
 
             @Override
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
index 7a68d0e..33006da 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
@@ -608,7 +608,7 @@ public class GridSystemServiceBS3 extends 
GridSystemServiceAbstract<BS3Grid> {
             final ObjectSpecification objectSpec) {
         for (final String collectionId : collectionIds) {
             final BS3Tab bs3Tab = new BS3Tab();
-            bs3Tab.setName(objectSpec.getAssociation(collectionId).getName());
+            
bs3Tab.setName(objectSpec.getAssociationElseFail(collectionId).getName());
             tabGroup.getTabs().add(bs3Tab);
             bs3Tab.setOwner(tabGroup);
 
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
index 193942b..bc75466 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
@@ -252,7 +252,7 @@ public class MetaModelServiceDefault implements 
MetaModelService {
         if(spec == null) {
             return null;
         }
-        final ObjectMember objectMemberIfAny = 
spec.getMember(featureId.getMemberName());
+        final ObjectMember objectMemberIfAny = 
spec.getMember(featureId.getMemberName()).orElse(null);
         if (objectMemberIfAny == null) {
             return null;
         }
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
index e6d2b81..d83cc8a 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
@@ -88,7 +88,7 @@ public interface ObjectSpecification extends Specification, 
ObjectActionContaine
         s1.getShortIdentifier().compareToIgnoreCase(s2.getShortIdentifier());
     }
 
-    ObjectMember getMember(String memberId);
+    Optional<? extends ObjectMember> getMember(String memberId);
 
     /**
      * @param onType
@@ -448,5 +448,7 @@ public interface ObjectSpecification extends Specification, 
ObjectActionContaine
         return isManagedBean() || isViewModel() || isEntity();
     }
 
+    
+
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
index 342eb02..6e88ed6 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
@@ -20,10 +20,12 @@
 package org.apache.isis.core.metamodel.spec.feature;
 
 import java.util.Collection;
+import java.util.Optional;
 import java.util.stream.Stream;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.core.commons.collections.Can;
+import org.apache.isis.core.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.spec.ActionType;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
@@ -34,7 +36,7 @@ public interface ObjectActionContainer {
     /**
      * Returns the action of the specified type with the specified signature.
      */
-    ObjectAction getObjectAction(ActionType type, String id, 
Can<ObjectSpecification> parameters);
+    Optional<ObjectAction> getObjectAction(ActionType type, String id, 
Can<ObjectSpecification> parameters);
 
     /**
      * Get the action object represented by the specified identity string.
@@ -46,7 +48,13 @@ public interface ObjectActionContainer {
      *
      * @see #getObjectAction(String)
      */
-    ObjectAction getObjectAction(ActionType type, String id);
+    Optional<ObjectAction> getObjectAction(ActionType type, String id);
+    
+    default ObjectAction getObjectActionElseFail(ActionType type, String id) {
+        return getObjectAction(type, id)
+                .orElseThrow(()->_Exceptions.noSuchElement("type=%s id=%s", 
type, id));  
+    }
+    
 
     /**
      * Get the action object represented by the specified identity string,
@@ -59,7 +67,12 @@ public interface ObjectActionContainer {
      *
      * @see #getObjectAction(ActionType, String)
      */
-    ObjectAction getObjectAction(String id);
+    Optional<ObjectAction> getObjectAction(String id);
+    
+    default ObjectAction getObjectActionElseFail(String id) {
+        return getObjectAction(id)
+                .orElseThrow(()->_Exceptions.noSuchElement("id=%s", id));  
+    }
 
     default Stream<ObjectAction> streamObjectActions(Contributed contributed) {
         return streamObjectActions(ActionType.ALL, contributed);
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociationContainer.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociationContainer.java
index 1576c02..87318f0 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociationContainer.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociationContainer.java
@@ -19,8 +19,10 @@
 
 package org.apache.isis.core.metamodel.spec.feature;
 
+import java.util.Optional;
 import java.util.stream.Stream;
 
+import org.apache.isis.core.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
 
 public interface ObjectAssociationContainer {
@@ -32,7 +34,13 @@ public interface ObjectAssociationContainer {
      * Throw a {@link ObjectSpecificationException} if no such association
      * exists.
      */
-    ObjectAssociation getAssociation(String id);
+    Optional<ObjectAssociation> getAssociation(String id);
+    
+    default ObjectAssociation getAssociationElseFail(String id) {
+        return getAssociation(id)
+                .orElseThrow(()->_Exceptions.noSuchElement("id=%s", id));
+    }
+    
 
     /**
      * Return all the fields that exist in an object of this specification,
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index 995d7b4..9b28d4f 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
@@ -80,7 +81,6 @@ import org.apache.isis.core.metamodel.spec.ActionType;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
 import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
@@ -684,18 +684,18 @@ public abstract class ObjectSpecificationAbstract extends 
FacetHolderImpl implem
     }
 
     @Override
-    public ObjectMember getMember(final String memberId) {
+    public Optional<? extends ObjectMember> getMember(final String memberId) {
         introspectUpTo(IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
 
         val objectAction = getObjectAction(memberId);
-        if(objectAction != null) {
+        if(objectAction.isPresent()) {
             return objectAction;
         }
         val association = getAssociation(memberId);
-        if(association != null) {
+        if(association.isPresent()) {
             return association;
         }
-        return null;
+        return Optional.empty();
     }
 
 
@@ -714,44 +714,11 @@ public abstract class ObjectSpecificationAbstract extends 
FacetHolderImpl implem
      * method for an {@link ObjectSpecificationOnContainer})
      */
     @Override
-    public ObjectAssociation getAssociation(final String id) {
+    public Optional<ObjectAssociation> getAssociation(final String id) {
         introspectUpTo(IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
-
-        ObjectAssociation oa = getAssociationWithId(id);
-        if(oa != null) {
-            return oa;
-        }
-        //TODO [2033] remove or replace        
-        //        if(IsisSystemEnvironment.get().isPrototyping()) {
-        //            // automatically refresh if not in production
-        //            // (better support for jrebel)
-        //
-        //            LOG.warn("Could not find association with id '{}'; 
invalidating cache automatically", id);
-        //            if(!invalidatingCache.get()) {
-        //                // make sure don't go into an infinite loop, though.
-        //                try {
-        //                    invalidatingCache.set(true);
-        //                    
getSpecificationLoader().invalidateCache(getCorrespondingClass());
-        //                } finally {
-        //                    invalidatingCache.set(false);
-        //                }
-        //            } else {
-        //                LOG.warn("... already invalidating cache earlier in 
stacktrace, so skipped this time");
-        //            }
-        //            oa = getAssociationWithId(id);
-        //            if(oa != null) {
-        //                return oa;
-        //            }
-        //        }
-        throw new ObjectSpecificationException(
-                String.format("No association called '%s' in '%s'", id, 
getSingularName()));
-    }
-
-    private ObjectAssociation getAssociationWithId(final String id) {
         return streamAssociations(Contributed.INCLUDED)
                 
.filter(objectAssociation->objectAssociation.getId().equals(id))
-                .findFirst()
-                .orElse(null);
+                .findFirst();
     }
 
     @Override
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 1f16d99..6591797 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -22,6 +22,7 @@ package 
org.apache.isis.core.metamodel.specloader.specimpl.dflt;
 import java.lang.reflect.Method;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.function.BiConsumer;
 import java.util.stream.Stream;
 
@@ -291,7 +292,7 @@ public class ObjectSpecificationDefault extends 
ObjectSpecificationAbstract impl
     // -- getObjectAction
 
     @Override
-    public ObjectAction getObjectAction(
+    public Optional<ObjectAction> getObjectAction(
             final ActionType type, 
             final String id, 
             final Can<ObjectSpecification> parameters) {
@@ -303,7 +304,7 @@ public class ObjectSpecificationDefault extends 
ObjectSpecificationAbstract impl
     }
 
     @Override
-    public ObjectAction getObjectAction(final ActionType type, final String 
id) {
+    public Optional<ObjectAction> getObjectAction(final ActionType type, final 
String id) {
         introspectUpTo(IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
 
         final Stream<ObjectAction> actions =
@@ -312,7 +313,7 @@ public class ObjectSpecificationDefault extends 
ObjectSpecificationAbstract impl
     }
 
     @Override
-    public ObjectAction getObjectAction(final String id) {
+    public Optional<ObjectAction> getObjectAction(final String id) {
         introspectUpTo(IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
 
         final Stream<ObjectAction> actions =
@@ -320,7 +321,7 @@ public class ObjectSpecificationDefault extends 
ObjectSpecificationAbstract impl
         return firstAction(actions, id);
     }
 
-    private static ObjectAction firstAction(
+    private static Optional<ObjectAction> firstAction(
             final Stream<ObjectAction> candidateActions,
             final String actionName,
             final Can<ObjectSpecification> parameters) {
@@ -328,8 +329,7 @@ public class ObjectSpecificationDefault extends 
ObjectSpecificationAbstract impl
         return candidateActions
                 .filter(action->actionName == null || 
actionName.equals(action.getId()))
                 .filter(action->isMatchingSignature(parameters, 
action.getParameters()))
-                .findAny()
-                .orElse(null);
+                .findAny();
     }
 
     private static  boolean isMatchingSignature(
@@ -351,7 +351,7 @@ public class ObjectSpecificationDefault extends 
ObjectSpecificationAbstract impl
         return true;
     }
 
-    private static ObjectAction firstAction(
+    private static Optional<ObjectAction> firstAction(
             final Stream<ObjectAction> candidateActions,
             final String id) {
 
@@ -371,8 +371,7 @@ public class ObjectSpecificationDefault extends 
ObjectSpecificationAbstract impl
                     }
                     return false;
                 })
-                .findFirst()
-                .orElse(null);
+                .findFirst();
     }
 
     /**
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/snapshot/XmlSnapshot.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/snapshot/XmlSnapshot.java
index a75ffe5..d326581 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/snapshot/XmlSnapshot.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/snapshot/XmlSnapshot.java
@@ -59,7 +59,6 @@ import 
org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
 import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
 import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
@@ -448,12 +447,10 @@ public class XmlSnapshot implements Snapshot {
 
         // locate the field in the object's class
         final ObjectSpecification nos = object.getSpecification();
-        ObjectAssociation field = null;
-        try {
-            // HACK: really want a ObjectSpecification.hasField method to
-            // check first.
-            field = nos.getAssociation(fieldName);
-        } catch (final ObjectSpecificationException ex) {
+        // HACK: really want a ObjectSpecification.hasField method to
+        // check first.
+        val field = nos.getAssociation(fieldName).orElse(null);
+        if (field == null) {
             if (log.isInfoEnabled()) {
                 log.info("includeField(Pl, Vec, Str): could not locate field, 
skipping");
             }
diff --git 
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
 
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
index 5cfa3af..134ab2b 100644
--- 
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
+++ 
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
@@ -21,12 +21,12 @@ package org.apache.isis.core.metamodel.testspec;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Stream;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.core.commons.collections.Can;
-import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.internal.collections._Lists;
 import org.apache.isis.core.commons.internal.ioc.BeanSort;
 import org.apache.isis.core.metamodel.consent.Consent;
@@ -49,6 +49,8 @@ import 
org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState;
 import org.apache.isis.core.security.authentication.AuthenticationSession;
 
+import lombok.val;
+
 public class ObjectSpecificationStub extends FacetHolderImpl implements 
ObjectSpecification {
 
     private ObjectAction action;
@@ -68,16 +70,16 @@ public class ObjectSpecificationStub extends 
FacetHolderImpl implements ObjectSp
     }
 
     @Override
-    public ObjectMember getMember(final String memberId) {
-        final ObjectAction objectAction = getObjectAction(memberId);
-        if(objectAction != null) {
+    public Optional<? extends ObjectMember> getMember(final String memberId) {
+        val objectAction = getObjectAction(memberId);
+        if(objectAction.isPresent()) {
             return objectAction;
         }
-        final ObjectAssociation association = getAssociation(memberId);
-        if(association != null) {
+        val association = getAssociation(memberId);
+        if(association.isPresent()) {
             return association;
         }
-        return null;
+        return Optional.empty();
     }
 
     @Override
@@ -110,13 +112,13 @@ public class ObjectSpecificationStub extends 
FacetHolderImpl implements ObjectSp
     }
 
     @Override
-    public ObjectAssociation getAssociation(final String name) {
+    public Optional<ObjectAssociation> getAssociation(final String name) {
         for (int i = 0; i < fields.size(); i++) {
             if (fields.get(i).getId().equals(name)) {
-                return fields.get(i);
+                return Optional.ofNullable(fields.get(i));
             }
         }
-        throw new IsisException("Field not found: " + name);
+        return Optional.empty();
     }
 
     @Override
@@ -153,32 +155,32 @@ public class ObjectSpecificationStub extends 
FacetHolderImpl implements ObjectSp
     }
 
     @Override
-    public ObjectAction getObjectAction(
+    public Optional<ObjectAction> getObjectAction(
             final ActionType type,
             final String name, 
             final Can<ObjectSpecification> parameters) {
         
         if (action != null && action.getId().equals(name)) {
-            return action;
+            return Optional.of(action);
         }
-        return null;
+        return Optional.empty();
     }
 
     @Override
-    public ObjectAction getObjectAction(final ActionType type, final String 
id) {
+    public Optional<ObjectAction> getObjectAction(final ActionType type, final 
String id) {
         final int openBracket = id.indexOf('(');
         return getObjectAction(type, id.substring(0, openBracket), null);
     }
 
     @Override
-    public ObjectAction getObjectAction(final String nameParmsIdentityString) {
+    public Optional<ObjectAction> getObjectAction(final String 
nameParmsIdentityString) {
         for (final ActionType type : ActionType.values()) {
-            final ObjectAction action = getObjectAction(type, 
nameParmsIdentityString);
-            if (action != null) {
+            val action = getObjectAction(type, nameParmsIdentityString);
+            if (action.isPresent()) {
                 return action;
             }
         }
-        return null;
+        return Optional.empty();
     }
 
     @Override
diff --git 
a/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
 
b/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
index beb7f29..24d8cc0 100644
--- 
a/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
+++ 
b/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
@@ -106,34 +106,34 @@ class DomainModelTest_usingGoodDomain {
         val holderSpec = 
specificationLoader.loadSpecification(ProperMemberSupport.class, 
                         IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
         
-        val mx_mixin = holderSpec.getObjectAction("action2"); // proper 
mixed-in action support
+        val mx_mixin = holderSpec.getObjectActionElseFail("action2"); // 
proper mixed-in action support
         assertNotNull(mx_mixin);
         
-        val mx_action = holderSpec.getObjectAction("action"); // when @Action 
at type level
+        val mx_action = holderSpec.getObjectActionElseFail("action"); // when 
@Action at type level
         assertNotNull(mx_action);
         assertEquals("action", mx_action.getId());
         assertEquals("foo", mx_action.getName());
         assertEquals("bar", mx_action.getDescription());
         
-        val mx_property = holderSpec.getAssociation("property"); // when 
@Property at type level
+        val mx_property = holderSpec.getAssociationElseFail("property"); // 
when @Property at type level
         assertNotNull(mx_property);
         assertEquals("property", mx_property.getId());
         assertEquals("foo", mx_property.getName());
         assertEquals("bar", mx_property.getDescription());
         
-        val mx_property2 = holderSpec.getAssociation("property2"); // when 
@Property at method level
+        val mx_property2 = holderSpec.getAssociationElseFail("property2"); // 
when @Property at method level
         assertNotNull(mx_property2);
         assertEquals("property2", mx_property2.getId());
         assertEquals("foo", mx_property2.getName());
         assertEquals("bar", mx_property2.getDescription());
         
-        val mx_collection = holderSpec.getAssociation("collection"); // when 
@Collection at type level
+        val mx_collection = holderSpec.getAssociationElseFail("collection"); 
// when @Collection at type level
         assertNotNull(mx_collection);
         assertEquals("collection", mx_collection.getId());
         assertEquals("foo", mx_collection.getName());
         assertEquals("bar", mx_collection.getDescription());
         
-        val mx_collection2 = holderSpec.getAssociation("collection2"); // when 
@Collection at method level
+        val mx_collection2 = holderSpec.getAssociationElseFail("collection2"); 
// when @Collection at method level
         assertNotNull(mx_collection2);
         assertEquals("collection2", mx_collection2.getId());
         assertEquals("foo", mx_collection2.getName());
diff --git 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainTypeResourceServerside.java
 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainTypeResourceServerside.java
index ee8ff97..cf8c818 100644
--- 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainTypeResourceServerside.java
+++ 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainTypeResourceServerside.java
@@ -39,9 +39,7 @@ import 
org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
 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.ObjectMember;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
@@ -71,6 +69,8 @@ import 
org.apache.isis.viewer.restfulobjects.rendering.util.Util;
 import 
org.apache.isis.viewer.restfulobjects.viewer.resources.serialization.SerializationStrategy;
 import org.apache.isis.viewer.restfulobjects.viewer.util.UrlParserUtils;
 
+import lombok.val;
+
 /**
  * Implementation note: it seems to be necessary to annotate the implementation
  * with {@link Path} rather than the interface (at least under RestEasy 1.0.2
@@ -160,8 +160,10 @@ public class DomainTypeResourceServerside extends 
ResourceAbstract implements Do
             throw 
RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
         }
 
-        final ObjectMember objectMember = 
parentSpec.getAssociation(propertyId);
-        if (objectMember == null || objectMember.isOneToManyAssociation()) {
+        val objectMember = parentSpec.getAssociation(propertyId)
+                
.orElseThrow(()->RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND));
+        
+        if (objectMember.isOneToManyAssociation()) {
             throw 
RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
         }
         final OneToOneAssociation property = (OneToOneAssociation) 
objectMember;
@@ -185,8 +187,10 @@ public class DomainTypeResourceServerside extends 
ResourceAbstract implements Do
             throw 
RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
         }
 
-        final ObjectMember objectMember = 
parentSpec.getAssociation(collectionId);
-        if (objectMember == null || objectMember.isOneToOneAssociation()) {
+        val objectMember = parentSpec.getAssociation(collectionId)
+                
.orElseThrow(()->RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND));
+        
+        if (objectMember.isOneToOneAssociation()) {
             throw 
RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
         }
         final OneToManyAssociation collection = (OneToManyAssociation) 
objectMember;
@@ -210,12 +214,9 @@ public class DomainTypeResourceServerside extends 
ResourceAbstract implements Do
             throw 
RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
         }
 
-        final ObjectMember objectMember = parentSpec.getObjectAction(actionId);
-        if (objectMember == null) {
-            throw 
RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
-        }
-        final ObjectAction action = (ObjectAction) objectMember;
-
+        val action = parentSpec.getObjectAction(actionId)
+                
.orElseThrow(()->RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND));
+        
         final ActionDescriptionReprRenderer renderer = new 
ActionDescriptionReprRenderer(getResourceContext(), null, 
JsonRepresentation.newMap());
         renderer.with(new ParentSpecAndAction(parentSpec, 
action)).includesSelf();
 
@@ -235,12 +236,9 @@ public class DomainTypeResourceServerside extends 
ResourceAbstract implements Do
             throw 
RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
         }
 
-        final ObjectMember objectMember = parentSpec.getObjectAction(actionId);
-        if (objectMember == null) {
-            throw 
RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
-        }
-        final ObjectAction parentAction = (ObjectAction) objectMember;
-
+        val parentAction = parentSpec.getObjectAction(actionId)
+                
.orElseThrow(()->RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND));
+        
         final ObjectActionParameter actionParam = 
parentAction.getParameterByName(paramName);
 
         final ActionParameterDescriptionReprRenderer renderer = new 
ActionParameterDescriptionReprRenderer(getResourceContext(), null, 
JsonRepresentation.newMap());
diff --git 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java
 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java
index 679db6c..28bb25c 100644
--- 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java
+++ 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java
@@ -22,9 +22,7 @@ import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
-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.ObjectAssociation;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
@@ -33,6 +31,8 @@ import 
org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
 import 
org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 import 
org.apache.isis.viewer.restfulobjects.rendering.domainobjects.MemberType;
 
+import lombok.val;
+
 /**
  * Utility class that encapsulates the logic for checking access to the 
specified
  * {@link ManagedObject}'s members.
@@ -63,16 +63,11 @@ public class ObjectAdapterAccessHelper {
     public OneToOneAssociation getPropertyThatIsVisibleForIntent(
             final String propertyId, final Intent intent) {
 
-        final ObjectAssociation association;
-        try {
-            final ObjectSpecification specification = 
objectAdapter.getSpecification();
-            association = specification.getAssociation(propertyId);
-        } catch(Exception ex) {
-            // fall through
-            throw notFoundException(propertyId, MemberType.PROPERTY);
-        }
+        val spec = objectAdapter.getSpecification();
+        val association = spec.getAssociation(propertyId)
+                .orElseThrow(()->notFoundException(propertyId, 
MemberType.PROPERTY));
 
-        if (association == null || !association.isOneToOneAssociation()) {
+        if (!association.isOneToOneAssociation()) {
             throw notFoundException(propertyId, MemberType.PROPERTY);
         }
 
@@ -83,17 +78,14 @@ public class ObjectAdapterAccessHelper {
     public OneToManyAssociation getCollectionThatIsVisibleForIntent(
             final String collectionId, final Intent intent) {
 
-        final ObjectAssociation association;
-        try {
-            final ObjectSpecification specification = 
objectAdapter.getSpecification();
-            association = specification.getAssociation(collectionId);
-        } catch(Exception ex) {
-            // fall through
-            throw notFoundException(collectionId, MemberType.COLLECTION);
-        }
-        if (association == null || !association.isOneToManyAssociation()) {
+        val spec = objectAdapter.getSpecification();
+        val association = spec.getAssociation(collectionId)
+                .orElseThrow(()->notFoundException(collectionId, 
MemberType.COLLECTION));
+        
+        if (!association.isOneToManyAssociation()) {
             throw notFoundException(collectionId, MemberType.COLLECTION);
         }
+        
         final OneToManyAssociation collection = (OneToManyAssociation) 
association;
         return memberThatIsVisibleForIntent(collection, MemberType.COLLECTION, 
intent);
     }
@@ -101,16 +93,10 @@ public class ObjectAdapterAccessHelper {
     public ObjectAction getObjectActionThatIsVisibleForIntent(
             final String actionId, final Intent intent) {
 
-        final ObjectAction action;
-        try {
-            final ObjectSpecification specification = 
objectAdapter.getSpecification();
-            action = specification.getObjectAction(actionId);
-        } catch(Exception ex) {
-            throw notFoundException(actionId, MemberType.ACTION);
-        }
-        if (action == null) {
-            throw notFoundException(actionId, MemberType.ACTION);
-        }
+        val spec = objectAdapter.getSpecification();
+        val action = spec.getObjectAction(actionId)
+                .orElseThrow(()->notFoundException(actionId, 
MemberType.ACTION));
+
         return memberThatIsVisibleForIntent(action, MemberType.ACTION, intent);
     }
 
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ActionMemento.java
 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ActionMemento.java
index 8a57e4d..3b2c3c5 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ActionMemento.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ActionMemento.java
@@ -88,7 +88,7 @@ public class ActionMemento implements Serializable {
             String nameParmsId,
             final SpecificationLoader specificationLoader) {
         final ObjectSpecification objectSpec = 
specificationLoader.lookupBySpecIdElseLoad(owningType);
-        return objectSpec.getObjectAction(actionType, nameParmsId);
+        return objectSpec.getObjectActionElseFail(actionType, nameParmsId);
     }
 
 }
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/CollectionMemento.java
 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/CollectionMemento.java
index 659fdfd..57292c7 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/CollectionMemento.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/CollectionMemento.java
@@ -103,7 +103,8 @@ public class CollectionMemento implements Serializable {
             ObjectSpecId owningType,
             String id,
             final SpecificationLoader specificationLoader) {
-        return (OneToManyAssociation) 
specificationLoader.lookupBySpecIdElseLoad(owningType).getAssociation(id);
+        return (OneToManyAssociation) 
specificationLoader.lookupBySpecIdElseLoad(owningType)
+                .getAssociationElseFail(id);
     }
 
 }
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PropertyMemento.java
 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PropertyMemento.java
index e6c0a00..f8ae5d1 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PropertyMemento.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PropertyMemento.java
@@ -81,7 +81,9 @@ public class PropertyMemento implements Serializable {
             ObjectSpecId owningType,
             String identifier,
             final SpecificationLoader specificationLoader) {
-        return (OneToOneAssociation) 
specificationLoader.lookupBySpecIdElseLoad(owningType).getAssociation(identifier);
+        
+        return (OneToOneAssociation) 
specificationLoader.lookupBySpecIdElseLoad(owningType)
+                .getAssociationElseFail(identifier);
     }
 
     /**
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
index c327696..a9f50f6 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
@@ -386,7 +386,7 @@ implements LinksProvider, UiHintContainer {
         final String collectionId = collectionLayoutData.getId();
         final ObjectSpecId objectSpecId = 
parentObjectAdapterMemento.getObjectSpecId();
         final ObjectSpecification objectSpec = 
specificationLoader.lookupBySpecIdElseLoad(objectSpecId);
-        final OneToManyAssociation otma = (OneToManyAssociation) 
objectSpec.getAssociation(collectionId);
+        final OneToManyAssociation otma = (OneToManyAssociation) 
objectSpec.getAssociationElseFail(collectionId);
         return otma;
     }
 
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
index 93dd5cd..c78a6c0 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
@@ -224,7 +224,7 @@ public final class ServiceActionUtil {
                     }
                     final EntityModel entityModel = 
EntityModel.ofAdapter(commonContext, serviceAdapter);
                     final ObjectAction objectAction = 
serviceAdapter.getSpecification()
-                            .getObjectAction(actionLayoutData.getId());
+                            
.getObjectAction(actionLayoutData.getId()).orElse(null);
                     if(objectAction == null) {
                         log.warn("No such action {}", 
actionLayoutData.getId());
                         continue;
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsSortableDataProvider.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsSortableDataProvider.java
index 950ad22..7e39671 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsSortableDataProvider.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsSortableDataProvider.java
@@ -37,8 +37,6 @@ import 
org.apache.isis.core.metamodel.interactions.InteractionUtils;
 import org.apache.isis.core.metamodel.interactions.ObjectVisibilityContext;
 import org.apache.isis.core.metamodel.interactions.VisibilityContext;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
@@ -125,16 +123,10 @@ public class CollectionContentsSortableDataProvider 
extends SortableDataProvider
             return null;
         }
 
-        final ObjectSpecification elementSpec = model.getTypeOfSpecification();
-        final String sortPropertyId = sort.getProperty();
+        val elementSpec = model.getTypeOfSpecification();
+        val sortPropertyId = sort.getProperty();
 
-        try {
-            // might be null, or throw ex
-            return elementSpec.getAssociation(sortPropertyId);
-        } catch(ObjectSpecificationException ex) {
-            // eg invalid propertyId
-            return null;
-        }
+        return elementSpec.getAssociation(sortPropertyId).orElse(null); // eg 
invalid propertyId
     }
 
     private Predicate<ManagedObject> ignoreHidden() {
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterPropertyColumn.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterPropertyColumn.java
index 15de3d7..4f26d37 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterPropertyColumn.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterPropertyColumn.java
@@ -111,7 +111,7 @@ public final class ObjectAdapterPropertyColumn extends 
ColumnAbstract<ManagedObj
 
         val adapter = rowModel.getObject();
         final EntityModel entityModel = 
EntityModel.ofAdapter(super.getCommonContext(), adapter);
-        final OneToOneAssociation property = (OneToOneAssociation) 
adapter.getSpecification().getAssociation(propertyExpression);
+        final OneToOneAssociation property = (OneToOneAssociation) 
adapter.getSpecification().getAssociationElseFail(propertyExpression);
         final PropertyMemento pm = new PropertyMemento(property);
 
         final ScalarModel scalarModel = entityModel.getPropertyModel(pm, 
EntityModel.Mode.VIEW, type.renderingHint());
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
index 15c0176..5642c5a 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
@@ -22,8 +22,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import javax.annotation.Nullable;
-
 import org.apache.wicket.Component;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
@@ -38,8 +36,6 @@ import org.apache.isis.core.commons.internal.base._Strings;
 import org.apache.isis.core.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
@@ -172,27 +168,18 @@ public class PropertyGroup extends 
PanelAbstract<EntityModel> implements HasDyna
         //
 
         val oas = _NullSafe.stream(properties)
-                .filter((final PropertyLayoutData propertyLayoutData) -> {
-                    return propertyLayoutData.getMetadataError() == null;
-                })
-                .map((final PropertyLayoutData propertyLayoutData)->{
-                    ObjectSpecification adapterSpecification = 
adapter.getSpecification();
-                    try {
-                        // this shouldn't happen, but has been reported 
(https://issues.apache.org/jira/browse/ISIS-1574),
-                        // suggesting that in some cases the GridService can 
get it wrong.  This is therefore a hack...
-                        return 
adapterSpecification.getAssociation(propertyLayoutData.getId());
-                    } catch (ObjectSpecificationException e) {
-                        return null;
-                    }
-                })
-                .filter((@Nullable final ObjectAssociation objectAssociation) 
-> {
-                    if(objectAssociation == null) {
-                        return false;
-                    }
-                    final HiddenFacet facet = 
objectAssociation.getFacet(HiddenFacet.class);
-                    if(facet != null && !facet.isFallback()) {
+                .filter(propertyLayoutData -> 
propertyLayoutData.getMetadataError() == null)
+                .map(propertyLayoutData -> 
+                    adapter.getSpecification()
+                    .getAssociation(propertyLayoutData.getId())
+                    .orElse(null)
+                )
+                .filter(_NullSafe::isPresent)
+                .filter(objectAssociation -> {
+                    val hiddenFacet = 
objectAssociation.getFacet(HiddenFacet.class);
+                    if(hiddenFacet != null && !hiddenFacet.isFallback()) {
                         // static invisible.
-                        if(facet.where() == Where.EVERYWHERE || facet.where() 
== Where.OBJECT_FORMS) {
+                        if(hiddenFacet.where() == Where.EVERYWHERE || 
hiddenFacet.where() == Where.OBJECT_FORMS) {
                             return false;
                         }
                     }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.java
index 2171db7..121943f 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.java
@@ -123,12 +123,11 @@ public class Col extends PanelAbstract<EntityModel> 
implements HasDynamicallyVis
         // (rendering depends on whether also showing the icon/title)
         final List<ActionLayoutData> actionLayoutDatas = bs3Col.getActions();
         val visibleActions = _NullSafe.stream(actionLayoutDatas)
-                .filter((final ActionLayoutData actionLayoutData) -> {
-                    return actionLayoutData.getMetadataError() == null;
-                })
-                .map((@Nullable final ActionLayoutData actionLayoutData) -> {
-                    return 
getModel().getTypeOfSpecification().getObjectAction(actionLayoutData.getId());
-                })
+                .filter(actionLayoutData -> 
actionLayoutData.getMetadataError() == null)
+                .filter(_NullSafe::isPresent)
+                .map(actionLayoutData -> 
+                    
getModel().getTypeOfSpecification().getObjectAction(actionLayoutData.getId()).orElse(null)
+                )
                 .filter(_NullSafe::isPresent)
                 .collect(Collectors.toList());
         //

Reply via email to