Created 08-12-2016 04:58 AM
Hi,
I've been trying to run an update processor script for nifi using Groovy. I am reusing the below script from Github.
import groovy.json.JsonBuilder import groovyx.net.http.RESTClient import static groovy.json.JsonOutput.prettyPrint import static groovy.json.JsonOutput.toJson import static groovyx.net.http.ContentType.JSON //@Grab(group='org.codehaus.groovy.modules.http-builder', // module='http-builder', //version='0.7.1') def processorName = 'Save File' def host = 'localhost' //def host = 'agrande-nifi-1' def port = 9090 def nifi = new RESTClient("http://$host:$port/nifi-api/") println 'Looking up a component to update...' def resp = nifi.get( path: 'controller/search-results', query: [q: processorName] ) assert resp.status == 200 assert resp.data.searchResultsDTO.processorResults.size() == 1 // println prettyPrint(toJson(resp.data)) def processorId = resp.data.searchResultsDTO.processorResults[0].id def processGroup= resp.data.searchResultsDTO.processorResults[0].groupId println "Found the component, id/group: $processorId/$processGroup" println 'Preparing to update the flow state...' resp = nifi.get(path: 'controller/revision') assert resp.status == 200 // stop the processor before we can update it println 'Stopping the processor to apply changes...' def builder = new JsonBuilder() builder { revision { clientId 'my awesome script' version resp.data.revision.version } processor { id "$processorId" state "STOPPED" } } resp = nifi.put( path: "controller/process-groups/$processGroup/processors/$processorId", body: builder.toPrettyString(), requestContentType: JSON ) assert resp.status == 200 // create a partial JSON update doc // TIP: don't name variables same as json keys, simplifies your life builder { revision { clientId 'my awesome script' version resp.data.revision.version } processor { id "$processorId" config { properties { 'Directory' '/tmp/staging' 'Create Missing Directories' 'true' } } } } println "Updating processor...\n${builder.toPrettyString()}" resp = nifi.put( path: "controller/process-groups/$processGroup/processors/$processorId", body: builder.toPrettyString(), requestContentType: JSON ) assert resp.status == 200 println "Updated ok." // println "Got this response back:" // print prettyPrint(toJson(resp.data)) println 'Bringing the updated processor back online...' builder { revision { clientId 'my awesome script' version resp.data.revision.version } processor { id "$processorId" state "RUNNING" } } resp = nifi.put( path: "controller/process-groups/$processGroup/processors/$processorId", body: builder.toPrettyString(), requestContentType: JSON ) assert resp.status == 200 println 'Ok'
Except i have commented out the Maven dependency part using @Grab part. I have directly download the http-builder-0.6.jar and put it into groovy designated Library directory to have the classes available. I have also downloaded and put the json-lib.jar in the library.
I'm still getting below exception at run-time
groovyx.net.http.ContentType.JSON
Caught: java.lang.NoClassDefFoundError: net/sf/json/JSONObject
java.lang.NoClassDefFoundError: net/sf/json/JSONObject
at groovyx.net.http.HTTPBuilder.<init>(HTTPBuilder.java:175)
at groovyx.net.http.HTTPBuilder.<init>(HTTPBuilder.java:194)
at groovyx.net.http.RESTClient.<init>(RESTClient.java:79)
at Groovy_Sample.run(Groovy_Sample.groovy:13)
Caused by: java.lang.ClassNotFoundException: net.sf.json.JSONObject
I cant trace out whats possibly going wrong, even with the jars in library, I have read that setting the right version in Maven dependency might help, but I dont use it, is there no way to do it without Maven? OR am i missing something with the Jar and libraries.
Created 08-13-2016 06:14 PM
You can provide additional dependencies to the ExecuteScript processor by using the "Module Directory" property as described here:
http://funnifi.blogspot.com/2016/02/executescript-using-modules.html
You generally shouldn't put any jars into NiFi's lib directory because that can impact all other NARs.
Created 08-12-2016 02:00 PM
Can you please try putting your jars under <nifi_home>/lib dir.
Created 08-13-2016 05:14 AM
According to following link, json-lib requires additional dependencies in your class path including groovy-all.jar. do you have these depndencies in your classpath?
Created 08-13-2016 06:14 PM
You can provide additional dependencies to the ExecuteScript processor by using the "Module Directory" property as described here:
http://funnifi.blogspot.com/2016/02/executescript-using-modules.html
You generally shouldn't put any jars into NiFi's lib directory because that can impact all other NARs.
Created 08-13-2016 06:58 PM
Absolutely correct! If you were to add any jars to lib/ it would be only the Apache Ivy JAR so you could use the @Grab annotation as described here: http://funnifi.blogspot.com/2016/05/using-groovy-grab-with-executescript.html. Otherwise, use Bryan's suggestion for best results.
Created 08-16-2016 11:22 AM
Hi Matt,
thanks for your comments, I followed what you said and downloaded the Apache Ivy Jar named : "ivy-2.4.0.jar" from http://ant.apache.org/ivy/download.cgi and put it under in $NIFI_HOME/lib folder and the restarted the NIFI service. As you highlighted, i should be able to use the grab annotation now.
@Grab(group='org.codehaus.groovy.modules.http-builder',
module='http-builder',
version='0.7.1')
So in the script i have un-commented the @Grab part and ran it from command line with groovysh. Now i'm getting the below error after executing the script. The error is in attached file. error.txt
Is some configuration still missing, i read your blog post to know that it has something to do with the Grape cache and we need to configure it correctly? I could see that there is no /grapes folder under the /groovy directory
Created 08-16-2016 06:32 PM
Do you have Groovy installed on your machine? If so try:
grape install org.codehaus.groovy.modules.http-builder http-builder 0.7.1
If that doesn't work, then the @Grab won't work either (lots of folks seem to have trouble grabbing that module). In that case you should put the http-builder JAR (and its dependencies) into some folder and use Module Directory as Bryan suggested.
Created 08-17-2016 09:33 AM
@Matt Burgess It worked! I tried with grape install command from command line and it popped some messages which stated that the jars are found in library. Now i can see a .groovy/grapes folder in documents which has the appropriate jar files! I ran the scripts thereafter and it successfully updated the processor properties as expected. I guess its now resolving the missing jar file paths on its own since the install. However I also noticed that having the @Grab part active or not doesn't matter to the code anymore.
Much appreciated and thanks a ton to you and Bryan for the most valuable inputs!