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 2018/06/15 13:30:25 UTC

[isis] branch master updated: ISIS-1963: workaround the issue by selective exception suppression

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 d7fefd3  ISIS-1963: workaround the issue by selective exception suppression
d7fefd3 is described below

commit d7fefd3edfcfb4c80032d46d29a132639db7bbd9
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Jun 15 15:29:25 2018 +0200

    ISIS-1963: workaround the issue by selective exception suppression
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1963
---
 .../commons/internal/exceptions/_Exceptions.java   | 149 +++++++++++++++++----
 .../core/webapp/content/ResourceCachingFilter.java |   7 +-
 .../wicket/ui/panels/PromptFormAbstract.java       |  45 ++++---
 3 files changed, 157 insertions(+), 44 deletions(-)

diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/exceptions/_Exceptions.java b/core/commons/src/main/java/org/apache/isis/commons/internal/exceptions/_Exceptions.java
index ceea19e..7200cc1 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/exceptions/_Exceptions.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/exceptions/_Exceptions.java
@@ -19,11 +19,15 @@
 
 package org.apache.isis.commons.internal.exceptions;
 
+import static org.apache.isis.commons.internal.base._With.requires;
+
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.function.Consumer;
 import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.stream.Stream;
 
 import javax.annotation.Nullable;
@@ -47,9 +51,9 @@ import org.apache.isis.commons.internal.functions._Functions;
 public final class _Exceptions {
 
 	private _Exceptions(){}
-	
+
 	// -- FRAMEWORK INTERNAL ERRORS 
-	
+
 	/**
 	 * Most likely to be used in switch statements to handle the default case.  
 	 * @param _case the unmatched case to be reported
@@ -58,7 +62,7 @@ public final class _Exceptions {
 	public static final IllegalArgumentException unmatchedCase(@Nullable Object _case) {
 		return new IllegalArgumentException("internal error: unmatched case in switch statement: "+_case);
 	}
-	
+
 	/**
 	 * Most likely to be used in switch statements to handle the default case.
 	 * @param format like in {@link java.lang.String#format(String, Object...)}
@@ -69,15 +73,15 @@ public final class _Exceptions {
 		Objects.requireNonNull(format);
 		return new IllegalArgumentException(String.format(format, _case));
 	}
-	
+
 	public static final IllegalStateException unexpectedCodeReach() {
 		return new IllegalStateException("internal error: code was reached, that is expected unreachable");
 	}	
-	
+
 	public static IllegalStateException notImplemented() {
 		return new IllegalStateException("internal error: code was reached, that is not implemented yet");
 	}
-	
+
 	/**
 	 * Used to hide from the compiler the fact, that this call always throws.
 	 * 
@@ -98,10 +102,41 @@ public final class _Exceptions {
 	public static IllegalStateException throwNotImplemented() {
 		throw notImplemented();
 	}
+
+	// -- SELECTIVE ERROR SUPPRESSION
+
+//	/**
+//	 * Allows to selectively ignore unchecked exceptions. Most likely used framework internally
+//	 * for workarounds, not properly dealing with the root cause. This way at least we know, where
+//	 * we placed such workarounds. 
+//	 * 
+//	 * @param runnable that might throw an unchecked exception
+//	 * @param suppress predicate that decides whether to suppress an exception
+//	 */
+//	public static void catchSilently(
+//			Runnable runnable, 
+//			Predicate<RuntimeException> suppress) {
+//		
+//		try {
+//			runnable.run();
+//		} catch (RuntimeException cause) {
+//			if(suppress.test(cause)) {
+//				return;
+//			}	
+//			throw cause;
+//		}
+//	}
 	
+	// -- SELECTIVE THROW
 	
+	public static <E extends Exception> void throwWhenTrue(E cause, Predicate<E> test) throws E {
+		if(test.test(cause)) {
+			throw cause;
+		}
+	}
+
 	// -- STACKTRACE UTILITITIES
-	
+
 	public static final Stream<String> streamStacktraceLines(@Nullable Throwable ex, int maxLines) {
 		if(ex==null) {
 			return Stream.empty();
@@ -110,7 +145,7 @@ public final class _Exceptions {
 				.map(StackTraceElement::toString)
 				.limit(maxLines);
 	}
-	
+
 	// -- CAUSAL CHAIN
 
 	public static List<Throwable> getCausalChain(@Nullable Throwable ex) {
@@ -125,7 +160,7 @@ public final class _Exceptions {
 		}
 		return chain;		
 	}
-	
+
 	public static Stream<Throwable> streamCausalChain(@Nullable Throwable ex) {
 		if(ex==null) {
 			return Stream.empty();
@@ -137,48 +172,116 @@ public final class _Exceptions {
 		return _Lists.lastElementIfAny(getCausalChain(ex));
 	}
 
-	// --
+	// -- FLUENT EXCEPTION
 	
 	/**
+	 * [ahuber] Experimental, remove if it adds no value. Otherwise expand.
+	 */
+	public static class FluentException<E extends Exception> {
+		
+		public static <E extends Exception> FluentException<E> of(E cause) {
+			return new FluentException<>(cause);
+		}
+		
+		private final E cause;
+
+		private FluentException(E cause) {
+			requires(cause, "cause");
+			this.cause = cause;
+		}
+		
+		public E getCause() {
+			return cause;
+		}
+
+		public Optional<String> getMessage() {
+			return Optional.ofNullable(cause.getMessage());
+		}
+		
+		// -- RE-THROW IDIOMS 
+		
+		public void rethrow() throws E {
+			throw cause;
+		}
+		
+		public void rethrowIf(Predicate<E> condition) throws E {
+			requires(condition, "condition");
+			if(condition.test(cause)) {
+				throw cause;
+			}
+		}
+		
+		public void suppressIf(Predicate<E> condition) throws E {
+			requires(condition, "condition");
+			if(!condition.test(cause)) {
+				throw cause;
+			}
+		}
+
+		public void rethrowIfMessageContains(String string) throws E {
+			requires(string, "string");
+			final boolean containsMessage = getMessage().map(msg->msg.contains(string)).orElse(false);
+			if(containsMessage) {
+				throw cause;
+			}
+		}
+		
+		public void suppressIfMessageContains(String string) throws E {
+			requires(string, "string");
+			final boolean containsMessage = getMessage().map(msg->msg.contains(string)).orElse(false);
+			if(!containsMessage) {
+				throw cause;
+			}
+		}
+		
+	}
+	
+	// --
+
+	/**
 	 * [ahuber] Experimental, remove if it adds no value. 
 	 */
 	public static class TryContext {
-		
+
 		private final Function<Exception, ? extends RuntimeException> toUnchecked;
-		
+
 		public TryContext(Function<Exception, ? extends RuntimeException> toUnchecked) {
 			this.toUnchecked = toUnchecked;
 		}
 
-	    // -- SHORTCUTS (RUNNABLE)
-	    
+		// -- SHORTCUTS (RUNNABLE)
+
 		public Runnable uncheckedRunnable(_Functions.CheckedRunnable checkedRunnable) {
 			return checkedRunnable.toUnchecked(toUnchecked);
 		}
-		
+
 		public void tryRun(_Functions.CheckedRunnable checkedRunnable) {
 			uncheckedRunnable(checkedRunnable).run();
 		}
-		
-	    // -- SHORTCUTS (FUNCTION)
-		
+
+		// -- SHORTCUTS (FUNCTION)
+
 		public <T, R> Function<T, R> uncheckedFunction(_Functions.CheckedFunction<T, R> checkedFunction) {
 			return checkedFunction.toUnchecked(toUnchecked);
 		}
-		
+
 		public <T, R> R tryApply(T obj, _Functions.CheckedFunction<T, R> checkedFunction) {
 			return uncheckedFunction(checkedFunction).apply(obj);
 		}
-		
-	    // -- SHORTCUTS (CONSUMER)
+
+		// -- SHORTCUTS (CONSUMER)
 
 		public <T> Consumer<T> uncheckedConsumer(_Functions.CheckedConsumer<T> checkedConsumer) {
 			return checkedConsumer.toUnchecked(toUnchecked);
 		}
-		
+
 		public <T> void tryAccept(T obj, _Functions.CheckedConsumer<T> checkedConsumer) {
 			uncheckedConsumer(checkedConsumer).accept(obj);
 		}
 	}
-	
+
+
+
+
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceCachingFilter.java b/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceCachingFilter.java
index 0d9c81d..893db9e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceCachingFilter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceCachingFilter.java
@@ -36,6 +36,8 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.isis.commons.internal.exceptions._Exceptions.FluentException;
+
 /**
  * Adapted from {@link http
  * ://www.digitalsanctuary.com/tech-blog/java/jboss/setting
@@ -235,9 +237,8 @@ public class ResourceCachingFilter implements Filter {
         try {
         	chain.doFilter(servletRequest, servletResponse);
         } catch (IOException e) {
-        	if(!isConnectionAbortException(e)) {
-        		throw e;
-        	}
+        	FluentException.of(e)
+        	.suppressIf(this::isConnectionAbortException);
 		}
     }
 
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PromptFormAbstract.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PromptFormAbstract.java
index bd9629e..6411b56 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PromptFormAbstract.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PromptFormAbstract.java
@@ -20,8 +20,22 @@ package org.apache.isis.viewer.wicket.ui.panels;
 
 import java.util.List;
 
-import com.google.common.collect.Lists;
-
+import org.apache.isis.commons.internal.exceptions._Exceptions.FluentException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
+import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettings;
+import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
+import org.apache.isis.viewer.wicket.model.models.BookmarkableModel;
+import org.apache.isis.viewer.wicket.model.models.FormExecutor;
+import org.apache.isis.viewer.wicket.model.models.FormExecutorContext;
+import org.apache.isis.viewer.wicket.model.models.ParentEntityModelProvider;
+import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarModelSubscriber2;
+import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract2;
+import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.FormFeedbackPanel;
+import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
+import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
 import org.apache.wicket.Component;
 import org.apache.wicket.MarkupContainer;
 import org.apache.wicket.Page;
@@ -40,21 +54,7 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.util.string.AppendingStringBuffer;
 
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
-import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettings;
-import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
-import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
-import org.apache.isis.viewer.wicket.model.models.BookmarkableModel;
-import org.apache.isis.viewer.wicket.model.models.FormExecutor;
-import org.apache.isis.viewer.wicket.model.models.FormExecutorContext;
-import org.apache.isis.viewer.wicket.model.models.ParentEntityModelProvider;
-import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarModelSubscriber2;
-import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract2;
-import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.FormFeedbackPanel;
-import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
-import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
-import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
+import com.google.common.collect.Lists;
 
 public abstract class PromptFormAbstract<T extends BookmarkableModel<ObjectAdapter>
                                                     & ParentEntityModelProvider
@@ -236,7 +236,16 @@ public abstract class PromptFormAbstract<T extends BookmarkableModel<ObjectAdapt
             completePrompt(target);
 
             okButton.send(target.getPage(), Broadcast.EXACT, newCompletedEvent(target, form));
-            target.add(form);
+            //TODO as of Wicket-8 we (for lack of a better solution) silently ignore java.lang.IllegalArgumentException: 
+            // 'Cannot update component because its page is not the same as the one this handler has been created for.'
+            
+            try {
+            	target.add(form);
+            } catch (IllegalArgumentException cause) {
+            	FluentException.of(cause)
+            	.suppressIfMessageContains("Cannot update component because its page is not the same");
+			} 
+                        
         }
 
     }

-- 
To stop receiving notification emails like this one, please contact
ahuber@apache.org.