This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new daee12aa1b Checked "Always log rows" in "Abort workflow" action leads
to wrong flow of execution, fixes #5982 (#7664)
daee12aa1b is described below
commit daee12aa1b4ccf3b280ac096d689e2bdf8be0ee7
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Tue Jul 28 15:24:42 2026 +0200
Checked "Always log rows" in "Abort workflow" action leads to wrong flow of
execution, fixes #5982 (#7664)
---
.../modules/ROOT/pages/workflow/actions/abort.adoc | 6 +
.../hop/workflow/actions/abort/ActionAbort.java | 96 +++++++++------
.../workflow/actions/abort/ActionAbortDialog.java | 56 ++++-----
.../abort/messages/messages_de_DE.properties | 5 +-
.../abort/messages/messages_en_US.properties | 6 +-
.../abort/messages/messages_es_AR.properties | 5 +-
.../abort/messages/messages_es_ES.properties | 5 +-
.../abort/messages/messages_fr_FR.properties | 5 +-
.../abort/messages/messages_it_IT.properties | 4 +-
.../abort/messages/messages_pt_BR.properties | 5 +-
.../abort/messages/messages_zh_CN.properties | 5 +-
.../workflow/actions/abort/ActionAbortTest.java | 129 ++++++++++++++++++++-
.../abort/WorkflowActionAbortLoadSaveTest.java | 20 +++-
13 files changed, 244 insertions(+), 103 deletions(-)
diff --git
a/docs/hop-user-manual/modules/ROOT/pages/workflow/actions/abort.adoc
b/docs/hop-user-manual/modules/ROOT/pages/workflow/actions/abort.adoc
index c7df153d44..377b7c0e70 100644
--- a/docs/hop-user-manual/modules/ROOT/pages/workflow/actions/abort.adoc
+++ b/docs/hop-user-manual/modules/ROOT/pages/workflow/actions/abort.adoc
@@ -26,6 +26,9 @@ The `Abort workflow` action immediately stops (aborts) a
running workflow.
Use the abort action if you want to explicitly terminate a workflow and mark
it as failed with an (optional) error message.
+The workflow is always marked as failed, whatever the action before the abort
returned.
+A parent workflow calling this workflow will follow its failure hop.
+
== Options
[options="header"]
@@ -35,4 +38,7 @@ Use the abort action if you want to explicitly terminate a
workflow and mark it
This name has to be unique in a single workflow.
A workflow action can be placed several times on the canvas, however it will
be the same workflow action.
|Message|Message to add in log when aborting
+|Log level of the message|The log level to write the message with, `Error` by
default.
+Lower the log level if you don't want the message to show up as an error in
the log.
+This only changes the logging: the workflow is marked as failed either way.
|===
\ No newline at end of file
diff --git
a/plugins/actions/abort/src/main/java/org/apache/hop/workflow/actions/abort/ActionAbort.java
b/plugins/actions/abort/src/main/java/org/apache/hop/workflow/actions/abort/ActionAbort.java
index cbeec7fb86..7bd1c2f2ee 100644
---
a/plugins/actions/abort/src/main/java/org/apache/hop/workflow/actions/abort/ActionAbort.java
+++
b/plugins/actions/abort/src/main/java/org/apache/hop/workflow/actions/abort/ActionAbort.java
@@ -18,17 +18,23 @@
package org.apache.hop.workflow.actions.abort;
import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.core.ICheckResult;
import org.apache.hop.core.Result;
import org.apache.hop.core.annotations.Action;
+import org.apache.hop.core.logging.LogLevel;
import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.core.xml.XmlHandler;
import org.apache.hop.i18n.BaseMessages;
import org.apache.hop.metadata.api.HopMetadataProperty;
import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.metadata.serializer.xml.ILegacyXml;
import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.action.ActionBase;
import org.apache.hop.workflow.action.IAction;
import org.apache.hop.workflow.action.validator.ActionValidatorUtils;
+import org.w3c.dom.Node;
/** Action type to abort a workflow. */
@Action(
@@ -39,18 +45,22 @@ import
org.apache.hop.workflow.action.validator.ActionValidatorUtils;
categoryDescription =
"i18n:org.apache.hop.workflow:ActionCategory.Category.General",
keywords = "i18n::ActionAbort.keyword",
documentationUrl = "/workflow/actions/abort.html")
-public class ActionAbort extends ActionBase implements Cloneable, IAction {
+public class ActionAbort extends ActionBase implements Cloneable, IAction,
ILegacyXml {
private static final Class<?> PKG = ActionAbort.class;
+ @Setter
+ @Getter
@HopMetadataProperty(key = "message")
private String messageAbort;
- @HopMetadataProperty(key = "always_log_rows")
- private boolean alwaysLogRows;
+ @Setter
+ @HopMetadataProperty(key = "loglevel", storeWithCode = true)
+ private LogLevel messageLogLevel;
public ActionAbort(String name, String description) {
super(name, description);
messageAbort = null;
+ messageLogLevel = LogLevel.ERROR;
}
public ActionAbort() {
@@ -60,7 +70,7 @@ public class ActionAbort extends ActionBase implements
Cloneable, IAction {
public ActionAbort(ActionAbort other) {
super(other.getName(), other.getDescription(), other.getPluginId());
this.messageAbort = other.messageAbort;
- this.alwaysLogRows = other.alwaysLogRows;
+ this.messageLogLevel = other.messageLogLevel;
}
@Override
@@ -68,6 +78,26 @@ public class ActionAbort extends ActionBase implements
Cloneable, IAction {
return new ActionAbort(this);
}
+ /**
+ * Backward compatible code.
+ *
+ * <p>Before the log level of the message became configurable, an
"always_log_rows" flag decided
+ * between minimal and error logging. That flag also determined whether the
workflow was marked as
+ * failed, which made the outcome of the abort depend on the action
preceding it. Aborting now
+ * always fails the workflow, the old flag only maps onto the log level of
the message.
+ */
+ @Override
+ public void convertLegacyXml(Node node) {
+ if (XmlHandler.getTagValue(node, "loglevel") == null) {
+ messageLogLevel =
+ "Y".equalsIgnoreCase(XmlHandler.getTagValue(node, "always_log_rows"))
+ ? LogLevel.MINIMAL
+ : LogLevel.ERROR;
+ } else if (messageLogLevel == null) {
+ messageLogLevel = LogLevel.ERROR;
+ }
+ }
+
/**
* Execute this action and return the result. In this case it means, just
set the result boolean
* in the Result class.
@@ -84,28 +114,39 @@ public class ActionAbort extends ActionBase implements
Cloneable, IAction {
msg = BaseMessages.getString(PKG,
"ActionAbort.Meta.CheckResult.Label");
}
- if (isAlwaysLogRows()) {
- logMinimal(BaseMessages.getString(PKG, "ActionAbort.Log.Wrote.Row",
nr, msg));
- } else {
- logError(BaseMessages.getString(PKG, "ActionAbort.Log.Wrote.Row", nr,
msg));
- result.setNrErrors(1);
- result.setResult(false);
- }
+ logMessage(msg);
} catch (Exception e) {
- result.setNrErrors(1);
- result.setResult(false);
logError(BaseMessages.getString(PKG,
"ActionAbort.Meta.CheckResult.CouldNotExecute") + e);
}
+ // Aborting always fails the workflow, no matter what the previous action
returned.
+ //
+ result.setNrErrors(1);
+ result.setResult(false);
+
// we fail so stop workflow execution
parentWorkflow.stopExecution();
return result;
}
+ /** Writes the abort message to the log with the configured log level. */
+ private void logMessage(String msg) {
+ switch (getMessageLogLevel()) {
+ case ERROR -> logError(msg);
+ case MINIMAL -> logMinimal(msg);
+ case BASIC -> logBasic(msg);
+ case DETAILED -> logDetailed(msg);
+ case DEBUG -> logDebug(msg);
+ case ROWLEVEL -> logRowlevel(msg);
+ case NOTHING -> {
+ // Don't log the message at all
+ }
+ }
+ }
+
@Override
public boolean resetErrorsBeforeExecution() {
- // we should be able to evaluate the errors in
- // the previous action.
+ // Leave the errors of the previous action alone, execute() sets the
result of the abort itself.
return false;
}
@@ -120,29 +161,12 @@ public class ActionAbort extends ActionBase implements
Cloneable, IAction {
}
/**
- * Set the message to display in the log
+ * Get the log level to write the message with
*
- * @param message the message to display
+ * @return the log level of the message
*/
- public void setMessageAbort(String message) {
- this.messageAbort = message;
- }
-
- /**
- * Get the message to display in the log
- *
- * @return the message
- */
- public String getMessageAbort() {
- return messageAbort;
- }
-
- public boolean isAlwaysLogRows() {
- return alwaysLogRows;
- }
-
- public void setAlwaysLogRows(boolean alwaysLogRows) {
- this.alwaysLogRows = alwaysLogRows;
+ public LogLevel getMessageLogLevel() {
+ return messageLogLevel == null ? LogLevel.ERROR : messageLogLevel;
}
@Override
diff --git
a/plugins/actions/abort/src/main/java/org/apache/hop/workflow/actions/abort/ActionAbortDialog.java
b/plugins/actions/abort/src/main/java/org/apache/hop/workflow/actions/abort/ActionAbortDialog.java
index b81291255d..d7555ef86b 100644
---
a/plugins/actions/abort/src/main/java/org/apache/hop/workflow/actions/abort/ActionAbortDialog.java
+++
b/plugins/actions/abort/src/main/java/org/apache/hop/workflow/actions/abort/ActionAbortDialog.java
@@ -17,6 +17,7 @@
package org.apache.hop.workflow.actions.abort;
+import org.apache.hop.core.logging.LogLevel;
import org.apache.hop.core.util.Utils;
import org.apache.hop.core.variables.IVariables;
import org.apache.hop.i18n.BaseMessages;
@@ -28,12 +29,9 @@ import org.apache.hop.ui.workflow.action.ActionDialog;
import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.action.IAction;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
@@ -47,7 +45,7 @@ public class ActionAbortDialog extends ActionDialog {
private TextVar wMessageAbort;
- private Button wAlwaysLogRows;
+ private Combo wMessageLogLevel;
public ActionAbortDialog(
Shell parent, ActionAbort action, WorkflowMeta workflowMeta, IVariables
variables) {
@@ -86,26 +84,28 @@ public class ActionAbortDialog extends ActionDialog {
fdMessageAbort.right = new FormAttachment(100, 0);
wMessageAbort.setLayoutData(fdMessageAbort);
- SelectionListener slMod =
- new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- action.setChanged();
- }
- };
- // Always log rows
- wAlwaysLogRows = new Button(shell, SWT.CHECK);
- wAlwaysLogRows.setSelection(true);
- PropsUi.setLook(wAlwaysLogRows);
- wAlwaysLogRows.setText(BaseMessages.getString(PKG,
"ActionAbortDialog.AlwaysLogRows.Label"));
- wAlwaysLogRows.setToolTipText(
- BaseMessages.getString(PKG,
"ActionAbortDialog.AlwaysLogRows.Tooltip"));
- wAlwaysLogRows.addSelectionListener(slMod);
- FormData fdAlwaysLogRows = new FormData();
- fdAlwaysLogRows.left = new FormAttachment(middle, 0);
- fdAlwaysLogRows.top = new FormAttachment(wMessageAbort, margin);
- fdAlwaysLogRows.right = new FormAttachment(100, 0);
- wAlwaysLogRows.setLayoutData(fdAlwaysLogRows);
+ // Log level of the message
+ Label wlMessageLogLevel = new Label(shell, SWT.RIGHT);
+ wlMessageLogLevel.setText(
+ BaseMessages.getString(PKG,
"ActionAbortDialog.MessageLogLevels.Label"));
+ PropsUi.setLook(wlMessageLogLevel);
+ FormData fdlMessageLogLevel = new FormData();
+ fdlMessageLogLevel.left = new FormAttachment(0, 0);
+ fdlMessageLogLevel.right = new FormAttachment(middle, -margin);
+ fdlMessageLogLevel.top = new FormAttachment(wMessageAbort, margin);
+ wlMessageLogLevel.setLayoutData(fdlMessageLogLevel);
+
+ wMessageLogLevel = new Combo(shell, SWT.SINGLE | SWT.READ_ONLY |
SWT.BORDER);
+ wMessageLogLevel.setItems(LogLevel.getLogLevelDescriptions());
+ PropsUi.setLook(wMessageLogLevel);
+ wMessageLogLevel.setToolTipText(
+ BaseMessages.getString(PKG,
"ActionAbortDialog.MessageLogLevels.Tooltip"));
+ wMessageLogLevel.addModifyListener(e -> action.setChanged());
+ FormData fdMessageLogLevel = new FormData();
+ fdMessageLogLevel.left = new FormAttachment(middle, 0);
+ fdMessageLogLevel.top = new FormAttachment(wlMessageLogLevel, 0,
SWT.CENTER);
+ fdMessageLogLevel.right = new FormAttachment(100, 0);
+ wMessageLogLevel.setLayoutData(fdMessageLogLevel);
getData();
focusActionName();
@@ -128,7 +128,7 @@ public class ActionAbortDialog extends ActionDialog {
if (action.getMessageAbort() != null) {
wMessageAbort.setText(action.getMessageAbort());
}
- wAlwaysLogRows.setSelection(action.isAlwaysLogRows());
+ wMessageLogLevel.select(action.getMessageLogLevel().getLevel());
}
private void cancel() {
@@ -147,7 +147,9 @@ public class ActionAbortDialog extends ActionDialog {
}
action.setName(wName.getText());
action.setMessageAbort(wMessageAbort.getText());
- action.setAlwaysLogRows(wAlwaysLogRows.getSelection());
+ if (wMessageLogLevel.getSelectionIndex() != -1) {
+
action.setMessageLogLevel(LogLevel.values()[wMessageLogLevel.getSelectionIndex()]);
+ }
dispose();
}
}
diff --git
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_de_DE.properties
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_de_DE.properties
index 9e14819e67..fde1e0a5e6 100644
---
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_de_DE.properties
+++
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_de_DE.properties
@@ -20,14 +20,11 @@
ActionAbort.Description=Workflow abbrechen
ActionAbort.keyword=abbrechen
-ActionAbort.Log.Wrote.Row=Zeilennummer {0} : {1}
ActionAbort.Meta.CheckResult.CouldNotExecute=Abbruch-Action konnte nicht
ausgef\u00FChrt werden:
ActionAbort.Meta.CheckResult.Label=Workflow wird abgebrochen.
ActionAbort.Name=Workflow abbrechen
-ActionAbortDialog.AlwaysLogRows.Label=Nicht als Fehler kennzeichnen
-ActionAbortDialog.AlwaysLogRows.Tooltip=Zeilen immer loggen, unabh\u00E4ngig
vom Log-Level
ActionAbortDialog.Label=Workflow abbrechen
ActionAbortDialog.MessageAbort.Label=Nachricht
ActionAbortDialog.MessageAbort.Tooltip=Die Nachricht, welche im Log erscheint
-ActionAbortDialog.MessageLogLevels.Label=Log-Level der Meldung:
+ActionAbortDialog.MessageLogLevels.Label=Log-Level der Meldung
ActionAbortDialog.Title=Workflow abbrechen
diff --git
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_en_US.properties
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_en_US.properties
index 7e49e70ab8..707510459e 100644
---
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_en_US.properties
+++
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_en_US.properties
@@ -19,14 +19,12 @@
ActionAbort.Description=Abort the workflow
ActionAbort.keyword=abort,stop,fail,cancel,terminate
-ActionAbort.Log.Wrote.Row=Seen row nr {0} \: {1}
ActionAbort.Meta.CheckResult.CouldNotExecute=Couldn't execute abort action\:
ActionAbort.Meta.CheckResult.Label=Aborting workflow.
ActionAbort.Name=Abort workflow
-ActionAbortDialog.AlwaysLogRows.Label=Always log rows
-ActionAbortDialog.AlwaysLogRows.Tooltip=Always log rows even if below current
log level
ActionAbortDialog.Label=Abort workflow
ActionAbortDialog.MessageAbort.Label=Message
ActionAbortDialog.MessageAbort.Tooltip=Message to display in the log
-ActionAbortDialog.MessageLogLevels.Label=Log level of the message:
+ActionAbortDialog.MessageLogLevels.Label=Log level of the message
+ActionAbortDialog.MessageLogLevels.Tooltip=The log level to write the message
with. The workflow is marked as failed regardless of this setting.
ActionAbortDialog.Title=Abort workflow
diff --git
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_es_AR.properties
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_es_AR.properties
index 4c23e915ad..239fe5b110 100644
---
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_es_AR.properties
+++
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_es_AR.properties
@@ -20,14 +20,11 @@
ActionAbort.Description=Abortar el trabajo
ActionAbort.keyword=abortar
-ActionAbort.Log.Wrote.Row=Fila no. {0} vista : {1}
ActionAbort.Meta.CheckResult.CouldNotExecute=No se puede ejecutar la
acci\u00F3n de abortar:
ActionAbort.Meta.CheckResult.Label=Abortando trabajo.
ActionAbort.Name=Abortar trabajo
-ActionAbortDialog.AlwaysLogRows.Label=Registrar filas siempre
-ActionAbortDialog.AlwaysLogRows.Tooltip=Registrar filas siempre incluso si
est\u00E1 bajo el nivel de registro actual
ActionAbortDialog.Label=Abortar trabajo
ActionAbortDialog.MessageAbort.Label=Mensaje
ActionAbortDialog.MessageAbort.Tooltip=Mensaje a mostrar en el log
-ActionAbortDialog.MessageLogLevels.Label=Nivel de registro del mensaje:
+ActionAbortDialog.MessageLogLevels.Label=Nivel de registro del mensaje
ActionAbortDialog.Title=Abortar trabajo
diff --git
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_es_ES.properties
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_es_ES.properties
index ebdcfb7e86..e84094d716 100644
---
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_es_ES.properties
+++
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_es_ES.properties
@@ -18,14 +18,11 @@
ActionAbort.Description=Abortar el flujo de trabajo
ActionAbort.keyword=abortar
-ActionAbort.Log.Wrote.Row=Visto fila nr {0} \: {1}
ActionAbort.Meta.CheckResult.CouldNotExecute=No se ha podido ejecutar la
acci\u00F3n de abortar\:
ActionAbort.Meta.CheckResult.Label=Abortar flujo de trabajo.
ActionAbort.Name=Abortar flujo de trabajo
-ActionAbortDialog.AlwaysLogRows.Label=Registrar filas siempre
-ActionAbortDialog.AlwaysLogRows.Tooltip=Registrar siempre las filas aunque
est\u00E9n por debajo del nivel de registro actual
ActionAbortDialog.Label=Abortar flujo de trabajo
ActionAbortDialog.MessageAbort.Label=Mensaje
ActionAbortDialog.MessageAbort.Tooltip=Mensaje que se mostrar\u00E1 en el
registro
-ActionAbortDialog.MessageLogLevels.Label=Nivel de registro del mensaje:
+ActionAbortDialog.MessageLogLevels.Label=Nivel de registro del mensaje
ActionAbortDialog.Title=Abortar flujo de trabajo
diff --git
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_fr_FR.properties
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_fr_FR.properties
index a7f61836df..09011108ff 100644
---
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_fr_FR.properties
+++
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_fr_FR.properties
@@ -17,14 +17,11 @@
ActionAbort.Description=Mise en \u00E9chec du workflow
ActionAbort.keyword=abandon, interrompre, stop
-ActionAbort.Log.Wrote.Row=Vue ligne n\u00B0 {0} : {1}
ActionAbort.Meta.CheckResult.CouldNotExecute=Impossible d''arr\u00EAter
l''ex\u00E9cution workflow\u00A0:
ActionAbort.Meta.CheckResult.Label=Mise en \u00E9chec du workflow.
ActionAbort.Name=Mise en \u00E9chec du workflow
-ActionAbortDialog.AlwaysLogRows.Label=Ne pas marquer comme erreur
-ActionAbortDialog.AlwaysLogRows.Tooltip=Toujours logger les lignes m\u00EAme
pour niveau de d\u00E9tail des logs inf\u00E9rieur
ActionAbortDialog.Label=Nom de l''action
ActionAbortDialog.MessageAbort.Label=Message
ActionAbortDialog.MessageAbort.Tooltip=Message \u00E0 ajouter \u00E0 la trace
-ActionAbortDialog.MessageLogLevels.Label=Niveau de log du message\u00A0:
+ActionAbortDialog.MessageLogLevels.Label=Niveau de log du message
ActionAbortDialog.Title=Abandonner le workflow
diff --git
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_it_IT.properties
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_it_IT.properties
index b69789dfb8..37bc31767c 100644
---
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_it_IT.properties
+++
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_it_IT.properties
@@ -25,6 +25,4 @@ ActionAbortDialog.Label=Annulla workflow
ActionAbortDialog.MessageAbort.Label=Messaggio
ActionAbortDialog.MessageAbort.Tooltip=Messaggio da visualizzare nel log
ActionAbortDialog.Title=Interrompi workflow
-ActionAbortDialog.AlwaysLogRows.Label=Registra sempre le righe
-ActionAbortDialog.AlwaysLogRows.Tooltip=Registra sempre le righe anche se
sotto il livello di log
-ActionAbortDialog.MessageLogLevels.Label=Livello di log del messaggio:
+ActionAbortDialog.MessageLogLevels.Label=Livello di log del messaggio
diff --git
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_pt_BR.properties
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_pt_BR.properties
index d1610c7398..7b2ff11c82 100644
---
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_pt_BR.properties
+++
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_pt_BR.properties
@@ -20,14 +20,11 @@
ActionAbort.Description=Abortar o fluxo de trabalho
ActionAbort.keyword=abortar,parar, falhar,cancelar,terminar
-ActionAbort.Log.Wrote.Row=Vendo linha Nr {0} : {1}
ActionAbort.Meta.CheckResult.CouldNotExecute=N\u00E3o foi poss\u00EDvel
executar a a\u00E7\u00E3o de abortar:
ActionAbort.Meta.CheckResult.Label=Abortando o fluxo de trabalho.
ActionAbort.Name=Abortar o fluxo de trabalho
-ActionAbortDialog.AlwaysLogRows.Label=Sempre registrar linhas
-ActionAbortDialog.AlwaysLogRows.Tooltip=Sempre registre as linhas, mesmo que
abaixo do n\u00EDvel de registro atual
ActionAbortDialog.Label=Abortar o fluxo de trabalho
ActionAbortDialog.MessageAbort.Label=Mensagem
ActionAbortDialog.MessageAbort.Tooltip=Mensagem a exibir no registro
-ActionAbortDialog.MessageLogLevels.Label=N\u00EDvel de registro da mensagem:
+ActionAbortDialog.MessageLogLevels.Label=N\u00EDvel de registro da mensagem
ActionAbortDialog.Title=Abortar o fluxo de trabalho
diff --git
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_zh_CN.properties
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_zh_CN.properties
index 724481ae7a..d2b2c9acc0 100644
---
a/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_zh_CN.properties
+++
b/plugins/actions/abort/src/main/resources/org/apache/hop/workflow/actions/abort/messages/messages_zh_CN.properties
@@ -19,14 +19,11 @@
ActionAbort.Description=\u7EC8\u6B62\u4EFB\u52A1
ActionAbort.keyword=abort
-ActionAbort.Log.Wrote.Row=\u89C1\u7B2C {0} \u884C\: {1}
ActionAbort.Meta.CheckResult.CouldNotExecute=\u4E0D\u80FD\u6267\u884C\u7EC8\u6B62
Action\:
ActionAbort.Meta.CheckResult.Label=\u7EC8\u6B62 Action.
ActionAbort.Name=\u7EC8\u6B62\u4F5C\u4E1A
-ActionAbortDialog.AlwaysLogRows.Label=\u603B\u662F\u8BB0\u5F55\u6570\u636E\u884C
-ActionAbortDialog.AlwaysLogRows.Tooltip=\u5373\u4F7F\u4F4E\u4E8E\u5F53\u524D\u65E5\u5FD7\u7EA7\u522B\u4E5F\u59CB\u7EC8\u8BB0\u5F55\u884C
ActionAbortDialog.Label=\u7EC8\u6B62\u4F5C\u4E1A
ActionAbortDialog.MessageAbort.Label=\u6D88\u606F
ActionAbortDialog.MessageAbort.Tooltip=\u65E5\u5FD7\u4E2D\u663E\u793A\u7684\u6D88\u606F
-ActionAbortDialog.MessageLogLevels.Label=\u6D88\u606F\u7684\u65E5\u5FD7\u7EA7\u522B:
+ActionAbortDialog.MessageLogLevels.Label=\u6D88\u606F\u7684\u65E5\u5FD7\u7EA7\u522B
ActionAbortDialog.Title=\u7EC8\u6B62\u4F5C\u4E1A
diff --git
a/plugins/actions/abort/src/test/java/org/apache/hop/workflow/actions/abort/ActionAbortTest.java
b/plugins/actions/abort/src/test/java/org/apache/hop/workflow/actions/abort/ActionAbortTest.java
index 62c11ddd81..385c8a19e4 100644
---
a/plugins/actions/abort/src/test/java/org/apache/hop/workflow/actions/abort/ActionAbortTest.java
+++
b/plugins/actions/abort/src/test/java/org/apache/hop/workflow/actions/abort/ActionAbortTest.java
@@ -18,26 +18,143 @@
package org.apache.hop.workflow.actions.abort;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
-import org.apache.hop.core.variables.Variables;
+import org.apache.hop.core.Result;
+import org.apache.hop.core.logging.HopLogStore;
+import org.apache.hop.core.logging.LogLevel;
import org.apache.hop.core.xml.XmlHandler;
+import org.apache.hop.metadata.serializer.xml.XmlMetadataUtil;
+import org.apache.hop.workflow.Workflow;
+import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.action.ActionMeta;
+import org.apache.hop.workflow.engine.IWorkflowEngine;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.w3c.dom.Node;
class ActionAbortTest {
+ private IWorkflowEngine<WorkflowMeta> parentWorkflow;
+
+ @BeforeAll
+ static void setUpBeforeClass() {
+ HopLogStore.init();
+ }
+
+ @BeforeEach
+ void setUp() {
+ parentWorkflow = mock(Workflow.class);
+ doReturn(LogLevel.ROWLEVEL).when(parentWorkflow).getLogLevel();
+ }
+
@Test
void testXmlRoundTrip() throws Exception {
final String message = "This is a test message";
ActionAbort action = new ActionAbort();
action.setMessageAbort(message);
- String xml = action.getXml();
+ action.setMessageLogLevel(LogLevel.BASIC);
- String actionXml =
- XmlHandler.openTag(ActionMeta.XML_TAG) + xml +
XmlHandler.closeTag(ActionMeta.XML_TAG);
- ActionAbort action2 = new ActionAbort();
- action2.loadXml(XmlHandler.loadXmlString(actionXml, ActionMeta.XML_TAG),
null, new Variables());
+ ActionAbort action2 = loadFromXml(action.getXml());
assertEquals(action.getMessageAbort(), action2.getMessageAbort());
+ assertEquals(LogLevel.BASIC, action2.getMessageLogLevel());
+ }
+
+ @Test
+ void defaultLogLevelIsError() {
+ assertEquals(LogLevel.ERROR, new ActionAbort().getMessageLogLevel());
+ }
+
+ /**
+ * Workflows created before the log level became configurable used an
"always_log_rows" flag to
+ * pick between minimal and error logging. It has to keep selecting the same
log level.
+ */
+ @Test
+ void legacyAlwaysLogRowsMapsOntoTheMessageLogLevel() throws Exception {
+ assertEquals(
+ LogLevel.MINIMAL,
+
loadFromXml("<message>abort</message><always_log_rows>Y</always_log_rows>")
+ .getMessageLogLevel());
+ assertEquals(
+ LogLevel.ERROR,
+
loadFromXml("<message>abort</message><always_log_rows>N</always_log_rows>")
+ .getMessageLogLevel());
+ assertEquals(LogLevel.ERROR,
loadFromXml("<message>abort</message>").getMessageLogLevel());
+ }
+
+ /** Once converted, the old flag isn't written back to the workflow. */
+ @Test
+ void legacyAlwaysLogRowsIsNotSerializedAgain() throws Exception {
+ ActionAbort action =
+
loadFromXml("<message>abort</message><always_log_rows>Y</always_log_rows>");
+
+ assertFalse(action.getXml().contains("always_log_rows"));
+ assertTrue(action.getXml().contains("<loglevel>Minimal</loglevel>"));
+ }
+
+ /**
+ * The abort has to fail the workflow on its own, without inheriting the
outcome of the action
+ * before it. See issue #5982: an action in between the failure and the
abort used to flip the
+ * workflow back to a success.
+ */
+ @Test
+ void abortFailsTheWorkflowWhateverThePreviousActionReturned() {
+ for (LogLevel logLevel : LogLevel.values()) {
+ Result previousResult = new Result();
+ previousResult.setResult(true);
+ previousResult.setNrErrors(0);
+
+ Result result = execute(logLevel, previousResult);
+
+ assertFalse(result.isResult(), "Abort should fail the workflow with log
level " + logLevel);
+ assertEquals(
+ 1, result.getNrErrors(), "Abort should report an error for log level
" + logLevel);
+ }
+ }
+
+ @Test
+ void abortFailsTheWorkflowAfterAFailedAction() {
+ Result previousResult = new Result();
+ previousResult.setResult(false);
+ previousResult.setNrErrors(1);
+
+ Result result = execute(LogLevel.ERROR, previousResult);
+
+ assertFalse(result.isResult());
+ assertEquals(1, result.getNrErrors());
+ }
+
+ @Test
+ void abortStopsTheParentWorkflow() {
+ execute(LogLevel.ERROR, new Result());
+
+ verify(parentWorkflow).stopExecution();
+ }
+
+ private Result execute(LogLevel logLevel, Result previousResult) {
+ ActionAbort action = new ActionAbort();
+ action.setMessageAbort("Aborting the workflow");
+ action.setMessageLogLevel(logLevel);
+ action.setParentWorkflow(parentWorkflow);
+
+ return action.execute(previousResult, 0);
+ }
+
+ /**
+ * De-serializes through {@link XmlMetadataUtil}, the way a workflow loads
the actions it holds.
+ * That path is annotation driven and calls {@link
ActionAbort#convertLegacyXml(Node)}, it does
+ * not go through {@code loadXml()}.
+ */
+ private ActionAbort loadFromXml(String xml) throws Exception {
+ String actionXml =
+ XmlHandler.openTag(ActionMeta.XML_TAG) + xml +
XmlHandler.closeTag(ActionMeta.XML_TAG);
+ Node node = XmlHandler.loadXmlString(actionXml, ActionMeta.XML_TAG);
+ return XmlMetadataUtil.deSerializeFromXml(node, ActionAbort.class, new
ActionAbort(), null);
}
}
diff --git
a/plugins/actions/abort/src/test/java/org/apache/hop/workflow/actions/abort/WorkflowActionAbortLoadSaveTest.java
b/plugins/actions/abort/src/test/java/org/apache/hop/workflow/actions/abort/WorkflowActionAbortLoadSaveTest.java
index 5083b15e13..2c9762face 100644
---
a/plugins/actions/abort/src/test/java/org/apache/hop/workflow/actions/abort/WorkflowActionAbortLoadSaveTest.java
+++
b/plugins/actions/abort/src/test/java/org/apache/hop/workflow/actions/abort/WorkflowActionAbortLoadSaveTest.java
@@ -17,8 +17,13 @@
package org.apache.hop.workflow.actions.abort;
import java.util.Arrays;
+import java.util.EnumSet;
import java.util.List;
import java.util.Map;
+import java.util.Random;
+import org.apache.hop.core.logging.LogLevel;
+import
org.apache.hop.pipeline.transforms.loadsave.validator.EnumLoadSaveValidator;
+import
org.apache.hop.pipeline.transforms.loadsave.validator.IFieldLoadSaveValidator;
import
org.apache.hop.workflow.action.loadsave.WorkflowActionLoadSaveTestSupport;
class WorkflowActionAbortLoadSaveTest extends
WorkflowActionLoadSaveTestSupport<ActionAbort> {
@@ -30,18 +35,27 @@ class WorkflowActionAbortLoadSaveTest extends
WorkflowActionLoadSaveTestSupport<
@Override
protected List<String> listAttributes() {
- return Arrays.asList("messageAbort", "alwaysLogRows");
+ return Arrays.asList("messageAbort", "messageLogLevel");
}
@Override
protected Map<String, String> createGettersMap() {
return toMap(
"messageAbort", "getMessageAbort",
- "alwaysLogRows", "isAlwaysLogRows");
+ "messageLogLevel", "getMessageLogLevel");
}
@Override
protected Map<String, String> createSettersMap() {
- return toMap("messageAbort", "setMessageAbort", "alwaysLogRows",
"setAlwaysLogRows");
+ return toMap(
+ "messageAbort", "setMessageAbort",
+ "messageLogLevel", "setMessageLogLevel");
+ }
+
+ @Override
+ protected Map<String, IFieldLoadSaveValidator<?>>
createAttributeValidatorsMap() {
+ EnumSet<LogLevel> logLevels = EnumSet.allOf(LogLevel.class);
+ LogLevel random = (LogLevel) logLevels.toArray()[new
Random().nextInt(logLevels.size())];
+ return toMap("messageLogLevel", new EnumLoadSaveValidator<>(random));
}
}