From d947988a9cd6eaadb45213e2c573974ddd66e20d Mon Sep 17 00:00:00 2001 From: sramazzina Date: Thu, 27 Apr 2023 15:42:08 +0200 Subject: [PATCH] fix #2840 NullPointerException in workflow executor --- .../workflowexecutor/WorkflowExecutor.java | 56 +++++++++++++++---- .../messages/messages_en_US.properties | 2 +- .../messages/messages_it_IT.properties | 16 +++--- 3 files changed, 54 insertions(+), 20 deletions(-) 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 41c0fba1a29..d033d3a813c 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 @@ -18,6 +18,7 @@ package org.apache.hop.pipeline.transforms.workflowexecutor; import com.google.common.annotations.VisibleForTesting; +import java.util.ArrayList; import org.apache.commons.lang.StringUtils; import org.apache.hop.core.Const; import org.apache.hop.core.Result; @@ -43,8 +44,6 @@ import org.apache.hop.workflow.engine.IWorkflowEngine; import org.apache.hop.workflow.engine.WorkflowEngineFactory; -import java.util.ArrayList; - /** Execute a workflow for every input row. */ public class WorkflowExecutor extends BaseTransform { private static final Class PKG = WorkflowExecutorMeta.class; // For Translator @@ -283,24 +282,59 @@ private void executeWorkflow() throws HopException { // Optionally also send the result rows to a specified target transform... // + boolean rowConsistencyChecked = false; + boolean consistencyPassed = true; + String missingFields = ""; + String expectedTypes = ""; + String currentTypes = ""; + if (meta.getResultRowsTargetTransformMeta() != null && result.getRows() != null) { + for (RowMetaAndData row : result.getRows()) { - Object[] targetRow = RowDataUtil.allocateRowData(data.resultRowsOutputRowMeta.size()); + // .. but before, perform all the consistency checks just one time just in the first result + // row + if (!rowConsistencyChecked) { + for (int i = 0; i < meta.getResultRowsField().length; i++) { + IValueMeta valueMeta = row.getRowMeta().getValueMeta(i); + if (valueMeta == null) { + missingFields += + (missingFields.length() > 0 ? missingFields = "," : "") + + meta.getResultRowsField()[i]; + consistencyPassed = false; + } - for (int i = 0; i < meta.getResultRowsField().length; i++) { - IValueMeta valueMeta = row.getRowMeta().getValueMeta(i); - if (valueMeta.getType() != meta.getResultRowsType()[i]) { - throw new HopException( + if (valueMeta != null && valueMeta.getType() != meta.getResultRowsType()[i]) { + expectedTypes += + (expectedTypes.length() > 0 ? expectedTypes = "," : "") + + ValueMetaFactory.getValueMetaName(meta.getResultRowsType()[i]); + currentTypes += + (currentTypes.length() > 0 ? currentTypes = "," : "") + valueMeta.getTypeDesc(); + consistencyPassed = false; + } + } + rowConsistencyChecked = true; + } + + if (!consistencyPassed) { + if (missingFields.length() > 0) { + logError("Unable to find required fields [" + missingFields + "] in result row!"); + } + + if (currentTypes.length() > 0) { + logError( BaseMessages.getString( - PKG, - "WorkflowExecutor.IncorrectDataTypePassed", - valueMeta.getTypeDesc(), - ValueMetaFactory.getValueMetaName(meta.getResultRowsType()[i]))); + PKG, "WorkflowExecutor.IncorrectDataTypePassed", currentTypes, expectedTypes)); } + + throw new HopException("We got into troubles while performing a consistency check on incoming result rows!"); + } + Object[] targetRow = RowDataUtil.allocateRowData(data.resultRowsOutputRowMeta.size()); + for (int i = 0; i < meta.getResultRowsField().length; i++) { targetRow[i] = row.getData()[i]; } + putRowTo(data.resultRowsOutputRowMeta, targetRow, data.resultRowsRowSet); } } diff --git a/plugins/transforms/workflowexecutor/src/main/resources/org/apache/hop/pipeline/transforms/workflowexecutor/messages/messages_en_US.properties b/plugins/transforms/workflowexecutor/src/main/resources/org/apache/hop/pipeline/transforms/workflowexecutor/messages/messages_en_US.properties index 47d9128cf77..a3461cb8d3a 100644 --- a/plugins/transforms/workflowexecutor/src/main/resources/org/apache/hop/pipeline/transforms/workflowexecutor/messages/messages_en_US.properties +++ b/plugins/transforms/workflowexecutor/src/main/resources/org/apache/hop/pipeline/transforms/workflowexecutor/messages/messages_en_US.properties @@ -32,7 +32,7 @@ WorkflowExecutorMeta.Exception.UnableToLoadWorkflow=It was not possible to load WorkflowExecutorDialog.ColumnInfo.Length=Length WorkflowExecutorMeta.ExecutionResults.FieldName.Label=Field name WorkflowExecutorDialog.GroupSize.Label=Number of rows to send to workflow\: -WorkflowExecutor.IncorrectDataTypePassed=The ''{0}'' data type passed from the workflows result rows does not correspond to the specified ''{1}'' data type. Make sure you are passing rows with the expected layout. +WorkflowExecutor.IncorrectDataTypePassed=The ''{0}'' data types passed from the workflows result rows does not correspond to the specified ''{1}'' data types. Make sure you are passing rows with the expected layout. WorkflowExecutorMeta.ResultRowsStream.Description=This output will contain the result rows after execution WorkflowExecutorDialog.ExecutionLinesDeletedField.Label=Number of rows deleted WorkflowExecutorDialog.ResultFiles.Tooltip=This tab allows you to specify where to send result files information to. diff --git a/plugins/transforms/workflowexecutor/src/main/resources/org/apache/hop/pipeline/transforms/workflowexecutor/messages/messages_it_IT.properties b/plugins/transforms/workflowexecutor/src/main/resources/org/apache/hop/pipeline/transforms/workflowexecutor/messages/messages_it_IT.properties index 147416dca21..106ce6093f5 100644 --- a/plugins/transforms/workflowexecutor/src/main/resources/org/apache/hop/pipeline/transforms/workflowexecutor/messages/messages_it_IT.properties +++ b/plugins/transforms/workflowexecutor/src/main/resources/org/apache/hop/pipeline/transforms/workflowexecutor/messages/messages_it_IT.properties @@ -21,14 +21,14 @@ WorkflowExecutorDialog.ColumnInfo.Field=Nome del campo WorkflowExecutor.UnexpectedError=Errore inatteso\: WorkflowExecutorMeta.Exception.ErrorLoadingJobExecutorDetailsFromXML=Errore di caricamento dei dettagli dell''esecutore workflow da XML WorkflowExecutorDialog.RunConfiguration.Label=Run configuration -WorkflowExecutorDialog.ResultFields.Label=Il layout atteso delle righe di risultato\: +WorkflowExecutorDialog.ResultFields.Label=Layout atteso delle righe di risultato\: WorkflowExecutorDialog.ExecutionFilesRetrievedField.Label=Nome campo con il numero dei file recuperati WorkflowExecutorDialog.Parameters.Title=Parametri WorkflowExecutorDialog.Parameters.column.Input=Valore statico di input WorkflowExecutorDialog.ExecutionTimeField.Label=Nome campo con il tempo di esecuzione (ms) WorkflowExecutorDialog.ColumnInfo.Length=Lunghezza -WorkflowExecutorDialog.GroupSize.Label=Il numero di righe da inviare al workflow -WorkflowExecutor.IncorrectDataTypePassed=Il tipo di dati ''{0}'' passato dalle righe di risultato del workflow non corrisponde al tipo di dati ''{1}''. Assicurarsi di passare le righe con il layout atteso. +WorkflowExecutorDialog.GroupSize.Label=Numero di righe da inviare al workflow +WorkflowExecutor.IncorrectDataTypePassed=I tipi di dati ''{0}'' passati dalle righe di risultato del workflow non corrispondono ai tipi dati attesi ''{1}''. Assicurarsi di passare righe con il layout atteso. WorkflowExecutorMeta.ResultRowsStream.Description=Quest''opzione conterr\u00E0 le righe di risultato dopo l''esecuzione WorkflowExecutorDialog.ExecutionLinesDeletedField.Label=Nome campo con il numero delle righe cancellate WorkflowExecutorDialog.ResultFiles.Tooltip=Questa tab consente di specificare dove spedire le informazioni del file di risultato. @@ -38,7 +38,7 @@ WorkflowExecutorMeta.CheckResult.TransformReceivingFieldsFromOtherTransforms=Que WorkflowExecutorDialog.ExecutionLogChannelIdField.Label=Nome campo con l''ID del canale di log WorkflowExecutorDialog.ExecutionResults.Title=Risultati di esecuzione WorkflowExecutorMeta.ReferencedObject.Description=Workflow -WorkflowExecutorDialog.ExecutionResultTarget.Label=Il transform di destinazione per i risultati d''esecuzione +WorkflowExecutorDialog.ExecutionResultTarget.Label=Transform di destinazione per i risultati d''esecuzione WorkflowExecutorMeta.Exception.UnableToLoadWorkflow=Non \u00E8 stato possibile caricare il workflow specificato WorkflowExecutor.Exception.GroupFieldNotFound=Il campo di gruppo ''{0}'' non \u00E8 stato trovato nell''input stream WorkflowExecutorDialog.Parameters.Tooltip=E'' possibile specificare i parametri da passare al workflow basati su valori fissi o sulla prima riga nei gruppi di righe passate al workflow. @@ -52,25 +52,25 @@ WorkflowExecutorMeta.CheckResult.TransformReceivingFields=Questo transform sta r WorkflowExecutorDialog.Parameters.column.Field=Campo da utilizzare WorkflowExecutorDialog.RowGroup.Tooltip=Determina quante righe di dati vengono passate al workflow prima dell''esecuzione WorkflowExecutorDialog.ExecutionLinesReadField.Label=Nome campo con il numero delle righe lette -WorkflowExecutorDialog.ResultFileNameField.Label=Il campo con il nome del file del risultato +WorkflowExecutorDialog.ResultFileNameField.Label=Campo con nome del file del risultato WorkflowExecutorMeta.ResultFilesStream.Description=Quest''output conterr\u00E0 i nomi file del risultato dopo l''esecuzione. WorkflowExecutorDialog.Parameters.column.Variable=Nome variabile / parametro WorkflowExecutorDialog.ErrorLoadingSpecifiedJob.Title=Errore WorkflowExecutorDialog.GroupField.Label=Campo su cui raggruppare le righe WorkflowExecutorDialog.ExecutionExitStatusField.Label=Nome campo con lo stato d''uscita WorkflowExecutorDialog.ColumnInfo.Type=Tipo di dati -WorkflowExecutorDialog.GroupTime.Label=Il tempo di attesa durante il recupero delle righe prima dell''esecuzione (ms) +WorkflowExecutorDialog.GroupTime.Label=Tempo di attesa per il recupero delle righe prima dell''esecuzione (ms) WorkflowExecutorDialog.ExecutionLinesWrittenField.Label=Nome campo con il numero delle righe scritte WorkflowExecutorDialog.Shell.Title=Esecutore workflow WorkflowExecutorDialog.ResultRows.Title=Righe di risultato WorkflowExecutorMeta.ResultStream.Description=Quest''opzione conterr\u00E0 il risultato dell''esecuzione WorkflowExecutorDialog.RowGroup.Title=Raggruppamento righe -WorkflowExecutorDialog.ResultRowsTarget.Label=Il transform di destinazione per le righe di risultato +WorkflowExecutorDialog.ResultRowsTarget.Label=Transform di destinazione per le righe di risultato WorkflowExecutorDialog.ErrorLoadingSpecifiedJob.Message=Errore durante il caricamento del workflow specificato\: WorkflowExecutorDialog.Parameters.InheritAll=Ereditare tutte le variabili dalla pipeline? WorkflowExecutorDialog.ExecutionLinesInputField.Label=Nome campo con il numero delle righe di input WorkflowExecutorMeta.CheckResult.NotReceivingAnyFields=Nessun campo di input ricevuto dai transforms precedenti -WorkflowExecutorDialog.ResultFilesTarget.Label=Il transform a cui spedire le informazioni del file di risultato +WorkflowExecutorDialog.ResultFilesTarget.Label=Transform a cui spedire le informazioni del file di risultato WorkflowExecutorDialog.ResultRows.Tooltip=E'' possibile specificare la destinazione e la specifica delle righe di risultato che devono essere passate dal workflow. WorkflowExecutorMeta.CheckResult.NoInputReceived=Nessun input ricevuto dai transforms precedenti WorkflowExecutorDialog.TransformName.Label=Nome transform