You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/02/22 11:01:50 UTC

[isis] branch master updated: ISIS-2538: during decision which java-script to inject client-side, we already need the action's result

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 01b2d39  ISIS-2538: during decision which java-script to inject client-side, we already need the action's result
01b2d39 is described below

commit 01b2d39cbe6e616fac3e76b3be2e44b6b6273ecf
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Feb 22 12:01:33 2021 +0100

    ISIS-2538: during decision which java-script to inject client-side, we
    already need the action's result
    
    this needs a modification to AjaxDeferredBehaviour such that it
    evaluates the action result early during this decision making phase and
    later reuse when wicket asks for the IRequestHandler to use for handling
    the acion result
---
 .../isis/applib/value/LocalResourcePath.java       |  3 +-
 .../apache/isis/applib/value/OpenUrlStrategy.java  |  8 +++
 .../viewer/wicket/model/models/ActionModel.java    |  8 +--
 .../widgets/linkandlabel/ActionLink.java           |  7 +-
 .../linkandlabel/AjaxDeferredBehaviour.java        | 80 +++++++++++++++-------
 5 files changed, 73 insertions(+), 33 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/LocalResourcePath.java b/api/applib/src/main/java/org/apache/isis/applib/value/LocalResourcePath.java
index ff1523b..320a3ca 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/LocalResourcePath.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/LocalResourcePath.java
@@ -29,6 +29,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
 import org.apache.isis.applib.annotation.Value;
 
+import lombok.Getter;
 import lombok.NonNull;
 
 /**
@@ -51,7 +52,7 @@ public final class LocalResourcePath implements Serializable {
 
     private static final long serialVersionUID = 1L;
     @NonNull private final String path;
-    @NonNull private final OpenUrlStrategy openUrlStrategy;
+    @Getter @NonNull private final OpenUrlStrategy openUrlStrategy;
 
     public LocalResourcePath(final @Nullable String path) throws IllegalArgumentException {
         this(path, null);
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/OpenUrlStrategy.java b/api/applib/src/main/java/org/apache/isis/applib/value/OpenUrlStrategy.java
index dc87922..0cb680b 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/OpenUrlStrategy.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/OpenUrlStrategy.java
@@ -28,4 +28,12 @@ package org.apache.isis.applib.value;
 public enum OpenUrlStrategy {
     NEW_WINDOW,
     SAME_WINDOW;
+
+    public boolean isNewWindow() {
+        return this==NEW_WINDOW;
+    }
+    
+    public boolean isSameWindow() {
+        return this==SAME_WINDOW;
+    }
 }
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index aacab39..946b176 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -268,11 +268,11 @@ implements FormUiModel, FormExecutorContext, BookmarkableModel {
 
     public static IRequestHandler redirectHandler(final Object value) {
         if(value instanceof java.net.URL) {
-            final java.net.URL url = (java.net.URL) value;
+            val url = (java.net.URL) value;
             return new RedirectRequestHandler(url.toString());
         }
         if(value instanceof LocalResourcePath) {
-            final LocalResourcePath localResourcePath = (LocalResourcePath) value;
+            val localResourcePath = (LocalResourcePath) value;
             return new RedirectRequestHandler(localResourcePath.getPath());
         }
         return null;
@@ -280,11 +280,11 @@ implements FormUiModel, FormExecutorContext, BookmarkableModel {
 
     public static IRequestHandler downloadHandler(final Object value) {
         if(value instanceof Clob) {
-            final Clob clob = (Clob)value;
+            val clob = (Clob)value;
             return handlerFor(resourceStreamFor(clob), clob);
         }
         if(value instanceof Blob) {
-            final Blob blob = (Blob)value;
+            val blob = (Blob)value;
             return handlerFor(resourceStreamFor(blob), blob);
         }
         return null;
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLink.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLink.java
index 3bfe071..52e675b 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLink.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLink.java
@@ -32,7 +32,6 @@ import org.apache.isis.applib.value.LocalResourcePath;
 import org.apache.isis.commons.internal.debug._Probe;
 import org.apache.isis.commons.internal.debug._Probe.EntryPoint;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.runtime.context.IsisAppCommonContext;
 import org.apache.isis.viewer.wicket.model.common.CommonContextUtils;
@@ -187,20 +186,20 @@ public abstract class ActionLink extends AjaxLink<ManagedObject> implements IAja
     AjaxDeferredBehaviour determineDeferredBehaviour() {
 
         val action = getObjectAction();
-        val actionModel = this.getActionModel();
         val actionReturnTypeSpec = action.getReturnType();
         
         if(action.getParameterCount() > 0 
                 || actionReturnTypeSpec == null) {
             return null; // default behavior, don't defer
         }
-        
+
+        val actionModel = this.getActionModel();
         val actionReturnType = actionReturnTypeSpec.getCorrespondingClass();
 
         // TODO: should unify with ActionResultResponseType (as used in ActionParametersPanel)
         if (actionReturnType == java.net.URL.class 
                 || actionReturnType == LocalResourcePath.class) {
-            return AjaxDeferredBehaviour.redirecting(actionModel);
+            return AjaxDeferredBehaviour.redirecting(this.getActionModel());
         }
         if ((actionReturnType == org.apache.isis.applib.value.Blob.class
                 || actionReturnType == org.apache.isis.applib.value.Clob.class)) {
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/AjaxDeferredBehaviour.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/AjaxDeferredBehaviour.java
index bd1e038..5b379d6 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/AjaxDeferredBehaviour.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/AjaxDeferredBehaviour.java
@@ -26,16 +26,22 @@ import org.apache.wicket.request.Url;
 import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
 import org.apache.wicket.util.time.Duration;
 
+import org.apache.isis.applib.value.LocalResourcePath;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponseHandlingStrategy;
 
 import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
 import lombok.val;
 
+@RequiredArgsConstructor
 public abstract class AjaxDeferredBehaviour extends AbstractAjaxBehavior {
     private static final long serialVersionUID = 1L;
     
+    private final @NonNull ActionModel actionModel;
+    
     // -- FACTORIES
     
     public static AjaxDeferredBehaviour redirecting(final @NonNull ActionModel actionModel){
@@ -44,23 +50,32 @@ public abstract class AjaxDeferredBehaviour extends AbstractAjaxBehavior {
          *
          * @see https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
          */
-        return new AjaxDeferredBehaviour() {
+        return new AjaxDeferredBehaviour(actionModel) {
 
             private static final long serialVersionUID = 1L;
-
+            
             @Override
-            protected IRequestHandler getRequestHandler() {
-                val resultAdapter = actionModel.execute();
-                val value = resultAdapter.getPojo();
-                return ActionModel.redirectHandler(value);
+            protected String javascriptFor(String url) {
+                // introspect the action result, to decide which JS to use
+                
+                val value = getResultValue();
+                
+                if(value instanceof LocalResourcePath) {
+                    if(((LocalResourcePath)value).getOpenUrlStrategy().isSameWindow()) {
+                        return javascriptFor_sameWindow(this, url);
+                    }
+                }
+                
+                return javascriptFor_newWindow(this, url);
             }
-
+            
             @Override
-            protected String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url) {
-                //TODO need to introspect the action result, to decide which JS to use
-                //not sure yet whether this is even possible
-                return javascriptFor_newWindow(deferredBehaviour, url);
+            protected IRequestHandler getRequestHandler() {
+                val value = getResultValue();
+                freeResultValue();
+                return ActionModel.redirectHandler(value);
             }
+            
         };
     }
     
@@ -70,17 +85,20 @@ public abstract class AjaxDeferredBehaviour extends AbstractAjaxBehavior {
          *
          * @see https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
          */
-        return new AjaxDeferredBehaviour() {
+        return new AjaxDeferredBehaviour(actionModel) {
 
             private static final long serialVersionUID = 1L;
 
             @Override
+            protected String javascriptFor(String url) {
+                return javascriptFor_sameWindow(this, url);
+            }
+            
+            @Override
             protected IRequestHandler getRequestHandler() {
-                val resultAdapter = actionModel.execute();
-                val value = resultAdapter!=null 
-                        ? resultAdapter.getPojo() 
-                        : null;
-
+                val value = getResultValue();
+                freeResultValue();
+                
                 val handler = ActionModel.downloadHandler(value);
 
                 //ISIS-1619, prevent clients from caching the response content
@@ -88,11 +106,7 @@ public abstract class AjaxDeferredBehaviour extends AbstractAjaxBehavior {
                         ? handler
                         : enforceNoCacheOnClientSide(handler);
             }
-
-            @Override
-            protected String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url) {
-                return javascriptFor_sameWindow(deferredBehaviour, url);
-            }
+            
         };
     }
     
@@ -105,7 +119,7 @@ public abstract class AjaxDeferredBehaviour extends AbstractAjaxBehavior {
             final @NonNull AjaxRequestTarget target) {
         
         val url = ActionResultResponseHandlingStrategy.expanded(getCallbackUrl().toString());
-        val js = javascriptFor(this, url);
+        val js = javascriptFor(url);
 
         // the timeout is needed to let Wicket release the channel
         target.appendJavaScript(String.format("setTimeout(%s, 100);", js));
@@ -120,7 +134,25 @@ public abstract class AjaxDeferredBehaviour extends AbstractAjaxBehavior {
     }
 
     protected abstract IRequestHandler getRequestHandler();
-    protected abstract String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url);
+    protected abstract String javascriptFor(String url);
+    
+    // -- RESULT MEMOIZATION
+    
+    private transient ManagedObject resultAdapter = null;
+    
+    protected Object getResultValue() {
+        if(resultAdapter==null) {
+            resultAdapter = actionModel.execute();
+        }
+        val value = resultAdapter!=null 
+                ? resultAdapter.getPojo() 
+                : null;
+        return value;
+    }
+    
+    protected void freeResultValue() {
+        resultAdapter = null;
+    }
     
     // -- HELPER