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 6fdc6e1034 fix duplicate result rows, fixes #5860 (#5861)
6fdc6e1034 is described below
commit 6fdc6e1034c5879e3c3dcf5195735e3a473caabc
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Mon Oct 20 23:40:58 2025 +0200
fix duplicate result rows, fixes #5860 (#5861)
---
core/src/main/java/org/apache/hop/core/Result.java | 381 +++------------------
.../org/apache/hop/core/gui/WorkflowTracker.java | 137 +++++---
.../apache/hop/execution/ExecutionDataBuilder.java | 2 +-
.../hop/execution/ExecutionStateBuilder.java | 2 +-
.../engines/local/LocalPipelineEngine.java | 2 +-
.../main/java/org/apache/hop/run/HopRunBase.java | 2 +-
.../java/org/apache/hop/workflow/ActionResult.java | 123 ++-----
.../java/org/apache/hop/workflow/Workflow.java | 23 +-
.../org/apache/hop/workflow/WorkflowPainter.java | 4 +-
.../engines/local/LocalWorkflowEngine.java | 2 +-
.../apache/hop/www/GetWorkflowStatusServlet.java | 2 +-
.../main/java/org/apache/hop/www/HopServer.java | 2 +-
.../concurrency/WorkflowTrackerUniquenessTest.java | 262 ++++++++++++++
.../apache/hop/core/gui/WorkflowTrackerTest.java | 19 +-
.../copyfiles/WorkflowActionCopyFilesTest.java | 4 +-
.../WorkflowActionEvalTableContentTest.java | 6 +-
.../filesexist/WorkflowActionFilesExistTest.java | 8 +-
.../WorkflowActionFolderIsEmptyTest.java | 4 +-
.../WorkflowActionMoveFilesLocalTest.java | 10 +-
.../apache/hop/workflow/actions/repeat/Repeat.java | 2 +-
.../setvariables/ActionSetVariablesTest.java | 22 +-
.../actions/snowflake/WarehouseManager.java | 2 +-
.../actions/waitforsql/ActionWaitForSql.java | 2 +-
.../workflow/actions/workflow/ActionWorkflow.java | 2 +-
.../action/ModifyActionLogLevelExtensionPoint.java | 2 +-
.../hop/mail/workflow/actions/mail/ActionMail.java | 2 +-
.../workflow/transform/WorkflowLogging.java | 2 +-
.../logging/xp/WorkflowLoggingExtensionPoint.java | 2 +-
.../pipelineexecutor/PipelineExecutor.java | 2 +-
.../pipeline/transforms/systemdata/SystemData.java | 2 +-
.../workflowexecutor/WorkflowExecutor.java | 2 +-
.../hopgui/file/pipeline/HopGuiPipelineGraph.java | 2 +-
.../hopgui/file/workflow/HopGuiWorkflowGraph.java | 6 +-
.../delegates/HopGuiWorkflowGridDelegate.java | 10 +-
ui/src/main/resources/ui/laf.properties | 4 +-
35 files changed, 506 insertions(+), 555 deletions(-)
diff --git a/core/src/main/java/org/apache/hop/core/Result.java
b/core/src/main/java/org/apache/hop/core/Result.java
index 74f0178608..2e8137046d 100644
--- a/core/src/main/java/org/apache/hop/core/Result.java
+++ b/core/src/main/java/org/apache/hop/core/Result.java
@@ -24,6 +24,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.exception.HopFileException;
import org.apache.hop.core.row.IRowMeta;
@@ -54,6 +56,8 @@ import org.w3c.dom.Node;
* <p>After execution of a workflow or pipeline, the Result can be
evaluated.
* </ul>
*/
+@Getter
+@Setter
public class Result implements Cloneable {
/** A constant specifying the tag value for the XML node of the result
object */
@@ -101,7 +105,7 @@ public class Result implements Cloneable {
/** The exit status. */
private int exitStatus;
- /** The rows. */
+ /** The rows resulting from the pipeline or workflow execution */
private List<RowMetaAndData> rows;
/** The result files. */
@@ -195,8 +199,8 @@ public class Result implements Cloneable {
// Clone result rows and files as well...
if (rows != null) {
List<RowMetaAndData> clonedRows = new ArrayList<>();
- for (int i = 0; i < rows.size(); i++) {
- clonedRows.add((rows.get(i)).clone());
+ for (RowMetaAndData row : rows) {
+ clonedRows.add(row.clone());
}
result.setRows(clonedRows);
}
@@ -232,205 +236,6 @@ public class Result implements Cloneable {
+ (stopped ? " (Stopped)" : ", result=" + result);
}
- /**
- * Returns the number of files retrieved during execution of this pipeline
or workflow
- *
- * @return the number of files retrieved
- */
- public long getNrFilesRetrieved() {
- return nrFilesRetrieved;
- }
-
- /**
- * Sets the number of files retrieved to the specified value
- *
- * @param filesRetrieved The number of files retrieved to set.
- */
- public void setNrFilesRetrieved(long filesRetrieved) {
- this.nrFilesRetrieved = filesRetrieved;
- }
-
- /**
- * Returns the entry number
- *
- * @return the entry number
- */
- public long getEntryNr() {
- return entryNr;
- }
-
- /**
- * Sets the entry number to the specified value
- *
- * @param entryNr The entry number to set.
- */
- public void setEntryNr(long entryNr) {
- this.entryNr = entryNr;
- }
-
- /**
- * Returns the exit status value.
- *
- * @return the exit status.
- */
- public int getExitStatus() {
- return exitStatus;
- }
-
- /**
- * Sets the exit status value to the specified value
- *
- * @param exitStatus The exit status to set.
- */
- public void setExitStatus(int exitStatus) {
- this.exitStatus = exitStatus;
- }
-
- /**
- * Returns the number of errors that occurred during this pipeline or
workflow
- *
- * @return the number of errors
- */
- public long getNrErrors() {
- return nrErrors;
- }
-
- /**
- * Sets the number of errors that occurred during execution of this pipeline
or workflow
- *
- * @param nrErrors The number of errors to set
- */
- public void setNrErrors(long nrErrors) {
- this.nrErrors = nrErrors;
- }
-
- /**
- * Returns the number of lines input during execution of this pipeline or
workflow
- *
- * @return the number of lines input
- */
- public long getNrLinesInput() {
- return nrLinesInput;
- }
-
- /**
- * Sets the number of lines input during execution of this pipeline or
workflow
- *
- * @param nrLinesInput The number of lines input to set.
- */
- public void setNrLinesInput(long nrLinesInput) {
- this.nrLinesInput = nrLinesInput;
- }
-
- /**
- * Returns the number of lines output during execution of this pipeline or
workflow
- *
- * @return the number of lines output
- */
- public long getNrLinesOutput() {
- return nrLinesOutput;
- }
-
- /**
- * Sets the number of lines output during execution of this pipeline or
workflow
- *
- * @param nrLinesOutput The number of lines output to set
- */
- public void setNrLinesOutput(long nrLinesOutput) {
- this.nrLinesOutput = nrLinesOutput;
- }
-
- /**
- * Returns the number of lines read during execution of this pipeline or
workflow
- *
- * @return the number of lines read
- */
- public long getNrLinesRead() {
- return nrLinesRead;
- }
-
- /**
- * Sets the number of lines read during execution of this pipeline or
workflow
- *
- * @param nrLinesRead The number of lines read to set.
- */
- public void setNrLinesRead(long nrLinesRead) {
- this.nrLinesRead = nrLinesRead;
- }
-
- /**
- * Returns the number of lines updated during execution of this pipeline or
workflow
- *
- * @return the number of lines updated
- */
- public long getNrLinesUpdated() {
- return nrLinesUpdated;
- }
-
- /**
- * Sets the number of lines updated during execution of this pipeline or
workflow
- *
- * @param nrLinesUpdated The number of lines updated to set.
- */
- public void setNrLinesUpdated(long nrLinesUpdated) {
- this.nrLinesUpdated = nrLinesUpdated;
- }
-
- /**
- * Returns the number of lines written during execution of this pipeline or
workflow
- *
- * @return the number of lines written
- */
- public long getNrLinesWritten() {
- return nrLinesWritten;
- }
-
- /**
- * Sets the number of lines written during execution of this pipeline or
workflow
- *
- * @param nrLinesWritten The number of lines written to set.
- */
- public void setNrLinesWritten(long nrLinesWritten) {
- this.nrLinesWritten = nrLinesWritten;
- }
-
- /**
- * Returns the number of lines deleted during execution of this pipeline or
workflow
- *
- * @return the number of lines deleted
- */
- public long getNrLinesDeleted() {
- return nrLinesDeleted;
- }
-
- /**
- * Sets the number of lines deleted during execution of this pipeline or
workflow
- *
- * @param nrLinesDeleted The number of lines deleted to set.
- */
- public void setNrLinesDeleted(long nrLinesDeleted) {
- this.nrLinesDeleted = nrLinesDeleted;
- }
-
- /**
- * Returns the boolean result of this pipeline or workflow
- *
- * @return true if the pipeline or workflow was successful, false otherwise
- */
- public boolean getResult() {
- return result;
- }
-
- /**
- * Sets the result of the pipeline or workflow. A value of true should
indicate a successful
- * execution, a value of false should indicate an error condition.
- *
- * @param result The boolean result to set.
- */
- public void setResult(boolean result) {
- this.result = result;
- }
-
/**
* Returns the resulting rowset from the workflow or pipeline. For example,
Result rows are used
* in workflows where entries wish to receive the results of previous
executions of workflows or
@@ -440,7 +245,7 @@ public class Result implements Cloneable {
* @return a List of rows associated with the result of execution of a
workflow or pipeline
*/
public List<RowMetaAndData> getRows() {
- return rows;
+ return new ArrayList<>(rows);
}
/**
@@ -449,25 +254,22 @@ public class Result implements Cloneable {
* @param rows The List of rows to set.
*/
public void setRows(List<RowMetaAndData> rows) {
- this.rows = rows;
- }
-
- /**
- * Returns whether the pipeline or workflow was stopped before completion
- *
- * @return true if stopped, false otherwise
- */
- public boolean isStopped() {
- return stopped;
+ if (rows == null) {
+ this.rows = new ArrayList<>();
+ } else {
+ this.rows = new ArrayList<>(rows);
+ }
}
/**
- * Sets whether the pipeline or workflow was stopped before completion
+ * Adds a single row to the result. Uses the row's hashCode as key to
automatically deduplicate.
*
- * @param stopped true if the pipeline or workflow was stopped, false
otherwise
+ * @param row The row to add
*/
- public void setStopped(boolean stopped) {
- this.stopped = stopped;
+ public void addRow(RowMetaAndData row) {
+ if (row != null) {
+ this.rows.add(row);
+ }
}
/** Clears the numbers in this result, setting them all to zero. Also
deletes the logging text */
@@ -502,7 +304,10 @@ public class Result implements Cloneable {
resultFiles.putAll(res.getResultFiles());
logChannelId = res.getLogChannelId();
logText = res.getLogText();
- rows.addAll(res.getRows());
+ // Copy rows as well (serial execution case)
+ if (res.rows != null && !res.rows.isEmpty()) {
+ rows.addAll(res.rows);
+ }
}
/**
@@ -533,9 +338,13 @@ public class Result implements Cloneable {
if (firstRow) {
firstRow = false;
rowMeta = row.getRowMeta();
- xml.append(rowMeta.getMetaXml());
+ if (rowMeta != null) {
+ xml.append(rowMeta.getMetaXml());
+ }
+ }
+ if (rowMeta != null) {
+ xml.append(rowMeta.getDataXml(row.getData()));
}
- xml.append(rowMeta.getDataXml(row.getData()));
}
xml.append(XmlHandler.closeTag(XML_ROWS_TAG));
@@ -643,21 +452,11 @@ public class Result implements Cloneable {
RowMeta rowMeta = new RowMeta(XmlHandler.getSubNode(resultRowsNode,
RowMeta.XML_META_TAG));
for (Node resultNode : resultNodes) {
Object[] rowData = rowMeta.getRow(resultNode);
- rows.add(new RowMetaAndData(rowMeta, rowData));
+ addRow(new RowMetaAndData(rowMeta, rowData));
}
}
}
- /**
- * Returns the result files as a Map with the filename as key and the
ResultFile object as value
- *
- * @return a Map with String as key and ResultFile as value.
- * @see ResultFile
- */
- public Map<String, ResultFile> getResultFiles() {
- return resultFiles;
- }
-
/**
* Returns the result files as a List of type ResultFile
*
@@ -669,53 +468,6 @@ public class Result implements Cloneable {
return new ArrayList<>(resultFiles.values());
}
- /**
- * Sets the result files for this Result to the specified Map of ResultFile
objects
- *
- * @param usedFiles The Map of result files to set. This is a Map with the
filename as key and
- * ResultFile object as value
- * @see ResultFile
- */
- public void setResultFiles(Map<String, ResultFile> usedFiles) {
- this.resultFiles = usedFiles;
- }
-
- /**
- * Returns the number of lines rejected during execution of this pipeline or
workflow
- *
- * @return the number of lines rejected
- */
- public long getNrLinesRejected() {
- return nrLinesRejected;
- }
-
- /**
- * Sets the number of lines rejected during execution of this pipeline or
workflow
- *
- * @param nrLinesRejected the number of lines rejected to set
- */
- public void setNrLinesRejected(long nrLinesRejected) {
- this.nrLinesRejected = nrLinesRejected;
- }
-
- /**
- * Returns the log channel id of the object that was executed (pipeline,
workflow, action, etc)
- *
- * @return the log channel id
- */
- public String getLogChannelId() {
- return logChannelId;
- }
-
- /**
- * Sets the log channel id of the object that was executed (pipeline,
workflow, action, etc)
- *
- * @param logChannelId the logChannelId to set
- */
- public void setLogChannelId(String logChannelId) {
- this.logChannelId = logChannelId;
- }
-
/**
* Increases the number of lines read by the specified value
*
@@ -788,76 +540,23 @@ public class Result implements Cloneable {
nrErrors += incr;
}
+ @Deprecated(since = "2.16")
/**
- * Returns all the text from any logging performed by the pipeline or
workflow
- *
- * @return the logging text as a string
- */
- public String getLogText() {
- return logText;
- }
-
- /**
- * Sets the logging text to the specified String
- *
- * @param logText the logText to set
- */
- public void setLogText(String logText) {
- this.logText = logText;
- }
-
- /**
- * Returns the elapsed time of the ETL execution in milliseconds
+ * Returns whether the pipeline or workflow was successful.
*
- * @return elapsed time of the ETL execution in milliseconds
+ * @deprecated Use {@link #isResult()} instead. This method remains for
backward compatibility and
+ * will be removed in a future release.
*/
- public long getElapsedTimeMillis() {
- return elapsedTimeMillis;
- }
-
- /**
- * Sets the elapsed time of the ETL execution in milliseconds
- *
- * @param elapsedTimeMillis elapsed time of the ETL execution in milliseconds
- */
- public void setElapsedTimeMillis(long elapsedTimeMillis) {
- this.elapsedTimeMillis = elapsedTimeMillis;
- }
-
- /**
- * Returns the unique identifier of an ETL execution, should one ever care
to declare one such
- *
- * @return unique identifier of an ETL execution, should one ever care to
declare one such
- */
- public String getExecutionId() {
- return executionId;
- }
-
- /**
- * Sets a unique identifier of an ETL execution, should one ever care to
declare one such
- *
- * @param executionId unique identifier of an ETL execution, should one ever
care to declare one
- * such
- */
- public void setExecutionId(String executionId) {
- this.executionId = executionId;
- }
-
- /**
- * Gets containerId
- *
- * @return value of containerId
- */
- public String getContainerId() {
- return containerId;
+ public boolean getResult() {
+ return result;
}
/**
- * Sets containerId
+ * Returns whether the pipeline or workflow execution was successful.
*
- * @param containerId value of containerId
+ * @return true if the execution was successful, false otherwise
*/
- public void setContainerId(String containerId) {
- this.containerId = containerId;
+ public boolean isResult() {
+ return result;
}
}
diff --git a/engine/src/main/java/org/apache/hop/core/gui/WorkflowTracker.java
b/engine/src/main/java/org/apache/hop/core/gui/WorkflowTracker.java
index 88b6062ba2..e1ee62de97 100644
--- a/engine/src/main/java/org/apache/hop/core/gui/WorkflowTracker.java
+++ b/engine/src/main/java/org/apache/hop/core/gui/WorkflowTracker.java
@@ -18,10 +18,15 @@
package org.apache.hop.core.gui;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
+import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.core.Const;
import org.apache.hop.core.util.EnvUtil;
import org.apache.hop.workflow.ActionResult;
@@ -29,6 +34,8 @@ import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.action.ActionMeta;
/** Responsible for tracking the execution of a workflow as a hierarchy. */
+@Getter
+@Setter
public class WorkflowTracker<T extends WorkflowMeta> {
/**
* The trackers for each individual action. Since we invoke
LinkedList.removeFirst() there is no
@@ -36,6 +43,12 @@ public class WorkflowTracker<T extends WorkflowMeta> {
*/
private LinkedList<WorkflowTracker> workflowTrackers;
+ /**
+ * Set to track unique identifiers of workflow trackers to prevent
duplicates when actions run in
+ * parallel
+ */
+ private Set<String> trackerIdentifiers;
+
/** If the workflowTrackers list is empty, then this is the result */
private ActionResult result;
@@ -70,6 +83,7 @@ public class WorkflowTracker<T extends WorkflowMeta> {
}
this.workflowTrackers = new LinkedList<>();
+ this.trackerIdentifiers = new HashSet<>();
this.maxChildren = maxChildren;
this.lock = new ReentrantReadWriteLock();
}
@@ -100,10 +114,21 @@ public class WorkflowTracker<T extends WorkflowMeta> {
public void addWorkflowTracker(WorkflowTracker workflowTracker) {
lock.writeLock().lock();
try {
- workflowTrackers.add(workflowTracker);
- while (workflowTrackers.size() > maxChildren) {
- // Use remove instead of subList
- workflowTrackers.removeFirst();
+ String identifier = workflowTracker.getUniqueIdentifier();
+
+ // Only add if this tracker is unique (not already present)
+ if (identifier != null && !trackerIdentifiers.contains(identifier)) {
+ workflowTrackers.add(workflowTracker);
+ trackerIdentifiers.add(identifier);
+
+ // Remove oldest entries if we exceed maxChildren
+ while (workflowTrackers.size() > maxChildren) {
+ WorkflowTracker removed = workflowTrackers.removeFirst();
+ String removedId = removed.getUniqueIdentifier();
+ if (removedId != null) {
+ trackerIdentifiers.remove(removedId);
+ }
+ }
}
} finally {
lock.writeLock().unlock();
@@ -150,7 +175,16 @@ public class WorkflowTracker<T extends WorkflowMeta> {
lock.writeLock().lock();
try {
this.workflowTrackers.clear();
+ this.trackerIdentifiers.clear();
this.workflowTrackers.addAll(workflowTrackers);
+
+ // Rebuild the identifier set
+ for (WorkflowTracker tracker : workflowTrackers) {
+ String identifier = tracker.getUniqueIdentifier();
+ if (identifier != null) {
+ this.trackerIdentifiers.add(identifier);
+ }
+ }
} finally {
lock.writeLock().unlock();
}
@@ -174,6 +208,7 @@ public class WorkflowTracker<T extends WorkflowMeta> {
lock.writeLock().lock();
try {
workflowTrackers.clear();
+ trackerIdentifiers.clear();
result = null;
} finally {
lock.writeLock().unlock();
@@ -207,20 +242,6 @@ public class WorkflowTracker<T extends WorkflowMeta> {
return null;
}
- /**
- * @return Returns the parentWorkflowTracker.
- */
- public WorkflowTracker getParentWorkflowTracker() {
- return parentWorkflowTracker;
- }
-
- /**
- * @param parentWorkflowTracker The parentWorkflowTracker to set.
- */
- public void setParentWorkflowTracker(WorkflowTracker parentWorkflowTracker) {
- this.parentWorkflowTracker = parentWorkflowTracker;
- }
-
public int getTotalNumberOfItems() {
lock.readLock().lock();
try {
@@ -237,44 +258,62 @@ public class WorkflowTracker<T extends WorkflowMeta> {
}
/**
- * @return the workflowFilename
+ * Gets a unique identifier for this workflow tracker. Uses the log channel
ID to uniquely
+ * identify each execution event. When actions run in parallel, the SAME
logChannelId means the
+ * SAME execution event, which should be deduplicated. Different
logChannelIds means different
+ * events.
+ *
+ * <p>Falls back to a combination of workflow name, action name, comment,
and timestamp if
+ * logChannelId is not available.
+ *
+ * @return A unique identifier string, or null if insufficient information
*/
- public String getWorfkflowFilename() {
- return workflowFilename;
- }
+ public String getUniqueIdentifier() {
+ if (result != null) {
+ // Fallback: construct identifier from available fields
+ StringBuilder identifier = new StringBuilder();
+ if (workflowName != null) {
+ identifier.append(workflowName).append("::");
+ }
+ if (workflowFilename != null) {
+ identifier.append(workflowFilename);
+ }
- /**
- * @param workflowFilename the workflowFilename to set
- */
- public void setWorkflowFilename(String workflowFilename) {
- this.workflowFilename = workflowFilename;
+ return identifier.length() > 0 ? identifier.toString() : null;
+ }
+ return null;
}
- /**
- * @return the workflowName
- */
- public String getWorkflowName() {
- return workflowName;
- }
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ WorkflowTracker<?> that = (WorkflowTracker<?>) o;
- /**
- * @param workflowName the workflowName to set
- */
- public void setWorkflowName(String workflowName) {
- this.workflowName = workflowName;
- }
+ String thisId = this.getUniqueIdentifier();
+ String thatId = that.getUniqueIdentifier();
- /**
- * @return the maxChildren
- */
- public int getMaxChildren() {
- return maxChildren;
+ // If both have identifiers, compare them
+ if (thisId != null && thatId != null) {
+ return thisId.equals(thatId);
+ }
+
+ // Fallback to comparing workflow name and filename
+ return Objects.equals(workflowName, that.workflowName)
+ && Objects.equals(workflowFilename, that.workflowFilename)
+ && Objects.equals(result, that.result);
}
- /**
- * @param maxChildren the maxChildren to set
- */
- public void setMaxChildren(int maxChildren) {
- this.maxChildren = maxChildren;
+ @Override
+ public int hashCode() {
+ String identifier = getUniqueIdentifier();
+ if (identifier != null) {
+ return identifier.hashCode();
+ }
+ return Objects.hash(workflowName, workflowFilename, result);
}
}
diff --git
a/engine/src/main/java/org/apache/hop/execution/ExecutionDataBuilder.java
b/engine/src/main/java/org/apache/hop/execution/ExecutionDataBuilder.java
index 189116d5b7..a00787fcdd 100644
--- a/engine/src/main/java/org/apache/hop/execution/ExecutionDataBuilder.java
+++ b/engine/src/main/java/org/apache/hop/execution/ExecutionDataBuilder.java
@@ -200,7 +200,7 @@ public final class ExecutionDataBuilder {
{
IRowMeta resultRowMeta = new
RowMetaBuilder().addString("key").addString(CONST_VALUE).build();
RowBuffer resultBuffer = new RowBuffer(resultRowMeta);
- resultBuffer.addRow(RESULT_KEY_RESULT, result.getResult() ? "true" :
"false");
+ resultBuffer.addRow(RESULT_KEY_RESULT, result.isResult() ? "true" :
"false");
resultBuffer.addRow(RESULT_KEY_ERRORS,
Long.toString(result.getNrErrors()));
resultBuffer.addRow(RESULT_KEY_STOPPED, result.isStopped() ? "true" :
"false");
diff --git
a/engine/src/main/java/org/apache/hop/execution/ExecutionStateBuilder.java
b/engine/src/main/java/org/apache/hop/execution/ExecutionStateBuilder.java
index efd7b8c47a..b11586c0cc 100644
--- a/engine/src/main/java/org/apache/hop/execution/ExecutionStateBuilder.java
+++ b/engine/src/main/java/org/apache/hop/execution/ExecutionStateBuilder.java
@@ -167,7 +167,7 @@ public final class ExecutionStateBuilder {
.withName(workflow.getWorkflowMeta().getName())
.withLoggingText(getLoggingText(workflow.getLogChannelId(),
lastLogLineNr))
.withLastLogLineNr(lastNrInLogStore)
- .withFailed(result != null && !result.getResult())
+ .withFailed(result != null && !result.isResult())
.withStatusDescription(workflow.getStatusDescription())
.withChildIds(
LoggingRegistry.getInstance().getChildrenMap().get(workflow.getLogChannelId()))
diff --git
a/engine/src/main/java/org/apache/hop/pipeline/engines/local/LocalPipelineEngine.java
b/engine/src/main/java/org/apache/hop/pipeline/engines/local/LocalPipelineEngine.java
index d4d5c3c47c..35d9170d65 100644
---
a/engine/src/main/java/org/apache/hop/pipeline/engines/local/LocalPipelineEngine.java
+++
b/engine/src/main/java/org/apache/hop/pipeline/engines/local/LocalPipelineEngine.java
@@ -162,7 +162,7 @@ public class LocalPipelineEngine extends Pipeline
implements IPipelineEngine<Pip
// All fine? Commit!
//
try {
- if (result.getResult() && !result.isStopped() &&
result.getNrErrors() == 0) {
+ if (result.isResult() && !result.isStopped() &&
result.getNrErrors() == 0) {
try {
database.commit(true);
pipeline
diff --git a/engine/src/main/java/org/apache/hop/run/HopRunBase.java
b/engine/src/main/java/org/apache/hop/run/HopRunBase.java
index 6e0c8bf57c..263e2e6251 100644
--- a/engine/src/main/java/org/apache/hop/run/HopRunBase.java
+++ b/engine/src/main/java/org/apache/hop/run/HopRunBase.java
@@ -396,7 +396,7 @@ public abstract class HopRunBase implements Runnable,
IHasHopMetadataProvider {
log.logMinimal("Starting workflow: " + workflowMeta.getFilename());
workflow.startExecution();
- setFinishedWithoutError(workflow.getResult().getResult());
+ setFinishedWithoutError(workflow.getResult().isResult());
} catch (Exception e) {
throw new ExecutionException(cmd, "Error running workflow locally", e);
}
diff --git a/engine/src/main/java/org/apache/hop/workflow/ActionResult.java
b/engine/src/main/java/org/apache/hop/workflow/ActionResult.java
index 4d99e97477..01f918dc35 100644
--- a/engine/src/main/java/org/apache/hop/workflow/ActionResult.java
+++ b/engine/src/main/java/org/apache/hop/workflow/ActionResult.java
@@ -19,6 +19,8 @@ package org.apache.hop.workflow;
import java.util.Comparator;
import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.core.Result;
/**
@@ -31,6 +33,8 @@ import org.apache.hop.core.Result;
*
* <p>
*/
+@Getter
+@Setter
public class ActionResult implements Cloneable, Comparator<ActionResult>,
Comparable<ActionResult> {
private Result result;
private String actionName;
@@ -87,90 +91,6 @@ public class ActionResult implements Cloneable,
Comparator<ActionResult>, Compar
}
}
- /**
- * @param result The result to set.
- */
- public void setResult(Result result) {
- this.result = result;
- }
-
- /**
- * @return Returns the result.
- */
- public Result getResult() {
- return result;
- }
-
- /**
- * @return Returns the comment.
- */
- public String getComment() {
- return comment;
- }
-
- /**
- * @param comment The comment to set.
- */
- public void setComment(String comment) {
- this.comment = comment;
- }
-
- /**
- * @return Returns the reason.
- */
- public String getReason() {
- return reason;
- }
-
- /**
- * @param reason The reason to set.
- */
- public void setReason(String reason) {
- this.reason = reason;
- }
-
- /**
- * @return Returns the logDate.
- */
- public Date getLogDate() {
- return logDate;
- }
-
- /**
- * @param logDate The logDate to set.
- */
- public void setLogDate(Date logDate) {
- this.logDate = logDate;
- }
-
- /**
- * @return the actionName
- */
- public String getActionName() {
- return actionName;
- }
-
- /**
- * @param actionName the actionName to set
- */
- public void setActionName(String actionName) {
- this.actionName = actionName;
- }
-
- /**
- * @return the actionFilename
- */
- public String getActionFilename() {
- return actionFilename;
- }
-
- /**
- * @param actionFilename the actionFilename to set
- */
- public void setActionFilename(String actionFilename) {
- this.actionFilename = actionFilename;
- }
-
@Override
public int compare(ActionResult one, ActionResult two) {
if (one == null && two != null) {
@@ -200,21 +120,28 @@ public class ActionResult implements Cloneable,
Comparator<ActionResult>, Compar
return compare(this, two);
}
- public String getLogChannelId() {
- return logChannelId;
- }
-
- /**
- * @return the checkpoint
- */
- public boolean isCheckpoint() {
- return checkpoint;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ActionResult that = (ActionResult) o;
+ return checkpoint == that.checkpoint
+ && java.util.Objects.equals(result, that.result)
+ && java.util.Objects.equals(actionName, that.actionName)
+ && java.util.Objects.equals(comment, that.comment)
+ && java.util.Objects.equals(reason, that.reason)
+ && java.util.Objects.equals(logDate, that.logDate)
+ && java.util.Objects.equals(actionFilename, that.actionFilename)
+ && java.util.Objects.equals(logChannelId, that.logChannelId);
}
- /**
- * @param checkpoint the checkpoint to set
- */
- public void setCheckpoint(boolean checkpoint) {
- this.checkpoint = checkpoint;
+ @Override
+ public int hashCode() {
+ return java.util.Objects.hash(
+ result, actionName, comment, reason, logDate, actionFilename,
logChannelId, checkpoint);
}
}
diff --git a/engine/src/main/java/org/apache/hop/workflow/Workflow.java
b/engine/src/main/java/org/apache/hop/workflow/Workflow.java
index 14c7c1372f..3564d629a0 100644
--- a/engine/src/main/java/org/apache/hop/workflow/Workflow.java
+++ b/engine/src/main/java/org/apache/hop/workflow/Workflow.java
@@ -687,7 +687,7 @@ public abstract class Workflow extends Variables
PKG,
"Workflow.Log.FinishedAction",
previous.getName(),
- previousResult.getResult() + ""));
+ previousResult.isResult() + ""));
}
}
@@ -843,7 +843,7 @@ public abstract class Workflow extends Variables
if (hopMeta.isUnconditional()) {
nextComment = BaseMessages.getString(PKG,
"Workflow.Comment.FollowedUnconditional");
} else {
- if (newResult.getResult()) {
+ if (newResult.isResult()) {
nextComment = BaseMessages.getString(PKG,
"Workflow.Comment.FollowedSuccess");
} else {
nextComment = BaseMessages.getString(PKG,
"Workflow.Comment.FollowedFailure");
@@ -856,7 +856,7 @@ public abstract class Workflow extends Variables
// green or red, execute the next action...
//
if (hopMeta.isUnconditional()
- || (actionMeta.isEvaluation() && (hopMeta.isEvaluation() ==
newResult.getResult()))) {
+ || (actionMeta.isEvaluation() && (hopMeta.isEvaluation() ==
newResult.isResult()))) {
// If the next action is a join, only execute once
if (nextAction.isJoin()) {
@@ -882,8 +882,15 @@ public abstract class Workflow extends Variables
Runnable runnable =
() -> {
try {
+ // Pass a previous result without rows to the parallel
branch so that
+ // branch-local result rows start from a clean slate but
still inherit
+ // metrics/files/etc.
+ Result prevWithoutRows = newResult.lightClone();
+ prevWithoutRows.setRows(null); // ensure rows are empty
+
Result threadResult =
- executeFromStart(nr + 1, newResult, nextAction,
actionMeta, nextComment);
+ executeFromStart(
+ nr + 1, prevWithoutRows, nextAction, actionMeta,
nextComment);
threadResults.add(threadResult);
} catch (Throwable e) {
log.logError(Const.getStackTracker(e));
@@ -967,9 +974,9 @@ public abstract class Workflow extends Variables
throw threadExceptions.poll();
}
- // In parallel execution, we aggregate all the results, simply add them to
- // the previous result...
- //
+ // In parallel execution, aggregate full results from branches. Since we
started each
+ // branch with no previous rows, any rows present here were produced by
the branch and
+ // should be included in the final result.
for (Result threadResult : threadResults) {
res.add(threadResult);
}
@@ -985,7 +992,7 @@ public abstract class Workflow extends Variables
if (log.isBasic()) {
log.logBasic(
BaseMessages.getString(
- PKG, "Workflow.Log.FinishedAction", actionMeta.getName(),
res.getResult() + ""));
+ PKG, "Workflow.Log.FinishedAction", actionMeta.getName(),
res.isResult() + ""));
}
}
diff --git a/engine/src/main/java/org/apache/hop/workflow/WorkflowPainter.java
b/engine/src/main/java/org/apache/hop/workflow/WorkflowPainter.java
index 71e9b76c08..5ee7ce74bf 100644
--- a/engine/src/main/java/org/apache/hop/workflow/WorkflowPainter.java
+++ b/engine/src/main/java/org/apache/hop/workflow/WorkflowPainter.java
@@ -252,7 +252,7 @@ public class WorkflowPainter extends
BasePainter<WorkflowHopMeta, ActionMeta> {
boolean actionError = false;
ActionResult actionResult = findActionResult(actionMeta);
if (actionResult != null && !actionResult.isCheckpoint()) {
- actionError = !actionResult.getResult().getResult();
+ actionError = !actionResult.getResult().isResult();
}
if (actionError || actionMeta.isMissing()) {
@@ -372,7 +372,7 @@ public class WorkflowPainter extends
BasePainter<WorkflowHopMeta, ActionMeta> {
actionMeta,
actionResult));
} else {
- if (result.getResult()) {
+ if (result.isResult()) {
gc.drawImage(EImage.SUCCESS, iconX, iconY, magnification);
areaOwners.add(
new AreaOwner(
diff --git
a/engine/src/main/java/org/apache/hop/workflow/engines/local/LocalWorkflowEngine.java
b/engine/src/main/java/org/apache/hop/workflow/engines/local/LocalWorkflowEngine.java
index 7a13483ba2..0fddf83ef6 100644
---
a/engine/src/main/java/org/apache/hop/workflow/engines/local/LocalWorkflowEngine.java
+++
b/engine/src/main/java/org/apache/hop/workflow/engines/local/LocalWorkflowEngine.java
@@ -137,7 +137,7 @@ public class LocalWorkflowEngine extends Workflow
implements IWorkflowEngine<Wor
// All fine? Commit!
//
try {
- if (result.getResult() && !result.isStopped() &&
result.getNrErrors() == 0) {
+ if (result.isResult() && !result.isStopped() &&
result.getNrErrors() == 0) {
try {
database.commit(true);
workflow
diff --git
a/engine/src/main/java/org/apache/hop/www/GetWorkflowStatusServlet.java
b/engine/src/main/java/org/apache/hop/www/GetWorkflowStatusServlet.java
index 400f031838..d16d5588f7 100644
--- a/engine/src/main/java/org/apache/hop/www/GetWorkflowStatusServlet.java
+++ b/engine/src/main/java/org/apache/hop/www/GetWorkflowStatusServlet.java
@@ -149,7 +149,7 @@ public class GetWorkflowStatusServlet extends
BaseHttpServlet implements IHopSer
for (ActionResult actionResult : workflow.getActionResults()) {
ActionStatus actionState = new ActionStatus();
actionState.setName(actionResult.getActionName());
- if (actionResult.getResult().getResult()) {
+ if (actionResult.getResult().isResult()) {
actionState.setStatus(Status.FINISHED);
} else {
actionState.setStatus(Status.STOPPED);
diff --git a/engine/src/main/java/org/apache/hop/www/HopServer.java
b/engine/src/main/java/org/apache/hop/www/HopServer.java
index e248742be7..7fb4961722 100644
--- a/engine/src/main/java/org/apache/hop/www/HopServer.java
+++ b/engine/src/main/java/org/apache/hop/www/HopServer.java
@@ -468,7 +468,7 @@ public class HopServer implements Runnable,
IHasHopMetadataProvider, IHopCommand
System.out.println(" Status: " +
workflowStatus.getStatusDescription());
System.out.println(" Log date: " +
formatDate(workflowStatus.getLogDate()));
if (result != null) {
- System.out.println(" Result: " + result.getResult());
+ System.out.println(" Result: " + result.isResult());
System.out.println(" Errors: " + result.getNrErrors());
}
if (printDetails) {
diff --git
a/engine/src/test/java/org/apache/hop/concurrency/WorkflowTrackerUniquenessTest.java
b/engine/src/test/java/org/apache/hop/concurrency/WorkflowTrackerUniquenessTest.java
new file mode 100644
index 0000000000..c37e9a04cf
--- /dev/null
+++
b/engine/src/test/java/org/apache/hop/concurrency/WorkflowTrackerUniquenessTest.java
@@ -0,0 +1,262 @@
+/*
+ * 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.hop.concurrency;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import org.apache.hop.core.gui.WorkflowTracker;
+import org.apache.hop.workflow.ActionResult;
+import org.apache.hop.workflow.WorkflowMeta;
+import org.junit.Test;
+
+/**
+ * Test to verify that WorkflowTracker enforces uniqueness per workflow
instance when multiple
+ * threads attempt to add duplicate trackers concurrently (as happens when
actions run in parallel).
+ * Each workflow (identified by name + filename) should only have one tracker.
+ */
+public class WorkflowTrackerUniquenessTest {
+
+ private static WorkflowMeta mockWorkflowMeta(String name) {
+ WorkflowMeta meta = mock(WorkflowMeta.class);
+ when(meta.getName()).thenReturn(name);
+ return meta;
+ }
+
+ /**
+ * Test that when multiple threads try to add WorkflowTrackers for the same
workflow, only one is
+ * actually added (uniqueness is enforced at workflow level).
+ */
+ @Test
+ public void testUniquenessWithSameWorkflow() throws Exception {
+ WorkflowTracker tracker = new
WorkflowTracker(mockWorkflowMeta("parent-workflow"));
+
+ final int NUM_THREADS = 10;
+
+ ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
+ CountDownLatch startLatch = new CountDownLatch(1);
+ CountDownLatch doneLatch = new CountDownLatch(NUM_THREADS);
+
+ // All threads will try to add a tracker for the same child workflow
+ for (int i = 0; i < NUM_THREADS; i++) {
+ final int threadNum = i;
+ executor.submit(
+ () -> {
+ try {
+ startLatch.await(); // Wait for all threads to be ready
+
+ ActionResult result =
+ new ActionResult(
+ null,
+ "log-channel-" + threadNum, // Different log channels
+ "Action started",
+ null,
+ "action-" + threadNum, // Different actions
+ null);
+
+ // All threads create trackers for the SAME workflow (same name)
+ WorkflowTracker childTracker =
+ new WorkflowTracker(mockWorkflowMeta("child-workflow"),
result);
+ tracker.addWorkflowTracker(childTracker);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ } finally {
+ doneLatch.countDown();
+ }
+ });
+ }
+
+ startLatch.countDown(); // Start all threads
+ assertTrue("Threads did not complete in time", doneLatch.await(5,
TimeUnit.SECONDS));
+ executor.shutdown();
+
+ // Verify only ONE tracker was added for the child workflow (not 10)
+ assertEquals("Expected only 1 unique tracker per workflow", 1,
tracker.nrWorkflowTrackers());
+ }
+
+ /**
+ * Test that when multiple threads add WorkflowTrackers for DIFFERENT
workflows, all are added
+ * (uniqueness is per workflow).
+ */
+ @Test
+ public void testUniquenessWithDifferentWorkflows() throws Exception {
+ WorkflowTracker tracker = new
WorkflowTracker(mockWorkflowMeta("parent-workflow"));
+
+ final int NUM_THREADS = 10;
+
+ ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
+ CountDownLatch startLatch = new CountDownLatch(1);
+ CountDownLatch doneLatch = new CountDownLatch(NUM_THREADS);
+
+ // Each thread adds a tracker for a DIFFERENT child workflow
+ for (int i = 0; i < NUM_THREADS; i++) {
+ final int threadNum = i;
+ executor.submit(
+ () -> {
+ try {
+ startLatch.await();
+
+ ActionResult result =
+ new ActionResult(
+ null,
+ "log-channel-" + threadNum,
+ "Action started",
+ null,
+ "test-action-" + threadNum,
+ null);
+
+ // Each thread creates a tracker for a DIFFERENT workflow
+ WorkflowTracker childTracker =
+ new WorkflowTracker(mockWorkflowMeta("child-workflow-" +
threadNum), result);
+ tracker.addWorkflowTracker(childTracker);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ } finally {
+ doneLatch.countDown();
+ }
+ });
+ }
+
+ startLatch.countDown();
+ assertTrue("Threads did not complete in time", doneLatch.await(5,
TimeUnit.SECONDS));
+ executor.shutdown();
+
+ // Verify all 10 unique workflow trackers were added (one per workflow)
+ assertEquals(
+ "Expected all 10 unique workflows to be tracked",
+ NUM_THREADS,
+ tracker.nrWorkflowTrackers());
+
+ // Verify all identifiers are unique
+ Set<String> identifiers = new HashSet<>();
+ for (int i = 0; i < tracker.nrWorkflowTrackers(); i++) {
+ WorkflowTracker child = tracker.getWorkflowTracker(i);
+ String identifier = child.getUniqueIdentifier();
+ assertTrue("Identifier should be unique: " + identifier,
identifiers.add(identifier));
+ }
+ }
+
+ /**
+ * Test that duplicate prevention works with workflow-level identifiers.
Multiple actions for the
+ * same workflow should only create one tracker.
+ */
+ @Test
+ public void testUniquenessPerWorkflow() throws Exception {
+ WorkflowTracker tracker = new
WorkflowTracker(mockWorkflowMeta("parent-workflow"));
+
+ final int NUM_THREADS = 5;
+
+ ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
+ CountDownLatch startLatch = new CountDownLatch(1);
+ CountDownLatch doneLatch = new CountDownLatch(NUM_THREADS);
+
+ // Create multiple trackers for the same workflow but different actions
+ for (int i = 0; i < NUM_THREADS; i++) {
+ final int threadNum = i;
+ executor.submit(
+ () -> {
+ try {
+ startLatch.await();
+
+ ActionResult result = new ActionResult();
+ result.setActionName("action-" + threadNum);
+ result.setComment("Action started");
+
+ // All threads try to add trackers for the SAME child workflow
+ WorkflowTracker childTracker =
+ new WorkflowTracker(mockWorkflowMeta("same-child-workflow"),
result);
+ tracker.addWorkflowTracker(childTracker);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ } finally {
+ doneLatch.countDown();
+ }
+ });
+ }
+
+ startLatch.countDown();
+ assertTrue("Threads did not complete in time", doneLatch.await(10,
TimeUnit.SECONDS));
+ executor.shutdown();
+
+ // Only one tracker should be added for the workflow (not one per action)
+ assertEquals("Expected only 1 tracker for the workflow", 1,
tracker.nrWorkflowTrackers());
+ }
+
+ /**
+ * Test the getUniqueIdentifier method directly. It should use workflow name
and filename only.
+ */
+ @Test
+ public void testGetUniqueIdentifier() {
+ WorkflowMeta meta = mockWorkflowMeta("test-workflow");
+
+ // Test with action result
+ ActionResult result1 = new ActionResult(null, "channel-123", null, null,
"action-1", null);
+
+ WorkflowTracker tracker1 = new WorkflowTracker(meta, result1);
+ String identifier1 = tracker1.getUniqueIdentifier();
+
+ // Should contain workflow name
+ assertTrue("Identifier should contain workflow name",
identifier1.contains("test-workflow"));
+
+ // Test that different actions in same workflow have same identifier
+ ActionResult result2 = new ActionResult(null, "channel-456", "Started",
null, "action-2", null);
+
+ WorkflowTracker tracker2 = new WorkflowTracker(meta, result2);
+ String identifier2 = tracker2.getUniqueIdentifier();
+
+ // Should be the same identifier (workflow-level, not action-level)
+ assertEquals("Same workflow should have same identifier", identifier1,
identifier2);
+ }
+
+ /**
+ * Test equals and hashCode methods. Trackers for the same workflow should
be equal, regardless of
+ * action.
+ */
+ @Test
+ public void testEqualsAndHashCode() {
+ WorkflowMeta meta1 = mockWorkflowMeta("workflow-A");
+ WorkflowMeta meta2 = mockWorkflowMeta("workflow-B");
+
+ // Create two trackers for the same workflow but different actions
+ ActionResult result1 = new ActionResult(null, "channel-1", null, null,
"action-1", null);
+ ActionResult result2 = new ActionResult(null, "channel-2", null, null,
"action-2", null);
+
+ WorkflowTracker tracker1 = new WorkflowTracker(meta1, result1);
+ WorkflowTracker tracker2 = new WorkflowTracker(meta1, result2);
+
+ // Should be equal because they're for the same workflow
+ assertEquals("Trackers for same workflow should be equal", tracker1,
tracker2);
+ assertEquals(
+ "Hash codes should match for equal objects", tracker1.hashCode(),
tracker2.hashCode());
+
+ // Create tracker for different workflow
+ ActionResult result3 = new ActionResult(null, "channel-3", null, null,
"action-1", null);
+ WorkflowTracker tracker3 = new WorkflowTracker(meta2, result3);
+
+ // Should not be equal (different workflow)
+ assertTrue("Trackers for different workflows should not be equal",
!tracker1.equals(tracker3));
+ }
+}
diff --git
a/engine/src/test/java/org/apache/hop/core/gui/WorkflowTrackerTest.java
b/engine/src/test/java/org/apache/hop/core/gui/WorkflowTrackerTest.java
index 9b0be55537..86808d04e7 100644
--- a/engine/src/test/java/org/apache/hop/core/gui/WorkflowTrackerTest.java
+++ b/engine/src/test/java/org/apache/hop/core/gui/WorkflowTrackerTest.java
@@ -88,8 +88,13 @@ public class WorkflowTrackerTest {
@Test
public void findJobTracker_EntryNameFound() {
WorkflowTracker workflowTracker = createTracker();
+ // Create trackers for different workflows (not just different actions)
WorkflowTracker[] children =
- new WorkflowTracker[] {createTracker("0"), createTracker("1"),
createTracker("2")};
+ new WorkflowTracker[] {
+ createTrackerForWorkflow("workflow-0", "0"),
+ createTrackerForWorkflow("workflow-1", "1"),
+ createTrackerForWorkflow("workflow-2", "2")
+ };
for (WorkflowTracker child : children) {
workflowTracker.addWorkflowTracker(child);
}
@@ -114,6 +119,18 @@ public class WorkflowTrackerTest {
return workflowTracker;
}
+ private static WorkflowTracker createTrackerForWorkflow(String workflowName,
String actionName) {
+ WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+ when(workflowMeta.getName()).thenReturn(workflowName);
+ WorkflowTracker workflowTracker = new WorkflowTracker(workflowMeta);
+ if (actionName != null) {
+ ActionResult result = mock(ActionResult.class);
+ when(result.getActionName()).thenReturn(actionName);
+ workflowTracker.setActionResult(result);
+ }
+ return workflowTracker;
+ }
+
private static ActionMeta createActionMeta(String actionName) {
IAction action = mock(IAction.class);
when(action.getName()).thenReturn(actionName);
diff --git
a/plugins/actions/copyfiles/src/test/java/org/apache/hop/workflow/actions/copyfiles/WorkflowActionCopyFilesTest.java
b/plugins/actions/copyfiles/src/test/java/org/apache/hop/workflow/actions/copyfiles/WorkflowActionCopyFilesTest.java
index b7c9c3ae0d..3df55d729a 100644
---
a/plugins/actions/copyfiles/src/test/java/org/apache/hop/workflow/actions/copyfiles/WorkflowActionCopyFilesTest.java
+++
b/plugins/actions/copyfiles/src/test/java/org/apache/hop/workflow/actions/copyfiles/WorkflowActionCopyFilesTest.java
@@ -83,7 +83,7 @@ class WorkflowActionCopyFilesTest {
.processFileFolder(
anyString(), anyString(), anyString(), any(Workflow.class),
any(Result.class));
verify(entry, atLeast(1)).preprocessfilefilder(any(String[].class));
- Assertions.assertFalse(result.getResult());
+ Assertions.assertFalse(result.isResult());
Assertions.assertEquals(1, result.getNrErrors());
}
@@ -101,7 +101,7 @@ class WorkflowActionCopyFilesTest {
verify(entry, times(srcPath.length))
.processFileFolder(
anyString(), anyString(), anyString(), any(Workflow.class),
any(Result.class));
- Assertions.assertFalse(result.getResult());
+ Assertions.assertFalse(result.isResult());
Assertions.assertEquals(3, result.getNrErrors());
}
diff --git
a/plugins/actions/evaluatetablecontent/src/test/java/org/apache/hop/workflow/actions/evaluatetablecontent/WorkflowActionEvalTableContentTest.java
b/plugins/actions/evaluatetablecontent/src/test/java/org/apache/hop/workflow/actions/evaluatetablecontent/WorkflowActionEvalTableContentTest.java
index 69eb538d74..b748ad1d1b 100644
---
a/plugins/actions/evaluatetablecontent/src/test/java/org/apache/hop/workflow/actions/evaluatetablecontent/WorkflowActionEvalTableContentTest.java
+++
b/plugins/actions/evaluatetablecontent/src/test/java/org/apache/hop/workflow/actions/evaluatetablecontent/WorkflowActionEvalTableContentTest.java
@@ -182,7 +182,7 @@ class WorkflowActionEvalTableContentTest {
Result res = action.execute(new Result(), 0);
- assertFalse(res.getResult(), "Eval number of rows should fail");
+ assertFalse(res.isResult(), "Eval number of rows should fail");
assertEquals(
0,
res.getNrErrors(),
@@ -199,7 +199,7 @@ class WorkflowActionEvalTableContentTest {
Result res = action.execute(new Result(), 0);
- assertTrue(res.getResult(), "Eval number of rows should be suceeded");
+ assertTrue(res.isResult(), "Eval number of rows should be suceeded");
assertEquals(0, res.getNrErrors(), "Apparently there should no error");
}
@@ -214,7 +214,7 @@ class WorkflowActionEvalTableContentTest {
Result res = action.execute(new Result(), 0);
- assertFalse(res.getResult(), "Eval number of rows should fail");
+ assertFalse(res.isResult(), "Eval number of rows should fail");
assertEquals(1, res.getNrErrors(), "Apparently there should be an error");
}
}
diff --git
a/plugins/actions/filesexist/src/test/java/org/apache/hop/workflow/actions/filesexist/WorkflowActionFilesExistTest.java
b/plugins/actions/filesexist/src/test/java/org/apache/hop/workflow/actions/filesexist/WorkflowActionFilesExistTest.java
index 6a3b40e831..21f3cdf252 100644
---
a/plugins/actions/filesexist/src/test/java/org/apache/hop/workflow/actions/filesexist/WorkflowActionFilesExistTest.java
+++
b/plugins/actions/filesexist/src/test/java/org/apache/hop/workflow/actions/filesexist/WorkflowActionFilesExistTest.java
@@ -82,7 +82,7 @@ class WorkflowActionFilesExistTest {
Result res = action.execute(new Result(), 0);
- assertFalse(res.getResult(), "Entry should fail");
+ assertFalse(res.isResult(), "Entry should fail");
assertEquals(
0,
res.getNrErrors(),
@@ -95,7 +95,7 @@ class WorkflowActionFilesExistTest {
Result res = action.execute(new Result(), 0);
- assertFalse(res.getResult(), "Action should fail");
+ assertFalse(res.isResult(), "Action should fail");
assertEquals(
1, res.getNrErrors(), "File with wrong name was specified. One error
should be reported");
}
@@ -105,7 +105,7 @@ class WorkflowActionFilesExistTest {
action.setFileItems(List.of(new FileItem(existingFile1), new
FileItem(existingFile2)));
Result res = action.execute(new Result(), 0);
- assertTrue(res.getResult());
+ assertTrue(res.isResult());
}
@Test
@@ -118,6 +118,6 @@ class WorkflowActionFilesExistTest {
new FileItem("nonExistingFile2.ext")));
Result res = action.execute(new Result(), 0);
- assertFalse(res.getResult());
+ assertFalse(res.isResult());
}
}
diff --git
a/plugins/actions/folderisempty/src/test/java/org/apache/hop/workflow/actions/folderisempty/WorkflowActionFolderIsEmptyTest.java
b/plugins/actions/folderisempty/src/test/java/org/apache/hop/workflow/actions/folderisempty/WorkflowActionFolderIsEmptyTest.java
index e7a318c3bc..1fb6d2c2e7 100644
---
a/plugins/actions/folderisempty/src/test/java/org/apache/hop/workflow/actions/folderisempty/WorkflowActionFolderIsEmptyTest.java
+++
b/plugins/actions/folderisempty/src/test/java/org/apache/hop/workflow/actions/folderisempty/WorkflowActionFolderIsEmptyTest.java
@@ -77,7 +77,7 @@ class WorkflowActionFolderIsEmptyTest {
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "For empty folder result should be true");
+ assertTrue(result.isResult(), "For empty folder result should be true");
assertEquals(0, result.getNrErrors(), "There should be no errors");
}
@@ -87,7 +87,7 @@ class WorkflowActionFolderIsEmptyTest {
Result result = action.execute(new Result(), 0);
- assertFalse(result.getResult(), "For non-empty folder result should be
false");
+ assertFalse(result.isResult(), "For non-empty folder result should be
false");
assertEquals(0, result.getNrErrors(), "There should be still no errors");
}
}
diff --git
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesLocalTest.java
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesLocalTest.java
index b424258823..bbe5b6ae10 100644
---
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesLocalTest.java
+++
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesLocalTest.java
@@ -67,7 +67,7 @@ class WorkflowActionMoveFilesLocalTest {
action.setDestinationIsAFile(true);
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Move operation should succeed");
+ assertTrue(result.isResult(), "Move operation should succeed");
assertFalse(Files.exists(sourceFile), "Source file should not exist");
assertTrue(Files.exists(destFile), "Destination file should exist");
assertEquals(
@@ -88,7 +88,7 @@ class WorkflowActionMoveFilesLocalTest {
action.setDestinationIsAFile(false);
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Move operation should succeed");
+ assertTrue(result.isResult(), "Move operation should succeed");
assertTrue(
Files.exists(destinationFolder.toPath().resolve("test1.txt")),
"test1.txt should be moved");
assertTrue(
@@ -108,7 +108,7 @@ class WorkflowActionMoveFilesLocalTest {
action.setDestinationIsAFile(true);
Result result = action.execute(new Result(), 0);
- assertFalse(result.getResult(), "Move should not succeed when destination
exists");
+ assertFalse(result.isResult(), "Move should not succeed when destination
exists");
assertTrue(Files.exists(sourceFile), "Source file should still exist");
assertEquals(
originalContent,
@@ -127,7 +127,7 @@ class WorkflowActionMoveFilesLocalTest {
action.setIfFileExists("overwrite_file");
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Move with overwrite should succeed");
+ assertTrue(result.isResult(), "Move with overwrite should succeed");
assertFalse(Files.exists(sourceFile), "Source file should not exist");
assertTrue(Files.exists(destFile), "Destination file should exist");
assertEquals(
@@ -149,7 +149,7 @@ class WorkflowActionMoveFilesLocalTest {
action.setCreateDestinationFolder(true);
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Move should succeed");
+ assertTrue(result.isResult(), "Move should succeed");
assertTrue(Files.exists(destinationFolder.toPath()), "Destination folder
should be created");
assertTrue(Files.exists(destFile), "File should be moved");
}
diff --git
a/plugins/actions/repeat/src/main/java/org/apache/hop/workflow/actions/repeat/Repeat.java
b/plugins/actions/repeat/src/main/java/org/apache/hop/workflow/actions/repeat/Repeat.java
index 15dcf5af78..c614c2c037 100644
---
a/plugins/actions/repeat/src/main/java/org/apache/hop/workflow/actions/repeat/Repeat.java
+++
b/plugins/actions/repeat/src/main/java/org/apache/hop/workflow/actions/repeat/Repeat.java
@@ -192,7 +192,7 @@ public class Repeat extends ActionBase implements IAction,
Cloneable {
repetitionNr++;
executionResult = executePipelineOrWorkflow(realFilename, nr,
executionResult, repetitionNr);
Result result = executionResult.result;
- if (!result.getResult() || result.getNrErrors() > 0 ||
result.isStopped()) {
+ if (!result.isResult() || result.getNrErrors() > 0 ||
result.isStopped()) {
logError("The repeating work encountered and error or was stopped.
This ends the loop.");
// On an false result, stop the loop
diff --git
a/plugins/actions/setvariables/src/test/java/org/apache/hop/workflow/actions/setvariables/ActionSetVariablesTest.java
b/plugins/actions/setvariables/src/test/java/org/apache/hop/workflow/actions/setvariables/ActionSetVariablesTest.java
index c10a24b00e..f415cc88b7 100644
---
a/plugins/actions/setvariables/src/test/java/org/apache/hop/workflow/actions/setvariables/ActionSetVariablesTest.java
+++
b/plugins/actions/setvariables/src/test/java/org/apache/hop/workflow/actions/setvariables/ActionSetVariablesTest.java
@@ -114,7 +114,7 @@ class ActionSetVariablesTest {
"src/test/resources/org/apache/hop/workflow/actions/setvariables/ASCIIText.properties");
action.setReplaceVars(true);
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertEquals("日本語", action.getVariable("Japanese"));
assertEquals("English", action.getVariable("English"));
assertEquals("中文", action.getVariable("Chinese"));
@@ -127,7 +127,7 @@ class ActionSetVariablesTest {
"src/test/resources/org/apache/hop/workflow/actions/setvariables/UTF8Text.properties");
action.setReplaceVars(true);
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertEquals("日本語", action.getVariable("Japanese"));
assertEquals("English", action.getVariable("English"));
assertEquals("中文", action.getVariable("Chinese"));
@@ -141,7 +141,7 @@ class ActionSetVariablesTest {
action.setFilename(propertiesFilename);
action.setReplaceVars(true);
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
RandomAccessFile fos = null;
try {
File file = new File(propertiesFilename);
@@ -172,7 +172,7 @@ class ActionSetVariablesTest {
action.setFilename(
"src/test/resources/org/apache/hop/workflow/actions/setvariables/configurationA.properties");
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertEquals("a", parentWorkflow.getVariable("propertyFile"));
assertEquals("a", parentWorkflow.getVariable("dynamicProperty"));
assertEquals("parentValue", parentWorkflow.getVariable("parentParam"));
@@ -180,7 +180,7 @@ class ActionSetVariablesTest {
action.setFilename(
"src/test/resources/org/apache/hop/workflow/actions/setvariables/configurationB.properties");
result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertEquals("b", parentWorkflow.getVariable("propertyFile"));
assertEquals("new", parentWorkflow.getVariable("newProperty"));
assertEquals("haha", parentWorkflow.getVariable("parentParam"));
@@ -190,7 +190,7 @@ class ActionSetVariablesTest {
action.setFilename(
"src/test/resources/org/apache/hop/workflow/actions/setvariables/configurationA.properties");
result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertEquals("a", parentWorkflow.getVariable("propertyFile"));
assertEquals("", parentWorkflow.getVariable("newProperty"));
assertEquals("parentValue", parentWorkflow.getVariable("parentParam"));
@@ -200,7 +200,7 @@ class ActionSetVariablesTest {
action.setFilename(
"src/test/resources/org/apache/hop/workflow/actions/setvariables/configurationB.properties");
result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertEquals("b", parentWorkflow.getVariable("propertyFile"));
assertEquals("new", parentWorkflow.getVariable("newProperty"));
assertEquals("haha", parentWorkflow.getVariable("parentParam"));
@@ -213,7 +213,7 @@ class ActionSetVariablesTest {
IHopMetadataProvider metadataProvider = mock(IHopMetadataProvider.class);
action.loadXml(getEntryNode("nullVariable", null, "JVM"),
metadataProvider, new Variables());
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertNull(System.getProperty("nullVariable"));
}
@@ -223,7 +223,7 @@ class ActionSetVariablesTest {
action.loadXml(
getEntryNode("nullVariable", null, "CURRENT_WORKFLOW"),
metadataProvider, new Variables());
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertNull(action.getVariable("nullVariable"));
}
@@ -234,7 +234,7 @@ class ActionSetVariablesTest {
getEntryNode("variableNotNull", "someValue", "JVM"), metadataProvider,
new Variables());
assertNull(System.getProperty("variableNotNull"));
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertEquals("someValue", System.getProperty("variableNotNull"));
}
@@ -247,7 +247,7 @@ class ActionSetVariablesTest {
new Variables());
assertNull(System.getProperty("variableNotNull"));
Result result = action.execute(new Result(), 0);
- assertTrue(result.getResult(), "Result should be true");
+ assertTrue(result.isResult(), "Result should be true");
assertEquals("someValue", action.getVariable("variableNotNull"));
}
diff --git
a/plugins/actions/snowflake/src/main/java/org/apache/hop/workflow/actions/snowflake/WarehouseManager.java
b/plugins/actions/snowflake/src/main/java/org/apache/hop/workflow/actions/snowflake/WarehouseManager.java
index f32e598754..ce6694cf97 100644
---
a/plugins/actions/snowflake/src/main/java/org/apache/hop/workflow/actions/snowflake/WarehouseManager.java
+++
b/plugins/actions/snowflake/src/main/java/org/apache/hop/workflow/actions/snowflake/WarehouseManager.java
@@ -411,7 +411,7 @@ public class WarehouseManager extends ActionBase implements
Cloneable, IAction {
Result result = previousResult;
result.setResult(validate());
- if (!result.getResult()) {
+ if (!result.isResult()) {
return result;
}
diff --git
a/plugins/actions/waitforsql/src/main/java/org/apache/hop/workflow/actions/waitforsql/ActionWaitForSql.java
b/plugins/actions/waitforsql/src/main/java/org/apache/hop/workflow/actions/waitforsql/ActionWaitForSql.java
index a314e1c96e..0ad3e53ec1 100644
---
a/plugins/actions/waitforsql/src/main/java/org/apache/hop/workflow/actions/waitforsql/ActionWaitForSql.java
+++
b/plugins/actions/waitforsql/src/main/java/org/apache/hop/workflow/actions/waitforsql/ActionWaitForSql.java
@@ -359,7 +359,7 @@ public class ActionWaitForSql extends ActionBase implements
Cloneable, IAction {
logBasic("Exception while waiting for SQL data: " + e.getMessage());
}
- if (result.getResult()) {
+ if (result.isResult()) {
// Remove error count set at the beginning of the method
//
result.setNrErrors(0);
diff --git
a/plugins/actions/workflow/src/main/java/org/apache/hop/workflow/actions/workflow/ActionWorkflow.java
b/plugins/actions/workflow/src/main/java/org/apache/hop/workflow/actions/workflow/ActionWorkflow.java
index 31a3642af9..7340b4a7d0 100644
---
a/plugins/actions/workflow/src/main/java/org/apache/hop/workflow/actions/workflow/ActionWorkflow.java
+++
b/plugins/actions/workflow/src/main/java/org/apache/hop/workflow/actions/workflow/ActionWorkflow.java
@@ -537,7 +537,7 @@ public class ActionWorkflow extends ActionBase implements
Cloneable, IAction {
// if one of them fails (in the loop), increase the number of errors
//
- if (oneResult.getResult() == false) {
+ if (oneResult.isResult() == false) {
result.setNrErrors(result.getNrErrors() + 1);
}
}
diff --git
a/plugins/misc/debug/src/main/java/org/apache/hop/debug/action/ModifyActionLogLevelExtensionPoint.java
b/plugins/misc/debug/src/main/java/org/apache/hop/debug/action/ModifyActionLogLevelExtensionPoint.java
index 11388be66a..a65a25ab70 100644
---
a/plugins/misc/debug/src/main/java/org/apache/hop/debug/action/ModifyActionLogLevelExtensionPoint.java
+++
b/plugins/misc/debug/src/main/java/org/apache/hop/debug/action/ModifyActionLogLevelExtensionPoint.java
@@ -181,7 +181,7 @@ public class ModifyActionLogLevelExtensionPoint
if (debugLevel.isLoggingResult()) {
log.logMinimal("Action results: ");
- log.logMinimal(" - result=" + result.getResult());
+ log.logMinimal(" - result=" + result.isResult());
log.logMinimal(" - stopped=" + result.isStopped());
log.logMinimal(" - linesRead=" +
result.getNrLinesRead());
log.logMinimal(" - linesWritten=" +
result.getNrLinesWritten());
diff --git
a/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/mail/ActionMail.java
b/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/mail/ActionMail.java
index c70c9373a1..7e710a1e8d 100644
---
a/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/mail/ActionMail.java
+++
b/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/mail/ActionMail.java
@@ -442,7 +442,7 @@ public class ActionMail extends ActionBase implements
Cloneable, IAction {
messageText
.append(
BaseMessages.getString(PKG, "ActionMail.Log.Comment.Result") +
" : ")
- .append(result.getResult())
+ .append(result.isResult())
.append(endRow);
messageText.append(endRow);
}
diff --git
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/transform/WorkflowLogging.java
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/transform/WorkflowLogging.java
index 5dfe9e42a8..f98e29ade9 100644
---
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/transform/WorkflowLogging.java
+++
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/transform/WorkflowLogging.java
@@ -136,7 +136,7 @@ public class WorkflowLogging extends
BaseTransform<WorkflowLoggingMeta, Workflow
transformRow[index++] = result.getEntryNr();
// Result (true/false)
- transformRow[index++] = result.getResult();
+ transformRow[index++] = result.isResult();
// Log channel ID
transformRow[index++] = actionResult.getLogChannelId();
diff --git
a/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/logging/xp/WorkflowLoggingExtensionPoint.java
b/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/logging/xp/WorkflowLoggingExtensionPoint.java
index 8b67d0c7ce..50e44f5483 100644
---
a/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/logging/xp/WorkflowLoggingExtensionPoint.java
+++
b/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/logging/xp/WorkflowLoggingExtensionPoint.java
@@ -307,7 +307,7 @@ public class WorkflowLoggingExtensionPoint
workflowPars.put("linesWritten",
workflowResult.getNrLinesWritten());
workflowPars.put("linesRejected",
workflowResult.getNrLinesRejected());
workflowPars.put("loggingText", workflowLoggingText);
- workflowPars.put("result", workflowResult.getResult());
+ workflowPars.put("result", workflowResult.isResult());
workflowPars.put("nrResultRows",
workflowResult.getRows().size());
workflowPars.put("nrResultFiles",
workflowResult.getResultFilesList().size());
workflowPars.put("containerId",
workflowResult.getContainerId());
diff --git
a/plugins/transforms/pipelineexecutor/src/main/java/org/apache/hop/pipeline/transforms/pipelineexecutor/PipelineExecutor.java
b/plugins/transforms/pipelineexecutor/src/main/java/org/apache/hop/pipeline/transforms/pipelineexecutor/PipelineExecutor.java
index 51932b6128..adb5832fad 100644
---
a/plugins/transforms/pipelineexecutor/src/main/java/org/apache/hop/pipeline/transforms/pipelineexecutor/PipelineExecutor.java
+++
b/plugins/transforms/pipelineexecutor/src/main/java/org/apache/hop/pipeline/transforms/pipelineexecutor/PipelineExecutor.java
@@ -427,7 +427,7 @@ public class PipelineExecutor extends
BaseTransform<PipelineExecutorMeta, Pipeli
outputRow[idx++] = Long.valueOf(System.currentTimeMillis() -
getData().groupTimeStart);
}
if (!Utils.isEmpty(meta.getExecutionResultField())) {
- outputRow[idx++] = Boolean.valueOf(result.getResult());
+ outputRow[idx++] = Boolean.valueOf(result.isResult());
}
if (!Utils.isEmpty(meta.getExecutionNrErrorsField())) {
outputRow[idx++] = Long.valueOf(result.getNrErrors());
diff --git
a/plugins/transforms/systemdata/src/main/java/org/apache/hop/pipeline/transforms/systemdata/SystemData.java
b/plugins/transforms/systemdata/src/main/java/org/apache/hop/pipeline/transforms/systemdata/SystemData.java
index 1857b9b4bd..65787aa7d5 100644
---
a/plugins/transforms/systemdata/src/main/java/org/apache/hop/pipeline/transforms/systemdata/SystemData.java
+++
b/plugins/transforms/systemdata/src/main/java/org/apache/hop/pipeline/transforms/systemdata/SystemData.java
@@ -536,7 +536,7 @@ public class SystemData extends
BaseTransform<SystemDataMeta, SystemDataData> {
Result previousResult = getPipeline().getPreviousResult();
boolean result = false;
if (previousResult != null) {
- result = previousResult.getResult();
+ result = previousResult.isResult();
}
row[index] = result;
break;
diff --git
a/plugins/transforms/workflowexecutor/src/main/java/org/apache/hop/pipeline/transforms/workflowexecutor/WorkflowExecutor.java
b/plugins/transforms/workflowexecutor/src/main/java/org/apache/hop/pipeline/transforms/workflowexecutor/WorkflowExecutor.java
index e9993590f1..9d41dcdc46 100644
---
a/plugins/transforms/workflowexecutor/src/main/java/org/apache/hop/pipeline/transforms/workflowexecutor/WorkflowExecutor.java
+++
b/plugins/transforms/workflowexecutor/src/main/java/org/apache/hop/pipeline/transforms/workflowexecutor/WorkflowExecutor.java
@@ -232,7 +232,7 @@ public class WorkflowExecutor extends
BaseTransform<WorkflowExecutorMeta, Workfl
outputRow[idx++] = Long.valueOf(System.currentTimeMillis() -
data.groupTimeStart);
}
if (!Utils.isEmpty(meta.getExecutionResultField())) {
- outputRow[idx++] = Boolean.valueOf(result.getResult());
+ outputRow[idx++] = Boolean.valueOf(result.isResult());
}
if (!Utils.isEmpty(meta.getExecutionNrErrorsField())) {
outputRow[idx++] = Long.valueOf(result.getNrErrors());
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
index 460656cc06..3bea8be9a2 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
@@ -2224,7 +2224,7 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
type = GuiActionType.Modify,
name = "i18n::HopGuiPipelineGraph.TransformAction.EditDescription.Name",
tooltip =
"i18n::HopGuiPipelineGraph.TransformAction.EditDescription.Tooltip",
- image = "ui/images/edit_description.svg",
+ image = "ui/images/edit.svg",
category = "Basic",
categoryOrder = "1")
public void editDescription(HopGuiPipelineTransformContext context) {
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
index f9dfc2fb5c..85fc02738e 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
@@ -1846,7 +1846,7 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
type = GuiActionType.Modify,
name =
"i18n::HopGuiWorkflowGraph.ContextualAction.EditActionDescription.Text",
tooltip =
"i18n::HopGuiWorkflowGraph.ContextualAction.EditActionDescription.Tooltip",
- image = "ui/images/edit_description.svg",
+ image = "ui/images/edit.svg",
category =
"i18n::HopGuiWorkflowGraph.ContextualAction.Category.Basic.Text",
categoryOrder = "1")
public void editActionDescription(HopGuiWorkflowActionContext context) {
@@ -2654,7 +2654,7 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
actionCopy = (ActionMeta) areaOwner.getParent();
Result result = actionResult.getResult();
tip.append("'").append(actionCopy.getName()).append("' ");
- if (result.getResult()) {
+ if (result.isResult()) {
tipImage = GuiResource.getInstance().getImageSuccess();
tip.append("finished successfully.");
} else {
@@ -2662,7 +2662,7 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
tip.append("failed.");
}
tip.append(Const.CR).append("------------------------").append(Const.CR).append(Const.CR);
- tip.append("Result :
").append(result.getResult()).append(Const.CR);
+ tip.append("Result :
").append(result.isResult()).append(Const.CR);
tip.append("Errors :
").append(result.getNrErrors()).append(Const.CR);
if (result.getNrLinesRead() > 0) {
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowGridDelegate.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowGridDelegate.java
index 7ae47fcd65..566b3f9dec 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowGridDelegate.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowGridDelegate.java
@@ -189,8 +189,8 @@ public class HopGuiWorkflowGridDelegate {
String workflowName = workflowTracker.getWorkflowName();
if (Utils.isEmpty(workflowName)) {
- if (!Utils.isEmpty(workflowTracker.getWorfkflowFilename())) {
- workflowName = workflowTracker.getWorfkflowFilename();
+ if (!Utils.isEmpty(workflowTracker.getWorkflowFilename())) {
+ workflowName = workflowTracker.getWorkflowFilename();
} else {
workflowName =
BaseMessages.getString(
@@ -198,7 +198,7 @@ public class HopGuiWorkflowGridDelegate {
}
}
treeItem.setText(0, workflowName);
- treeItem.setText(4, Const.NVL(workflowTracker.getWorfkflowFilename(),
""));
+ treeItem.setText(4, Const.NVL(workflowTracker.getWorkflowFilename(),
""));
TreeMemory.getInstance()
.storeExpanded(STRING_CHEF_LOG_TREE_NAME, new String[]
{workflowName}, true);
@@ -268,11 +268,11 @@ public class HopGuiWorkflowGridDelegate {
if (res != null) {
treeItem.setText(
2,
- res.getResult()
+ res.isResult()
? BaseMessages.getString(PKG, "WorkflowLog.Tree.Success")
: BaseMessages.getString(PKG,
"WorkflowLog.Tree.Failure"));
treeItem.setText(5, Long.toString(res.getEntryNr()));
- if (res.getResult()) {
+ if (res.isResult()) {
treeItem.setImage(2,
GuiResource.getInstance().getImageSuccess());
treeItem.setForeground(2,
GuiResource.getInstance().getColorSuccessGreen());
} else {
diff --git a/ui/src/main/resources/ui/laf.properties
b/ui/src/main/resources/ui/laf.properties
index a348493590..3ac74dd289 100644
--- a/ui/src/main/resources/ui/laf.properties
+++ b/ui/src/main/resources/ui/laf.properties
@@ -38,7 +38,7 @@ CNC_image=ui/images/CNC.svg
CNC_tree_image=ui/images/CNC_tree.svg
CollapseAll16_image=ui/images/CollapseAll:16#16.svg
CollapseAll_image=ui/images/CollapseAll.svg
-Color_image=ui/images/edit_option.svg
+Color_image=ui/images/edit.svg
ContextMenu_image=ui/images/context_menu.svg
ContinueLog_image=ui/images/run.svg
CopyHop_image=ui/images/copy-hop.svg
@@ -57,7 +57,7 @@ documentationUrl=manual/latest
DropHere_image=ui/images/drop_here.svg
DUM_image=ui/images/dummy.svg
Edit_image=ui/images/generic-edit:16#16.svg
-EditOption_image=ui/images/edit_option.svg
+EditOption_image=ui/images/edit.svg
EditSmall_image=ui/images/generic-edit.svg
errorArrow_image=ui/images/Error_Arrow.svg
ErrorHop_image=ui/images/false.svg