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 2021/07/06 12:36:08 UTC
[isis] 03/11: ISIS-2789: copies InteractionScope to
InteractionScopeHACK prior to rebase
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch ISIS-2789
in repository https://gitbox.apache.org/repos/asf/isis.git
commit afd4fe5d60fa681b0411c83338eccf31bbcb4bf6
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Jul 6 08:30:42 2021 +0100
ISIS-2789: copies InteractionScope to InteractionScopeHACK prior to rebase
---
.../interaction/scope/InteractionScopeHACK.java | 174 +++++++++++++++++++++
1 file changed, 174 insertions(+)
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeHACK.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeHACK.java
new file mode 100644
index 0000000..4b5d39e
--- /dev/null
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeHACK.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.core.interaction.scope;
+
+import java.util.HashMap;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.beans.factory.config.Scope;
+
+import org.apache.isis.applib.services.iactnlayer.InteractionLayerTracker;
+import org.apache.isis.commons.internal.debug._Probe;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+
+import lombok.Data;
+import lombok.extern.log4j.Log4j2;
+import lombok.val;
+
+/**
+ * @since 2.0
+ */
+@Log4j2
+class InteractionScopeHACK implements Scope, InteractionScopeLifecycleHandler {
+
+ @Inject private InteractionLayerTracker iInteractionLayerTracker;
+
+ @Data(staticConstructor = "of")
+ private static class ScopedObject {
+ final String name;
+ Object instance;
+ Runnable destructionCallback;
+ void preDestroy() {
+ log.debug("destroy isis-interaction scoped {}", name);
+ if(destructionCallback!=null) {
+ destructionCallback.run();
+ }
+ }
+ }
+
+
+ static class ScopedObjects extends HashMap<String, ScopedObject> {
+ }
+
+ @Override
+ public Object get(String name, ObjectFactory<?> objectFactory) {
+
+ ensureInteractionLayerTrackerInjected();
+
+ if(!iInteractionLayerTracker.isInInteraction()) {
+ throw _Exceptions.illegalState("Creation of bean %s with @InteractionScope requires the "
+ + "calling %s to have an open Interaction on the thread-local stack. Running into "
+ + "this issue might be caused by use of ... @Inject MyScopedBean bean ..., instead of "
+ + "... @Inject Provider<MyScopedBean> provider ...", name, _Probe.currentThreadId());
+ }
+
+ val interaction = iInteractionLayerTracker.currentInteractionElseFail();
+ val scopedObjects = interaction.computeAttributeIfAbsent(ScopedObjects.class, clazz -> new ScopedObjects());
+
+ val existingScopedObject = scopedObjects.get(name);
+ if(existingScopedObject!=null) {
+ return existingScopedObject.getInstance();
+ }
+
+ val newScopedObject = ScopedObject.of(name);
+ scopedObjects.put(name, newScopedObject); // just set a stub with a name only
+
+ log.debug("create new isis-interaction scoped {}", name);
+ newScopedObject.setInstance(objectFactory.getObject()); // triggers call to registerDestructionCallback
+
+ return newScopedObject.getInstance();
+ }
+
+
+ @Override
+ public Object remove(final String name) {
+ ensureInteractionLayerTrackerInjected();
+ return iInteractionLayerTracker.currentInteraction()
+ .map(interaction -> {
+ final ScopedObjects scopedObjects = interaction.getAttribute(ScopedObjects.class);
+ if (scopedObjects == null) {
+ return null;
+ }
+ ScopedObject removedIfAny = scopedObjects.remove(name);
+ if(scopedObjects.isEmpty()) {
+ interaction.removeAttribute(ScopedObjects.class);
+ }
+ if (removedIfAny == null) {
+ return null;
+ }
+ // javadoc for Scope says to remove destruction callback.
+ removedIfAny.destructionCallback = null;
+ return removedIfAny.instance;
+ })
+ .orElse(null);
+ }
+
+ private void ensureInteractionLayerTrackerInjected() {
+ if (iInteractionLayerTracker == null) {
+ throw _Exceptions.illegalState("Management of beans with @InteractionScope requires the "
+ + "InteractionScopeBeanFactoryPostProcessor registered and initialized.");
+ }
+ }
+
+ @Override
+ public void registerDestructionCallback(String name, Runnable callback) {
+ ensureInteractionLayerTrackerInjected();
+ iInteractionLayerTracker.currentInteraction()
+ .ifPresent(interaction -> {
+ final ScopedObjects scopedObjects = interaction.getAttribute(ScopedObjects.class);
+ if (scopedObjects == null) {
+ return;
+ }
+ final ScopedObject scopedObject = scopedObjects.get(name);
+ if (scopedObject == null) {
+ return;
+ }
+ scopedObject.destructionCallback = callback;
+ });
+ }
+
+ @Override
+ public Object resolveContextualObject(String key) {
+ // null by convention if not supported
+ return null;
+ }
+
+ @Override
+ public String getConversationId() {
+ // null by convention if not supported
+ return iInteractionLayerTracker.getInteractionId()
+ .map(UUID::toString)
+ .orElse(null);
+ }
+
+ @Override
+ public void onTopLevelInteractionOpened() {
+ // nothing to do
+ }
+
+ @Override
+ public void onTopLevelInteractionClosing() {
+ ensureInteractionLayerTrackerInjected();
+ iInteractionLayerTracker.currentInteraction()
+ .ifPresent(interaction -> {
+ final ScopedObjects scopedObjects = interaction.getAttribute(ScopedObjects.class);
+ if (scopedObjects == null) {
+ return;
+ }
+ val scopedObjectValues = scopedObjects.values();
+ scopedObjectValues.forEach(ScopedObject::preDestroy);
+ scopedObjects.clear();
+ interaction.removeAttribute(ScopedObjects.class);
+ });
+ }
+
+}