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 2014/10/09 13:26:47 UTC

[5/6] ISIS-917: further refactorings to simplify the API of the (newly rechristened) RepresentationService.

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelper.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelper.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelper.java
index 97cce01..15a65da 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelper.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelper.java
@@ -16,15 +16,18 @@
  */
 package org.apache.isis.viewer.restfulobjects.server.resources;
 
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.JsonValueEncoder;
-import org.apache.isis.viewer.restfulobjects.server.ResourceContext;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+import org.apache.isis.viewer.restfulobjects.rendering.util.Util;
 import org.apache.isis.viewer.restfulobjects.server.util.OidUtils;
-import org.apache.isis.viewer.restfulobjects.server.util.UrlParserUtils;
 
 /**
  * Utility class that encapsulates the logic for parsing some content (JSON, or a simple string that is JSON)
@@ -33,26 +36,21 @@ import org.apache.isis.viewer.restfulobjects.server.util.UrlParserUtils;
  */
 public class JsonParserHelper {
 
-    static enum Intent {
-        ACCESS, MUTATE;
+    private final static Pattern OBJECT_OID = Pattern.compile(".*objects\\/([^/]+)\\/(.+)");
 
-        public boolean isMutate() {
-            return this == MUTATE;
-        }
-    }
-
-    private final ResourceContext resourceContext;
+    private final RendererContext rendererContext;
     private final ObjectSpecification objectSpec;
 
-    public JsonParserHelper(ResourceContext resourceContext, ObjectSpecification objectSpecification) {
+    public JsonParserHelper(
+            final RendererContext rendererContext, ObjectSpecification objectSpecification) {
         this.objectSpec = objectSpecification;
-        this.resourceContext = resourceContext;
+        this.rendererContext = rendererContext;
     }
 
 
     /**
      * @param bodyAsString
-     *            - as per {@link Util#asStringUtf8(java.io.InputStream)}
+     *            - as per {@link org.apache.isis.viewer.restfulobjects.rendering.util.Util#asStringUtf8(java.io.InputStream)}
      * @return
      */
     ObjectAdapter parseAsMapWithSingleValue(final String bodyAsString) {
@@ -63,7 +61,7 @@ public class JsonParserHelper {
     ObjectAdapter parseAsMapWithSingleValue(final JsonRepresentation arguments) {
         final JsonRepresentation representation = arguments.getRepresentation("value");
         if (arguments.size() != 1 || representation == null) {
-            throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.BAD_REQUEST, "Body should be a map with a single key 'value' whose value represents an instance of type '%s'", Util.resourceFor(objectSpec));
+            throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.BAD_REQUEST, "Body should be a map with a single key 'value' whose value represents an instance of type '%s'", resourceFor(objectSpec));
         }
 
         return objectAdapterFor(arguments);
@@ -122,14 +120,14 @@ public class JsonParserHelper {
             argRepr.mapPut("invalidReason", reason);
             throw new IllegalArgumentException(reason);
         }
-        final String oidFromHref = UrlParserUtils.encodedOidFromLink(argValueRepr);
+        final String oidFromHref = encodedOidFromLink(argValueRepr);
         if (oidFromHref == null) {
             final String reason = "Could not parse 'href' to identify the object's OID";
             argRepr.mapPut("invalidReason", reason);
             throw new IllegalArgumentException(reason);
         }
 
-        final ObjectAdapter objectAdapter = OidUtils.getObjectAdapterElseNull(resourceContext, oidFromHref);
+        final ObjectAdapter objectAdapter = OidUtils.getObjectAdapterElseNull(rendererContext, oidFromHref);
         if (objectAdapter == null) {
             final String reason = "'href' does not reference a known entity";
             argRepr.mapPut("invalidReason", reason);
@@ -138,4 +136,26 @@ public class JsonParserHelper {
         return objectAdapter;
     }
 
+    static String encodedOidFromLink(final JsonRepresentation link) {
+        final String href = link.getString("href");
+
+        final Matcher matcher = OBJECT_OID.matcher(href);
+        if (!matcher.matches()) {
+            return null;
+        }
+        String domainType = matcher.group(1);
+        String instanceId = matcher.group(2);
+        return getOidMarshaller().joinAsOid(domainType, instanceId);
+    }
+
+    private static String resourceFor(final ObjectSpecification objectSpec) {
+        // TODO: should return a string in the form
+        // http://localhost:8080/types/xxx
+        return objectSpec.getFullIdentifier();
+    }
+
+    private static OidMarshaller getOidMarshaller() {
+        return new OidMarshaller();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectActionArgHelper.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectActionArgHelper.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectActionArgHelper.java
index 1d807a5..7bb3fa2 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectActionArgHelper.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectActionArgHelper.java
@@ -26,8 +26,8 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
-import org.apache.isis.viewer.restfulobjects.server.ResourceContext;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 
 /**
  * Utility class that encapsulates the logic for parsing arguments to be invoked by an 
@@ -35,15 +35,15 @@ import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationExc
  */
 public class ObjectActionArgHelper {
 
-    private final ResourceContext resourceContext;
+    private final RendererContext rendererContext;
     private final ObjectAdapter objectAdapter;
     private final ObjectAction action;
 
     public ObjectActionArgHelper(
-            final ResourceContext resourceContext,
+            final RendererContext rendererContext,
             final ObjectAdapter objectAdapter,
             final ObjectAction action) {
-        this.resourceContext = resourceContext;
+        this.rendererContext = rendererContext;
         this.objectAdapter = objectAdapter;
         this.action = action;
     }
@@ -58,7 +58,7 @@ public class ObjectActionArgHelper {
             final JsonRepresentation argRepr = argList.get(i);
             final ObjectSpecification paramSpec = parameters.get(i).getSpecification();
             try {
-                final ObjectAdapter argAdapter = new JsonParserHelper(resourceContext, paramSpec).objectAdapterFor(argRepr);
+                final ObjectAdapter argAdapter = new JsonParserHelper(rendererContext, paramSpec).objectAdapterFor(argRepr);
                 argAdapters.add(argAdapter);
 
                 // validate individual arg

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectAdapterAccessHelper.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectAdapterAccessHelper.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectAdapterAccessHelper.java
index 6b17816..f979b81 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectAdapterAccessHelper.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ObjectAdapterAccessHelper.java
@@ -23,9 +23,9 @@ import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.*;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
 import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.MemberType;
-import org.apache.isis.viewer.restfulobjects.server.ResourceContext;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 
 /**
  * Utility class that encapsulates the logic for checking access to the specified
@@ -33,6 +33,11 @@ import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationExc
  */
 public class ObjectAdapterAccessHelper {
 
+    public static void throwNotFoundException(final String memberId, final MemberType memberType) {
+        final String memberTypeStr = memberType.name().toLowerCase();
+        throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.NOT_FOUND, "%s '%s' either does not exist or is not visible", memberTypeStr, memberId);
+    }
+
     static enum Intent {
         ACCESS, MUTATE;
 
@@ -42,17 +47,17 @@ public class ObjectAdapterAccessHelper {
     }
 
     private final ObjectAdapter objectAdapter;
-    private final ResourceContext resourceContext;
+    private final RendererContext rendererContext;
 
-    public ObjectAdapterAccessHelper(ResourceContext resourceContext, ObjectAdapter objectAdapter) {
+    public ObjectAdapterAccessHelper(RendererContext rendererContext, ObjectAdapter objectAdapter) {
         this.objectAdapter = objectAdapter;
-        this.resourceContext = resourceContext;
+        this.rendererContext = rendererContext;
     }
 
     public OneToOneAssociation getPropertyThatIsVisibleForIntent(
             final String propertyId, final Intent intent) {
 
-        final Where where = resourceContext.getWhere();
+        final Where where = rendererContext.getWhere();
 
         final ObjectAssociation association;
         try {
@@ -60,12 +65,12 @@ public class ObjectAdapterAccessHelper {
             association = specification.getAssociation(propertyId);
         } catch(Exception ex) {
             // fall through
-            Util.throwNotFoundException(propertyId, MemberType.PROPERTY);
+            throwNotFoundException(propertyId, MemberType.PROPERTY);
             return null; // to keep compiler happy.
         }
 
         if (association == null || !association.isOneToOneAssociation()) {
-            Util.throwNotFoundException(propertyId, MemberType.PROPERTY);
+            throwNotFoundException(propertyId, MemberType.PROPERTY);
         }
 
         final OneToOneAssociation property = (OneToOneAssociation) association;
@@ -75,18 +80,18 @@ public class ObjectAdapterAccessHelper {
     public OneToManyAssociation getCollectionThatIsVisibleForIntent(
             final String collectionId, final Intent intent) {
 
-        final Where where = resourceContext.getWhere();
+        final Where where = rendererContext.getWhere();
         final ObjectAssociation association;
         try {
             final ObjectSpecification specification = objectAdapter.getSpecification();
             association = specification.getAssociation(collectionId);
         } catch(Exception ex) {
             // fall through
-            Util.throwNotFoundException(collectionId, MemberType.COLLECTION);
+            throwNotFoundException(collectionId, MemberType.COLLECTION);
             return null; // to keep compiler happy.
         }
         if (association == null || !association.isOneToManyAssociation()) {
-            Util.throwNotFoundException(collectionId, MemberType.COLLECTION);
+            throwNotFoundException(collectionId, MemberType.COLLECTION);
         }
         final OneToManyAssociation collection = (OneToManyAssociation) association;
         return memberThatIsVisibleForIntent(collection, MemberType.COLLECTION, intent);
@@ -95,18 +100,18 @@ public class ObjectAdapterAccessHelper {
     public ObjectAction getObjectActionThatIsVisibleForIntent(
             final String actionId, final Intent intent) {
 
-        final Where where = resourceContext.getWhere();
+        final Where where = rendererContext.getWhere();
 
         final ObjectAction action;
         try {
             final ObjectSpecification specification = objectAdapter.getSpecification();
             action = specification.getObjectAction(actionId);
         } catch(Exception ex) {
-            Util.throwNotFoundException(actionId, MemberType.ACTION);
+            throwNotFoundException(actionId, MemberType.ACTION);
             return null; // to keep compiler happy.
         }
         if (action == null) {
-            Util.throwNotFoundException(actionId, MemberType.ACTION);
+            throwNotFoundException(actionId, MemberType.ACTION);
         }
         return memberThatIsVisibleForIntent(action, MemberType.ACTION, intent);
     }
@@ -114,12 +119,12 @@ public class ObjectAdapterAccessHelper {
     public <T extends ObjectMember> T memberThatIsVisibleForIntent(
             final T objectMember, final MemberType memberType, final Intent intent) {
 
-        final Where where = resourceContext.getWhere();
+        final Where where = rendererContext.getWhere();
 
         final String memberId = objectMember.getId();
-        final AuthenticationSession authenticationSession = resourceContext.getAuthenticationSession();
+        final AuthenticationSession authenticationSession = rendererContext.getAuthenticationSession();
         if (objectMember.isVisible(authenticationSession, objectAdapter, where).isVetoed()) {
-            Util.throwNotFoundException(memberId, memberType);
+            throwNotFoundException(memberId, memberType);
         }
         if (intent.isMutate()) {
             final Consent usable = objectMember.isUsable(authenticationSession, objectAdapter, where);

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
index 7855b71..3bac4b4 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
@@ -18,14 +18,11 @@
  */
 package org.apache.isis.viewer.restfulobjects.server.resources;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.core.*;
-import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.map.JsonMappingException;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.profiles.Localization;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
@@ -35,46 +32,19 @@ 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.OidMarshaller;
 import org.apache.isis.core.metamodel.services.ServiceUtil;
-import org.apache.isis.core.metamodel.spec.ActionType;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
-import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
+import org.apache.isis.viewer.restfulobjects.rendering.util.Util;
 import org.apache.isis.viewer.restfulobjects.server.ResourceContext;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
 import org.apache.isis.viewer.restfulobjects.server.util.OidUtils;
 import org.apache.isis.viewer.restfulobjects.server.util.UrlDecoderUtils;
 
 public abstract class ResourceAbstract {
 
-
-    protected final static JsonMapper jsonMapper = JsonMapper.instance();
-
-    public enum Caching {
-        ONE_DAY(24 * 60 * 60), ONE_HOUR(60 * 60), NONE(0);
-
-        private final CacheControl cacheControl;
-
-        private Caching(final int maxAge) {
-            this.cacheControl = new CacheControl();
-            if (maxAge > 0) {
-                cacheControl.setMaxAge(maxAge);
-            } else {
-                cacheControl.setNoCache(true);
-            }
-        }
-
-        public CacheControl getCacheControl() {
-            return cacheControl;
-        }
-    }
-
-    // nb: SET is excluded; we simply flatten contributed actions.
-    public final static ActionType[] ACTION_TYPES = { ActionType.USER, ActionType.DEBUG, ActionType.EXPLORATION };
-
     @Context
     HttpHeaders httpHeaders;
 
@@ -138,29 +108,9 @@ public abstract class ResourceAbstract {
     }
 
     // //////////////////////////////////////////////////////////////
-    // Rendering
-    // //////////////////////////////////////////////////////////////
-
-    protected static String jsonFor(final Object object) {
-        try {
-            return jsonMapper.write(object);
-        } catch (final JsonGenerationException e) {
-            throw new RuntimeException(e);
-        } catch (final JsonMappingException e) {
-            throw new RuntimeException(e);
-        } catch (final IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    // //////////////////////////////////////////////////////////////
     // Isis integration
     // //////////////////////////////////////////////////////////////
 
-    protected ObjectSpecification getSpecification(final String specFullName) {
-        return getSpecificationLoader().loadSpecification(specFullName);
-    }
-
     protected ObjectAdapter getObjectAdapterElseThrowNotFound(String domainType, final String instanceId) {
         ObjectAdapter objectAdapter = getObjectAdapterElseNull(domainType, instanceId);
 

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResponseGeneratorService.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResponseGeneratorService.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResponseGeneratorService.java
deleted file mode 100644
index dcddc6d..0000000
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResponseGeneratorService.java
+++ /dev/null
@@ -1,269 +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.restfulobjects.server.resources;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.List;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.ResponseBuilder;
-import org.apache.isis.applib.annotation.ActionSemantics;
-import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.version.Version;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
-import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
-import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.*;
-import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ActionResultReprRenderer.SelfLink;
-import org.apache.isis.viewer.restfulobjects.server.ResourceContext;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
-import org.apache.isis.viewer.restfulobjects.server.resources.ResourceAbstract.Caching;
-
-@DomainService
-public class ResponseGeneratorService {
-
-    private static final DateFormat ETAG_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-
-    public static interface ResponseContext {
-        public ResourceContext getResourceContext();
-        public ObjectAdapter getObjectAdapter();
-        public ObjectAdapterLinkTo getAdapterLinkTo();
-    }
-
-
-    // //////////////////////////////////////////////////////////////
-    // objectRepresentation
-    // //////////////////////////////////////////////////////////////
-
-    @Programmatic
-    public Response objectRepresentation(final ResponseContext responseContext) {
-
-        final ResourceContext resourceContext = responseContext.getResourceContext();
-        final ObjectAdapter objectAdapter = responseContext.getObjectAdapter();
-
-        final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(resourceContext, null, JsonRepresentation.newMap());
-        renderer.with(objectAdapter).includesSelf();
-
-        final ResponseBuilder responseBuilder = Responses.ofOk(renderer, Caching.NONE);
-
-        final Version version = objectAdapter.getVersion();
-        if (version != null && version.getTime() != null) {
-            responseBuilder.tag(ETAG_FORMAT.format(version.getTime()));
-        }
-        return buildResponse(responseBuilder);
-    }
-
-    // //////////////////////////////////////////////////////////////
-    // propertyDetails
-    // //////////////////////////////////////////////////////////////
-
-    public enum MemberMode {
-        NOT_MUTATING {
-            @Override
-            public void apply(final AbstractObjectMemberReprRenderer<?, ?> renderer) {
-                renderer.asStandalone();
-            }
-        },
-        MUTATING {
-            @Override
-            public void apply(final AbstractObjectMemberReprRenderer<?, ?> renderer) {
-                renderer.asMutated();
-            }
-        };
-
-        public abstract void apply(AbstractObjectMemberReprRenderer<?, ?> renderer);
-    }
-
-    @Programmatic
-    public Response propertyDetails(
-            final ResponseContext responseContext,
-            final String propertyId, final MemberMode memberMode, final Caching caching) {
-
-        final ResourceContext resourceContext = responseContext.getResourceContext();
-        final ObjectAdapter objectAdapter = responseContext.getObjectAdapter();
-        final ObjectAdapterLinkTo adapterLinkTo = responseContext.getAdapterLinkTo();
-
-        ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter);
-
-        final OneToOneAssociation property = accessHelper.getPropertyThatIsVisibleForIntent(propertyId, ObjectAdapterAccessHelper.Intent.ACCESS);
-
-        final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(resourceContext, null, null, JsonRepresentation.newMap());
-
-        renderer.with(new ObjectAndProperty(objectAdapter, property)).usingLinkTo(adapterLinkTo);
-
-        memberMode.apply(renderer);
-
-        return Responses.ofOk(renderer, caching).build();
-    }
-
-    // //////////////////////////////////////////////////////////////
-    // collectionDetails
-    // //////////////////////////////////////////////////////////////
-
-    @Programmatic
-    public Response collectionDetails(
-            final ResponseContext responseContext,
-            final String collectionId, final MemberMode memberMode, final Caching caching) {
-
-        final ResourceContext resourceContext = responseContext.getResourceContext();
-        final ObjectAdapter objectAdapter = responseContext.getObjectAdapter();
-        final ObjectAdapterLinkTo adapterLinkTo = responseContext.getAdapterLinkTo();
-
-        ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter);
-
-        final OneToManyAssociation collection = accessHelper.getCollectionThatIsVisibleForIntent(collectionId, ObjectAdapterAccessHelper.Intent.ACCESS);
-
-        final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(resourceContext, null, null, JsonRepresentation.newMap());
-
-        renderer.with(new ObjectAndCollection(objectAdapter, collection)).usingLinkTo(adapterLinkTo);
-
-        memberMode.apply(renderer);
-
-        final ResponseBuilder responseBuilder = Responses.ofOk(renderer, caching);
-        return buildResponse(responseBuilder);
-    }
-
-    // //////////////////////////////////////////////////////////////
-    // action Prompt
-    // //////////////////////////////////////////////////////////////
-
-    @Programmatic
-    public Response actionPrompt(
-            final ResponseContext responseContext,
-            final String actionId) {
-
-        final ResourceContext resourceContext = responseContext.getResourceContext();
-        final ObjectAdapter objectAdapter = responseContext.getObjectAdapter();
-        final ObjectAdapterLinkTo adapterLinkTo = responseContext.getAdapterLinkTo();
-
-        ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter);
-
-        final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectAdapterAccessHelper.Intent.ACCESS);
-
-        final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(resourceContext, null, null, JsonRepresentation.newMap());
-
-        renderer.with(new ObjectAndAction(objectAdapter, action)).usingLinkTo(adapterLinkTo).asStandalone();
-
-        final ResponseBuilder responseBuilder = Responses.ofOk(renderer, Caching.NONE);
-        return buildResponse(responseBuilder);
-    }
-
-    // //////////////////////////////////////////////////////////////
-    // invoke action
-    // //////////////////////////////////////////////////////////////
-
-    @Programmatic
-    public Response invokeActionQueryOnly(
-            final ResponseContext responseContext,
-            final String actionId, final JsonRepresentation arguments) {
-
-        final ResourceContext resourceContext = responseContext.getResourceContext();
-        final ObjectAdapter objectAdapter = responseContext.getObjectAdapter();
-        final ObjectAdapterLinkTo adapterLinkTo = responseContext.getAdapterLinkTo();
-
-        final ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter);
-
-        final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectAdapterAccessHelper.Intent.MUTATE);
-
-        final ActionSemantics.Of actionSemantics = action.getSemantics();
-        if (actionSemantics != ActionSemantics.Of.SAFE) {
-            throw RestfulObjectsApplicationException.createWithMessage(HttpStatusCode.METHOD_NOT_ALLOWED, "Method not allowed; action '%s' is not query only", action.getId());
-        }
-
-        final ResponseBuilder responseBuilder = invokeActionUsingAdapters(responseContext, action, arguments, SelfLink.INCLUDED);
-        return buildResponse(responseBuilder);
-    }
-
-    @Programmatic
-    public Response invokeActionIdempotent(
-            final ResponseContext responseContext,
-            final String actionId, final JsonRepresentation arguments) {
-
-        final ResourceContext resourceContext = responseContext.getResourceContext();
-        final ObjectAdapter objectAdapter = responseContext.getObjectAdapter();
-
-        final ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter);
-
-        final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectAdapterAccessHelper.Intent.MUTATE);
-
-        final ActionSemantics.Of actionSemantics = action.getSemantics();
-        if (!actionSemantics.isIdempotentInNature()) {
-            throw RestfulObjectsApplicationException.createWithMessage(HttpStatusCode.METHOD_NOT_ALLOWED, "Method not allowed; action '%s' is not idempotent", action.getId());
-        }
-        final ResponseBuilder responseBuilder = invokeActionUsingAdapters(responseContext, action, arguments, SelfLink.EXCLUDED);
-        return buildResponse(responseBuilder);
-    }
-
-    @Programmatic
-    public Response invokeAction(
-            final ResponseContext responseContext,
-            final String actionId, final JsonRepresentation arguments) {
-
-        final ResourceContext resourceContext = responseContext.getResourceContext();
-        final ObjectAdapter objectAdapter = responseContext.getObjectAdapter();
-
-        ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter);
-
-        final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectAdapterAccessHelper.Intent.MUTATE);
-
-        final ResponseBuilder responseBuilder = invokeActionUsingAdapters(responseContext, action, arguments, SelfLink.EXCLUDED);
-        return buildResponse(responseBuilder);
-    }
-
-    /**
-     * Overridable to allow further customization.
-     */
-    protected Response buildResponse(final ResponseBuilder responseBuilder) {
-        return responseBuilder.build();
-    }
-
-    //region > helpers
-    private ResponseBuilder invokeActionUsingAdapters(
-            final ResponseContext responseContext,
-            final ObjectAction action, final JsonRepresentation arguments, SelfLink selfLink) {
-
-        final ResourceContext resourceContext = responseContext.getResourceContext();
-        final ObjectAdapter objectAdapter = responseContext.getObjectAdapter();
-        final ObjectAdapterLinkTo adapterLinkTo = responseContext.getAdapterLinkTo();
-
-        final ObjectActionArgHelper argHelper = new ObjectActionArgHelper(resourceContext, objectAdapter, action);
-
-        final List<ObjectAdapter> argAdapters = argHelper.parseAndValidateArguments(arguments);
-
-        // invoke
-        final ObjectAdapter[] argArray2 = argAdapters.toArray(new ObjectAdapter[0]);
-        final ObjectAdapter returnedAdapter = action.execute(objectAdapter, argArray2);
-
-        // response
-        final ActionResultReprRenderer renderer = new ActionResultReprRenderer(resourceContext, null, selfLink, JsonRepresentation.newMap());
-
-        renderer.with(new ObjectAndActionInvocation(objectAdapter, action, arguments, returnedAdapter)).using(adapterLinkTo);
-
-        final ResponseBuilder respBuilder = Responses.ofOk(renderer, Caching.NONE);
-
-        final Version version = objectAdapter.getVersion();
-        Responses.addLastModifiedAndETagIfAvailable(respBuilder, version);
-
-        return respBuilder;
-    }
-    //endregion
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/Responses.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/Responses.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/Responses.java
deleted file mode 100644
index da3bef2..0000000
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/Responses.java
+++ /dev/null
@@ -1,64 +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.restfulobjects.server.resources;
-
-import java.util.Date;
-import javax.ws.rs.core.EntityTag;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import org.joda.time.DateTime;
-import org.joda.time.format.ISODateTimeFormat;
-import org.apache.isis.core.metamodel.adapter.version.Version;
-import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
-import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
-
-public final class Responses {
-
-    private Responses(){}
-
-    public static Response.ResponseBuilder ofNoContent() {
-        return of(RestfulResponse.HttpStatusCode.NO_CONTENT);
-    }
-
-    public static Response.ResponseBuilder ofOk(final ReprRenderer<?, ?> renderer, final ResourceAbstract.Caching caching) {
-        return ofOk(renderer, caching, null);
-    }
-
-    public static Response.ResponseBuilder ofOk(final ReprRenderer<?, ?> renderer, final ResourceAbstract.Caching caching, final Version version) {
-        final MediaType mediaType = renderer.getMediaType();
-        final Response.ResponseBuilder response = of(RestfulResponse.HttpStatusCode.OK).type(mediaType).cacheControl(caching.getCacheControl()).entity(ResourceAbstract.jsonFor(renderer.render()));
-        return addLastModifiedAndETagIfAvailable(response, version);
-    }
-
-    protected static Response.ResponseBuilder of(final RestfulResponse.HttpStatusCode httpStatusCode) {
-        return Response.status(httpStatusCode.getJaxrsStatusType()).type(MediaType.APPLICATION_JSON_TYPE);
-    }
-
-    public static Response.ResponseBuilder addLastModifiedAndETagIfAvailable(final Response.ResponseBuilder responseBuilder, final Version version) {
-        if (version != null && version.getTime() != null) {
-            final Date time = version.getTime();
-            responseBuilder.lastModified(time);
-            responseBuilder.tag(asETag(time));
-        }
-        return responseBuilder;
-    }
-
-    private static EntityTag asETag(final Date time) {
-        final String utcTime = ISODateTimeFormat.basicDateTime().print(new DateTime(time));
-        return new EntityTag(utcTime, true);
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
index e226fa0..9d1b0c6 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
@@ -28,7 +28,9 @@ import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
 import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
 import org.apache.isis.viewer.restfulobjects.applib.user.UserResource;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+import org.apache.isis.viewer.restfulobjects.rendering.Caching;
+import org.apache.isis.viewer.restfulobjects.rendering.Responses;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 
 public class UserResourceServerside extends ResourceAbstract implements UserResource {
 

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/Util.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/Util.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/Util.java
deleted file mode 100644
index 4af8803..0000000
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/Util.java
+++ /dev/null
@@ -1,124 +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.restfulobjects.server.resources;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Map;
-import com.google.common.base.Charsets;
-import com.google.common.io.ByteStreams;
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.map.JsonMappingException;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
-import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
-import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
-import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.MemberType;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
-
-public final class Util {
-
-    private Util(){}
-
-    // //////////////////////////////////////////////////////////////
-    // parsing
-    // //////////////////////////////////////////////////////////////
-
-    /**
-     * Parse {@link java.io.InputStream} to String, else throw exception
-     */
-    public static String asStringUtf8(final InputStream body) {
-        try {
-            final byte[] byteArray = ByteStreams.toByteArray(body);
-            return new String(byteArray, Charsets.UTF_8);
-        } catch (final IOException e) {
-            throw RestfulObjectsApplicationException.createWithCauseAndMessage(RestfulResponse.HttpStatusCode.BAD_REQUEST, e, "could not read body");
-        }
-    }
-
-    /**
-     * Parse (body) string to {@link org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation}, else throw exception
-     */
-    public static JsonRepresentation readAsMap(final String body) {
-        if (body == null) {
-            return JsonRepresentation.newMap();
-        }
-        final String bodyTrimmed = body.trim();
-        if (bodyTrimmed.isEmpty()) {
-            return JsonRepresentation.newMap();
-        }
-        return read(bodyTrimmed, "body");
-    }
-
-    /**
-     * Parse (query) string to {@link org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation}, else throw exception
-     */
-    public static JsonRepresentation readQueryStringAsMap(final String queryString) {
-        if (queryString == null) {
-            return JsonRepresentation.newMap();
-        }
-        final String queryStringTrimmed = queryString.trim();
-        if (queryStringTrimmed.isEmpty()) {
-            return JsonRepresentation.newMap();
-        }
-        return read(queryStringTrimmed, "query string");
-    }
-
-    /**
-     * REVIEW - looks similar to above methods, but now unused; can it be deleted?
-     */
-    public static JsonRepresentation readParameterMapAsMap(final Map<String, String[]> parameterMap) {
-        final JsonRepresentation map = JsonRepresentation.newMap();
-        for (final Map.Entry<String, String[]> parameter : parameterMap.entrySet()) {
-            map.mapPut(parameter.getKey(), parameter.getValue()[0]);
-        }
-        return map;
-    }
-
-    private static JsonRepresentation read(final String args, final String argsNature) {
-        try {
-            final JsonRepresentation jsonRepr = JsonMapper.instance().read(args);
-            if (!jsonRepr.isMap()) {
-                throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.BAD_REQUEST, "could not read %s as a JSON map", argsNature);
-            }
-            return jsonRepr;
-        } catch (final JsonParseException e) {
-            throw RestfulObjectsApplicationException.createWithCauseAndMessage(RestfulResponse.HttpStatusCode.BAD_REQUEST, e, "could not parse %s", argsNature);
-        } catch (final JsonMappingException e) {
-            throw RestfulObjectsApplicationException.createWithCauseAndMessage(RestfulResponse.HttpStatusCode.BAD_REQUEST, e, "could not read %s as JSON", argsNature);
-        } catch (final IOException e) {
-            throw RestfulObjectsApplicationException.createWithCauseAndMessage(RestfulResponse.HttpStatusCode.BAD_REQUEST, e, "could not parse %s", argsNature);
-        }
-    }
-
-
-    // //////////////////////////////////////////////////////////////
-    // misc
-    // //////////////////////////////////////////////////////////////
-
-    static String resourceFor(final ObjectSpecification objectSpec) {
-        // TODO: should return a string in the form
-        // http://localhost:8080/types/xxx
-        return objectSpec.getFullIdentifier();
-    }
-
-
-    public static void throwNotFoundException(final String memberId, final MemberType memberType) {
-        final String memberTypeStr = memberType.name().toLowerCase();
-        throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.NOT_FOUND, "%s '%s' either does not exist or is not visible", memberTypeStr, memberId);
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java
index 3e78a9c..c2d3da9 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java
@@ -32,7 +32,9 @@ import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
 import org.apache.isis.viewer.restfulobjects.applib.version.VersionResource;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+import org.apache.isis.viewer.restfulobjects.rendering.Caching;
+import org.apache.isis.viewer.restfulobjects.rendering.Responses;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 
 /**
  * Implementation note: it seems to be necessary to annotate the implementation

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/NOTUSED_PathUtils.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/NOTUSED_PathUtils.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/NOTUSED_PathUtils.java
new file mode 100644
index 0000000..cf7d080
--- /dev/null
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/NOTUSED_PathUtils.java
@@ -0,0 +1,40 @@
+/*
+ *  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.restfulobjects.server.util;
+
+import javax.servlet.http.HttpServletRequest;
+
+
+public final class NOTUSED_PathUtils {
+
+    private NOTUSED_PathUtils() {
+    }
+
+    public static String combine(final HttpServletRequest request, final String... pathElements) {
+        final StringBuilder buf = new StringBuilder(request.getContextPath());
+        for (final String pathElement : pathElements) {
+            if (!pathElement.startsWith("/")) {
+                buf.append("/");
+            }
+            buf.append(pathElement);
+        }
+        return buf.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java
index d55ba71..a4856ba 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java
@@ -39,22 +39,27 @@ public final class OidUtils {
     /**
      * @return {@code null} if not persistent and not a view model.
      */
-    public static ObjectAdapter getObjectAdapterElseNull(final RendererContext resourceContext,
-                                                         final String domainType, final String instanceIdEncoded) {
+    public static ObjectAdapter getObjectAdapterElseNull(
+            final RendererContext rendererContext,
+            final String domainType, final String instanceIdEncoded) {
         final String instanceIdUnencoded = UrlDecoderUtils.urlDecode(instanceIdEncoded);
         String oidStrUnencoded = getOidMarshaller().joinAsOid(domainType, instanceIdUnencoded);
-        return getObjectAdapter(resourceContext, oidStrUnencoded);
+        return getObjectAdapter(rendererContext, oidStrUnencoded);
     }
 
     /**
      * see {@link #getObjectAdapterElseNull(org.apache.isis.viewer.restfulobjects.rendering.RendererContext, String, String)}
      */
-    public static ObjectAdapter getObjectAdapterElseNull(final RendererContext resourceContext, final String oidStrEncoded) {
+    public static ObjectAdapter getObjectAdapterElseNull(
+            final RendererContext rendererContext,
+            final String oidStrEncoded) {
         String oidStrUnencoded = UrlDecoderUtils.urlDecode(oidStrEncoded);
-        return getObjectAdapter(resourceContext, oidStrUnencoded);
+        return getObjectAdapter(rendererContext, oidStrUnencoded);
     }
 
-    private static ObjectAdapter getObjectAdapter(RendererContext resourceContext, String oidStrUnencoded) {
+    private static ObjectAdapter getObjectAdapter(
+            final RendererContext rendererContext,
+            final String oidStrUnencoded) {
         RootOidDefault rootOid = RootOidDefault.deString(oidStrUnencoded, getOidMarshaller());
         final ObjectSpecId specId = rootOid.getObjectSpecId();
 
@@ -65,7 +70,7 @@ public final class OidUtils {
         }
 
         // TODO: the logic to figure out which PersistenceSession API to call should be pushed down into PersistenceSession itself.
-        final PersistenceSession persistenceSession = resourceContext.getPersistenceSession();
+        final PersistenceSession persistenceSession = rendererContext.getPersistenceSession();
 
         if(spec.containsFacet(ViewModelFacet.class)) {
 

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/PathUtils.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/PathUtils.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/PathUtils.java
deleted file mode 100644
index 2410679..0000000
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/PathUtils.java
+++ /dev/null
@@ -1,40 +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.restfulobjects.server.util;
-
-import javax.servlet.http.HttpServletRequest;
-
-
-public final class PathUtils {
-
-    private PathUtils() {
-    }
-
-    public static String combine(final HttpServletRequest request, final String... pathElements) {
-        final StringBuilder buf = new StringBuilder(request.getContextPath());
-        for (final String pathElement : pathElements) {
-            if (!pathElement.startsWith("/")) {
-                buf.append("/");
-            }
-            buf.append(pathElement);
-        }
-        return buf.toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtils.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtils.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtils.java
index 4921a1b..ec7f71c 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtils.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtils.java
@@ -20,26 +20,13 @@ package org.apache.isis.viewer.restfulobjects.server.util;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
-import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 
 public final class UrlParserUtils {
 
-    private final static Pattern OBJECT_OID = Pattern.compile(".*objects\\/([^/]+)\\/(.+)");;
-    private final static Pattern DOMAIN_TYPE = Pattern.compile(".*domain-types\\/([^/]+).*");;
+    private UrlParserUtils(){}
 
-    public final static String encodedOidFromLink(final JsonRepresentation link) {
-        final String href = link.getString("href");
-        
-        final Matcher matcher = OBJECT_OID.matcher(href);
-        if (!matcher.matches()) {
-            return null;
-        }
-        String domainType = matcher.group(1);
-        String instanceId = matcher.group(2);
-        return getOidMarshaller().joinAsOid(domainType, instanceId);
-    }
+    private final static Pattern DOMAIN_TYPE = Pattern.compile(".*domain-types\\/([^/]+).*");;
 
     public final static String domainTypeFrom(final JsonRepresentation link) {
         return domainTypeFrom(link.getString("href"));
@@ -53,8 +40,5 @@ public final class UrlParserUtils {
         return matcher.group(1);
     }
 
-    private static OidMarshaller getOidMarshaller() {
-        return new OidMarshaller();
-    }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java
index f83eb59..824db47 100644
--- a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java
+++ b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java
@@ -32,6 +32,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
index b900a62..8dae5e9 100644
--- a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
+++ b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
@@ -31,6 +31,7 @@ import org.junit.Test;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
 import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 
 public class RestfulObjectsApplicationExceptionMapperTest {
 

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java
index c694d49..b119ba9 100644
--- a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java
+++ b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java
@@ -24,7 +24,8 @@ import static org.junit.Assert.assertThat;
 import org.junit.Test;
 
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
-import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
+import org.apache.isis.viewer.restfulobjects.rendering.util.Util;
 
 public class DomainResourceHelperTest_readBodyAsMap {
 

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelpTest.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelpTest.java b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelpTest.java
new file mode 100644
index 0000000..8d64a93
--- /dev/null
+++ b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/JsonParserHelpTest.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.viewer.restfulobjects.server.resources;
+
+import org.junit.Test;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+
+import static org.junit.Assert.assertEquals;
+
+public class JsonParserHelpTest {
+
+    @Test
+    public void oidFromLink() throws Exception {
+        final JsonRepresentation link = JsonRepresentation.newMap();
+        link.mapPut("href", "http://localhost/objects/OID/1");
+        final String oidFromHref = JsonParserHelper.encodedOidFromLink(link);
+        assertEquals("OID:1", oidFromHref);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java
index edbff05..b659df4 100644
--- a/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java
+++ b/core/viewer-restfulobjects-server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java
@@ -18,21 +18,12 @@
  */
 package org.apache.isis.viewer.restfulobjects.server.util;
 
-import static org.junit.Assert.assertEquals;
-
 import org.junit.Test;
-
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 
-public class UrlParserUtilsTest {
+import static org.junit.Assert.assertEquals;
 
-    @Test
-    public void oidFromLink() throws Exception {
-        final JsonRepresentation link = JsonRepresentation.newMap();
-        link.mapPut("href", "http://localhost/objects/OID/1");
-        final String oidFromHref = UrlParserUtils.encodedOidFromLink(link);
-        assertEquals("OID:1", oidFromHref);
-    }
+public class UrlParserUtilsTest {
 
     @Test
     public void domainTypeFromLink() throws Exception {

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/example/application/todoapp/webapp/src/main/java/webapp/CustomRepresentationService.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/webapp/src/main/java/webapp/CustomRepresentationService.java b/example/application/todoapp/webapp/src/main/java/webapp/CustomRepresentationService.java
new file mode 100644
index 0000000..9cf70af
--- /dev/null
+++ b/example/application/todoapp/webapp/src/main/java/webapp/CustomRepresentationService.java
@@ -0,0 +1,32 @@
+/*
+ *  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 webapp;
+
+import javax.ws.rs.core.Response;
+import org.apache.isis.viewer.restfulobjects.rendering.service.RepresentationServiceForRestfulObjects;
+
+public class CustomRepresentationService extends RepresentationServiceForRestfulObjects {
+
+    @Override
+    protected Response buildResponse(Response.ResponseBuilder responseBuilder) {
+        responseBuilder.header("X-ResponseGeneratedBy", getClass().getCanonicalName());
+        return super.buildResponse(responseBuilder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/example/application/todoapp/webapp/src/main/java/webapp/CustomResponseGeneratorService.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/webapp/src/main/java/webapp/CustomResponseGeneratorService.java b/example/application/todoapp/webapp/src/main/java/webapp/CustomResponseGeneratorService.java
deleted file mode 100644
index 7fb1c9a..0000000
--- a/example/application/todoapp/webapp/src/main/java/webapp/CustomResponseGeneratorService.java
+++ /dev/null
@@ -1,32 +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 webapp;
-
-import javax.ws.rs.core.Response;
-import org.apache.isis.viewer.restfulobjects.server.resources.ResponseGeneratorService;
-
-public class CustomResponseGeneratorService extends ResponseGeneratorService {
-
-    @Override
-    protected Response buildResponse(Response.ResponseBuilder responseBuilder) {
-        responseBuilder.header("X-ResponseGeneratedBy", getClass().getCanonicalName());
-        return super.buildResponse(responseBuilder);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/6907534b/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties
index 2b70530..11f9141 100644
--- a/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties
@@ -149,7 +149,7 @@ isis.services = \
                 org.apache.isis.objectstore.jdo.applib.service.exceprecog.ExceptionRecognizerCompositeForJdoObjectStore,\
                 #,\
                 1:webapp.CustomMementoService,\
-                1:webapp.CustomResponseGeneratorService
+                1:webapp.CustomRepresentationService
 
 
 # Specify the (optional) test fixtures