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/01/31 11:46:17 UTC

[2/3] ISIS-657, ISIS-660, ISIS-661, ISIS-662, ISIS-663, ISIS-667, ISIS-668, ISIS-670: JDO services

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdo.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdo.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdo.java
index 5dd0387..1e58d11 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdo.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdo.java
@@ -25,9 +25,9 @@ import org.apache.isis.applib.AbstractService;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.clock.Clock;
 import org.apache.isis.applib.services.interaction.Interaction;
-import org.apache.isis.applib.services.interaction.spi.InteractionFactory;
+import org.apache.isis.applib.services.interaction.spi.InteractionService;
 
-public class InteractionServiceJdo extends AbstractService implements InteractionFactory {
+public class InteractionServiceJdo extends AbstractService implements InteractionService {
 
     @SuppressWarnings("unused")
     private static final Logger LOG = LoggerFactory.getLogger(InteractionServiceJdo.class);
@@ -47,13 +47,17 @@ public class InteractionServiceJdo extends AbstractService implements Interactio
 
     @Programmatic
     @Override
-    public void startTransaction(Interaction interaction, UUID transactionId) {
+    public void startTransaction(final Interaction interaction, final UUID transactionId) {
         if(interaction instanceof InteractionJdo) {
             // should be the case, since this service created the object in the #create() method
-            InteractionJdo interactionJdo = (InteractionJdo) interaction;
-            if(interactionJdo.getTransactionId() == null) {
-                interactionJdo.setTransactionId(transactionId);
+            final InteractionJdo interactionJdo = (InteractionJdo) interaction;
+            final UUID currentTransactionId = interactionJdo.getTransactionId();
+            if(currentTransactionId != null && !currentTransactionId.equals(transactionId)) {
+                // the logic in IsisTransaction means that any subsequent transactions within a given interaction
+                // should reuse the xactnId of the first transaction created within that interaction.
+                throw new IllegalStateException("Attempting to set a different transactionId on interaction");
             }
+            interactionJdo.setTransactionId(transactionId);
         }
     }
 
@@ -71,7 +75,7 @@ public class InteractionServiceJdo extends AbstractService implements Interactio
     }
 
     /**
-     * Not API, factored out from {@link InteractionRepository}.
+     * Not API, factored out from {@link InteractionServiceJdoRepository}.
      */
     InteractionJdo asPersistableInteractionJdo(final Interaction interaction) {
         if(interaction.getNature() == Interaction.Nature.ACTION_INVOCATION) {

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdoRepository.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdoRepository.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdoRepository.java
new file mode 100644
index 0000000..8fea1c3
--- /dev/null
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionServiceJdoRepository.java
@@ -0,0 +1,72 @@
+/**
+ *  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.objectstore.jdo.applib.service.interaction;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.isis.applib.AbstractFactoryAndRepository;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.query.QueryDefault;
+import org.apache.isis.applib.services.interaction.Interaction;
+import org.apache.isis.applib.services.interaction.InteractionContext;
+
+
+public class InteractionServiceJdoRepository extends AbstractFactoryAndRepository {
+
+    @Programmatic
+    public InteractionJdo findByTransactionId(final UUID transactionId) {
+        persistCurrentInteractionIfRequired();
+        return firstMatch(
+                new QueryDefault<InteractionJdo>(InteractionJdo.class, 
+                        "findByTransactionId", 
+                        "transactionId", transactionId.toString()));
+    }
+
+    private void persistCurrentInteractionIfRequired() {
+        if(interactionContext != null && interactionService != null) {
+            Interaction interaction = interactionContext.getInteraction();
+            final InteractionJdo interactionJdo = interactionService.asPersistableInteractionJdo(interaction);
+            persistIfNotAlready(interactionJdo);
+        }
+    }
+
+    
+    @Programmatic
+    public List<InteractionJdo> findCurrent() {
+        persistCurrentInteractionIfRequired();
+        return allMatches(
+                new QueryDefault<InteractionJdo>(InteractionJdo.class, "findCurrent"));
+    }
+    
+    @Programmatic
+    public List<InteractionJdo> findCompleted() {
+        persistCurrentInteractionIfRequired();
+        return allMatches(
+                new QueryDefault<InteractionJdo>(InteractionJdo.class, "findCompleted"));
+    }
+
+    // //////////////////////////////////////
+
+    
+    @javax.inject.Inject
+    private InteractionServiceJdo interactionService;
+    
+    @javax.inject.Inject
+    private InteractionContext interactionContext;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/Util.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/Util.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/Util.java
new file mode 100644
index 0000000..031817a
--- /dev/null
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/interaction/Util.java
@@ -0,0 +1,68 @@
+/**
+ *  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.objectstore.jdo.applib.service.interaction;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.Timestamp;
+
+import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.services.HasTransactionId;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.applib.services.interaction.Interaction;
+
+public class Util {
+
+    private Util() {}
+
+    public static Bookmark bookmarkFor(final String str) {
+        return str != null? new Bookmark(str): null;
+    }
+
+    public static String asString(Bookmark bookmark) {
+        return bookmark != null? bookmark.toString(): null;
+    }
+
+    public static Object lookupBookmark(Bookmark bookmark, final BookmarkService bookmarkService, DomainObjectContainer container) {
+        try {
+            return bookmarkService != null
+                    ? bookmarkService.lookup(bookmark)
+                    : null;
+        } catch(RuntimeException ex) {
+            if(ex.getClass().getName().contains("ObjectNotFoundException")) {
+                container.warnUser("Object not found - has it since been deleted?");
+                return null;
+            } 
+            throw ex;
+        }
+    }
+
+    
+    public static String abbreviated(final String str, final int maxLength) {
+        return str != null? (str.length() < maxLength ? str : str.substring(0, maxLength - 3) + "..."): null;
+    }
+
+    public static BigDecimal durationBetween(Timestamp startedAt, Timestamp completedAt) {
+        if(completedAt == null) {
+            return null;
+        }
+        long millis = completedAt.getTime() - startedAt.getTime();
+        return new BigDecimal(millis).divide(new BigDecimal(1000)).setScale(3, RoundingMode.HALF_EVEN);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEvent.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEvent.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEvent.java
deleted file mode 100644
index f167bcb..0000000
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEvent.java
+++ /dev/null
@@ -1,270 +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.objectstore.jdo.applib.service.publish;
-
-
-import java.util.UUID;
-
-import javax.jdo.annotations.IdentityType;
-
-import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.annotation.ActionSemantics;
-import org.apache.isis.applib.annotation.ActionSemantics.Of;
-import org.apache.isis.applib.annotation.Bulk;
-import org.apache.isis.applib.annotation.Hidden;
-import org.apache.isis.applib.annotation.Immutable;
-import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.MultiLine;
-import org.apache.isis.applib.annotation.NotPersisted;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.Title;
-import org.apache.isis.applib.annotation.TypicalLength;
-import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.services.HasTransactionId;
-import org.apache.isis.applib.services.publish.EventMetadata;
-import org.apache.isis.applib.services.publish.EventType;
-
-@javax.jdo.annotations.PersistenceCapable(
-        identityType=IdentityType.APPLICATION,
-        table="IsisPublishedEvent")
-@javax.jdo.annotations.Queries( {
-    @javax.jdo.annotations.Query(
-            name="findByStateOrderByTimestamp", language="JDOQL",  
-            value="SELECT "
-                    + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEvent "
-                    + "WHERE state == :state ORDER BY timestamp"),
-    @javax.jdo.annotations.Query(
-            name="findByTransactionId", language="JDOQL",  
-            value="SELECT "
-                    + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEvent "
-                    + "WHERE transactionId == :transactionId")
-            
-})
-@Immutable
-public class PublishedEvent implements HasTransactionId {
-
-    public static enum State {
-        QUEUED, PROCESSED
-    }
-    
-    // //////////////////////////////////////
-
-    private String title;
-
-    @javax.jdo.annotations.Column(allowsNull="false", length=255)
-    @Title
-    @Hidden
-    public String getTitle() {
-        return title;
-    }
-
-    public void setTitle(final String title) {
-        this.title = title;
-    }
-
-    // //////////////////////////////////////
-
-    private long timestamp;
-
-    @MemberOrder(sequence = "1")
-    public long getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(final long timestamp) {
-        this.timestamp = timestamp;
-    }
-    
-    // //////////////////////////////////////
-
-    private String id;
-
-    /**
-     * Programmatic because information also available in the {@link #getId() id}.
-     * 
-     * <p>
-     * Length of 47 because 36 chars (UUID) + 1 character + 10 chars for sequence number (an int) 
-     * 
-     * <p>
-     * @see EventMetadata#getId()
-     * @see https://issues.apache.org/jira/browse/ISIS-632
-     */
-    @javax.jdo.annotations.Column(length=47)
-    @javax.jdo.annotations.PrimaryKey
-    @TypicalLength(47)
-    @MemberOrder(sequence = "2")
-    public String getId() {
-        return id;
-    }
-
-    public void setId(final String id) {
-        this.id = id;
-    }
-    
-    // //////////////////////////////////////
-
-    private UUID transactionId;
-
-    /**
-     * Hidden (<tt>@Programmatic</tt>) because information also available in the {@link #getId() id}.
-     */
-    @javax.jdo.annotations.Column(length=36)
-    @Programmatic
-    @Override
-    public UUID getTransactionId() {
-        return transactionId;
-    }
-
-    @Override
-    public void setTransactionId(final UUID transactionId) {
-        this.transactionId = transactionId;
-    }
-    
-    // //////////////////////////////////////
-
-    private int sequence;
-
-    /**
-     * Hidden (<tt>@Programmatic</tt>) because information also available in the {@link #getId() id}.
-     * 
-     * @see #getId()
-     */
-    @Programmatic
-    public int getSequence() {
-        return sequence;
-    }
-
-    public void setSequence(final int sequence) {
-        this.sequence = sequence;
-    }
-    
-    // //////////////////////////////////////
-
-    private EventType eventType;
-
-    @javax.jdo.annotations.Column(allowsNull="false")
-    @MemberOrder(sequence = "3")
-    public EventType getEventType() {
-        return eventType;
-    }
-
-    public void setEventType(final EventType eventType) {
-        this.eventType = eventType;
-    }
-    
-    // //////////////////////////////////////
-
-    private String user;
-    
-    @javax.jdo.annotations.Column(allowsNull="false", length=50)
-    @MemberOrder(sequence = "4")
-    public String getUser() {
-        return user;
-    }
-    
-    public void setUser(final String user) {
-        this.user = user;
-    }
-    
-    // //////////////////////////////////////
-
-    private State state;
-
-    @javax.jdo.annotations.Column(allowsNull="false", length=20)
-    @MemberOrder(sequence = "5")
-    public State getState() {
-        return state;
-    }
-
-    public void setState(final State state) {
-        this.state = state;
-    }
-    private PublishedEvent setStateAndReturn(State state) {
-        setState(state);
-        return this;
-    }
-    
-    // //////////////////////////////////////
-
-    @javax.jdo.annotations.NotPersistent
-    @NotPersisted
-    @MultiLine(numberOfLines=20)
-    @Hidden(where=Where.ALL_TABLES)
-    @MemberOrder(sequence = "6")
-    public String getSerializedForm() {
-        return IoUtils.fromUtf8ZippedBytes("serializedForm", getSerializedFormZipped());
-    }
-
-    public void setSerializedForm(final String serializedForm) {
-        final byte[] zippedBytes = IoUtils.toUtf8ZippedBytes("serializedForm", serializedForm);
-        setSerializedFormZipped(zippedBytes);
-    }
-    
-    // //////////////////////////////////////
-
-    @javax.jdo.annotations.Column
-    private byte[] serializedFormZipped;
-
-    @Programmatic // ignored by Isis
-    public byte[] getSerializedFormZipped() {
-        return serializedFormZipped;
-    }
-
-    public void setSerializedFormZipped(final byte[] serializedFormZipped) {
-        this.serializedFormZipped = serializedFormZipped;
-    }
-    
-    // //////////////////////////////////////
-
- 
-    @Bulk
-    @ActionSemantics(Of.IDEMPOTENT)
-    @MemberOrder(sequence="10")
-    public PublishedEvent processed() {
-        return setStateAndReturn(State.PROCESSED);
-    }
-
-
-    @Bulk
-    @ActionSemantics(Of.IDEMPOTENT)
-    @MemberOrder(sequence="11")
-    public PublishedEvent reQueue() {
-        return setStateAndReturn(State.QUEUED);
-    }
-
-    @Bulk
-    @MemberOrder(sequence="12")
-    public void delete() {
-        container.removeIfNotAlready(this);
-    }
-    
-
-    // //////////////////////////////////////
-
-    private DomainObjectContainer container;
-
-    public void setDomainObjectContainer(final DomainObjectContainer container) {
-        this.container = container;
-    }
-
-
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventContributions.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventContributions.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventContributions.java
deleted file mode 100644
index f81d0f8..0000000
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventContributions.java
+++ /dev/null
@@ -1,47 +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.objectstore.jdo.applib.service.publish;
-
-import java.util.List;
-
-import org.apache.isis.applib.AbstractFactoryAndRepository;
-import org.apache.isis.applib.annotation.ActionSemantics;
-import org.apache.isis.applib.annotation.Render;
-import org.apache.isis.applib.annotation.ActionSemantics.Of;
-import org.apache.isis.applib.annotation.NotContributed;
-import org.apache.isis.applib.annotation.NotContributed.As;
-import org.apache.isis.applib.annotation.Render.Type;
-import org.apache.isis.applib.annotation.NotInServiceMenu;
-import org.apache.isis.applib.services.HasTransactionId;
-
-
-public class PublishedEventContributions extends AbstractFactoryAndRepository {
-
-    @ActionSemantics(Of.SAFE)
-    @NotInServiceMenu
-    @NotContributed(As.ACTION)
-    @Render(Type.EAGERLY)
-    public List<PublishedEvent> publishedEvents(final HasTransactionId hasTransactionId) {
-        return publishedEventRepository.findByTransactionId(hasTransactionId.getTransactionId());
-    }
-    
-    // //////////////////////////////////////
-
-    @javax.inject.Inject
-    private PublishedEventRepository publishedEventRepository;
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdo.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdo.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdo.java
new file mode 100644
index 0000000..b7a9542
--- /dev/null
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdo.java
@@ -0,0 +1,310 @@
+/*
+ *  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.objectstore.jdo.applib.service.publish;
+
+import java.util.UUID;
+
+import javax.jdo.annotations.IdentityType;
+
+import org.datanucleus.management.jmx.ManagementManager;
+
+import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.Bulk;
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.Immutable;
+import org.apache.isis.applib.annotation.MemberGroupLayout;
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.MultiLine;
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.annotation.NotPersisted;
+import org.apache.isis.applib.annotation.ObjectType;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.annotation.Title;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.HasTransactionId;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.applib.services.publish.EventType;
+import org.apache.isis.objectstore.jdo.applib.service.JdoColumnLength;
+import org.apache.isis.objectstore.jdo.applib.service.interaction.Util;
+
+@javax.jdo.annotations.PersistenceCapable(
+        identityType=IdentityType.APPLICATION,
+        table="IsisPublishedEvent", 
+        objectIdClass=PublishedEventJdoPK.class)
+@javax.jdo.annotations.Queries( {
+    @javax.jdo.annotations.Query(
+            name="findByStateOrderByTimestamp", language="JDOQL",  
+            value="SELECT "
+                    + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+                    + "WHERE state == :state ORDER BY timestamp"),
+    @javax.jdo.annotations.Query(
+            name="findByTransactionId", language="JDOQL",  
+            value="SELECT "
+                    + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+                    + "WHERE transactionId == :transactionId")
+})
+@MemberGroupLayout(
+        //columnSpans={5,0,7},
+        left={"Identifiers","Detail"})
+@Immutable
+@ObjectType("IsisPublishedEvent")
+public class PublishedEventJdo implements HasTransactionId {
+
+    public static enum State {
+        QUEUED, PROCESSED
+    }
+    
+    // //////////////////////////////////////
+
+    private UUID transactionId;
+
+    /**
+     * The unique identifier (a GUID) of the transaction in which this published event was persisted.
+     * 
+     * <p>
+     * The combination of ({@link #getTransactionId() transactionId}, {@link #getSequence() sequence}) makes up the
+     * primary key.
+     */
+    @javax.jdo.annotations.PrimaryKey
+    @javax.jdo.annotations.Column(allowsNull="false",length=JdoColumnLength.TRANSACTION_ID)
+    @MemberOrder(name="Identifiers", sequence = "10")
+    @Hidden(where=Where.PARENTED_TABLES)
+    @Override
+    public UUID getTransactionId() {
+        return transactionId;
+    }
+
+    @Override
+    public void setTransactionId(final UUID transactionId) {
+        this.transactionId = transactionId;
+    }
+
+    
+    // //////////////////////////////////////
+    // sequence
+    // //////////////////////////////////////
+
+    private int sequence;
+
+    /**
+     * The 0-based additional identifier of a published event within the given {@link #getTransactionId() transaction}.
+     * 
+     * <p>
+     * The combination of ({@link #getTransactionId() transactionId}, {@link #getSequence() sequence}) makes up the
+     * primary key.
+     */
+    @javax.jdo.annotations.PrimaryKey
+    @MemberOrder(name="Identifiers", sequence = "20")
+    public int getSequence() {
+        return sequence;
+    }
+
+    public void setSequence(final int sequence) {
+        this.sequence = sequence;
+    }
+    
+
+    // //////////////////////////////////////
+    // user (property)
+    // //////////////////////////////////////
+
+    private String user;
+    
+    @javax.jdo.annotations.Column(allowsNull="false", length=50)
+    @MemberOrder(name="Identifiers", sequence = "30")
+    @Hidden(where=Where.PARENTED_TABLES)
+    public String getUser() {
+        return user;
+    }
+    
+    public void setUser(final String user) {
+        this.user = user;
+    }
+    
+
+    // //////////////////////////////////////
+    // timestamp (property)
+    // //////////////////////////////////////
+
+    private java.sql.Timestamp timestamp;
+
+    @javax.jdo.annotations.Persistent
+    @javax.jdo.annotations.Column(allowsNull="false")
+    @MemberOrder(name="Identifiers", sequence = "40")
+    @Hidden(where=Where.PARENTED_TABLES)
+    public java.sql.Timestamp getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(final java.sql.Timestamp timestamp) {
+        this.timestamp = timestamp;
+    }
+    
+
+    // //////////////////////////////////////
+    // title
+    // //////////////////////////////////////
+
+    private String title;
+
+    @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.PublishedEvent.TITLE)
+    @Title
+    @MemberOrder(name="Detail", sequence = "10")
+    @Named("Target")
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(final String title) {
+        this.title = title;
+    }
+    
+    // //////////////////////////////////////
+
+    
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(name="Title", sequence="1")
+    @Named("Open")
+    public Object openTitleObject() {
+        String title2 = getTitle();
+        int indexOf = title2.indexOf("^");
+        if(indexOf != -1) {
+            title2 = title2.substring(0, indexOf);
+        }
+        return Util.lookupBookmark(Util.bookmarkFor(title2), bookmarkService, container);
+    }
+    public boolean hideOpenTitleObject() {
+        return getTitle() == null;
+    }
+
+    // //////////////////////////////////////
+    // eventType (property)
+    // //////////////////////////////////////
+
+    private EventType eventType;
+
+    @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.PublishedEvent.EVENT_TYPE)
+    @MemberOrder(name="Detail",sequence = "20")
+    public EventType getEventType() {
+        return eventType;
+    }
+
+    public void setEventType(final EventType eventType) {
+        this.eventType = eventType;
+    }
+    
+
+    // //////////////////////////////////////
+    // state (property)
+    // //////////////////////////////////////
+
+    private State state;
+
+    @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.PublishedEvent.STATE)
+    @MemberOrder(name="Detail", sequence = "30")
+    public State getState() {
+        return state;
+    }
+
+    public void setState(final State state) {
+        this.state = state;
+    }
+    private PublishedEventJdo setStateAndReturn(State state) {
+        setState(state);
+        return this;
+    }
+    
+
+    // //////////////////////////////////////
+    // serializedFormZipped (property)
+    // serializedForm (derived property)
+    // //////////////////////////////////////
+
+    @javax.jdo.annotations.NotPersistent
+    @NotPersisted
+    @MultiLine(numberOfLines=20)
+    @Hidden(where=Where.ALL_TABLES)
+    @MemberOrder(name="Detail", sequence = "40")
+    public String getSerializedForm() {
+        return IoUtils.fromUtf8ZippedBytes("serializedForm", getSerializedFormZipped());
+    }
+
+    public void setSerializedForm(final String serializedForm) {
+        final byte[] zippedBytes = IoUtils.toUtf8ZippedBytes("serializedForm", serializedForm);
+        setSerializedFormZipped(zippedBytes);
+    }
+
+    // //////////////////////////////////////
+
+    
+    @javax.jdo.annotations.Column
+    private byte[] serializedFormZipped;
+
+    @Programmatic // ignored by Isis
+    public byte[] getSerializedFormZipped() {
+        return serializedFormZipped;
+    }
+
+    public void setSerializedFormZipped(final byte[] serializedFormZipped) {
+        this.serializedFormZipped = serializedFormZipped;
+    }
+
+    
+
+    // //////////////////////////////////////
+    // processed (action)
+    // reQueue   (action)
+    // delete    (action)
+    // //////////////////////////////////////
+
+ 
+    @Bulk
+    @ActionSemantics(Of.IDEMPOTENT)
+    @MemberOrder( name="State", sequence="10")
+    public PublishedEventJdo processed() {
+        return setStateAndReturn(State.PROCESSED);
+    }
+
+
+    @Bulk
+    @ActionSemantics(Of.IDEMPOTENT)
+    @MemberOrder(name="State", sequence="11")
+    public PublishedEventJdo reQueue() {
+        return setStateAndReturn(State.QUEUED);
+    }
+
+    @Bulk
+    @MemberOrder(name="State", sequence="12")
+    public void delete() {
+        container.removeIfNotAlready(this);
+    }
+    
+
+    // //////////////////////////////////////
+
+    @javax.inject.Inject
+    private BookmarkService bookmarkService;
+
+    @javax.inject.Inject
+    private DomainObjectContainer container;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdoPK.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdoPK.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdoPK.java
new file mode 100644
index 0000000..0666ed3
--- /dev/null
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdoPK.java
@@ -0,0 +1,102 @@
+/*
+ *  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.objectstore.jdo.applib.service.publish;
+
+import java.io.Serializable;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+public class PublishedEventJdoPK implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String SEPARATOR = "_";
+
+    public UUID transactionId;
+    public int sequence;
+
+    // //////////////////////////////////////
+
+    
+    public PublishedEventJdoPK() {
+    }
+    
+    public PublishedEventJdoPK(final String value) {
+        final StringTokenizer token = new StringTokenizer (value, SEPARATOR);
+        this.transactionId = UUID.fromString(token.nextToken());
+        this.sequence = Integer.parseInt(token.nextToken());
+    }
+
+    // //////////////////////////////////////
+
+    public UUID getTransactionId() {
+        return transactionId;
+    }
+    public void setTransactionId(UUID transactionId) {
+        this.transactionId = transactionId;
+    }
+    
+    // //////////////////////////////////////
+
+    public int getSequence() {
+        return sequence;
+    }
+    public void setSequence(int sequence) {
+        this.sequence = sequence;
+    }
+    
+    // //////////////////////////////////////
+
+    
+    
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + sequence;
+        result = prime * result + ((transactionId == null) ? 0 : transactionId.hashCode());
+        return result;
+    }
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        PublishedEventJdoPK other = (PublishedEventJdoPK) obj;
+        if (sequence != other.sequence)
+            return false;
+        if (transactionId == null) {
+            if (other.transactionId != null)
+                return false;
+        } else if (!transactionId.equals(other.transactionId))
+            return false;
+        return true;
+    }
+    
+    // //////////////////////////////////////
+
+    
+    @Override
+    public String toString() {
+        return transactionId + SEPARATOR + sequence;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventRepository.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventRepository.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventRepository.java
deleted file mode 100644
index ebb170b..0000000
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventRepository.java
+++ /dev/null
@@ -1,71 +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.objectstore.jdo.applib.service.publish;
-
-import java.util.List;
-import java.util.UUID;
-
-import org.apache.isis.applib.AbstractFactoryAndRepository;
-import org.apache.isis.applib.annotation.ActionSemantics;
-import org.apache.isis.applib.annotation.NotContributed;
-import org.apache.isis.applib.annotation.NotInServiceMenu;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.ActionSemantics.Of;
-import org.apache.isis.applib.annotation.NotContributed.As;
-import org.apache.isis.applib.query.QueryDefault;
-import org.apache.isis.applib.services.HasTransactionId;
-
-public class PublishedEventRepository extends AbstractFactoryAndRepository {
-
-    @Programmatic
-    public List<PublishedEvent> findQueued() {
-        return allMatches(
-                new QueryDefault<PublishedEvent>(PublishedEvent.class, 
-                        "findByStateOrderByTimestamp", 
-                        "state", PublishedEvent.State.QUEUED));
-    }
-
-    @Programmatic
-    public List<PublishedEvent> findProcessed() {
-        return allMatches(
-                new QueryDefault<PublishedEvent>(PublishedEvent.class, 
-                        "findByStateOrderByTimestamp", 
-                        "state", PublishedEvent.State.PROCESSED));
-    }
-
-    @Programmatic
-    public List<PublishedEvent> findByTransactionId(final UUID transactionId) {
-        return allMatches(
-                new QueryDefault<PublishedEvent>(PublishedEvent.class, 
-                        "findByTransactionId", 
-                        "transactionId", transactionId));
-    }
-
-    @Programmatic
-    public void purgeProcessed() {
-        // REVIEW: this is not particularly performant.
-        // much better would be to go direct to the JDO API.
-        List<PublishedEvent> processedEvents = findProcessed();
-        for (PublishedEvent publishedEvent : processedEvents) {
-            publishedEvent.delete();
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java
index b1fbc9d..97fb3d6 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java
@@ -35,15 +35,14 @@ public class PublishingServiceJdo extends AbstractService implements PublishingS
 
     @Override
     @Programmatic
-    public void publish(EventMetadata metadata, EventPayload payload) {
+    public void publish(final EventMetadata metadata, final EventPayload payload) {
         final String serializedEvent = eventSerializer.serialize(metadata, payload).toString();
-        final PublishedEvent publishedEvent = newTransientInstance(PublishedEvent.class);
+        final PublishedEventJdo publishedEvent = newTransientInstance(PublishedEventJdo.class);
         publishedEvent.setSerializedForm(serializedEvent);
-        publishedEvent.setId(metadata.getId());
         publishedEvent.setTransactionId(metadata.getTransactionId());
         publishedEvent.setSequence(metadata.getSequence());
         publishedEvent.setEventType(metadata.getEventType());
-        publishedEvent.setTimestamp(metadata.getTimestamp());
+        publishedEvent.setTimestamp(metadata.getJavaSqlTimestamp());
         publishedEvent.setUser(metadata.getUser());
         publishedEvent.setTitle(metadata.getTitle());
         persist(publishedEvent);
@@ -52,6 +51,7 @@ public class PublishingServiceJdo extends AbstractService implements PublishingS
     // //////////////////////////////////////
 
     private EventSerializer eventSerializer;
+    
     @Override
     public void setEventSerializer(EventSerializer eventSerializer) {
         this.eventSerializer = eventSerializer;

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoContributions.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoContributions.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoContributions.java
new file mode 100644
index 0000000..1709f64
--- /dev/null
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoContributions.java
@@ -0,0 +1,47 @@
+/**
+ *  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.objectstore.jdo.applib.service.publish;
+
+import java.util.List;
+
+import org.apache.isis.applib.AbstractFactoryAndRepository;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.Render;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.applib.annotation.NotContributed.As;
+import org.apache.isis.applib.annotation.Render.Type;
+import org.apache.isis.applib.annotation.NotInServiceMenu;
+import org.apache.isis.applib.services.HasTransactionId;
+
+
+public class PublishingServiceJdoContributions extends AbstractFactoryAndRepository {
+
+    @ActionSemantics(Of.SAFE)
+    @NotInServiceMenu
+    @NotContributed(As.ACTION)
+    @Render(Type.EAGERLY)
+    public List<PublishedEventJdo> publishedEvents(final HasTransactionId hasTransactionId) {
+        return publishedEventRepository.findByTransactionId(hasTransactionId.getTransactionId());
+    }
+    
+    // //////////////////////////////////////
+
+    @javax.inject.Inject
+    private PublishingServiceJdoRepository publishedEventRepository;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoRepository.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoRepository.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoRepository.java
new file mode 100644
index 0000000..6fb948b
--- /dev/null
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoRepository.java
@@ -0,0 +1,71 @@
+/*
+ *  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.objectstore.jdo.applib.service.publish;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.isis.applib.AbstractFactoryAndRepository;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.applib.annotation.NotInServiceMenu;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.NotContributed.As;
+import org.apache.isis.applib.query.QueryDefault;
+import org.apache.isis.applib.services.HasTransactionId;
+
+public class PublishingServiceJdoRepository extends AbstractFactoryAndRepository {
+
+    @Programmatic
+    public List<PublishedEventJdo> findQueued() {
+        return allMatches(
+                new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class, 
+                        "findByStateOrderByTimestamp", 
+                        "state", PublishedEventJdo.State.QUEUED));
+    }
+
+    @Programmatic
+    public List<PublishedEventJdo> findProcessed() {
+        return allMatches(
+                new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class, 
+                        "findByStateOrderByTimestamp", 
+                        "state", PublishedEventJdo.State.PROCESSED));
+    }
+
+    @Programmatic
+    public List<PublishedEventJdo> findByTransactionId(final UUID transactionId) {
+        return allMatches(
+                new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class, 
+                        "findByTransactionId", 
+                        "transactionId", transactionId));
+    }
+
+    @Programmatic
+    public void purgeProcessed() {
+        // REVIEW: this is not particularly performant.
+        // much better would be to go direct to the JDO API.
+        List<PublishedEventJdo> processedEvents = findProcessed();
+        for (PublishedEventJdo publishedEvent : processedEvents) {
+            publishedEvent.delete();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java
index 84084a5..22d5e77 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java
@@ -24,10 +24,11 @@ import javax.jdo.annotations.IdentityType;
 import org.apache.isis.applib.annotation.Named;
 import org.apache.isis.applib.services.settings.ApplicationSetting;
 import org.apache.isis.applib.services.settings.SettingType;
+import org.apache.isis.objectstore.jdo.applib.service.JdoColumnLength;
 
 @javax.jdo.annotations.PersistenceCapable(
         identityType = IdentityType.APPLICATION,
-        table="ApplicationSetting")
+        table="IsisApplicationSetting")
 @javax.jdo.annotations.Queries({ 
      @javax.jdo.annotations.Query(
              name = "findByKey", language = "JDOQL", 
@@ -43,7 +44,8 @@ import org.apache.isis.applib.services.settings.SettingType;
 @Named("Application Setting")
 public class ApplicationSettingJdo extends SettingAbstractJdo implements ApplicationSetting {
 
-    @javax.jdo.annotations.Column(length=128)
+
+    @javax.jdo.annotations.Column(length=JdoColumnLength.SettingAbstract.SETTING_KEY)
     @javax.jdo.annotations.PrimaryKey
     public String getKey() {
         return super.getKey();
@@ -55,7 +57,7 @@ public class ApplicationSettingJdo extends SettingAbstractJdo implements Applica
 
     // //////////////////////////////////////
 
-    @javax.jdo.annotations.Column(length=254)
+    @javax.jdo.annotations.Column(length=JdoColumnLength.DESCRIPTION)
     @javax.jdo.annotations.Persistent
     @Override
     public String getDescription() {
@@ -68,7 +70,7 @@ public class ApplicationSettingJdo extends SettingAbstractJdo implements Applica
     
     // //////////////////////////////////////
 
-    @javax.jdo.annotations.Column(allowsNull="false")
+    @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.SettingAbstract.VALUE_RAW)
     @javax.jdo.annotations.Persistent
     @Override
     public String getValueRaw() {
@@ -81,7 +83,7 @@ public class ApplicationSettingJdo extends SettingAbstractJdo implements Applica
     
     // //////////////////////////////////////
 
-    @javax.jdo.annotations.Column(allowsNull="false", length=20)
+    @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.SettingAbstract.SETTING_TYPE)
     @javax.jdo.annotations.Persistent
     @Override
     public SettingType getType() {

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java
index a30ca0e3..014455a 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java
@@ -29,7 +29,6 @@ import org.apache.isis.applib.annotation.ActionSemantics.Of;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Named;
 import org.apache.isis.applib.annotation.Optional;
-import org.apache.isis.applib.annotation.TypeOf;
 import org.apache.isis.applib.query.QueryDefault;
 import org.apache.isis.applib.services.settings.ApplicationSetting;
 import org.apache.isis.applib.services.settings.ApplicationSettingsService;

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java
index 128777d..f1ff4b2 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java
@@ -21,19 +21,18 @@ package org.apache.isis.objectstore.jdo.applib.service.settings;
 
 
 import javax.jdo.annotations.IdentityType;
-import javax.jdo.annotations.Persistent;
-import javax.jdo.annotations.PrimaryKey;
 
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Named;
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.services.settings.SettingType;
 import org.apache.isis.applib.services.settings.UserSetting;
+import org.apache.isis.objectstore.jdo.applib.service.JdoColumnLength;
 
 @javax.jdo.annotations.PersistenceCapable(
         identityType = IdentityType.APPLICATION, 
-        objectIdClass=UserSettingPrimaryKey.class,
-        table="UserSetting")
+        objectIdClass=UserSettingJdoPK.class,
+        table="IsisUserSetting")
 @javax.jdo.annotations.Queries({ 
     @javax.jdo.annotations.Query(
             name = "findByUserAndKey", language = "JDOQL", 
@@ -61,7 +60,7 @@ public class UserSettingJdo extends SettingAbstractJdo implements UserSetting {
     
     private String user;
 
-    @javax.jdo.annotations.Column(length=50)
+    @javax.jdo.annotations.Column(length=JdoColumnLength.USER_NAME)
     @javax.jdo.annotations.PrimaryKey
     @Title(sequence="5", append=": ")
     @MemberOrder(sequence = "5")
@@ -75,7 +74,7 @@ public class UserSettingJdo extends SettingAbstractJdo implements UserSetting {
 
     // //////////////////////////////////////
 
-    @javax.jdo.annotations.Column(length=128)
+    @javax.jdo.annotations.Column(length=JdoColumnLength.SettingAbstract.SETTING_KEY)
     @javax.jdo.annotations.PrimaryKey
     @Title(sequence="10")
     @Override
@@ -89,7 +88,7 @@ public class UserSettingJdo extends SettingAbstractJdo implements UserSetting {
 
     // //////////////////////////////////////
 
-    @javax.jdo.annotations.Column(length=254)
+    @javax.jdo.annotations.Column(length=JdoColumnLength.DESCRIPTION)
     @javax.jdo.annotations.Persistent
     @Override
     public String getDescription() {
@@ -102,7 +101,7 @@ public class UserSettingJdo extends SettingAbstractJdo implements UserSetting {
     
     // //////////////////////////////////////
 
-    @javax.jdo.annotations.Column(allowsNull="false")
+    @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.SettingAbstract.VALUE_RAW)
     @javax.jdo.annotations.Persistent
     @Title(prepend=" = ", sequence="30")
     @Override
@@ -116,7 +115,7 @@ public class UserSettingJdo extends SettingAbstractJdo implements UserSetting {
     
     // //////////////////////////////////////
 
-    @javax.jdo.annotations.Column(allowsNull="false", length=20)
+    @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.SettingAbstract.SETTING_TYPE)
     @javax.jdo.annotations.Persistent
     @Override
     public SettingType getType() {
@@ -127,5 +126,4 @@ public class UserSettingJdo extends SettingAbstractJdo implements UserSetting {
         super.setType(type);
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdoPK.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdoPK.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdoPK.java
new file mode 100644
index 0000000..13a20ed
--- /dev/null
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdoPK.java
@@ -0,0 +1,90 @@
+/**
+ *  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.objectstore.jdo.applib.service.settings;
+
+import java.io.Serializable;
+import java.util.StringTokenizer;
+
+/**
+ * @see http://www.datanucleus.org/products/datanucleus/jdo/primary_key.html
+ */
+public class UserSettingJdoPK implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    
+    public String user;
+    public String key;
+    
+    public UserSettingJdoPK ()
+    {
+    }
+
+    public String getUser() {
+        return user;
+    }
+
+    public void setUser(String user) {
+        this.user = user;
+    }
+
+    public String getKey() {
+        return key;
+    }
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+
+    /**
+     * Constructor accepting same input as generated by toString().
+     */
+    public UserSettingJdoPK(String value) 
+    {
+        StringTokenizer token = new StringTokenizer (value, ";;");
+        token.nextToken();               // className
+        this.setUser(token.nextToken());   // user
+        this.setKey(token.nextToken());    // key
+    }
+
+    public boolean equals(Object obj)
+    {
+        if (obj == this)
+        {
+            return true;
+        }
+        if (!(obj instanceof UserSettingJdoPK))
+        {
+            return false;
+        }
+        UserSettingJdoPK c = (UserSettingJdoPK)obj;
+
+        return getUser().equals(c.getUser()) && getKey().equals(c.getKey());
+    }
+
+    public int hashCode ()
+    {
+        return this.getUser().hashCode() ^ this.getKey().hashCode();
+    }
+
+    public String toString ()
+    {
+        // Give output expected by String constructor
+        return this.getClass().getName() + ";;"  + this.getUser() + ";;" + this.getKey();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingPrimaryKey.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingPrimaryKey.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingPrimaryKey.java
deleted file mode 100644
index 423ac25..0000000
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingPrimaryKey.java
+++ /dev/null
@@ -1,90 +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.objectstore.jdo.applib.service.settings;
-
-import java.io.Serializable;
-import java.util.StringTokenizer;
-
-/**
- * @see http://www.datanucleus.org/products/datanucleus/jdo/primary_key.html
- */
-public class UserSettingPrimaryKey implements Serializable
-{
-    private static final long serialVersionUID = 1L;
-
-    
-    public String user;
-    public String key;
-    
-    public UserSettingPrimaryKey ()
-    {
-    }
-
-    public String getUser() {
-        return user;
-    }
-
-    public void setUser(String user) {
-        this.user = user;
-    }
-
-    public String getKey() {
-        return key;
-    }
-    public void setKey(String key) {
-        this.key = key;
-    }
-
-
-    /**
-     * Constructor accepting same input as generated by toString().
-     */
-    public UserSettingPrimaryKey(String value) 
-    {
-        StringTokenizer token = new StringTokenizer (value, ";;");
-        token.nextToken();               // className
-        this.setUser(token.nextToken());   // user
-        this.setKey(token.nextToken());    // key
-    }
-
-    public boolean equals(Object obj)
-    {
-        if (obj == this)
-        {
-            return true;
-        }
-        if (!(obj instanceof UserSettingPrimaryKey))
-        {
-            return false;
-        }
-        UserSettingPrimaryKey c = (UserSettingPrimaryKey)obj;
-
-        return getUser().equals(c.getUser()) && getKey().equals(c.getKey());
-    }
-
-    public int hashCode ()
-    {
-        return this.getUser().hashCode() ^ this.getKey().hashCode();
-    }
-
-    public String toString ()
-    {
-        // Give output expected by String constructor
-        return this.getClass().getName() + ";;"  + this.getUser() + ";;" + this.getKey();
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/component/objectstore/jdo/jdo-applib/src/test/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionJdoTest_next.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/test/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionJdoTest_next.java b/component/objectstore/jdo/jdo-applib/src/test/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionJdoTest_next.java
new file mode 100644
index 0000000..9b7b2ba
--- /dev/null
+++ b/component/objectstore/jdo/jdo-applib/src/test/java/org/apache/isis/objectstore/jdo/applib/service/interaction/InteractionJdoTest_next.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.objectstore.jdo.applib.service.interaction;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+public class InteractionJdoTest_next {
+
+    @Test
+    public void test() {
+        InteractionJdo interaction = new InteractionJdo();
+        assertThat(interaction.next("foo"), is(0));
+        assertThat(interaction.next("foo"), is(1));
+        assertThat(interaction.next("bar"), is(0));
+        assertThat(interaction.next("bar"), is(1));
+        assertThat(interaction.next("foo"), is(2));
+        assertThat(interaction.next("bar"), is(2));
+        assertThat(interaction.next("bar"), is(3));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/main/java/org/apache/isis/applib/services/HasTransactionId.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/HasTransactionId.java b/core/applib/src/main/java/org/apache/isis/applib/services/HasTransactionId.java
index 9feeeb5..1cc2946 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/HasTransactionId.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/HasTransactionId.java
@@ -42,4 +42,6 @@ public interface HasTransactionId {
 
     public void setTransactionId(final UUID transactionId);
 
+    
+
 }    

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/main/java/org/apache/isis/applib/services/audit/AuditingService3.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/audit/AuditingService3.java b/core/applib/src/main/java/org/apache/isis/applib/services/audit/AuditingService3.java
index 4520180..9426573 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/audit/AuditingService3.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/audit/AuditingService3.java
@@ -19,6 +19,7 @@
 package org.apache.isis.applib.services.audit;
 
 import java.sql.Timestamp;
+import java.util.UUID;
 
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.bookmark.Bookmark;
@@ -29,12 +30,15 @@ import org.apache.isis.applib.services.bookmark.Bookmark;
 public interface AuditingService3 {
     
     @Programmatic
-    public void audit(java.sql.Timestamp timestamp, String user, Bookmark target, String propertyId, String preValue, String postValue);
+    public void audit(
+            final UUID transactionId, final Bookmark target, final String propertyId, 
+            final String preValue, final String postValue, 
+            final String user, final java.sql.Timestamp timestamp);
     
     public static class Stderr implements AuditingService3 {
 
         @Override
-        public void audit(Timestamp timestamp, String user, Bookmark target, String propertyId, String preValue, String postValue) {
+        public void audit(UUID transactionId, Bookmark target, String propertyId, String preValue, String postValue, String user, Timestamp timestamp) {
             String auditMessage = target.toString() + " by " + user + ", " + propertyId +": " + preValue + " -> " + postValue;
             System.err.println(auditMessage);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundTaskService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundTaskService.java b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundTaskService.java
index 679a404..783afc6 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundTaskService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundTaskService.java
@@ -14,9 +14,5 @@ import java.util.UUID;
  */
 public interface BackgroundTaskService {
 
-    /**
-     * @param actionInvocationMemento
-     * @param transactionId - if any.
-     */
-    void execute(ActionInvocationMemento actionInvocationMemento, UUID transactionId);
+    void execute(final ActionInvocationMemento actionInvocationMemento, final UUID transactionId, final int sequence);
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/main/java/org/apache/isis/applib/services/interaction/Interaction.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/interaction/Interaction.java b/core/applib/src/main/java/org/apache/isis/applib/services/interaction/Interaction.java
index 2119d1d..00a7fa3 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/interaction/Interaction.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/interaction/Interaction.java
@@ -18,17 +18,15 @@ package org.apache.isis.applib.services.interaction;
 
 import java.sql.Timestamp;
 
-import org.joda.time.DateTime;
-
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Disabled;
 import org.apache.isis.applib.clock.Clock;
+import org.apache.isis.applib.services.HasTransactionId;
 import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.bookmark.BookmarkHolder;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.applib.services.interaction.spi.InteractionFactory;
+import org.apache.isis.applib.services.interaction.spi.InteractionService;
 
-public interface Interaction {
+public interface Interaction extends HasTransactionId {
 
     /**
      * The user that initiated the interaction.
@@ -49,14 +47,14 @@ public interface Interaction {
      * The date/time at which the interaction started.
      */
     @Disabled
-    public abstract Timestamp getStartedAt();
+    public abstract Timestamp getTimestamp();
     /**
      * <b>NOT API</b>: intended to be called only by the framework.
      * 
      * <p>
      * Implementation notes: set when the Isis PersistenceSession is opened.  Uses the applib {@link Clock}.
      */
-    public abstract void setStartedAt(Timestamp startedAt);
+    public abstract void setTimestamp(Timestamp startedAt);
     
     
     // //////////////////////////////////////
@@ -158,7 +156,7 @@ public interface Interaction {
      * <p>
      * The Isis implementations uses this field as to a hint as to whether to populate the interaction's
      * {@link Interaction#setActionIdentifier(String) action identifier} and related properties.  The expectation 
-     * is that implementations of {@link InteractionFactory} will only persist interactions that were explicitly started
+     * is that implementations of {@link InteractionService} will only persist interactions that were explicitly started
      * by the user.
      */
     public static enum Nature {
@@ -208,5 +206,19 @@ public interface Interaction {
      * <b>NOT API</b>: intended to be called only by the framework.
      */
     public void setResult(Bookmark resultBookmark);
+
+    
+    // //////////////////////////////////////
+
+    
+    /**
+     * Generates numbers in a named sequence
+     * 
+     * <p>
+     * Used to support <tt>BackgroundTaskServiceJdo</tt> and <tt>PublishingServiceJdo</tt> implementations whose
+     * persisted entities are uniquely identified by a ({@link #getTransactionId() transactionId}, <tt>sequence</tt>)
+     * tuple.
+     */
+    public int next(final String sequenceName);
     
 }    

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/main/java/org/apache/isis/applib/services/interaction/InteractionDefault.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/interaction/InteractionDefault.java b/core/applib/src/main/java/org/apache/isis/applib/services/interaction/InteractionDefault.java
index 9194b03..2396ca2 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/interaction/InteractionDefault.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/interaction/InteractionDefault.java
@@ -17,9 +17,15 @@
 package org.apache.isis.applib.services.interaction;
 
 import java.sql.Timestamp;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
 
+import com.google.common.collect.Maps;
+
+import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.interaction.spi.InteractionFactory;
+import org.apache.isis.applib.services.interaction.spi.InteractionService;
 import org.apache.isis.applib.util.ObjectContracts;
 
 public class InteractionDefault implements Interaction {
@@ -102,12 +108,12 @@ public class InteractionDefault implements Interaction {
     // //////////////////////////////////////
 
     private Timestamp startedAt;
-    public Timestamp getStartedAt() {
+    public Timestamp getTimestamp() {
         return startedAt;
     }
 
     @Override
-    public void setStartedAt(Timestamp startedAt) {
+    public void setTimestamp(Timestamp startedAt) {
         this.startedAt = startedAt;
     }
 
@@ -141,7 +147,7 @@ public class InteractionDefault implements Interaction {
      * <b>NOT API</b>: intended to be called only by the framework.
      * 
      * <p>
-     * Implementation notes: populated by the viewer as hint to {@link InteractionFactory} implementation.
+     * Implementation notes: populated by the viewer as hint to {@link InteractionService} implementation.
      */
     @Override
     public void setNature(Nature nature) {
@@ -187,4 +193,36 @@ public class InteractionDefault implements Interaction {
     }
     
     
+    // //////////////////////////////////////
+    
+    private UUID transactionId;
+    
+    @Override
+    public UUID getTransactionId() {
+        return transactionId;
+    }
+    @Override
+    public void setTransactionId(UUID transactionId) {
+        this.transactionId = transactionId;
+    }
+    
+    
+    // //////////////////////////////////////
+
+    private final Map<String, AtomicInteger> sequenceByName = Maps.newHashMap();
+
+    @Programmatic
+    @Override
+    public int next(String sequenceName) {
+        AtomicInteger next = sequenceByName.get(sequenceName);
+        if(next == null) {
+            next = new AtomicInteger(0);
+            sequenceByName.put(sequenceName, next);
+        } else {
+            next.incrementAndGet();
+        }
+        return next.get();
+    }
+    
+    
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/main/java/org/apache/isis/applib/services/interaction/spi/InteractionFactory.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/interaction/spi/InteractionFactory.java b/core/applib/src/main/java/org/apache/isis/applib/services/interaction/spi/InteractionFactory.java
deleted file mode 100644
index 03fb653..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/interaction/spi/InteractionFactory.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.isis.applib.services.interaction.spi;
-
-import java.util.UUID;
-
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.interaction.Interaction;
-
-/**
- * Intended for service to implement, providing a different implementation of
- * {@link Interaction}.
- * 
- * <p>
- * The default implementation (provided automatically by the framework) will
- * instantiate an in-memory implementation of {@link Interaction}.  However, other
- * services (eg as provided by the JDO objectstore) might provide a persistable 
- * {@link Interaction} object.
- */
-public interface InteractionFactory {
-
-    @Programmatic
-    Interaction create();
-    
-    /**
-     * Although the transactionId is also provided via {@link InteractionOutcome} in the
-     * {@link #complete(Interaction)} callback, it is passed in here as well
-     * so that an implementation can ensure that the {@link Interaction} is fully populated in order
-     * to persist if required.
-     * 
-     * <p>
-     * One case where this may be supported (for example, by the <tt>InteractionServiceJdo</tt> implementation)
-     * is to flush still-running {@link Interaction}s to the database on-demand.
-     */
-    @Programmatic
-    void startTransaction(final Interaction interaction, final UUID transactionId);
-    
-    @Programmatic
-    void complete(final Interaction interaction);
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/main/java/org/apache/isis/applib/services/interaction/spi/InteractionService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/interaction/spi/InteractionService.java b/core/applib/src/main/java/org/apache/isis/applib/services/interaction/spi/InteractionService.java
new file mode 100644
index 0000000..749b162
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/interaction/spi/InteractionService.java
@@ -0,0 +1,55 @@
+/**
+ *  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.interaction.spi;
+
+import java.util.UUID;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.interaction.Interaction;
+
+/**
+ * Intended for service to implement, providing a different implementation of
+ * {@link Interaction}.
+ * 
+ * <p>
+ * The default implementation (provided automatically by the framework) will
+ * instantiate an in-memory implementation of {@link Interaction}.  However, other
+ * services (eg as provided by the JDO objectstore) might provide a persistable 
+ * {@link Interaction} object.
+ */
+public interface InteractionService {
+
+    @Programmatic
+    Interaction create();
+    
+    /**
+     * Although the transactionId is also provided via {@link InteractionOutcome} in the
+     * {@link #complete(Interaction)} callback, it is passed in here as well
+     * so that an implementation can ensure that the {@link Interaction} is fully populated in order
+     * to persist if required.
+     * 
+     * <p>
+     * One case where this may be supported (for example, by the <tt>InteractionServiceJdo</tt> implementation)
+     * is to flush still-running {@link Interaction}s to the database on-demand.
+     */
+    @Programmatic
+    void startTransaction(final Interaction interaction, final UUID transactionId);
+    
+    @Programmatic
+    void complete(final Interaction interaction);
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventMetadata.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventMetadata.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventMetadata.java
index 88b40c7..1272574 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventMetadata.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventMetadata.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.applib.services.publish;
 
+import java.sql.Timestamp;
 import java.util.UUID;
 
 /**
@@ -34,10 +35,14 @@ public class EventMetadata {
     private final UUID transactionId;
     private final int sequence;
     private final String user;
-    private final long timestamp;
+    private final java.sql.Timestamp javaSqlTimestamp;
     private final String title;
     private final EventType eventType;
     
+    /**
+     * @deprecated - use {@link #EventMetadata(UUID, int, EventType, String, Timestamp, String)}
+     */
+    @Deprecated
     public EventMetadata(
             final UUID transactionId, 
             final int sequence, 
@@ -45,10 +50,20 @@ public class EventMetadata {
             final String user, 
             final long timestamp, 
             final String title) {
+        this(transactionId, sequence, eventType, user, new java.sql.Timestamp(timestamp), title);
+    }
+    
+    public EventMetadata(
+            final UUID transactionId, 
+            final int sequence, 
+            final EventType eventType, 
+            final String user, 
+            final java.sql.Timestamp javaSqlTimestamp, 
+            final String title) {
         this.transactionId = transactionId;
         this.sequence = sequence;
         this.user = user;
-        this.timestamp = timestamp;
+        this.javaSqlTimestamp = javaSqlTimestamp;
         this.title = title;
         this.eventType = eventType;
     }
@@ -81,12 +96,19 @@ public class EventMetadata {
     public String getUser() {
         return user;
     }
+    
+    public Timestamp getJavaSqlTimestamp() {
+        return javaSqlTimestamp;
+    }
+
     /**
      * The timestamp, in milliseconds, since an epoch time.
-     * @return
+     * 
+     * @deprecated - use {@link #getJavaSqlTimestamp()}
      */
+    @Deprecated
     public long getTimestamp() {
-        return timestamp;
+        return getJavaSqlTimestamp().getTime();
     }
     
     /**
@@ -113,4 +135,5 @@ public class EventMetadata {
         return getId();
     }
 
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/applib/src/test/java/org/apache/isis/applib/services/interaction/InteractionDefaultTest_next.java
----------------------------------------------------------------------
diff --git a/core/applib/src/test/java/org/apache/isis/applib/services/interaction/InteractionDefaultTest_next.java b/core/applib/src/test/java/org/apache/isis/applib/services/interaction/InteractionDefaultTest_next.java
new file mode 100644
index 0000000..ca27ad9
--- /dev/null
+++ b/core/applib/src/test/java/org/apache/isis/applib/services/interaction/InteractionDefaultTest_next.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.services.interaction;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+public class InteractionDefaultTest_next {
+
+    @Test
+    public void test() {
+        InteractionDefault interaction = new InteractionDefault();
+        assertThat(interaction.next("foo"), is(0));
+        assertThat(interaction.next("foo"), is(1));
+        assertThat(interaction.next("bar"), is(0));
+        assertThat(interaction.next("bar"), is(1));
+        assertThat(interaction.next("foo"), is(2));
+        assertThat(interaction.next("bar"), is(2));
+        assertThat(interaction.next("bar"), is(3));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/49c7c05d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/ActionInvocationFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/ActionInvocationFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/ActionInvocationFacet.java
index f98dfc7..8943f3a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/ActionInvocationFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/ActionInvocationFacet.java
@@ -21,7 +21,11 @@ package org.apache.isis.core.metamodel.facets.actions.invoke;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.UUID;
 
+import org.apache.isis.applib.services.HasTransactionId;
+import org.apache.isis.applib.services.interaction.InteractionContext;
+import org.apache.isis.applib.services.interaction.spi.InteractionService;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
@@ -53,11 +57,15 @@ public interface ActionInvocationFacet extends Facet {
         private final List<ObjectAdapter> parameters;
         private final ObjectAdapter result;
 
-        public CurrentInvocation(ObjectAdapter target, IdentifiedHolder action, ObjectAdapter[] parameters, ObjectAdapter result) {
+        public CurrentInvocation(
+                final ObjectAdapter target, final IdentifiedHolder action, final ObjectAdapter[] parameters, 
+                final ObjectAdapter result) {
             this(target, action, Arrays.asList(parameters), result);
         }
 
-        public CurrentInvocation(ObjectAdapter target, IdentifiedHolder action, List<ObjectAdapter> parameters, ObjectAdapter result) {
+        public CurrentInvocation(
+                final ObjectAdapter target, final IdentifiedHolder action, final List<ObjectAdapter> parameters, 
+                final ObjectAdapter result) {
             this.target = target;
             this.action = action;
             this.parameters = parameters;
@@ -79,6 +87,11 @@ public interface ActionInvocationFacet extends Facet {
         }
     }
     
+    /**
+     * TODO...
+     * @deprecated - should instead use the InteractionContext request.
+     */
+    @Deprecated
     public static ThreadLocal<CurrentInvocation> currentInvocation = new ThreadLocal<CurrentInvocation>();