[ https://issues.apache.org/jira/browse/NIFI-8050?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Matt Burgess resolved NIFI-8050. -------------------------------- Fix Version/s: 1.10.0 Assignee: Matt Burgess Resolution: Fixed The RecordSetWriter API was changed to include a Map<String,String> argument in the createWriter() method. The Migration Guide (https://cwiki.apache.org/confluence/display/NIFI/Migration+Guidance) has been updated to include this documentation. > Custom Groovy writer breaks during upgrade > ------------------------------------------ > > Key: NIFI-8050 > URL: https://issues.apache.org/jira/browse/NIFI-8050 > Project: Apache NiFi > Issue Type: Bug > Components: Core Framework > Reporter: Pierre Villard > Assignee: Matt Burgess > Priority: Major > Fix For: 1.10.0 > > > A couple of issues when upgrading NiFi and using a custom scripted writer > with Groovy. > The scripted writer was something like: > {code:java} > import ... > class GroovyRecordSetWriter implements RecordSetWriter { > ... > @Override > WriteResult write(Record r) throws IOException { > ... > } > @Override > String getMimeType() { ... } > @Override > WriteResult write(final RecordSet rs) throws IOException { > ... > } > public void beginRecordSet() throws IOException { ... } > @Override > public WriteResult finishRecordSet() throws IOException { ... } > @Override > public void close() throws IOException {} > @Override > public void flush() throws IOException {} > } > class GroovyRecordSetWriterFactory extends AbstractControllerService > implements RecordSetWriterFactory { > @Override > RecordSchema getSchema(Map<String, String> variables, RecordSchema > readSchema) throws SchemaNotFoundException, IOException { > null > } > @Override > RecordSetWriter createWriter(ComponentLog logger, RecordSchema schema, > OutputStream out) throws SchemaNotFoundException, IOException { > new GroovyRecordSetWriter(out) > } > } > writer = new GroovyRecordSetWriterFactory() > {code} > With NIFI-6318 we changed a method in the interface RecordSetWriterFactory. > When using the above code in NiFi 1.9.2, it works fine but after an upgrade > on 1.11.4, this breaks. The Controller Service, when enabled, is throwing the > below message: > {quote}Can't have an abstract method in a non-abstract class. The class > 'GroovyRecordSetWriterFactory' must be declared abstract or the method > 'org.apache.nifi.serialization.RecordSetWriter > createWriter(org.apache.nifi.logging.ComponentLog, > org.apache.nifi.serialization.record.RecordSchema, java.io.OutputStream, > java.util.Map)' must be implemented. > {quote} > However the controller service is successfully enabled and the processors > referencing it can be started. When using the ConvertRecord processor with > the problematic controller service, it will throw the below NPE: > {code:java} > 2020-11-26 15:46:13,876 ERROR [Timer-Driven Process Thread-25] > o.a.n.processors.standard.ConvertRecord > ConvertRecord[id=8b5456ae-71dc-3bd3-d0c0-df50d196fc00] Failed to process > StandardFlowFileRecord[uuid=adebfcf6-b449-4d01-90a7-0463930aade0,claim=StandardContentClaim > [resourceClaim=StandardResourceClaim[id=1606401933295-1, container=default, > section=1], offset=80, > length=296],offset=0,name=adebfcf6-b449-4d01-90a7-0463930aade0,size=296]; > will route to failure: java.lang.NullPointerException > java.lang.NullPointerException: null at > org.apache.nifi.processors.standard.AbstractRecordProcessor$1.process(AbstractRecordProcessor.java:151) > at > org.apache.nifi.controller.repository.StandardProcessSession.write(StandardProcessSession.java:2986) > at > org.apache.nifi.processors.standard.AbstractRecordProcessor.onTrigger(AbstractRecordProcessor.java:122) > at > org.apache.nifi.processor.AbstractProcessor.onTrigger(AbstractProcessor.java:27) > at > org.apache.nifi.controller.StandardProcessorNode.onTrigger(StandardProcessorNode.java:1173) > at > org.apache.nifi.controller.tasks.ConnectableTask.invoke(ConnectableTask.java:214) > at > org.apache.nifi.controller.scheduling.TimerDrivenSchedulingAgent$1.run(TimerDrivenSchedulingAgent.java:117) > at org.apache.nifi.engine.FlowEngine$2.run(FlowEngine.java:110) at > java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at > java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at > java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) > at > java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) > at > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) > at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) > at java.lang.Thread.run(Thread.java:748) > {code} > The fix is quite simple, it's just required to add the proper implementation > method in the Groovy script. Something like: > {code:java} > class GroovyRecordSetWriterFactory extends AbstractControllerService > implements RecordSetWriterFactory { > @Override > RecordSchema getSchema(Map<String, String> variables, RecordSchema > readSchema) throws SchemaNotFoundException, IOException { > null > } > @Override > RecordSetWriter createWriter(ComponentLog logger, RecordSchema schema, > OutputStream out) throws SchemaNotFoundException, IOException { > new GroovyRecordSetWriter(out) > } > @Override > RecordSetWriter createWriter(ComponentLog logger, RecordSchema schema, > OutputStream out, Map<String, String> variables) throws > SchemaNotFoundException, IOException { > return createWriter(logger, schema, out) > } > } > {code} > However, there are two things to improve: > * if possible the controller service should not be successfully enabled - > throwing a bulletin is nice but not enough in some environments where flow > deployment is completely automated without the access to the UI. Besides the > bulletin is only shown for 5 minutes and will then disappear. Besides, > enabling/disabling the controller service without making any change to the > script body won't perform the validation/compilation again and the bulletin > won't be shown. It can make things hard to debug/locate since the NPE is not > providing much info. > * the NPE should be handled properly to provide a more meaningful message -- This message was sent by Atlassian Jira (v8.3.4#803005)