What are the attributes of the processor? Do you have : @InputRequirement(InputRequirement.Requirement.INPUT_FORBIDDEN) or anything?
You should take a look at the Listen** processors. They do not have any inputs etc, and run processing queued input from a background thread. You can have on modified queue a change and then have trigger process the queue of changes. > On Jan 8, 2021, at 11:04, Russell Bateman <r...@windofkeltia.com> wrote: > > I only put the code I want to execute in onTrigger(), I suspected it would > not fire there. I know that this isn't what processors do. Configuration is a > messy problem to solve when your downstreamers want it made easy. This is > supposed to be a solution that allows them to remain in the NiFi UI and not > have to run off doing harder things to configure. I could put what I'm doing > in /HumanReadables/ into a real, running processor, but then, I would kind of > have to add them to several processors and I wanted to avoid the confusion > that created. > > Here's the code. Thanks. > > import com.windofkeltia.constants.HumanReadableMappings; > > ... > > @TriggerWhenEmpty > @SideEffectFree > @CapabilityDescription( "Dynamic properties can be created to specify (or add > to) static configuration" > + " of key-value substitution pairs. See additional > details." ) > public class HumanReadables extends AbstractProcessor > { > @Override > public void onTrigger( final ProcessContext context, final ProcessSession > session ) throws ProcessException > { > getLogger().info( "inside onTrigger()..." ); > > for( Map.Entry< PropertyDescriptor, String > entry : > context.getProperties().entrySet() ) > { > PropertyDescriptor property = entry.getKey(); > > // do work here--maybe pre-wipe all key-value pairs if we're just going > to recreate them? > final String PROPERTY_NAME = property.getName(); > final String PROPERTY_VALUE = entry.getValue(); > > logger.trace( "Processing configurable mappings titled \"" + > PROPERTY_NAME + "\"" ); > > try > { > harvestDynamicPropertyMappings( PROPERTY_VALUE ); > } > catch( Exception e ) > { > getLogger().debug( e.getMessage() ); > } > } > } > > protected static void harvestDynamicPropertyMappings( final String > PROPERTY_VALUE ) > { > final String[] LINES = PROPERTY_VALUE.split( "\n" ); > int lineNumber = 0; > > if( LINES.length < 1 ) > return; > > final String WHICH_LIST = LINES[ 0 ]; > > for( final String VALUE_LINE : LINES ) > { > char delimiter = VALUE_LINE.charAt( 0 ); > int position = VALUE_LINE.indexOf( delimiter, 1 ); > String key, value; > > key = ( position < 0 ) ? VALUE_LINE.substring( 1 ) : > VALUE_LINE.substring( 1, position ).trim(); > value = ( position > 0 ) ? VALUE_LINE.substring( position + 1 ).trim() > : ""; > > HumanReadableMappings.add( key, value ); > } > } > > @Override > protected PropertyDescriptor getSupportedDynamicPropertyDescriptor( final > String propertyDescriptorName ) > { > return new PropertyDescriptor.Builder() > .required( false ) > .name( propertyDescriptorName ) > .addValidator( > StandardValidators.NON_EMPTY_VALIDATOR ) > // or .addValidator( Validator.VALID ) if > you do not wish it validated! > .dynamic( true ) > .build(); > } > > private volatile Set< String > dynamicPropertyNames = new HashSet<>(); > > @Override > public void onPropertyModified( final PropertyDescriptor descriptor, final > String oldValue, final String newValue ) > { > getLogger().info( oldValue + " -> " + newValue ); > > final Set< String > newDynamicPropertyNames = new HashSet<>( > dynamicPropertyNames ); > > if( isNull( newValue ) ) > newDynamicPropertyNames.remove( descriptor.getName() ); > else if( isNull( oldValue ) && descriptor.isDynamic() ) > newDynamicPropertyNames.add( descriptor.getName() ); > > dynamicPropertyNames = Collections.unmodifiableSet( > newDynamicPropertyNames ); > > final Set< String > allDynamicProperties = dynamicPropertyNames; > } > > @OnScheduled public void processProperties( final ProcessContext context ) > { > for( Map.Entry< PropertyDescriptor, String > entry : > context.getProperties().entrySet() ) > { > PropertyDescriptor descriptor = entry.getKey(); > > if( descriptor.isDynamic() ) > getLogger().debug( "Dynamic property named:\n " + > descriptor.getName() > + ", value: " + entry.getValue().replaceAll( > "\n", " + " ) ); > } > } > > protected static final String DEFAULT_MAPPING_VALUE = "" > + "|http://loinc.org |LOINC\n" > + "|http://snomed.info/sct |SNOMED\n" > + "|http://www.ama-assn.org/go/cpt |CPT\n" > + "|http://aapc.org |CPT\n" > + "|http://www.nlm.nih.gov/research/umls/rxnorm |RxNorm\n" > + "|http://hl7.org/fhir/sid/ndc |NDC\n" > + "|http://hl7.org/fhir/sid/icd-9-cm |ICD-9\n" > + "|http://hl7.org/fhir/sid/icd-10 |ICD-10\n"; > > public static final PropertyDescriptor DEFAULT_MAPPINGS = new > PropertyDescriptor.Builder() > .name( "default mappings" ) > .displayName( "Default mappings" ) > .required( false ) > .expressionLanguageSupported( ExpressionLanguageScope.NONE ) > .defaultValue( DEFAULT_MAPPING_VALUE ) > .addValidator( Validator.VALID ) > .description( "These default mappings are already set up, but can be > changed. To erase completely," > + " merely clear the value of this property and ignore it > in favor of creating and" > + " maintaining one or more of your own dynamic > properties.") > .build(); > > private List< PropertyDescriptor > properties; > > @Override > public void init( final ProcessorInitializationContext context ) > { > List< PropertyDescriptor > properties = new ArrayList<>(); > properties.add( DEFAULT_MAPPINGS ); > this.properties = Collections.unmodifiableList( properties ); > } > > @Override public List< PropertyDescriptor > > getSupportedPropertyDescriptors() { return properties; } > } >