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 00:05:27 UTC

[3/4] git commit: ISIS-554: reworking dashboard into a @HomePage annotation

ISIS-554: reworking dashboard into a @HomePage annotation

instead of a @Dashboard service, instead we indicate that precisely (at most)
one domain service action is the @HomePage action.  This can return any object,
eg a view model representing a dashboard, or a simple list, or may even
accept arguments (in which case an action prompt will be automatically displayed).

In addition:
- slight hack to lazily maintain the specId cache after loading any spec
  - required for view model specs that are not eagerly loaded
- new convenience AbstractHomePageDashboardService added to applib
- ActionPanel's NoResultHandler removed, since had no function
  (and was causing the EmptyCollectionPanelFactory to not correctly render an empty
  collection for @HomePage action that returned no results)
- added convenience AbstractContainedObject#newViewModelInstance(...) method

Minor fixes to CSS:
- so that hovering over a plain label in a Wicket viewer
  table is shown as a regular default cursor, not a pointer (hand)
- on custom application.css in quickstart app, for x-abc demo styles

- minor fixes to CSS


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

Branch: refs/heads/master
Commit: d43a07a0d6a2f4b08dc6bce629d08f522b8b0875
Parents: ed4fa4a
Author: Dan Haywood <da...@apache.org>
Authored: Thu Oct 10 22:46:05 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Thu Oct 10 22:46:05 2013 +0100

----------------------------------------------------------------------
 .../wicket/viewer/IsisWicketApplication.java    |   2 +-
 .../wicket/model/common/NoResultsHandler.java   |  34 ------
 .../viewer/wicket/model/models/ActionModel.java |  50 ---------
 .../ui/components/actions/ActionPanel.java      |  13 ++-
 .../CollectionContentsAsAjaxTablePanel.css      |   5 +
 .../empty/EmptyCollectionPanelFactory.java      |   7 +-
 .../entity/EntityActionLinkFactory.java         |   8 +-
 .../viewer/wicket/ui/pages/home/HomePage.html   |   2 +-
 .../viewer/wicket/ui/pages/home/HomePage.java   |  47 ++++++--
 .../isis/applib/AbstractContainedObject.java    |  12 +++
 .../isis/applib/annotation/Dashboard.java       |  36 -------
 .../apache/isis/applib/annotation/HomePage.java |  41 +++++++
 .../AbstractHomePageDashboardService.java       |  93 ++++++++++++++++
 .../facets/actions/homepage/HomePageFacet.java  |  34 ++++++
 .../actions/homepage/HomePageFacetAbstract.java |  36 +++++++
 .../facets/object/dashboard/DashboardFacet.java |  34 ------
 .../dashboard/DashboardFacetAbstract.java       |  36 -------
 .../DeveloperUtilitiesServiceDefault.java       |   5 +-
 .../specloader/ObjectReflectorDefault.java      |   9 +-
 .../specloader/SpecificationCacheDefault.java   |   8 +-
 .../specimpl/ObjectSpecificationAbstract.java   |   4 +-
 .../dflt/ObjectSpecificationDefault.java        |   7 +-
 .../HomePageAnnotationFacetFactory.java         | 106 +++++++++++++++++++
 .../homepage/HomePageFacetAnnotation.java       |  30 ++++++
 .../actions/homepage/HomePageFacetImpl.java     |  31 ++++++
 .../DashboardAnnotationFacetFactory.java        |  95 -----------------
 .../dashboard/DashboardFacetAnnotation.java     |  30 ------
 .../object/dashboard/DashboardFacetImpl.java    |  31 ------
 .../dflt/ProgrammingModelFacetsJava5.java       |   4 +-
 .../HomePageAnnotationFacetFactoryTest.java     |  66 ++++++++++++
 .../DashboardAnnotationFacetFactoryTest.java    |  61 -----------
 .../system/persistence/OidGenerator.java        |   6 +-
 .../dom/src/main/java/app/ToDoAppDashboard.java |  31 ++++--
 .../main/java/app/ToDoAppDashboardService.java  |  49 +++++++++
 .../dom/src/main/java/dom/todo/ToDoItems.java   |   4 -
 .../src/main/resources/webapp/welcome.html      |   3 +-
 .../src/main/webapp/WEB-INF/isis.properties     |   2 +-
 .../webapp/src/main/webapp/css/application.css  |   5 +-
 38 files changed, 610 insertions(+), 467 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index a654776..c390dbb 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -58,7 +58,7 @@ import org.apache.isis.core.commons.resource.ResourceStreamSourceCurrentClassCla
 import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
-import org.apache.isis.core.metamodel.facets.object.dashboard.DashboardFacet;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
 import org.apache.isis.core.metamodel.services.ServiceUtil;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.runtime.logging.IsisLoggingConfigurer;

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/NoResultsHandler.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/NoResultsHandler.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/NoResultsHandler.java
deleted file mode 100644
index 93aa5e5..0000000
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/NoResultsHandler.java
+++ /dev/null
@@ -1,34 +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.model.common;
-
-import java.io.Serializable;
-
-import org.apache.wicket.Component;
-
-/**
- * Decouples the mechanism for letting the user acknowledge that no results
- * returned from action (eg an 'OK' button).
- */
-public interface NoResultsHandler extends Serializable {
-
-    void onNoResults(Component context);
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index 6c18727..672bb53 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -27,7 +27,6 @@ import java.util.regex.Pattern;
 
 import com.google.common.collect.Maps;
 
-import org.apache.wicket.Component;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 import org.apache.isis.applib.Identifier;
@@ -47,7 +46,6 @@ 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.runtime.system.context.IsisContext;
-import org.apache.isis.viewer.wicket.model.common.NoResultsHandler;
 import org.apache.isis.viewer.wicket.model.mementos.ActionMemento;
 import org.apache.isis.viewer.wicket.model.mementos.ActionParameterMemento;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
@@ -247,24 +245,6 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
         return objectAction.promptForParameters(contextAdapter)?Mode.PARAMETERS:Mode.RESULTS;
     }
 
-//	private static void addActionParamContextIfPossible(final ObjectAction objectAction, final ObjectAdapter contextAdapter, final PageParameters pageParameters) {
-//        if (contextAdapter == null) {
-//            return;
-//        }
-//        if(!objectAction.isContributed()) {
-//            return;
-//        }
-//        int i = 0;
-//        for (final ObjectActionParameter actionParam : objectAction.getParameters()) {
-//            if (ObjectActionParameters.compatibleWith(contextAdapter, actionParam)) {
-//                final String oidKeyValue = "" + i + "=" + contextAdapter.getOid().enString(getOidMarshaller());
-//                PageParameterNames.ACTION_PARAM_CONTEXT.addStringTo(pageParameters, oidKeyValue);
-//                return;
-//            }
-//            i++;
-//        }
-//    }
-
     private static String determineActionId(final ObjectAction objectAction) {
         final Identifier identifier = objectAction.getIdentifier();
         if (identifier != null) {
@@ -283,8 +263,6 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
     private Mode actionMode;
     private final SingleResultsMode singleResultsMode;
 
-    private NoResultsHandler noResultsHandler;
-
     /**
      * Lazily populated in {@link #getArgumentModel(ActionParameterMemento)}
      */
@@ -296,18 +274,6 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
 
         setArgumentsIfPossible(pageParameters);
         setContextArgumentIfPossible(pageParameters);
-
-        // TODO: if #args < param count, then change the actionMode
-
-        setNoResultsHandler(new NoResultsHandler() {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public void onNoResults(final Component context) {
-                reset();
-                context.setResponsePage(context.getPage());
-            }
-        });
     }
 
     private static ActionMemento newActionMementoFrom(final PageParameters pageParameters) {
@@ -320,7 +286,6 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
     private static ObjectAdapterMemento newObjectAdapterMementoFrom(final PageParameters pageParameters) {
         RootOid oid = oidFor(pageParameters);
         if(oid.isTransient()) {
-            //return ObjectAdapterMemento.
             return null;
         } else {
             return ObjectAdapterMemento.createPersistent(oid);
@@ -494,18 +459,6 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
         return arguments;
     }
 
-
-    /**
-     * The {@link NoResultsHandler}, if any,
-     */
-    public NoResultsHandler getNoResultsHandler() {
-        return noResultsHandler;
-    }
-
-    public void setNoResultsHandler(final NoResultsHandler noResultsHandler) {
-        this.noResultsHandler = noResultsHandler;
-    }
-
     public ActionExecutor getExecutor() {
         return executor;
     }
@@ -539,8 +492,6 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
         return bookmarkPolicy.value() == BookmarkPolicy.AS_ROOT && safeSemantics;
     }
 
-    
-    
     //////////////////////////////////////////////////
     // Dependencies (from context)
     //////////////////////////////////////////////////
@@ -550,5 +501,4 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
     }
 
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
index 50c0ccc..756b53c 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
@@ -78,7 +78,14 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
      * 
      * @see #hideAllBut(ComponentType)
      */
-    private static final List<ComponentType> COMPONENT_TYPES = Arrays.asList(ComponentType.PARAMETERS, ComponentType.ENTITY_LINK, ComponentType.ENTITY, ComponentType.VALUE, ComponentType.EMPTY_COLLECTION, ComponentType.VOID_RETURN, ComponentType.COLLECTION_CONTENTS);
+    private static final List<ComponentType> COMPONENT_TYPES = Arrays.asList(
+            ComponentType.PARAMETERS, 
+            ComponentType.ENTITY_LINK, 
+            ComponentType.ENTITY, 
+            ComponentType.VALUE, 
+            ComponentType.EMPTY_COLLECTION, 
+            ComponentType.VOID_RETURN, 
+            ComponentType.COLLECTION_CONTENTS);
 
     private static final String ID_ACTION_NAME = "actionName";
 
@@ -161,6 +168,9 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
         }
     }
 
+    /**
+     * @return whether to clear args or not (they aren't if there was a validation exception)
+     */
     private boolean executeActionOnTargetAndProcessResults(ObjectAdapter targetAdapter, MarkupContainer feedbackForm) {
 
         // validate the action parameters (if any)
@@ -181,7 +191,6 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
             getTransactionManager().flushTransaction();
             
             final ResultType resultType = ResultType.determineFor(resultAdapter);
-            
             resultType.addResults(this, resultAdapter);
 
             if (actionModel.isBookmarkable()) {

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css
index 60e2876..662f50d 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css
@@ -187,3 +187,8 @@
     color: #000;
     background-color:#E3E3D9;
 }
+
+/* bootstrap seems to set to 'pointer' */
+.collectionContentsAsAjaxTablePanel label:hover {
+	cursor: default;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/empty/EmptyCollectionPanelFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/empty/EmptyCollectionPanelFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/empty/EmptyCollectionPanelFactory.java
index 7186976..e35d158 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/empty/EmptyCollectionPanelFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/empty/EmptyCollectionPanelFactory.java
@@ -22,7 +22,6 @@ package org.apache.isis.viewer.wicket.ui.components.empty;
 import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
-import org.apache.isis.viewer.wicket.model.common.NoResultsHandler;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
@@ -41,11 +40,7 @@ public class EmptyCollectionPanelFactory extends ComponentFactoryAbstract implem
         if (!(model instanceof ActionModel)) {
             return ApplicationAdvice.DOES_NOT_APPLY;
         }
-        final ActionModel actionModel = (ActionModel) model;
-
-        final NoResultsHandler hasNoResultsHandler = actionModel.getNoResultsHandler();
-        // fail fast if a NoResultsHandler has not been specified
-        return appliesIf(hasNoResultsHandler != null);
+        return ApplicationAdvice.APPLIES;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/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 550206c..1dde6e8 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
@@ -103,9 +103,11 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
         final ObjectAdapter contextAdapter = entityModel.getObject();
 
         // use NO concurrency checking because the link is rendered on the entity page.
-        // REVIEW: is this good enough.  On the one hand we need it because otherwise a change done by this user basically prevents all actions from working
-        // on the other hand, if a change were made by some other user, then this user would want to know...
-        // perhaps the generated bookmarks need to subscribe to the EntityModel that backs the page?
+        
+        // REVIEW: is this good enough?  
+        // - On the one hand we need it because otherwise a change done by this user basically prevents all actions from working
+        // - on the other hand, if a change were made by some other user, then this user would want to know...
+        //   perhaps the generated bookmarks need to subscribe to the EntityModel that backs the page?
         final PageParameters pageParameters = ActionModel.createPageParameters(adapter, action, contextAdapter, ActionModel.SingleResultsMode.REDIRECT, ConcurrencyChecking.NO_CHECK);
         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/d43a07a0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html
index acc8113..2c57c08 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html
@@ -32,7 +32,7 @@
 			<div class="homePage">
                 <div wicket:id="bookmarks"/>
 				<div wicket:id="welcome"/>
-                <div wicket:id="entity"/>
+                <div wicket:id="action"/>
 			</div>
 		</wicket:extend>
 	</body>

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
index a1fd09e..4c0fb42 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
@@ -22,13 +22,21 @@ package org.apache.isis.viewer.wicket.ui.pages.home;
 import java.util.List;
 
 import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+import org.apache.wicket.model.IModel;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.facets.object.dashboard.DashboardFacet;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
+import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.mementos.ActionMemento;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.ActionModel.Mode;
+import org.apache.isis.viewer.wicket.model.models.ActionModel.SingleResultsMode;
+import org.apache.isis.viewer.wicket.model.util.MementoFunctions;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
 import org.apache.isis.viewer.wicket.ui.util.Components;
@@ -51,24 +59,41 @@ public class HomePage extends PageAbstract {
     }
 
     private void buildGui() {
-        final ObjectAdapter dashboardAdapter = lookupDashboard();
-        if(dashboardAdapter != null) {
+        final HomePageTuple homePageTuple = lookupHomePageAction();
+        if(homePageTuple != null) {
             Components.permanentlyHide(this, ComponentType.WELCOME); 
-            getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.ENTITY, new EntityModel(dashboardAdapter));
+            final ObjectAdapterMemento serviceMemento = MementoFunctions.fromAdapter().apply(homePageTuple.serviceAdapter);
+            ActionMemento homePageActionMemento = MementoFunctions.fromAction().apply(homePageTuple.action);
+            Mode mode = homePageTuple.action.getParameterCount() > 0? Mode.PARAMETERS : Mode.RESULTS;
+            final IModel<?> actionModel = ActionModel.create(serviceMemento, homePageActionMemento, mode, SingleResultsMode.INLINE);
+            getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.ACTION, actionModel);
         } else {
-            Components.permanentlyHide(this, ComponentType.ENTITY);
+            Components.permanentlyHide(this, ComponentType.ACTION);
             getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.WELCOME, null);
         }
     }
 
-    private ObjectAdapter lookupDashboard() {
-        List<ObjectAdapter> serviceAdapters = IsisContext.getPersistenceSession().getServices();
+    private static class HomePageTuple {
+        HomePageTuple(ObjectAdapter serviceAdapter, ObjectAction objectAction) {
+            this.serviceAdapter = serviceAdapter;
+            action = objectAction;
+        }
+        ObjectAdapter serviceAdapter;
+        ObjectAction action;
+    }
+    
+    private HomePageTuple lookupHomePageAction() {
+        List<ObjectAdapter> serviceAdapters = getPersistenceSession().getServices();
         for (ObjectAdapter serviceAdapter : serviceAdapters) {
             final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
-            if(serviceSpec.containsFacet(DashboardFacet.class)) {
-                return serviceAdapter;
+            List<ObjectAction> objectActions = serviceSpec.getObjectActions(Contributed.EXCLUDED);
+            for (ObjectAction objectAction : objectActions) {
+                if(objectAction.containsFacet(HomePageFacet.class)) {
+                    return new HomePageTuple(serviceAdapter, objectAction);
+                }
             }
         }
         return null;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java b/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
index 3882b80..c9703ed 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
@@ -25,6 +25,7 @@ import com.google.common.base.Predicate;
 
 import org.apache.isis.applib.annotation.Aggregated;
 import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.ViewModel;
 import org.apache.isis.applib.filter.Filter;
 import org.apache.isis.applib.query.Query;
 import org.apache.isis.applib.security.UserMemento;
@@ -76,6 +77,17 @@ public abstract class AbstractContainedObject {
     }
 
     /**
+     * Create a new {@link ViewModel} of specified type, identified by memento.
+     * 
+     * @param ofType
+     * @param memento
+     * @return
+     */
+    protected <T extends ViewModel> T newViewModelInstance(final Class<T> ofType, final String memento) {
+        return getContainer().newViewModelInstance(ofType, memento);
+    }
+
+    /**
      * Create an instance that will be persisted as part of this domain object
      * (ie this domain object is its parent in the aggregate).
      * 

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/applib/src/main/java/org/apache/isis/applib/annotation/Dashboard.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Dashboard.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Dashboard.java
deleted file mode 100644
index d319bc2..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Dashboard.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.applib.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Indicates that the domain service on which it is annotated should be rendered as the
- * home page, representing  dashboard of commonly accessed objects and invoked actions. 
- */
-@Inherited
-@Target({ ElementType.TYPE })
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Dashboard {
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/applib/src/main/java/org/apache/isis/applib/annotation/HomePage.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/HomePage.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/HomePage.java
new file mode 100644
index 0000000..03c040e
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/HomePage.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that the (no-arg) action (on a domain service) to be invoked automatically
+ * and the contents used for the home page.
+ * 
+ * <p>
+ * Typically this action would return a {@link ViewModel} representing a dashboard
+ * (from which the user can navigate to commonly used objects and invoked actions);
+ * it might also simply invoke an action that returns a list.
+ */
+@Inherited
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HomePage {
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/applib/src/main/java/org/apache/isis/applib/services/homepage/AbstractHomePageDashboardService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/homepage/AbstractHomePageDashboardService.java b/core/applib/src/main/java/org/apache/isis/applib/services/homepage/AbstractHomePageDashboardService.java
new file mode 100644
index 0000000..4c2390b
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/homepage/AbstractHomePageDashboardService.java
@@ -0,0 +1,93 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.homepage;
+
+import org.apache.isis.applib.AbstractService;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.HomePage;
+import org.apache.isis.applib.annotation.ViewModel;
+
+/**
+ * Convenience domain service to create a view model (eg a dashboard) to be rendered automatically
+ * on the home page of the application.
+ *
+ * <p>
+ * For example, subclass as follows:
+ * 
+ * <pre>
+ * public class MyAppDashboardService extends AbstractHomePageDashboardService&lt;MyAppDashboard&gt; {
+ *     public MyAppDashboardService() { super(MyAppDashboard.class); }
+ * }
+ * </pre>
+ * 
+ * <p>
+ * then register in <tt>isis.properties</tt> in the usual way.
+ * 
+ * <p>
+ * However, if your application requires more flexibility (for example, returning different view models 
+ * for different users), then do <i>not</i> subclass from this service; instead write your own service
+ * with a no-arg action with the {@link HomePage} annotation.
+ */
+@Hidden
+public abstract class AbstractHomePageDashboardService<T extends ViewModel> extends AbstractService {
+    
+    /**
+     * The default value to use for the {@link #id}.
+     */
+    private static final String ID_DEFAULT = "dashboard";
+    
+    private final Class<T> viewModel;
+    /**
+     * Both the id of this service, and also the memento of the view model.
+     */
+    private final String id;
+
+    public AbstractHomePageDashboardService(final Class<T> dashboardViewModel) {
+        this(dashboardViewModel, ID_DEFAULT);
+    }
+    
+    /**
+     * @param viewModel - view model to instantiate and return. 
+     * @param id- both the id of this service, and also the memento of the view model.
+     */
+    public AbstractHomePageDashboardService(final Class<T> viewModel, final String id) {
+        this.viewModel = viewModel;
+        this.id = id;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    public String iconName() {
+        return id;
+    }
+
+    // //////////////////////////////////////
+
+    @ActionSemantics(Of.SAFE)
+    @HomePage
+    public T lookup() {
+        return newViewModelInstance(viewModel, id);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/homepage/HomePageFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/homepage/HomePageFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/homepage/HomePageFacet.java
new file mode 100644
index 0000000..2285f62
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/homepage/HomePageFacet.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.actions.homepage;
+
+import org.apache.isis.core.metamodel.facets.MarkerFacet;
+
+/**
+ * Indicates that the (no-arg) action (on a domain service) to be invoked automatically
+ * and the contents used for the home page.
+ * 
+ * <p>
+ * In the standard Apache Isis Programming Model, typically corresponds to
+ * applying the <tt>@HomePage</tt> annotation at the class level.
+ */
+public interface HomePageFacet extends MarkerFacet {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/homepage/HomePageFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/homepage/HomePageFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/homepage/HomePageFacetAbstract.java
new file mode 100644
index 0000000..9b6acae
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/homepage/HomePageFacetAbstract.java
@@ -0,0 +1,36 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.actions.homepage;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
+
+public abstract class HomePageFacetAbstract extends MarkerFacetAbstract implements HomePageFacet {
+
+    public static Class<? extends Facet> type() {
+        return HomePageFacet.class;
+    }
+
+    public HomePageFacetAbstract(final FacetHolder holder) {
+        super(type(), holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/dashboard/DashboardFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/dashboard/DashboardFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/dashboard/DashboardFacet.java
deleted file mode 100644
index 614cd9a..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/dashboard/DashboardFacet.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets.object.dashboard;
-
-import org.apache.isis.core.metamodel.facets.MarkerFacet;
-
-/**
- * Indicates that the domain service on which it is annotated should be rendered as the
- * home page, representing  dashboard of commonly accessed objects and invoked actions. 
- * 
- * <p>
- * In the standard Apache Isis Programming Model, typically corresponds to
- * applying the <tt>@Dashboard</tt> annotation at the class level.
- */
-public interface DashboardFacet extends MarkerFacet {
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/dashboard/DashboardFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/dashboard/DashboardFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/dashboard/DashboardFacetAbstract.java
deleted file mode 100644
index f3bf664..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/dashboard/DashboardFacetAbstract.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets.object.dashboard;
-
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
-
-public abstract class DashboardFacetAbstract extends MarkerFacetAbstract implements DashboardFacet {
-
-    public static Class<? extends Facet> type() {
-        return DashboardFacet.class;
-    }
-
-    public DashboardFacetAbstract(final FacetHolder holder) {
-        super(type(), holder);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
index b57bbc3..47cbee7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
@@ -43,7 +43,7 @@ import org.apache.isis.applib.value.Clob;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManagerAware;
-import org.apache.isis.core.metamodel.facets.object.dashboard.DashboardFacet;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
 import org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
@@ -171,8 +171,7 @@ public class DeveloperUtilitiesServiceDefault implements DeveloperUtilitiesServi
             @Override
             public boolean apply(ObjectSpecification input) {
                 return  !input.isAbstract() && 
-                        (!input.isService() || 
-                          input.isService() && input.containsFacet(DashboardFacet.class)) && 
+                        !input.isService() && 
                         !input.isValue() && 
                         !input.isParentedOrFreeCollection();
             }});

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
index df0c261..cd5b944 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
@@ -405,7 +405,14 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App
      */
     @Override
     public ObjectSpecification loadSpecification(final Class<?> type) {
-        return internalLoadSpecification(type);
+        final ObjectSpecification spec = internalLoadSpecification(type);
+        if(spec == null) {
+            return null;
+        }
+        if(getCache().isInitialized() && getCache().getByObjectType(spec.getSpecId()) == null) {
+            getCache().recache(spec.getSpecId(), spec);
+        }
+        return spec;
     }
 
     private ObjectSpecification internalLoadSpecification(final Class<?> type) {

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java
index 1078520..1933a72 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java
@@ -52,14 +52,14 @@ class SpecificationCacheDefault {
     }
 
     public ObjectSpecification getByObjectType(ObjectSpecId objectSpecID) {
-        if (specById == null) {
+        if (!isInitialized()) {
             throw new IllegalStateException("SpecificationCache by object type has not yet been initialized");
         }
         return specById.get(objectSpecID);
     }
 
     /**
-     * Populated as a result of running {@link MetaModelValidator#validate() validation} after all specs have been loaded. 
+     * Populated as a result of running {@link MetaModelValidator#validate() validation} after xxxallxxx most specs have been loaded. 
      */
     void setCacheBySpecId(Map<ObjectSpecId, ObjectSpecification> specById) {
         this.specById = Maps.newHashMap();
@@ -82,5 +82,9 @@ class SpecificationCacheDefault {
     public void recache(ObjectSpecId specId, ObjectSpecification spec) {
         specById.put(specId, spec);
     }
+    
+    boolean isInitialized() {
+        return specById != null;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
----------------------------------------------------------------------
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 79f3c4f..fca48aa 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
@@ -52,6 +52,7 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetHolderImpl;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
 import org.apache.isis.core.metamodel.facets.describedas.DescribedAsFacet;
 import org.apache.isis.core.metamodel.facets.help.HelpFacet;
@@ -59,7 +60,6 @@ import org.apache.isis.core.metamodel.facets.hide.HiddenFacet;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import org.apache.isis.core.metamodel.facets.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.object.aggregated.ParentedFacet;
-import org.apache.isis.core.metamodel.facets.object.dashboard.DashboardFacet;
 import org.apache.isis.core.metamodel.facets.object.dirty.ClearDirtyObjectFacet;
 import org.apache.isis.core.metamodel.facets.object.dirty.IsDirtyObjectFacet;
 import org.apache.isis.core.metamodel.facets.object.dirty.MarkDirtyObjectFacet;
@@ -965,7 +965,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
      * then returns an empty list.
      */
     protected List<ObjectAction> createContributeeActions() {
-        if (isService() && !containsFacet(DashboardFacet.class)) {
+        if (isService()) {
             return Collections.emptyList();
         }
         final List<ObjectAction> contributeeActions = Lists.newArrayList();

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
----------------------------------------------------------------------
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 50c0925..e5f376c 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
@@ -47,11 +47,11 @@ import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.FacetedMethod;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
 import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
 import org.apache.isis.core.metamodel.facets.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.named.NamedFacetInferred;
 import org.apache.isis.core.metamodel.facets.object.callbacks.CallbackUtils;
 import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedCallbackFacet;
-import org.apache.isis.core.metamodel.facets.object.dashboard.DashboardFacet;
 import org.apache.isis.core.metamodel.facets.object.icon.IconFacet;
 import org.apache.isis.core.metamodel.facets.object.plural.PluralFacet;
 import org.apache.isis.core.metamodel.facets.object.plural.PluralFacetInferred;
@@ -283,10 +283,7 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
      */
     @Override
     public void markAsService() {
-        // the dashboard service can contain associations; no other. 
-        if(!containsFacet(DashboardFacet.class)) {
-            ensureServiceHasNoAssociations();
-        }
+        ensureServiceHasNoAssociations();
         isService = true;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageAnnotationFacetFactory.java
new file mode 100644
index 0000000..6c95a79
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageAnnotationFacetFactory.java
@@ -0,0 +1,106 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.homepage;
+
+import java.util.List;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.annotation.HomePage;
+import org.apache.isis.applib.services.homepage.AbstractHomePageDashboardService;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
+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.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor;
+import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+
+public class HomePageAnnotationFacetFactory extends FacetFactoryAbstract implements MetaModelValidatorRefiner{
+
+    public HomePageAnnotationFacetFactory() {
+        super(FeatureType.ACTIONS_ONLY);
+    }
+
+    @Override
+    public void process(ProcessMethodContext processMethodContext) {
+        final HomePage annotation = Annotations.getAnnotation(processMethodContext.getMethod(), HomePage.class);
+        if (annotation == null) {
+            return;
+        } 
+        final FacetedMethod facetHolder = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new HomePageFacetAnnotation(facetHolder));
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner#refineMetaModelValidator(org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite, org.apache.isis.core.commons.config.IsisConfiguration)
+     */
+    @Override
+    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
+        metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor()));
+    }
+
+    private Visitor newValidatorVisitor() {
+        return new MetaModelValidatorVisiting.SummarizingVisitor() {
+
+            private final List<String> annotated = Lists.newArrayList();
+            
+            @Override
+            public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
+                final List<ObjectAction> objectActions = objectSpec.getObjectActions(Contributed.EXCLUDED);
+                if(objectSpec.getCorrespondingClass() == AbstractHomePageDashboardService.class) {
+                    // ignore this one
+                    return true;
+                }
+                for (ObjectAction objectAction : objectActions) {
+                    if(objectAction.containsFacet(HomePageFacet.class)) {
+                        final String fullIdentifier = objectAction.getIdentifier().toClassAndNameIdentityString();
+                        
+                        // TODO: it would good to flag if the facet is found on any non-services, however
+                        // ObjectSpecification.isService(...) can only be trusted once a PersistenceSession exists.
+                        // this ought to be improved upon at some point...
+                        annotated.add(fullIdentifier);
+                        
+                    }
+                }
+                return true; // keep searching
+            }
+
+            @Override
+            public void summarize(ValidationFailures validationFailures) {
+                if(annotated.size()>1) {
+                    final String nonServiceNamesStr = Joiner.on(", ").join(annotated);
+                    validationFailures.add(
+                            "Only one service action can be specified as the dashboard; "
+                            + "found HomePageFacet on these actions: %s", nonServiceNamesStr);
+                }
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageFacetAnnotation.java
new file mode 100644
index 0000000..a0e212a
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageFacetAnnotation.java
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.homepage;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+
+public class HomePageFacetAnnotation extends HomePageFacetImpl {
+
+    public HomePageFacetAnnotation(final FacetHolder holder) {
+        super(holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageFacetImpl.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageFacetImpl.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageFacetImpl.java
new file mode 100644
index 0000000..7160d30
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageFacetImpl.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.homepage;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacetAbstract;
+
+public class HomePageFacetImpl extends HomePageFacetAbstract {
+
+    public HomePageFacetImpl(final FacetHolder holder) {
+        super(holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardAnnotationFacetFactory.java
deleted file mode 100644
index 833f0e8..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardAnnotationFacetFactory.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.progmodel.facets.object.dashboard;
-
-import java.util.List;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.Lists;
-
-import org.apache.isis.applib.annotation.Dashboard;
-import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facetapi.FacetUtil;
-import org.apache.isis.core.metamodel.facetapi.FeatureType;
-import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner;
-import org.apache.isis.core.metamodel.facets.Annotations;
-import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.isis.core.metamodel.facets.object.dashboard.DashboardFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
-import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting;
-import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor;
-import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
-
-public class DashboardAnnotationFacetFactory extends FacetFactoryAbstract implements MetaModelValidatorRefiner{
-
-    public DashboardAnnotationFacetFactory() {
-        super(FeatureType.OBJECTS_ONLY);
-    }
-
-    @Override
-    public void process(final ProcessClassContext processClassContext) {
-        final Dashboard annotation = Annotations.getAnnotation(processClassContext.getCls(), Dashboard.class);
-        FacetUtil.addFacet(create(annotation, processClassContext.getFacetHolder()));
-    }
-
-    private DashboardFacet create(final Dashboard annotation, final FacetHolder holder) {
-        return annotation != null ? new DashboardFacetAnnotation(holder) : null;
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner#refineMetaModelValidator(org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite, org.apache.isis.core.commons.config.IsisConfiguration)
-     */
-    @Override
-    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
-        metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor()));
-    }
-
-    private Visitor newValidatorVisitor() {
-        return new MetaModelValidatorVisiting.SummarizingVisitor() {
-
-            private final List<String> annotated = Lists.newArrayList();
-            
-            @Override
-            public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
-                if(objectSpec.containsFacet(DashboardFacet.class)) {
-                    final String fullIdentifier = objectSpec.getFullIdentifier();
-                    
-                    // TODO: it would good to flag if the facet is found on any non-services, however
-                    // ObjectSpecification.isService(...) can only be trusted once a PersistenceSession exists.
-                    // this ought to be improved upon at some point...
-                    annotated.add(fullIdentifier);
-                }
-                return true; // keep searching
-            }
-
-            @Override
-            public void summarize(ValidationFailures validationFailures) {
-                if(annotated.size()>1) {
-                    final String nonServiceNamesStr = Joiner.on(", ").join(annotated);
-                    validationFailures.add(
-                            "Only one service can be specified as the dashboard; "
-                            + "found DashboardFacet on these classes: %s", nonServiceNamesStr);
-                }
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardFacetAnnotation.java
deleted file mode 100644
index 811a245..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardFacetAnnotation.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.progmodel.facets.object.dashboard;
-
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-
-public class DashboardFacetAnnotation extends DashboardFacetImpl {
-
-    public DashboardFacetAnnotation(final FacetHolder holder) {
-        super(holder);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardFacetImpl.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardFacetImpl.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardFacetImpl.java
deleted file mode 100644
index 73ced39..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardFacetImpl.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.progmodel.facets.object.dashboard;
-
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.object.dashboard.DashboardFacetAbstract;
-
-public class DashboardFacetImpl extends DashboardFacetAbstract {
-
-    public DashboardFacetImpl(final FacetHolder holder) {
-        super(holder);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index cd66a72..a136d39 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -26,6 +26,7 @@ import org.apache.isis.core.progmodel.facets.actions.bulk.annotation.BulkAnnotat
 import org.apache.isis.core.progmodel.facets.actions.debug.annotation.DebugAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.defaults.method.ActionDefaultsFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.exploration.annotation.ExplorationAnnotationFacetFactory;
+import org.apache.isis.core.progmodel.facets.actions.homepage.HomePageAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.invoke.ActionInvocationFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.notcontributed.annotation.NotContributedAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.notinservicemenu.annotation.NotInServiceMenuAnnotationFacetFactory;
@@ -76,7 +77,6 @@ import org.apache.isis.core.progmodel.facets.object.callbacks.remove.RemoveCallb
 import org.apache.isis.core.progmodel.facets.object.callbacks.update.UpdateCallbackFacetFactory;
 import org.apache.isis.core.progmodel.facets.object.choices.enums.EnumFacetFactory;
 import org.apache.isis.core.progmodel.facets.object.cssclass.CssClassAnnotationForTypeFacetFactory;
-import org.apache.isis.core.progmodel.facets.object.dashboard.DashboardAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.object.defaults.annotation.DefaultedAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.object.describedas.annotation.DescribedAsAnnotationOnTypeFacetFactory;
 import org.apache.isis.core.progmodel.facets.object.dirty.method.DirtyMethodsFacetFactory;
@@ -317,7 +317,7 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         
         addFactory(AggregatedAnnotationFacetFactory.class);
         addFactory(BookmarkableAnnotationFacetFactory.class);
-        addFactory(DashboardAnnotationFacetFactory.class);
+        addFactory(HomePageAnnotationFacetFactory.class);
         addFactory(BoundedAnnotationFacetFactory.class);
         addFactory(BoundedMarkerInterfaceFacetFactory.class);
         addFactory(DebugAnnotationFacetFactory.class);

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageAnnotationFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageAnnotationFacetFactoryTest.java
new file mode 100644
index 0000000..df966b1
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/actions/homepage/HomePageAnnotationFacetFactoryTest.java
@@ -0,0 +1,66 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.homepage;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.applib.annotation.HomePage;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
+import org.apache.isis.core.metamodel.facets.actions.semantics.ActionSemanticsFacet;
+import org.apache.isis.core.progmodel.facets.AbstractFacetFactoryTest;
+
+public class HomePageAnnotationFacetFactoryTest extends AbstractFacetFactoryTest {
+
+    private HomePageAnnotationFacetFactory facetFactory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        facetFactory = new HomePageAnnotationFacetFactory();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        facetFactory = null;
+        super.tearDown();
+    }
+
+    public void testHomePageAnnotationPickedUpOnAction() {
+        class HomePageService {
+            @HomePage
+            public Object lookup() { return null; }
+        }
+
+        final Method actionMethod = findMethod(HomePageService.class, "lookup");
+
+        facetFactory.process(new ProcessMethodContext(Customer.class, null, null, actionMethod, methodRemover, facetedMethod));
+
+        final Facet facet = facetedMethod.getFacet(HomePageFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof HomePageFacetAnnotation);
+
+        assertNoMethodsRemoved();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardAnnotationFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardAnnotationFacetFactoryTest.java
deleted file mode 100644
index eae4a49..0000000
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/dashboard/DashboardAnnotationFacetFactoryTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.progmodel.facets.object.dashboard;
-
-import org.apache.isis.applib.annotation.Dashboard;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessClassContext;
-import org.apache.isis.core.metamodel.facets.object.dashboard.DashboardFacet;
-import org.apache.isis.core.progmodel.facets.AbstractFacetFactoryTest;
-
-public class DashboardAnnotationFacetFactoryTest extends AbstractFacetFactoryTest {
-
-    private DashboardAnnotationFacetFactory facetFactory;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        facetFactory = new DashboardAnnotationFacetFactory();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        facetFactory = null;
-        super.tearDown();
-    }
-
-    public void testDashboardAnnotationPickedUpOnClass() {
-        @Dashboard
-        class Customer {
-        }
-
-        facetFactory.process(new ProcessClassContext(Customer.class, methodRemover, facetedMethod));
-
-        final Facet facet = facetedMethod.getFacet(DashboardFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof DashboardFacetAnnotation);
-        final DashboardFacetAnnotation notPersistableFacetAnnotation = (DashboardFacetAnnotation) facet;
-
-        assertNoMethodsRemoved();
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/OidGenerator.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/OidGenerator.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/OidGenerator.java
index a6aadef..12a3349 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/OidGenerator.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/OidGenerator.java
@@ -63,10 +63,10 @@ public class OidGenerator implements DebuggableWithTitle {
      * supplied pojo, uniquely distinguishable from any other {@link Oid}.
      */
     public final RootOid createTransientOrViewModelOid(final Object pojo) {
-        final ObjectSpecId objectSpecId = objectSpecIdFor(pojo);
+        ObjectSpecification spec = getSpecificationLookup().loadSpecification(pojo.getClass());
+        final ObjectSpecId objectSpecId = spec.getSpecId();
         final String transientIdentifier = identifierGenerator.createTransientIdentifierFor(objectSpecId, pojo);
-        final ObjectSpecification spec = getSpecificationLookup().lookupBySpecId(objectSpecId);
-        final State state = spec != null && spec.containsFacet(ViewModelFacet.class)? State.VIEWMODEL:State.TRANSIENT;
+        final State state = spec.containsFacet(ViewModelFacet.class)? State.VIEWMODEL:State.TRANSIENT;
         return new RootOidDefault(objectSpecId, transientIdentifier, state);
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboard.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboard.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboard.java
index afdb2ed..4fea1b5 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboard.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboard.java
@@ -20,30 +20,39 @@ package app;
 
 import java.util.List;
 
-import org.apache.isis.applib.AbstractFactoryAndRepository;
-import org.apache.isis.applib.annotation.Dashboard;
+import org.apache.isis.applib.AbstractViewModel;
 import org.apache.isis.applib.annotation.Disabled;
 import org.apache.isis.applib.annotation.Named;
 import org.apache.isis.applib.annotation.Render;
 import org.apache.isis.applib.annotation.Render.Type;
 
-@Dashboard
-@Named("Dashboard")
-public class ToDoAppDashboard extends AbstractFactoryAndRepository {
+public class ToDoAppDashboard extends AbstractViewModel {
 
+    public String title() {
+        return "Dashboard";
+    }
+    
+    public String iconName() {
+        return "Dashboard";
+    }
+    
     // //////////////////////////////////////
-    // Identification in the UI
+    // ViewModel contract
     // //////////////////////////////////////
 
+    private String memento;
+    
     @Override
-    public String getId() {
-        return "dashboard";
+    public String viewModelMemento() {
+        return memento;
     }
 
-    public String iconName() {
-        return "Dashboard";
+    @Override
+    public void viewModelInit(String memento) {
+        this.memento = memento;
     }
 
+
     // //////////////////////////////////////
     // getAnalysisByCategory
     // //////////////////////////////////////
@@ -72,8 +81,10 @@ public class ToDoAppDashboard extends AbstractFactoryAndRepository {
     // //////////////////////////////////////
     
     private ToDoItemAnalysis toDoItemAnalysis;
+    
     public void injectToDoItemAnalysis(ToDoItemAnalysis toDoItemAnalysis) {
         this.toDoItemAnalysis = toDoItemAnalysis;
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboardService.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboardService.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboardService.java
new file mode 100644
index 0000000..4b8e2772
--- /dev/null
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/app/ToDoAppDashboardService.java
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package app;
+
+import org.apache.isis.applib.AbstractService;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.HomePage;
+
+@Hidden
+public class ToDoAppDashboardService extends AbstractService {
+
+    private static final String ID = "dashboard";
+
+    public String getId() {
+        return ID;
+    }
+
+    public String iconName() {
+        return ID;
+    }
+
+    // //////////////////////////////////////
+
+    @ActionSemantics(Of.SAFE)
+    @HomePage
+    public ToDoAppDashboard lookup() {
+        return newViewModelInstance(ToDoAppDashboard.class, ID);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
index 133d014..1d9b7fb 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
@@ -22,8 +22,6 @@ import java.math.BigDecimal;
 import java.util.Collections;
 import java.util.List;
 
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 
 import dom.todo.ToDoItem.Category;
@@ -31,12 +29,10 @@ import dom.todo.ToDoItem.Subcategory;
 
 import org.joda.time.LocalDate;
 
-import org.apache.isis.applib.AbstractFactoryAndRepository;
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.annotation.ActionSemantics;
 import org.apache.isis.applib.annotation.ActionSemantics.Of;
 import org.apache.isis.applib.annotation.Bookmarkable;
-import org.apache.isis.applib.annotation.Dashboard;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Named;
 import org.apache.isis.applib.annotation.Optional;

http://git-wip-us.apache.org/repos/asf/isis/blob/d43a07a0/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/welcome.html
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/welcome.html b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/welcome.html
index b9e77fc..8cd6f04 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/welcome.html
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/welcome.html
@@ -24,8 +24,7 @@
     <br/>
     This app has been generated using Isis' 
     <a href="http://isis.apache.org/getting-started/quickstart-archetype.html">quickstart</a> archetype, 
-    which configures Isis' most commonly used components as part of a straightforward
-    &quot;todo&quot; app.
+    which configures Isis' most commonly used components in a straightforward &quot;todo&quot; app.
     <br/>
     <br/>
     The core domain functionality class is provided by the <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java"  target="_blank">ToDoItem</a> domain class.