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/07 15:55:36 UTC
[isis] branch ISIS-2502-ex.recog updated: ISIS-2502: registers the
ExceptionRecognizerForOtherDataAccessProblem
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch ISIS-2502-ex.recog
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/ISIS-2502-ex.recog by this push:
new 83617d4 ISIS-2502: registers the ExceptionRecognizerForOtherDataAccessProblem
83617d4 is described below
commit 83617d4accdb99534d053022fa05818d34448e0a
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sun Feb 7 16:55:20 2021 +0100
ISIS-2502: registers the ExceptionRecognizerForOtherDataAccessProblem
also makes the ExceptionRecognizer construction a bit more flexible
---
.../exceprecog/ExceptionRecognizerAbstract.java | 34 +++++++++++++---------
.../exceprecog/ExceptionRecognizerForType.java | 17 +++++------
.../exceprecog/ExceptionRecognizerForTypeTest.java | 6 ++--
.../IsisModuleCoreRuntimeServices.java | 2 ++
.../ExceptionRecognizerForDataAccessException.java | 10 +++----
...ceptionRecognizerForOtherDataAccessProblem.java | 28 +++++++++++++++++-
.../wicket/ui/panels/FormExecutorDefault.java | 30 ++++++++-----------
7 files changed, 78 insertions(+), 49 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerAbstract.java b/api/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerAbstract.java
index 4651b88..3850c42 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerAbstract.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerAbstract.java
@@ -22,7 +22,6 @@ import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
import javax.inject.Inject;
@@ -66,32 +65,42 @@ public abstract class ExceptionRecognizerAbstract implements ExceptionRecognizer
* Convenience for subclass implementations that always prefixes the exception message
* with the supplied text
*/
- protected static UnaryOperator<String> prefix(final String prefix) {
- return $->prefix + ": " + $;
+ protected static Function<Throwable, String> prefix(final String prefix) {
+ return rootCause->prefix + ": " + rootCause.getMessage();
}
private final Category category;
private final Predicate<Throwable> predicate;
- private final Function<String,String> messageParser;
+ private final Function<Throwable, String> rootCauseMessageFormatter;
protected boolean logRecognizedExceptions;
- public ExceptionRecognizerAbstract(final Category category, Predicate<Throwable> predicate, final Function<String,String> messageParser) {
+ public ExceptionRecognizerAbstract(
+ final Category category,
+ final Predicate<Throwable> predicate,
+ final Function<Throwable, String> rootCauseMessageFormatter) {
Objects.requireNonNull(predicate);
this.category = category;
this.predicate = predicate;
- this.messageParser = messageParser != null ? messageParser : Function.identity();
+ this.rootCauseMessageFormatter = rootCauseMessageFormatter != null
+ ? rootCauseMessageFormatter
+ : Throwable::getMessage;
}
- public ExceptionRecognizerAbstract(Predicate<Throwable> predicate, final Function<String,String> messageParser) {
- this(Category.OTHER, predicate, messageParser);
+ public ExceptionRecognizerAbstract(
+ final Predicate<Throwable> predicate,
+ final Function<Throwable, String> rootCauseMessageFormatter) {
+ this(Category.OTHER, predicate, rootCauseMessageFormatter);
}
- public ExceptionRecognizerAbstract(Category category, Predicate<Throwable> predicate) {
+ public ExceptionRecognizerAbstract(
+ final Category category,
+ final Predicate<Throwable> predicate) {
this(category, predicate, null);
}
- public ExceptionRecognizerAbstract(Predicate<Throwable> predicate) {
+ public ExceptionRecognizerAbstract(
+ final Predicate<Throwable> predicate) {
this(Category.OTHER, predicate);
}
@@ -114,9 +123,8 @@ public abstract class ExceptionRecognizerAbstract implements ExceptionRecognizer
}
}
final Throwable rootCause = _Exceptions.getRootCause(throwable);
- final String rootCauseMessage = rootCause.getMessage();
- final String parsedMessage = messageParser.apply(rootCauseMessage);
- return parsedMessage;
+ final String formattedMessage = rootCauseMessageFormatter.apply(rootCause);
+ return formattedMessage;
})
.filter(_NullSafe::isPresent)
.findFirst();
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java b/api/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java
index 5edbd5e..5f96545 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java
@@ -20,7 +20,6 @@ package org.apache.isis.applib.services.exceprecog;
import java.util.function.Function;
import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
import static org.apache.isis.commons.internal.exceptions._Exceptions.containsAnyOfTheseMessages;
import static org.apache.isis.commons.internal.exceptions._Exceptions.getCausalChain;
@@ -95,15 +94,15 @@ public class ExceptionRecognizerForType extends ExceptionRecognizerAbstract {
public ExceptionRecognizerForType(
final Category category,
final Class<? extends Exception> exceptionType,
- final UnaryOperator<String> messageParser) {
- this(category, ofType(exceptionType), messageParser);
+ final Function<Throwable, String> rootCauseMessageFormatter) {
+ this(category, ofType(exceptionType), rootCauseMessageFormatter);
}
public ExceptionRecognizerForType(
final Category category,
final Predicate<Throwable> predicate,
- final UnaryOperator<String> messageParser) {
- super(category, predicate, messageParser);
+ final Function<Throwable, String> rootCauseMessageFormatter) {
+ super(category, predicate, rootCauseMessageFormatter);
}
public ExceptionRecognizerForType(
@@ -114,14 +113,14 @@ public class ExceptionRecognizerForType extends ExceptionRecognizerAbstract {
public ExceptionRecognizerForType(
final Class<? extends Exception> exceptionType,
- final UnaryOperator<String> messageParser) {
- this(Category.OTHER, exceptionType, messageParser);
+ final Function<Throwable, String> rootCauseMessageFormatter) {
+ this(Category.OTHER, exceptionType, rootCauseMessageFormatter);
}
public ExceptionRecognizerForType(
final Predicate<Throwable> predicate,
- final UnaryOperator<String> messageParser) {
- this(Category.OTHER, predicate, messageParser);
+ final Function<Throwable, String> rootCauseMessageFormatter) {
+ this(Category.OTHER, predicate, rootCauseMessageFormatter);
}
public ExceptionRecognizerForType(Class<? extends Exception> exceptionType) {
diff --git a/api/applib/src/test/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForTypeTest.java b/api/applib/src/test/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForTypeTest.java
index 23625c1..7d0016c 100644
--- a/api/applib/src/test/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForTypeTest.java
+++ b/api/applib/src/test/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForTypeTest.java
@@ -20,7 +20,7 @@
package org.apache.isis.applib.services.exceprecog;
import java.util.Optional;
-import java.util.function.UnaryOperator;
+import java.util.function.Function;
import org.junit.Test;
@@ -45,7 +45,7 @@ public class ExceptionRecognizerForTypeTest {
}
}
- private UnaryOperator<String> prepend = $ -> "pre: " + $;
+ private Function<Throwable, String> rootCauseMessageFormatter = ex -> "pre: " + ex.getMessage();
@Test
public void whenRecognized() {
@@ -61,7 +61,7 @@ public class ExceptionRecognizerForTypeTest {
@Test
public void whenRecognizedWithMessageParser() {
- ersForType = new ExceptionRecognizerForType(FooException.class, prepend);
+ ersForType = new ExceptionRecognizerForType(FooException.class, rootCauseMessageFormatter);
assertThat(ersForType.recognize(new FooException()).get().getReason(), is("pre: foo"));
}
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
index a0c5385..7fb081a 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
@@ -53,6 +53,7 @@ import org.apache.isis.core.runtimeservices.queryresultscache.QueryResultsCacheD
import org.apache.isis.core.runtimeservices.recognizer.ExceptionRecognizerServiceDefault;
import org.apache.isis.core.runtimeservices.recognizer.dae.impl.ExceptionRecognizerForDataAlreadyExists;
import org.apache.isis.core.runtimeservices.recognizer.dae.impl.ExceptionRecognizerForObjectNotFound;
+import org.apache.isis.core.runtimeservices.recognizer.dae.impl.ExceptionRecognizerForOtherDataAccessProblem;
import org.apache.isis.core.runtimeservices.recognizer.dae.impl.ExceptionRecognizerForRelatedDataExists;
import org.apache.isis.core.runtimeservices.recognizer.dae.impl.ExceptionRecognizerForUnableToSaveData;
import org.apache.isis.core.runtimeservices.repository.RepositoryServiceDefault;
@@ -124,6 +125,7 @@ import org.apache.isis.core.runtimeservices.xmlsnapshot.XmlSnapshotServiceDefaul
ExceptionRecognizerForObjectNotFound.class,
ExceptionRecognizerForRelatedDataExists.class,
ExceptionRecognizerForUnableToSaveData.class,
+ ExceptionRecognizerForOtherDataAccessProblem.class,
})
public class IsisModuleCoreRuntimeServices {
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/recognizer/dae/ExceptionRecognizerForDataAccessException.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/recognizer/dae/ExceptionRecognizerForDataAccessException.java
index 39494c9..f86c298 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/recognizer/dae/ExceptionRecognizerForDataAccessException.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/recognizer/dae/ExceptionRecognizerForDataAccessException.java
@@ -18,8 +18,8 @@
*/
package org.apache.isis.core.runtimeservices.recognizer.dae;
+import java.util.function.Function;
import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerForType;
import org.apache.isis.core.config.IsisConfiguration;
@@ -34,8 +34,8 @@ extends ExceptionRecognizerForType {
final IsisConfiguration isisConfiguration,
final Category category,
final Predicate<Throwable> predicate,
- final UnaryOperator<String> messageParser) {
- super(category, predicate, messageParser);
+ final Function<Throwable, String> rootCauseMessageFormatter) {
+ super(category, predicate, rootCauseMessageFormatter);
super.setDisabled(
isisConfiguration.getCore().getRuntimeServices()
@@ -46,8 +46,8 @@ extends ExceptionRecognizerForType {
final IsisConfiguration isisConfiguration,
final Category category,
final Class<? extends Exception> exceptionType,
- final UnaryOperator<String> messageParser) {
- this(isisConfiguration, category, ofType(exceptionType), messageParser);
+ final Function<Throwable, String> rootCauseMessageFormatter) {
+ this(isisConfiguration, category, ofType(exceptionType), rootCauseMessageFormatter);
}
}
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/recognizer/dae/impl/ExceptionRecognizerForOtherDataAccessProblem.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/recognizer/dae/impl/ExceptionRecognizerForOtherDataAccessProblem.java
index f781bc8..f6fd0d5 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/recognizer/dae/impl/ExceptionRecognizerForOtherDataAccessProblem.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/recognizer/dae/impl/ExceptionRecognizerForOtherDataAccessProblem.java
@@ -18,6 +18,8 @@
*/
package org.apache.isis.core.runtimeservices.recognizer.dae.impl;
+import java.util.stream.Collectors;
+
import javax.inject.Inject;
import javax.inject.Named;
@@ -27,9 +29,12 @@ import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.apache.isis.applib.annotation.OrderPrecedence;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.config.IsisConfiguration;
import org.apache.isis.core.runtimeservices.recognizer.dae.ExceptionRecognizerForDataAccessException;
+import lombok.val;
+
/**
* Recognizes exceptions of type {@link DataAccessException} if no one else does (fallback).
*
@@ -49,7 +54,28 @@ extends ExceptionRecognizerForDataAccessException {
super(conf,
Category.OTHER,
ofType(org.springframework.dao.DataAccessException.class),
- prefix("An unrecognized data access problem has occurred: "));
+ rootCause->toMessage(rootCause));
}
+ private static String toMessage(Throwable rootCause) {
+
+ val causalInfo = _Exceptions.getCausalChain(rootCause)
+ .stream()
+ .skip(1L)
+ .map(ex->String.format("%s: %s", ex.getClass().getSimpleName(), ex.getMessage()))
+ .collect(Collectors.joining(", "));
+
+ return causalInfo.isEmpty()
+ ? String.format(
+ "An unrecognized data access problem has occurred: %s\ncaused by %s",
+ rootCause.getMessage(),
+ rootCause.getClass().getSimpleName()
+ )
+ : String.format(
+ "An unrecognized data access problem has occurred: %s\ncausal chain: %s",
+ rootCause.getMessage(),
+ causalInfo);
+ }
+
+
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/FormExecutorDefault.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/FormExecutorDefault.java
index d1f7a79..cddadad 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/FormExecutorDefault.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/FormExecutorDefault.java
@@ -41,7 +41,6 @@ import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerService;
import org.apache.isis.applib.services.i18n.TranslationService;
import org.apache.isis.applib.services.message.MessageService;
import org.apache.isis.applib.services.registry.ServiceRegistry;
-import org.apache.isis.applib.services.xactn.TransactionService;
import org.apache.isis.commons.functional.Result;
import org.apache.isis.commons.internal.collections._Sets;
import org.apache.isis.core.interaction.session.InteractionFactory;
@@ -90,7 +89,8 @@ implements FormExecutor {
* @param feedbackFormIfAny
* @param withinPrompt
*
- * @return <tt>false</tt> - if invalid args; if concurrency exception; <tt>true</tt> if redirecting to new page, or repainting all components
+ * @return <tt>false</tt> - if invalid args;
+ * <tt>true</tt> if redirecting to new page, or repainting all components
*/
@Override
public boolean executeAndProcessResults(
@@ -119,6 +119,7 @@ implements FormExecutor {
return false;
}
+ val commonContext = targetEntityModel.getCommonContext();
//
// the following line will (attempt to) invoke the action, and will in turn either:
@@ -128,30 +129,23 @@ implements FormExecutor {
// 2. return a null result (from a successful action returning void)
//
// 3. throws a RuntimeException, either:
- // a) as result of application throwing RecoverableException/ApplicationException (DN xactn still intact)
- // b) as result of DB exception, eg uniqueness constraint violation (DN xactn marked to abort)
- // Either way, as a side-effect the Isis transaction will be set to MUST_ABORT (IsisTransactionManager does this)
+ // a) as result of application throwing RecoverableException (DN transaction still intact)
+ // b) as result of DB exception, eg uniqueness constraint violation (DN transaction marked to abort)
//
// (The DB exception might actually be thrown by the flush() that follows.
//
val resultAdapter = obtainResultAdapter();
// flush any queued changes; any concurrency or violation exceptions will actually be thrown here
- {
- val commonContext = targetEntityModel.getCommonContext();
- commonContext.getInteractionTracker().currentInteractionSession()
- .ifPresent(interaction->{
- commonContext.lookupServiceElseFail(TransactionService.class)
- .flushTransaction();
- });
- }
+ if(commonContext.getInteractionTracker().isInInteractionSession()) {
+ commonContext.getTransactionService().flushTransaction();
- // update target, since version updated (concurrency checks)
- targetAdapter = targetEntityModel.getManagedObject();
- if(!EntityUtil.isDestroyed(targetAdapter)) {
- targetEntityModel.resetPropertyModels();
+ // update target, since version updated
+ targetAdapter = targetEntityModel.getManagedObject();
+ if(!EntityUtil.isDestroyed(targetAdapter)) {
+ targetEntityModel.resetPropertyModels();
+ }
}
-
// hook to close prompt etc.
onExecuteAndProcessResults(targetIfAny);