This is an automated email from the ASF dual-hosted git repository.
markap14 pushed a commit to branch support/nifi-1.13
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/support/nifi-1.13 by this push:
new d12ac9c NIFI-8266: Fix NPE when validating supported properties
against validation context - Removed schema properties from
FreeFormTextRecordSetWriter causing validation issues
d12ac9c is described below
commit d12ac9cb95182bb6a4bff9ac89d5c913d81211c6
Author: Matthew Burgess <[email protected]>
AuthorDate: Fri Feb 26 10:57:09 2021 -0500
NIFI-8266: Fix NPE when validating supported properties against validation
context
- Removed schema properties from FreeFormTextRecordSetWriter causing
validation issues
This closes #4851.
Signed-off-by: Mark Payne <[email protected]>
---
.../components/AbstractConfigurableComponent.java | 53 +++++++++++-----------
.../nifi/text/FreeFormTextRecordSetWriter.java | 19 ++++----
.../nifi/text/TestFreeFormTextRecordSetWriter.java | 7 ---
.../jetty/ControllerServiceTestContext.java | 11 ++++-
4 files changed, 44 insertions(+), 46 deletions(-)
diff --git
a/nifi-api/src/main/java/org/apache/nifi/components/AbstractConfigurableComponent.java
b/nifi-api/src/main/java/org/apache/nifi/components/AbstractConfigurableComponent.java
index 4758802..1daeb43 100644
---
a/nifi-api/src/main/java/org/apache/nifi/components/AbstractConfigurableComponent.java
+++
b/nifi-api/src/main/java/org/apache/nifi/components/AbstractConfigurableComponent.java
@@ -90,40 +90,39 @@ public abstract class AbstractConfigurableComponent
implements ConfigurableCompo
@Override
public final Collection<ValidationResult> validate(final ValidationContext
context) {
- // goes through supported properties
+ // goes through context properties, should match supported properties
+ supported dynamic properties
final Collection<ValidationResult> results = new ArrayList<>();
+ final Set<PropertyDescriptor> contextDescriptors =
context.getProperties().keySet();
final List<PropertyDescriptor> supportedDescriptors =
getSupportedPropertyDescriptors();
- if (null != supportedDescriptors) {
- for (final PropertyDescriptor descriptor : supportedDescriptors) {
- // If the property descriptor's dependency is not satisfied,
the property does not need to be considered, as it's not relevant to the
- // component's functionality.
- final boolean dependencySatisfied =
context.isDependencySatisfied(descriptor, this::getPropertyDescriptor);
- if (!dependencySatisfied) {
- continue;
- }
+ for (final PropertyDescriptor descriptor : contextDescriptors) {
+ // If the property descriptor's dependency is not satisfied, the
property does not need to be considered, as it's not relevant to the
+ // component's functionality.
+ final boolean dependencySatisfied =
context.isDependencySatisfied(descriptor, this::getPropertyDescriptor);
+ if (!dependencySatisfied) {
+ continue;
+ }
- validateDependencies(descriptor, context, results);
+ validateDependencies(descriptor, context, results);
- String value = context.getProperty(descriptor).getValue();
- if (value == null) {
- value = descriptor.getDefaultValue();
- }
+ String value = context.getProperty(descriptor).getValue();
+ if (value == null) {
+ value = descriptor.getDefaultValue();
+ }
- if (value == null && descriptor.isRequired()) {
- String displayName = descriptor.getDisplayName();
- ValidationResult.Builder builder = new
ValidationResult.Builder().valid(false).input(null).subject(displayName != null
? displayName : descriptor.getName());
- builder = (displayName != null) ?
builder.explanation(displayName + " is required") :
builder.explanation(descriptor.getName() + " is required");
- results.add(builder.build());
- continue;
- } else if (value == null) {
- continue;
- }
+ if (value == null && descriptor.isRequired()) {
+ String displayName = descriptor.getDisplayName();
+ ValidationResult.Builder builder = new
ValidationResult.Builder().valid(false).input(null).subject(displayName != null
? displayName : descriptor.getName());
+ builder = (displayName != null) ?
builder.explanation(displayName + " is required") :
builder.explanation(descriptor.getName() + " is required");
+ results.add(builder.build());
+ continue;
+ } else if (value == null) {
+ continue;
+ }
- final ValidationResult result = descriptor.validate(value,
context);
- if (!result.isValid()) {
- results.add(result);
- }
+ final ValidationResult result = descriptor.validate(value,
context);
+ if (!result.isValid()) {
+ results.add(result);
}
}
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/main/java/org/apache/nifi/text/FreeFormTextRecordSetWriter.java
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/main/java/org/apache/nifi/text/FreeFormTextRecordSetWriter.java
index 4ebc19f..f91eb0c 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/main/java/org/apache/nifi/text/FreeFormTextRecordSetWriter.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/main/java/org/apache/nifi/text/FreeFormTextRecordSetWriter.java
@@ -22,19 +22,17 @@ import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.annotation.lifecycle.OnEnabled;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.PropertyValue;
-import org.apache.nifi.context.PropertyContext;
+import org.apache.nifi.controller.AbstractControllerService;
import org.apache.nifi.controller.ConfigurationContext;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.processor.util.StandardValidators;
-import org.apache.nifi.schema.access.InheritSchemaFromRecord;
-import org.apache.nifi.schema.access.SchemaAccessStrategy;
-import org.apache.nifi.schemaregistry.services.SchemaRegistry;
+import org.apache.nifi.schema.access.SchemaNotFoundException;
import org.apache.nifi.serialization.RecordSetWriter;
import org.apache.nifi.serialization.RecordSetWriterFactory;
-import org.apache.nifi.serialization.SchemaRegistryRecordSetWriter;
import org.apache.nifi.serialization.record.RecordSchema;
+import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
@@ -46,7 +44,7 @@ import java.util.Map;
+ "text is able to make use of the Expression Language to reference
each of the fields that are available "
+ "in a Record, as well as the attributes in the FlowFile and
variables. If there is a name collision, the field name/value is used before
attributes or variables. "
+ "Each record in the RecordSet will be separated by a single newline
character.")
-public class FreeFormTextRecordSetWriter extends SchemaRegistryRecordSetWriter
implements RecordSetWriterFactory {
+public class FreeFormTextRecordSetWriter extends AbstractControllerService
implements RecordSetWriterFactory {
static final PropertyDescriptor TEXT = new PropertyDescriptor.Builder()
.name("Text")
.description("The text to use when writing the results. This property
will evaluate the Expression Language using any of the fields available in a
Record.")
@@ -81,13 +79,12 @@ public class FreeFormTextRecordSetWriter extends
SchemaRegistryRecordSetWriter i
}
@Override
- public RecordSetWriter createWriter(final ComponentLog logger, final
RecordSchema schema, final OutputStream out, final Map<String, String>
variables) {
- return new FreeFormTextWriter(textValue, characterSet, out, variables);
+ public RecordSchema getSchema(Map<String, String> variables, RecordSchema
readSchema) throws SchemaNotFoundException, IOException {
+ return readSchema;
}
@Override
- protected SchemaAccessStrategy getSchemaAccessStrategy(String strategy,
SchemaRegistry schemaRegistry, PropertyContext context) {
- return new InheritSchemaFromRecord();
+ public RecordSetWriter createWriter(final ComponentLog logger, final
RecordSchema schema, final OutputStream out, final Map<String, String>
variables) {
+ return new FreeFormTextWriter(textValue, characterSet, out, variables);
}
-
}
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/text/TestFreeFormTextRecordSetWriter.java
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/text/TestFreeFormTextRecordSetWriter.java
index 581a0db..f6abbca 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/text/TestFreeFormTextRecordSetWriter.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/text/TestFreeFormTextRecordSetWriter.java
@@ -17,14 +17,11 @@
package org.apache.nifi.text;
import org.apache.nifi.reporting.InitializationException;
-import org.apache.nifi.schema.access.SchemaAccessUtils;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.Test;
import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
@@ -35,13 +32,9 @@ public class TestFreeFormTextRecordSetWriter {
private TestRunner setup(FreeFormTextRecordSetWriter writer) throws
InitializationException, IOException {
TestRunner runner =
TestRunners.newTestRunner(TestFreeFormTextRecordSetWriterProcessor.class);
- final String outputSchemaText = new
String(Files.readAllBytes(Paths.get("src/test/resources/text/testschema")));
-
runner.addControllerService("writer", writer);
runner.setProperty(TestFreeFormTextRecordSetWriterProcessor.WRITER,
"writer");
- runner.setProperty(writer, SchemaAccessUtils.SCHEMA_ACCESS_STRATEGY,
SchemaAccessUtils.SCHEMA_TEXT_PROPERTY);
- runner.setProperty(writer, SchemaAccessUtils.SCHEMA_TEXT,
outputSchemaText);
runner.setProperty(writer, FreeFormTextRecordSetWriter.TEXT, "ID:
${ID}, Name: ${NAME}, Age: ${AGE}, Country: ${COUNTRY}, Username:
${user.name}");
return runner;
diff --git
a/nifi-nar-bundles/nifi-websocket-bundle/nifi-websocket-services-jetty/src/test/java/org/apache/nifi/websocket/jetty/ControllerServiceTestContext.java
b/nifi-nar-bundles/nifi-websocket-bundle/nifi-websocket-services-jetty/src/test/java/org/apache/nifi/websocket/jetty/ControllerServiceTestContext.java
index 04cccdb..2e29437 100644
---
a/nifi-nar-bundles/nifi-websocket-bundle/nifi-websocket-services-jetty/src/test/java/org/apache/nifi/websocket/jetty/ControllerServiceTestContext.java
+++
b/nifi-nar-bundles/nifi-websocket-bundle/nifi-websocket-services-jetty/src/test/java/org/apache/nifi/websocket/jetty/ControllerServiceTestContext.java
@@ -23,6 +23,8 @@ import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.util.MockControllerServiceInitializationContext;
import org.apache.nifi.util.MockPropertyValue;
+import java.util.HashMap;
+import java.util.Map;
import java.util.function.Function;
import static org.mockito.ArgumentMatchers.any;
@@ -44,7 +46,14 @@ public class ControllerServiceTestContext {
doAnswer(invocation ->
configurationContext.getProperty(invocation.getArgument(0)))
.when(validationContext).getProperty(any(PropertyDescriptor.class));
doReturn(true).when(validationContext).isDependencySatisfied(any(PropertyDescriptor.class),
any(Function.class));
- controllerService.getPropertyDescriptors().forEach(prop ->
setDefaultValue(prop));
+ // Return the service's properties as the context's
+ final Map<PropertyDescriptor,String> propDescriptors = new HashMap<>();
+ controllerService.getPropertyDescriptors().forEach(prop -> {
+ setDefaultValue(prop);
+ propDescriptors.put(prop, prop.getName());
+ });
+
+ doReturn(propDescriptors).when(validationContext).getProperties();
}
public MockControllerServiceInitializationContext
getInitializationContext() {