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 2015/11/13 18:57:15 UTC

[04/11] isis git commit: ISIS-915 and ISIS-1251: use JAXB to create memento for the RecreatableObjectFacetForXmlRootElementAnnotation implementation of ViewModelFacet. Also factored out UrlEncodingService.

ISIS-915 and ISIS-1251: use JAXB to create memento for the RecreatableObjectFacetForXmlRootElementAnnotation implementation of ViewModelFacet.  Also factored out UrlEncodingService.


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

Branch: refs/heads/master
Commit: 9163f6db4fd5214057ee3562e0fae2c52ce0df36
Parents: b599436
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Nov 13 09:59:11 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Nov 13 09:59:11 2015 +0000

----------------------------------------------------------------------
 .../isis/applib/services/jaxb/JaxbService.java  |   6 +-
 .../urlencoding/UrlEncodingService.java         |  44 +++++
 ...bleObjectFacetForDomainObjectAnnotation.java |   7 +-
 .../RecreatableObjectFacetAbstract.java         |  45 ++++-
 ...creatableObjectFacetDeclarativeAbstract.java | 166 -------------------
 ...ectFacetDeclarativeInitializingAbstract.java | 165 ++++++++++++++++++
 .../RecreatableObjectFacetFactory.java          |   4 +-
 ...acetForRecreatableDomainObjectInterface.java |   6 +-
 ...jectFacetForRecreatableObjectAnnotation.java |   5 +-
 ...bjectFacetForRecreatableObjectInterface.java |   6 +-
 ...atableObjectFacetForViewModelAnnotation.java |   5 +-
 ...eObjectFacetForXmlRootElementAnnotation.java |  39 ++++-
 .../facets/object/viewmodel/ViewModelFacet.java |  49 ++++++
 .../services/jaxb/JaxbServiceDefault.java       |  49 ++++--
 .../jaxb/util/PersistentEntityAdapter.java      |  51 ------
 .../services/memento/MementoServiceDefault.java |  38 ++---
 .../system/persistence/PersistenceSession.java  |  46 +++--
 ...odaLocalTimeXMLGregorianCalendarAdapter.java |   4 -
 .../jaxbadapters/PersistentEntityAdapter.java   |  51 ++++++
 19 files changed, 493 insertions(+), 293 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/applib/src/main/java/org/apache/isis/applib/services/jaxb/JaxbService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/jaxb/JaxbService.java b/core/applib/src/main/java/org/apache/isis/applib/services/jaxb/JaxbService.java
index 61c0ecb..4c7c03b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/jaxb/JaxbService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/jaxb/JaxbService.java
@@ -23,9 +23,11 @@ import org.apache.isis.applib.annotation.Programmatic;
 public interface JaxbService {
 
     @Programmatic
-    public String toXml(final Dto dto);
+    <T> T fromXml(Class<T> domainClass, String memento);
 
     @Programmatic
-    public Map<String, String> toXsd(final Dto dto);
+    public String toXml(final Object domainObject);
 
+    @Programmatic
+    public Map<String, String> toXsd(final Object domainObject);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingService.java b/core/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingService.java
new file mode 100644
index 0000000..9c8c25f
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingService.java
@@ -0,0 +1,44 @@
+/**
+ *  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.urlencoding;
+
+import java.nio.charset.Charset;
+
+import com.google.common.io.BaseEncoding;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Programmatic;
+
+@DomainService(
+        nature = NatureOfService.DOMAIN
+)
+public class UrlEncodingService {
+
+    @Programmatic
+    public String decode(String str) {
+        final byte[] bytes = BaseEncoding.base64Url().decode(str);
+        return new String(bytes, Charset.forName("UTF-8"));
+    }
+
+    @Programmatic
+    public String encode(final String xmlStr) {
+        byte[] bytes = xmlStr.getBytes(Charset.forName("UTF-8"));
+        return BaseEncoding.base64Url().encode(bytes);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java
index 5c5eb13..7ea9baa 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java
@@ -25,11 +25,12 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
 import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
-import org.apache.isis.core.metamodel.facets.object.recreatable.RecreatableObjectFacetDeclarativeAbstract;
+import org.apache.isis.core.metamodel.facets.object.recreatable.RecreatableObjectFacetDeclarativeInitializingAbstract;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 
-public class RecreatableObjectFacetForDomainObjectAnnotation extends RecreatableObjectFacetDeclarativeAbstract {
+public class RecreatableObjectFacetForDomainObjectAnnotation extends
+        RecreatableObjectFacetDeclarativeInitializingAbstract {
 
     public static ViewModelFacet create(
             final DomainObject domainObject,
@@ -92,7 +93,7 @@ public class RecreatableObjectFacetForDomainObjectAnnotation extends Recreatable
             final AdapterManager adapterManager,
             final ServicesInjector servicesInjector,
             final PostConstructMethodCache postConstructMethodCache) {
-        super(holder, architecturalLayer, specificationLoader, adapterManager, servicesInjector,
+        super(holder, architecturalLayer, RecreationMechanism.INITIALIZES, specificationLoader, adapterManager, servicesInjector,
                 postConstructMethodCache);
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
index a117e37..969d007 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
@@ -28,11 +28,14 @@ import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
 import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
 import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 
 public abstract class RecreatableObjectFacetAbstract extends MarkerFacetAbstract implements ViewModelFacet {
 
     private final ArchitecturalLayer architecturalLayer;
     private final PostConstructMethodCache postConstructMethodCache;
+    private final ViewModelFacet.RecreationMechanism recreationMechanism;
+    protected final ServicesInjector servicesInjector;
 
     public static Class<? extends Facet> type() {
         return ViewModelFacet.class;
@@ -41,10 +44,14 @@ public abstract class RecreatableObjectFacetAbstract extends MarkerFacetAbstract
     public RecreatableObjectFacetAbstract(
             final FacetHolder holder,
             final ArchitecturalLayer architecturalLayer,
-            final PostConstructMethodCache postConstructMethodCache) {
+            final RecreationMechanism recreationMechanism,
+            final PostConstructMethodCache postConstructMethodCache,
+            final ServicesInjector servicesInjector) {
         super(type(), holder);
         this.architecturalLayer = architecturalLayer;
         this.postConstructMethodCache = postConstructMethodCache;
+        this.recreationMechanism = recreationMechanism;
+        this.servicesInjector = servicesInjector;
     }
 
     @Override
@@ -64,19 +71,49 @@ public abstract class RecreatableObjectFacetAbstract extends MarkerFacetAbstract
     }
 
     @Override
+    public RecreationMechanism getRecreationMechanism() {
+        return recreationMechanism;
+    }
+
+    @Override
+    public final Object instantiate(
+            final Class<?> viewModelClass,
+            final String mementoStr) {
+        if(getRecreationMechanism() == RecreationMechanism.INITIALIZES) {
+            throw new IllegalStateException("This view model instantiates rather than initializes");
+        }
+        final Object viewModelPojo = doInstantiate(viewModelClass, mementoStr);
+        servicesInjector.injectInto(viewModelPojo);
+        invokePostConstructMethod(viewModelPojo);
+        return viewModelPojo;
+    }
+
+    /**
+     * Hook for subclass; must be overridden if {@link #getRecreationMechanism()} is {@link RecreationMechanism#INSTANTIATES} (ignored otherwise).
+     */
+    protected Object doInstantiate(final Class<?> viewModelClass, final String mementoStr) {
+        throw new IllegalStateException("doInstantiate() must be overridden if RecreationMechanism is INSTANTIATES");
+    }
+
+    @Override
     public final void initialize(
             final Object viewModelPojo,
             final String mementoStr) {
+        if(getRecreationMechanism() == RecreationMechanism.INSTANTIATES) {
+            throw new IllegalStateException("This view model instantiates rather than initializes");
+        }
         doInitialize(viewModelPojo, mementoStr);
         invokePostConstructMethod(viewModelPojo);
     }
 
     /**
-     * Mandatory hook for subclasses.
+     * Hook for subclass; must be overridden if {@link #getRecreationMechanism()} is {@link RecreationMechanism#INITIALIZES} (ignored otherwise).
      */
-    protected abstract void doInitialize(
+    protected void doInitialize(
             final Object viewModelPojo,
-            final String mementoStr);
+            final String mementoStr) {
+        throw new IllegalStateException("doInitialize() must be overridden if RecreationMechanism is INITIALIZE");
+    }
 
     private void invokePostConstructMethod(final Object viewModel) {
         final Method postConstructMethod = postConstructMethodCache.postConstructMethodFor(viewModel);

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeAbstract.java
deleted file mode 100644
index 0c8cf64..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeAbstract.java
+++ /dev/null
@@ -1,166 +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.recreatable;
-
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.applib.services.memento.MementoService;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
-import org.apache.isis.core.metamodel.adapter.oid.Oid;
-import org.apache.isis.core.metamodel.adapter.oid.RootOid;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
-import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySetterFacet;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-import org.apache.isis.core.metamodel.spec.ObjectSpecId;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.SpecificationLoader;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-
-public abstract class RecreatableObjectFacetDeclarativeAbstract extends RecreatableObjectFacetAbstract {
-
-    private final SpecificationLoader specificationLoader;
-    private final ServicesInjector servicesInjector;
-    private final AdapterManager adapterManager;
-
-    public RecreatableObjectFacetDeclarativeAbstract(
-            final FacetHolder holder,
-            final ArchitecturalLayer architecturalLayer,
-            final SpecificationLoader specificationLoader,
-            final AdapterManager adapterManager,
-            final ServicesInjector servicesInjector,
-            final PostConstructMethodCache postConstructMethodCache) {
-        super(holder, architecturalLayer, postConstructMethodCache);
-        this.specificationLoader = specificationLoader;
-        this.servicesInjector = servicesInjector;
-        this.adapterManager = adapterManager;
-    }
-
-    @Override
-    protected void doInitialize(
-            final Object viewModelPojo,
-            final String mementoStr) {
-
-        final MementoService mementoService = servicesInjector.lookupService(MementoService.class);
-        final BookmarkService bookmarkService = servicesInjector.lookupService(BookmarkService.class);
-
-        final MementoService.Memento memento = mementoService.parse(mementoStr);
-
-        final Set<String> mementoKeys = memento.keySet();
-
-        // manually recreate the adapter in order to be able to query state via the metamodel
-        ObjectAdapter viewModelAdapter = adapterManager.getAdapterFor(viewModelPojo);
-        if(viewModelAdapter == null) {
-            final ObjectSpecification objectSpecification = specificationLoader.loadSpecification(viewModelPojo.getClass());
-            final ObjectSpecId objectSpecId = objectSpecification.getSpecId();
-            viewModelAdapter = adapterManager.mapRecreatedPojo(new RootOid(objectSpecId, mementoStr, Oid.State.VIEWMODEL), viewModelPojo);
-        }
-
-        final ObjectSpecification spec = viewModelAdapter.getSpecification();
-        final List<OneToOneAssociation> properties = spec.getProperties(Contributed.EXCLUDED);
-        for (OneToOneAssociation property : properties) {
-            final String propertyId = property.getId();
-
-            Object propertyValue = null;
-
-            if(mementoKeys.contains(propertyId)) {
-                final Class<?> propertyType = property.getSpecification().getCorrespondingClass();
-                propertyValue = memento.get(propertyId, propertyType);
-            } else if(mementoKeys.contains(propertyId + ".bookmark")) {
-                final Bookmark propertyValueBookmark = memento.get(propertyId + ".bookmark", Bookmark.class);
-                propertyValue = bookmarkService.lookup(propertyValueBookmark);
-            }
-
-            if(propertyValue != null) {
-                property.set(viewModelAdapter, adapterManager.adapterFor(propertyValue), InteractionInitiatedBy.FRAMEWORK);
-            }
-        }
-    }
-    
-    @Override
-    public String memento(Object viewModelPojo) {
-
-        final MementoService mementoService = servicesInjector.lookupService(MementoService.class);
-        final BookmarkService bookmarkService = servicesInjector.lookupService(BookmarkService.class);
-
-        final MementoService.Memento memento = mementoService.create();
-
-        // this is horrible, but there's a catch-22 here...
-        // we need an adapter in order to query the state of the object via the metamodel, on the other hand
-        // we can't create an adapter without the identifier, which is what we're trying to derive
-        // so... we create a temporary transient adapter, use it to wrap this adapter and interrogate this pojo,
-        // then throw away that adapter (remove from the adapter map)
-        boolean createdTemporaryAdapter = false;
-        ObjectAdapter viewModelAdapter = adapterManager.getAdapterFor(viewModelPojo);
-        if(viewModelAdapter == null) {
-            final ObjectSpecification objectSpecification = specificationLoader.loadSpecification(viewModelPojo.getClass());
-            final ObjectSpecId objectSpecId = objectSpecification.getSpecId();
-            viewModelAdapter = adapterManager.mapRecreatedPojo(RootOid.create(objectSpecId, UUID.randomUUID().toString()), viewModelPojo);
-
-            createdTemporaryAdapter = true;
-        }
-
-        try {
-            final ObjectSpecification spec = viewModelAdapter.getSpecification();
-            final List<OneToOneAssociation> properties = spec.getProperties(Contributed.EXCLUDED);
-            for (OneToOneAssociation property : properties) {
-                // ignore read-only
-                if(!property.containsDoOpFacet(PropertySetterFacet.class)) {
-                    continue;
-                }
-                // ignore those explicitly annotated as @NotPersisted
-                if(property.isNotPersisted()) {
-                    continue;
-                }
-
-                // otherwise, include
-
-                // REVIEW: this look to be the same as viewModelAdapter, above?
-                final ObjectAdapter ownerAdapter = adapterManager.adapterFor(viewModelPojo);
-
-                final ObjectAdapter propertyValueAdapter = property.get(ownerAdapter,
-                        InteractionInitiatedBy.FRAMEWORK);
-                if(propertyValueAdapter != null) {
-                    final Object propertyValue = propertyValueAdapter.getObject();
-                    if(mementoService.canSet(propertyValue)) {
-                        memento.set(property.getId(), propertyValue);
-                    } else {
-                        final Bookmark propertyValueBookmark = bookmarkService.bookmarkFor(propertyValue);
-                        memento.set(property.getId() + ".bookmark", propertyValueBookmark);
-                    }
-                }
-            }
-            return memento.asString();
-        } finally {
-            if(createdTemporaryAdapter) {
-                adapterManager.removeAdapter(viewModelAdapter);
-            }
-        }
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
new file mode 100644
index 0000000..205f21d
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
@@ -0,0 +1,165 @@
+/*
+ *  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.recreatable;
+
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.applib.services.memento.MementoService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
+import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySetterFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+public abstract class RecreatableObjectFacetDeclarativeInitializingAbstract extends RecreatableObjectFacetAbstract {
+
+    private final SpecificationLoader specificationLoader;
+    private final AdapterManager adapterManager;
+
+    public RecreatableObjectFacetDeclarativeInitializingAbstract(
+            final FacetHolder holder,
+            final ArchitecturalLayer architecturalLayer,
+            final RecreationMechanism recreationMechanism,
+            final SpecificationLoader specificationLoader,
+            final AdapterManager adapterManager,
+            final ServicesInjector servicesInjector,
+            final PostConstructMethodCache postConstructMethodCache) {
+        super(holder, architecturalLayer, recreationMechanism, postConstructMethodCache, servicesInjector);
+        this.specificationLoader = specificationLoader;
+        this.adapterManager = adapterManager;
+    }
+
+    @Override
+    protected void doInitialize(
+            final Object viewModelPojo,
+            final String mementoStr) {
+
+        final MementoService mementoService = servicesInjector.lookupService(MementoService.class);
+        final BookmarkService bookmarkService = servicesInjector.lookupService(BookmarkService.class);
+
+        final MementoService.Memento memento = mementoService.parse(mementoStr);
+
+        final Set<String> mementoKeys = memento.keySet();
+
+        // manually recreate the adapter in order to be able to query state via the metamodel
+        ObjectAdapter viewModelAdapter = adapterManager.getAdapterFor(viewModelPojo);
+        if(viewModelAdapter == null) {
+            final ObjectSpecification objectSpecification = specificationLoader.loadSpecification(viewModelPojo.getClass());
+            final ObjectSpecId objectSpecId = objectSpecification.getSpecId();
+            viewModelAdapter = adapterManager.mapRecreatedPojo(new RootOid(objectSpecId, mementoStr, Oid.State.VIEWMODEL), viewModelPojo);
+        }
+
+        final ObjectSpecification spec = viewModelAdapter.getSpecification();
+        final List<OneToOneAssociation> properties = spec.getProperties(Contributed.EXCLUDED);
+        for (OneToOneAssociation property : properties) {
+            final String propertyId = property.getId();
+
+            Object propertyValue = null;
+
+            if(mementoKeys.contains(propertyId)) {
+                final Class<?> propertyType = property.getSpecification().getCorrespondingClass();
+                propertyValue = memento.get(propertyId, propertyType);
+            } else if(mementoKeys.contains(propertyId + ".bookmark")) {
+                final Bookmark propertyValueBookmark = memento.get(propertyId + ".bookmark", Bookmark.class);
+                propertyValue = bookmarkService.lookup(propertyValueBookmark);
+            }
+
+            if(propertyValue != null) {
+                property.set(viewModelAdapter, adapterManager.adapterFor(propertyValue), InteractionInitiatedBy.FRAMEWORK);
+            }
+        }
+    }
+    
+    @Override
+    public String memento(Object viewModelPojo) {
+
+        final MementoService mementoService = servicesInjector.lookupService(MementoService.class);
+        final BookmarkService bookmarkService = servicesInjector.lookupService(BookmarkService.class);
+
+        final MementoService.Memento memento = mementoService.create();
+
+        // this is horrible, but there's a catch-22 here...
+        // we need an adapter in order to query the state of the object via the metamodel, on the other hand
+        // we can't create an adapter without the identifier, which is what we're trying to derive
+        // so... we create a temporary transient adapter, use it to wrap this adapter and interrogate this pojo,
+        // then throw away that adapter (remove from the adapter map)
+        boolean createdTemporaryAdapter = false;
+        ObjectAdapter viewModelAdapter = adapterManager.getAdapterFor(viewModelPojo);
+        if(viewModelAdapter == null) {
+            final ObjectSpecification objectSpecification = specificationLoader.loadSpecification(viewModelPojo.getClass());
+            final ObjectSpecId objectSpecId = objectSpecification.getSpecId();
+            viewModelAdapter = adapterManager.mapRecreatedPojo(RootOid.create(objectSpecId, UUID.randomUUID().toString()), viewModelPojo);
+
+            createdTemporaryAdapter = true;
+        }
+
+        try {
+            final ObjectSpecification spec = viewModelAdapter.getSpecification();
+            final List<OneToOneAssociation> properties = spec.getProperties(Contributed.EXCLUDED);
+            for (OneToOneAssociation property : properties) {
+                // ignore read-only
+                if(!property.containsDoOpFacet(PropertySetterFacet.class)) {
+                    continue;
+                }
+                // ignore those explicitly annotated as @NotPersisted
+                if(property.isNotPersisted()) {
+                    continue;
+                }
+
+                // otherwise, include
+
+                // REVIEW: this look to be the same as viewModelAdapter, above?
+                final ObjectAdapter ownerAdapter = adapterManager.adapterFor(viewModelPojo);
+
+                final ObjectAdapter propertyValueAdapter = property.get(ownerAdapter,
+                        InteractionInitiatedBy.FRAMEWORK);
+                if(propertyValueAdapter != null) {
+                    final Object propertyValue = propertyValueAdapter.getObject();
+                    if(mementoService.canSet(propertyValue)) {
+                        memento.set(property.getId(), propertyValue);
+                    } else {
+                        final Bookmark propertyValueBookmark = bookmarkService.bookmarkFor(propertyValue);
+                        memento.set(property.getId() + ".bookmark", propertyValueBookmark);
+                    }
+                }
+            }
+            return memento.asString();
+        } finally {
+            if(createdTemporaryAdapter) {
+                adapterManager.removeAdapter(viewModelAdapter);
+            }
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java
index fcda954..ec03ff4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java
@@ -71,7 +71,7 @@ public class RecreatableObjectFacetFactory extends FacetFactoryAbstract
         if (ViewModel.class.isAssignableFrom(processClassContext.getCls())) {
             final PostConstructMethodCache postConstructMethodCache = this;
             FacetUtil.addFacet(new RecreatableObjectFacetForRecreatableObjectInterface(
-                    processClassContext.getFacetHolder(), postConstructMethodCache));
+                    processClassContext.getFacetHolder(), postConstructMethodCache, servicesInjector));
         }
 
         // ViewModel annotation
@@ -86,7 +86,7 @@ public class RecreatableObjectFacetFactory extends FacetFactoryAbstract
         if (RecreatableDomainObject.class.isAssignableFrom(processClassContext.getCls())) {
             final PostConstructMethodCache postConstructMethodCache = this;
             FacetUtil.addFacet(new RecreatableObjectFacetForRecreatableDomainObjectInterface(
-                    processClassContext.getFacetHolder(), postConstructMethodCache));
+                    processClassContext.getFacetHolder(), postConstructMethodCache, servicesInjector));
         }
 
         // DomainObject(nature=VIEW_MODEL) is managed by the DomainObjectFacetFactory

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java
index c59ef86..bc638e6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java
@@ -22,13 +22,15 @@ package org.apache.isis.core.metamodel.facets.object.recreatable;
 import org.apache.isis.applib.RecreatableDomainObject;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 
 public class RecreatableObjectFacetForRecreatableDomainObjectInterface extends RecreatableObjectFacetAbstract {
 
     public RecreatableObjectFacetForRecreatableDomainObjectInterface(
             final FacetHolder holder,
-            final PostConstructMethodCache postConstructMethodCache) {
-        super(holder, ArchitecturalLayer.DOMAIN, postConstructMethodCache);
+            final PostConstructMethodCache postConstructMethodCache,
+            final ServicesInjector servicesInjector) {
+        super(holder, ArchitecturalLayer.DOMAIN, RecreationMechanism.INITIALIZES, postConstructMethodCache, servicesInjector);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectAnnotation.java
index 30af377..f7c3fa6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectAnnotation.java
@@ -25,7 +25,8 @@ import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 
-public class RecreatableObjectFacetForRecreatableObjectAnnotation extends RecreatableObjectFacetDeclarativeAbstract {
+public class RecreatableObjectFacetForRecreatableObjectAnnotation extends
+        RecreatableObjectFacetDeclarativeInitializingAbstract {
 
     public RecreatableObjectFacetForRecreatableObjectAnnotation(
             final FacetHolder holder,
@@ -33,7 +34,7 @@ public class RecreatableObjectFacetForRecreatableObjectAnnotation extends Recrea
             final AdapterManager adapterManager,
             final ServicesInjector servicesInjector,
             final PostConstructMethodCache postConstructMethodCache) {
-        super(holder, ArchitecturalLayer.APPLICATION,
+        super(holder, ArchitecturalLayer.APPLICATION, RecreationMechanism.INITIALIZES,
                 specificationLoader, adapterManager, servicesInjector, postConstructMethodCache);
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java
index 67cd85d..3765f8c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java
@@ -22,13 +22,15 @@ package org.apache.isis.core.metamodel.facets.object.recreatable;
 import org.apache.isis.applib.ViewModel;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 
 public class RecreatableObjectFacetForRecreatableObjectInterface extends RecreatableObjectFacetAbstract {
 
     public RecreatableObjectFacetForRecreatableObjectInterface(
             final FacetHolder holder,
-            final PostConstructMethodCache postConstructMethodCache) {
-        super(holder, ArchitecturalLayer.APPLICATION, postConstructMethodCache);
+            final PostConstructMethodCache postConstructMethodCache,
+            final ServicesInjector servicesInjector) {
+        super(holder, ArchitecturalLayer.APPLICATION, RecreationMechanism.INITIALIZES, postConstructMethodCache, servicesInjector);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForViewModelAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForViewModelAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForViewModelAnnotation.java
index dec2264..41da143 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForViewModelAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForViewModelAnnotation.java
@@ -25,7 +25,8 @@ import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 
-public class RecreatableObjectFacetForViewModelAnnotation extends RecreatableObjectFacetDeclarativeAbstract {
+public class RecreatableObjectFacetForViewModelAnnotation extends
+        RecreatableObjectFacetDeclarativeInitializingAbstract {
 
     public RecreatableObjectFacetForViewModelAnnotation(
             final FacetHolder holder,
@@ -33,7 +34,7 @@ public class RecreatableObjectFacetForViewModelAnnotation extends RecreatableObj
             final AdapterManager adapterManager,
             final ServicesInjector servicesInjector,
             final PostConstructMethodCache postConstructMethodCache) {
-        super(holder, ArchitecturalLayer.APPLICATION,
+        super(holder, ArchitecturalLayer.APPLICATION, RecreationMechanism.INITIALIZES,
                 specificationLoader, adapterManager, servicesInjector, postConstructMethodCache);
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
index e416416..06581c3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
@@ -19,13 +19,19 @@
 
 package org.apache.isis.core.metamodel.facets.object.recreatable;
 
+import org.apache.isis.applib.services.jaxb.JaxbService;
+import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 
-public class RecreatableObjectFacetForXmlRootElementAnnotation extends RecreatableObjectFacetDeclarativeAbstract {
+public class RecreatableObjectFacetForXmlRootElementAnnotation extends RecreatableObjectFacetAbstract {
+
+    private final SpecificationLoader specificationLoader;
+    private final AdapterManager adapterManager;
+    private final ServicesInjector servicesInjector;
 
     public RecreatableObjectFacetForXmlRootElementAnnotation(
             final FacetHolder holder,
@@ -33,8 +39,35 @@ public class RecreatableObjectFacetForXmlRootElementAnnotation extends Recreatab
             final AdapterManager adapterManager,
             final ServicesInjector servicesInjector,
             final PostConstructMethodCache postConstructMethodCache) {
-        super(holder, ArchitecturalLayer.APPLICATION,
-                specificationLoader, adapterManager, servicesInjector, postConstructMethodCache);
+        super(holder, ArchitecturalLayer.APPLICATION, RecreationMechanism.INSTANTIATES,
+                postConstructMethodCache, servicesInjector);
+
+        this.specificationLoader = specificationLoader;
+        this.adapterManager = adapterManager;
+        this.servicesInjector = servicesInjector;
     }
 
+    @Override
+    protected Object doInstantiate(final Class<?> viewModelClass, final String mementoStr) {
+
+        final JaxbService jaxbService = servicesInjector.lookupService(JaxbService.class);
+        final UrlEncodingService urlEncodingService =
+                servicesInjector.lookupService(UrlEncodingService.class);
+
+        final String xmlStr = urlEncodingService.decode(mementoStr);
+        final Object viewModelPojo = jaxbService.fromXml(viewModelClass, xmlStr);
+        return viewModelPojo;
+    }
+
+    @Override
+    public String memento(final Object pojo) {
+
+        final JaxbService jaxbService = servicesInjector.lookupService(JaxbService.class);
+        final UrlEncodingService urlEncodingService =
+                servicesInjector.lookupService(UrlEncodingService.class);
+
+        final String xml = jaxbService.toXml(pojo);
+        final String encoded = urlEncodingService.encode(xml);
+        return encoded;
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
index 78fbb3b..355895e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.core.metamodel.facets.object.viewmodel;
 
+import org.apache.isis.applib.annotation.Nature;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 
 /**
@@ -38,13 +39,52 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
  */
 public interface ViewModelFacet extends Facet {
 
+
     public enum ArchitecturalLayer {
         APPLICATION,
         DOMAIN
     }
 
+    public enum RecreationMechanism {
+        /**
+         * Instantiates a new instance and then populates
+         */
+        INSTANTIATES,
+        /**
+         * Initializes an instance already created by the framework
+         */
+        INITIALIZES;
+
+        public boolean isInstantiates() {
+            return this == INSTANTIATES;
+        }
+        public boolean isInitializes() {
+            return this == INITIALIZES;
+        }
+    }
+
+    /**
+     * Whether this implementation supports the recreation of objects by {@link RecreationMechanism#INSTANTIATES instantiating} (and implicitly also initializing) a new pojo, or by {@link RecreationMechanism#INITIALIZES initializing} a pojo created and passed to it by the framework.
+     *
+     * <p>
+     *     Determines whether the framework then calls {@link #instantiate(Class, String)} or if it calls {@link #initialize(Object, String)}.
+     * </p>
+     */
+    RecreationMechanism getRecreationMechanism();
+
+    /**
+     * Will be called if {@link #getRecreationMechanism()} is {@link RecreationMechanism#INITIALIZES}.
+     */
     void initialize(Object pojo, String memento);
 
+    /**
+     * Will be called only call if {@link #getRecreationMechanism()} is {@link RecreationMechanism#INSTANTIATES}.
+     */
+    Object instantiate(final Class<?> viewModelClass, String memento);
+
+    /**
+     * Obtain a memento of the pojo, which can then be used to reinstantiate (either by {@link #instantiate(Class, String)} or {@link #initialize(Object, String)}) subsequently.
+     */
     String memento(Object pojo);
 
     /**
@@ -52,7 +92,16 @@ public interface ViewModelFacet extends Facet {
      */
     boolean isCloneable(Object pojo);
 
+    /**
+     * View models are implicitly immutable (their state is determined by their {@link #memento(Object)}), so this
+     * method allows the framework to clone an existing view model to mutate it, thereby simulating editable
+     * view models.
+     */
     Object clone(Object pojo);
 
+    /**
+     * Currently metadata only, capturing the nature of the view model, eg {@link Nature#EXTERNAL_ENTITY} is a {@link ArchitecturalLayer#DOMAIN domain} layer where as {@link Nature#VIEW_MODEL} is {@link ArchitecturalLayer#APPLICATION application} layer.
+     * @return
+     */
     ArchitecturalLayer getArchitecturalLayer();
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/JaxbServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/JaxbServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/JaxbServiceDefault.java
index 4fd19aa..562a666 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/JaxbServiceDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/JaxbServiceDefault.java
@@ -17,6 +17,7 @@
 package org.apache.isis.core.runtime.services.jaxb;
 
 import java.io.IOException;
+import java.io.StringReader;
 import java.io.StringWriter;
 import java.util.Map;
 
@@ -24,41 +25,46 @@ import javax.inject.Inject;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
 
 import org.apache.isis.applib.ApplicationException;
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.services.jaxb.Dto;
 import org.apache.isis.applib.services.jaxb.JaxbService;
 import org.apache.isis.core.runtime.services.jaxb.util.CatalogingSchemaOutputResolver;
-import org.apache.isis.core.runtime.services.jaxb.util.PersistentEntityAdapter;
+import org.apache.isis.schema.utils.jaxbadapters.PersistentEntityAdapter;
 
 @DomainService(
         nature = NatureOfService.DOMAIN
 )
 public class JaxbServiceDefault implements JaxbService {
 
-    public Map<String,String> toXsd(final Dto dto) {
-
+    @Override
+    public <T> T fromXml(final Class<T> domainClass, final String memento) {
         try {
-            final Class<? extends Dto> dtoClass = dto.getClass();
-            final JAXBContext context = JAXBContext.newInstance(dtoClass);
+            final JAXBContext context = JAXBContext.newInstance(domainClass);
 
-            final CatalogingSchemaOutputResolver outputResolver = new CatalogingSchemaOutputResolver();
-            context.generateSchema(outputResolver);
+            final PersistentEntityAdapter adapter = new PersistentEntityAdapter();
+            container.injectServicesInto(adapter);
 
-            return outputResolver.asMap();
-        } catch (final JAXBException | IOException ex) {
+            final Unmarshaller unmarshaller = context.createUnmarshaller();
+            unmarshaller.setAdapter(PersistentEntityAdapter.class, adapter);
+
+            final Object unmarshal = unmarshaller.unmarshal(new StringReader(memento));
+            return (T) unmarshal;
+
+        } catch (final JAXBException ex) {
             throw new ApplicationException(ex);
         }
     }
 
-    public String toXml(final Dto dto)  {
+    @Override
+    public String toXml(final Object domainObject)  {
 
         try {
-            final Class<? extends Dto> dtoClass = dto.getClass();
-            final JAXBContext context = JAXBContext.newInstance(dtoClass);
+            final Class<?> domainClass = domainObject.getClass();
+            final JAXBContext context = JAXBContext.newInstance(domainClass);
 
             final PersistentEntityAdapter adapter = new PersistentEntityAdapter();
             container.injectServicesInto(adapter);
@@ -68,15 +74,30 @@ public class JaxbServiceDefault implements JaxbService {
             marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
             final StringWriter sw = new StringWriter();
-            marshaller.marshal(dto, sw);
+            marshaller.marshal(domainObject, sw);
             return sw.toString();
 
         } catch (final JAXBException ex) {
             throw new ApplicationException(ex);
         }
+    }
 
+    public Map<String,String> toXsd(final Object domainObject) {
+
+        try {
+            final Class<?> domainClass = domainObject.getClass();
+            final JAXBContext context = JAXBContext.newInstance(domainClass);
+
+            final CatalogingSchemaOutputResolver outputResolver = new CatalogingSchemaOutputResolver();
+            context.generateSchema(outputResolver);
+
+            return outputResolver.asMap();
+        } catch (final JAXBException | IOException ex) {
+            throw new ApplicationException(ex);
+        }
     }
 
+
     @Inject
     DomainObjectContainer container;
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/util/PersistentEntityAdapter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/util/PersistentEntityAdapter.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/util/PersistentEntityAdapter.java
deleted file mode 100644
index 6987129..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/jaxb/util/PersistentEntityAdapter.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.isis.core.runtime.services.jaxb.util;
-
-import javax.inject.Inject;
-import javax.xml.bind.annotation.adapters.XmlAdapter;
-
-import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.schema.common.v1.BookmarkObjectState;
-import org.apache.isis.schema.common.v1.OidDto;
-
-public class PersistentEntityAdapter extends XmlAdapter<OidDto, Object> {
-
-    @Override
-    public Object unmarshal(final OidDto oidDto) throws Exception {
-
-        final String objectType = oidDto.getObjectType();
-        final String identifier = oidDto.getObjectIdentifier();
-        final Bookmark bookmark = new Bookmark(objectType, identifier);
-
-        return bookmarkService.lookup(bookmark);
-    }
-
-    @Override
-    public OidDto marshal(final Object domainObject) throws Exception {
-        final Bookmark bookmark = bookmarkService.bookmarkFor(domainObject);
-        final OidDto oidDto = new OidDto();
-        oidDto.setObjectIdentifier(bookmark.getIdentifier());
-        oidDto.setObjectState(BookmarkObjectState.PERSISTENT);
-        oidDto.setObjectType(bookmark.getObjectType());
-        return oidDto;
-    }
-
-    @Inject
-    BookmarkService bookmarkService;
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/runtime/src/main/java/org/apache/isis/core/runtime/services/memento/MementoServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/memento/MementoServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/memento/MementoServiceDefault.java
index ee39527..bfe7372 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/memento/MementoServiceDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/memento/MementoServiceDefault.java
@@ -16,14 +16,14 @@
  */
 package org.apache.isis.core.runtime.services.memento;
 
-import java.nio.charset.Charset;
 import java.util.List;
 import java.util.Set;
 
+import javax.inject.Inject;
+
 import com.google.common.base.Function;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
-import com.google.common.io.BaseEncoding;
 
 import org.dom4j.Document;
 import org.dom4j.DocumentHelper;
@@ -33,6 +33,7 @@ import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.memento.MementoService;
+import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
 
 /**
  * This service provides a mechanism by which a serializable memento of arbitrary state can be created.  Most
@@ -53,14 +54,20 @@ public class MementoServiceDefault implements MementoService {
         private final boolean noEncoding;
         private final Document doc;
 
-        MementoDefault(boolean noEncoding) {
-            this(DocumentHelper.createDocument(), noEncoding);
+        private final UrlEncodingService urlEncodingService;
+
+        MementoDefault(boolean noEncoding, final UrlEncodingService urlEncodingService) {
+            this(DocumentHelper.createDocument(), noEncoding, urlEncodingService);
             doc.addElement("memento");
         }
 
-        MementoDefault(Document doc, boolean noEncoding) {
+        MementoDefault(
+                Document doc,
+                boolean noEncoding,
+                final UrlEncodingService urlEncodingService) {
             this.doc = doc;
             this.noEncoding = noEncoding;
+            this.urlEncodingService = urlEncodingService;
         }
         
         @Override
@@ -83,7 +90,7 @@ public class MementoServiceDefault implements MementoService {
         }
 
         protected String encode(final String xmlStr) {
-            return noEncoding ? xmlStr : base64UrlEncode(xmlStr);
+            return noEncoding ? xmlStr : urlEncodingService.encode(xmlStr);
         }
 
         private static final Function<Element, String> ELEMENT_NAME = new Function<Element, String>(){
@@ -132,7 +139,7 @@ public class MementoServiceDefault implements MementoService {
     @Programmatic
     @Override
     public Memento create() {
-        return new MementoDefault(noEncoding);
+        return new MementoDefault(noEncoding, urlEncodingService);
     }
 
 
@@ -143,28 +150,21 @@ public class MementoServiceDefault implements MementoService {
         if (noEncoding) {
             xmlStr = str;
         } else {
-            xmlStr = base64UrlDecode(str);
+            xmlStr = urlEncodingService.decode(str);
         }
         final Document doc = Dom4jUtil.parse(xmlStr);
-        return new MementoDefault(doc, noEncoding);
+        return new MementoDefault(doc, noEncoding, urlEncodingService);
     }
 
     @Programmatic
     @Override
     public boolean canSet(final Object input) {
-        return input != null ? Dom4jUtil.isSupportedClass(input.getClass()) : true;
+        return input == null || Dom4jUtil.isSupportedClass(input.getClass());
     }
 
     // //////////////////////////////////////
 
-    private static String base64UrlDecode(String str) {
-        final byte[] bytes = BaseEncoding.base64Url().decode(str);
-        return new String(bytes, Charset.forName("UTF-8"));
-    }
-    
-    private static String base64UrlEncode(final String xmlStr) {
-        byte[] bytes = xmlStr.getBytes(Charset.forName("UTF-8"));
-        return BaseEncoding.base64Url().encode(bytes);
-    }
+    @Inject
+    UrlEncodingService urlEncodingService;
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
index 0e72141..f561705 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
@@ -579,23 +579,40 @@ public class PersistenceSession implements
     }
 
     private ObjectAdapter createInstance(
-            final ObjectSpecification objectSpec,
+            final ObjectSpecification spec,
             final Variant variant,
             final String memento) {
         if (LOG.isDebugEnabled()) {
-            LOG.debug("creating " + variant + " instance of " + objectSpec);
+            LOG.debug("creating " + variant + " instance of " + spec);
         }
-        final Object pojo = instantiateAndInjectServices(objectSpec);
+        final Object pojo;
 
         if(variant == Variant.VIEW_MODEL) {
-            final ViewModelFacet facet = objectSpec.getFacet(ViewModelFacet.class);
-            initialize(facet, pojo, memento);
+            pojo = recreateViewModel(spec, memento);
+        } else {
+            pojo = instantiateAndInjectServices(spec);
+
         }
 
         final ObjectAdapter adapter = adapterFor(pojo);
         return initializePropertiesAndDoCallback(adapter);
     }
 
+    private Object recreateViewModel(final ObjectSpecification spec, final String memento) {
+        final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
+        if(facet == null) {
+            throw new IllegalArgumentException("spec does not have ViewModelFacet; spec is " + spec.getFullIdentifier());
+        }
+
+        final Object viewModelPojo;
+        if(facet.getRecreationMechanism().isInitializes()) {
+            viewModelPojo = instantiateAndInjectServices(spec);
+            facet.initialize(viewModelPojo, memento);
+        } else {
+            viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), memento);
+        }
+        return viewModelPojo;
+    }
 
     public Object instantiateAndInjectServices(final ObjectSpecification objectSpec) {
 
@@ -1596,25 +1613,20 @@ public class PersistenceSession implements
     private Object recreatePojoDefault(final RootOid rootOid) {
         final ObjectSpecification spec =
                 specificationLoader.lookupBySpecId(rootOid.getObjectSpecId());
-        final Object pojo = instantiateAndInjectServices(spec);
-        if(rootOid.isViewModel()) {
-            // initialize the view model pojo from the oid's identifier
+        final Object pojo;
 
-            final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
-            if(facet == null) {
-                throw new IllegalArgumentException("spec does not have RecreatableObjectFacet; " + rootOid.toString() + "; spec is " + spec.getFullIdentifier());
-            }
+        if(rootOid.isViewModel()) {
 
             final String memento = rootOid.getIdentifier();
-            initialize(facet, pojo, memento);
+            pojo = recreateViewModel(spec, memento);
+
+        } else {
+            pojo = instantiateAndInjectServices(spec);
+
         }
         return pojo;
     }
 
-    private void initialize(final ViewModelFacet facet, final Object pojo, final String memento) {
-        facet.initialize(pojo, memento);
-    }
-
     /**
      * {@inheritDoc}
      */

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/JodaLocalTimeXMLGregorianCalendarAdapter.java
----------------------------------------------------------------------
diff --git a/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/JodaLocalTimeXMLGregorianCalendarAdapter.java b/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/JodaLocalTimeXMLGregorianCalendarAdapter.java
index 3410ded..9648929 100644
--- a/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/JodaLocalTimeXMLGregorianCalendarAdapter.java
+++ b/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/JodaLocalTimeXMLGregorianCalendarAdapter.java
@@ -23,8 +23,6 @@ import javax.xml.datatype.XMLGregorianCalendar;
 import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;
 
 import org.joda.time.LocalTime;
-import org.joda.time.format.DateTimeFormatter;
-import org.joda.time.format.ISODateTimeFormat;
 
 /**
  * Not registered in the XSD schema (as a JAXB binding, because can only map xs:dateTime once (and have chosen to map to LocalDateTime).
@@ -33,8 +31,6 @@ public final class JodaLocalTimeXMLGregorianCalendarAdapter {
     private JodaLocalTimeXMLGregorianCalendarAdapter() {
     }
 
-    private static DateTimeFormatter formatter = ISODateTimeFormat.dateTime();
-
     public static LocalTime parse(final XMLGregorianCalendar xgc) {
         if(xgc == null) return null;
 

http://git-wip-us.apache.org/repos/asf/isis/blob/9163f6db/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntityAdapter.java
----------------------------------------------------------------------
diff --git a/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntityAdapter.java b/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntityAdapter.java
new file mode 100644
index 0000000..0ff29b3
--- /dev/null
+++ b/core/schema/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntityAdapter.java
@@ -0,0 +1,51 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.schema.utils.jaxbadapters;
+
+import javax.inject.Inject;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.schema.common.v1.BookmarkObjectState;
+import org.apache.isis.schema.common.v1.OidDto;
+
+public class PersistentEntityAdapter extends XmlAdapter<OidDto, Object> {
+
+    @Override
+    public Object unmarshal(final OidDto oidDto) throws Exception {
+
+        final String objectType = oidDto.getObjectType();
+        final String identifier = oidDto.getObjectIdentifier();
+        final Bookmark bookmark = new Bookmark(objectType, identifier);
+
+        return bookmarkService.lookup(bookmark);
+    }
+
+    @Override
+    public OidDto marshal(final Object domainObject) throws Exception {
+        final Bookmark bookmark = bookmarkService.bookmarkFor(domainObject);
+        final OidDto oidDto = new OidDto();
+        oidDto.setObjectIdentifier(bookmark.getIdentifier());
+        oidDto.setObjectState(BookmarkObjectState.PERSISTENT);
+        oidDto.setObjectType(bookmark.getObjectType());
+        return oidDto;
+    }
+
+    @Inject
+    BookmarkService bookmarkService;
+}