Eric,

So I just learned ALOT about the bowels of the context and
initialization framework while digging into this issue, and needless
to say we will need a better way of making this available to scripts.
Here's some info:

1) The ControllerServiceInitializationContext object passed into
initialize() is an anonymous object that passes along the
ScriptedLookupService's context objects, such as the
ControllerServiceLookup.
2) The ControllerServiceLookup interface does not have a method
signature for getControllerServiceIdentifiers(Class, String) to pass
in the process group id.
3) The ControllerServiceLookup object returned by the
ControllerServiceInitializationContext.getControllerServiceLookup()
method is a StandardControllerServiceInitializationContext
4) Note that the context object passed into the initialize() method
and the one returned by context.getControllerServiceLookup() are
different (but both are ControllerServiceInitializationContext impls)
5) The StandardControllerServiceInitializationContext object contains
a private ControllerServiceProvider called serviceProvider of type
StandardControllerServiceProvider, the anonymous context object does
not
6) The StandardControllerServiceInitializationContext object delegates
the getControllerServiceIdentifiers(Class) method to the
serviceProvider
7) serviceProvider (a StandardControllerServiceProvider) does not
allow the call to the getControllerServiceIdentifiers(Class)
signature, and instead throws the error you're seeing
8) None of these objects can get at the process group ID. This is
because they are not associated with a ConfigurableComponent
9) ScriptedLookupService, after calling the script's initialize()
method, will then call the script's onEnabled(ConfigurationContext)
method if it exists. This is currently undocumented [1]
10) The script's onEnabled(ConfigurationContext) method will get a
StandardConfigurationContext object
11) The StandardConfigurationContext object has a private
ConfiguredComponent named component, it is actually a
StandardControllerServiceNode object
12) You can get the process group ID by calling the component's
getProcessGroupIdentifier() method
13) The StandardConfigurationContext object also has a private
ControllerServiceLookup named serviceLookup, it is actually a
StandardControllerServiceProvider object
14) Since we can get a process group ID from #11-12, we can now call
the supported method on the ControllerServiceProvider interface,
namely getControllerServiceIdentifiers(Class, String)
15) Getting at private members (#11 &13) is allowed in Groovy, but
IIRC only works if you don't have a security manager/policies on the
JVM.

TL;DR You can't currently get controller services by name in the
initialize() method, you have to implement onEnabled instead. If you
want to use logging, however, you'll need to save off the logger in
the initialize() method. Here's a working version of onEnabled:

void onEnabled(ConfigurationContext context) {
    lookup = context.serviceLookup
    processGroupId = context.component?.processGroupIdentifier
    /* Get sql-connection */
    def dbcpServiceId =
lookup.getControllerServiceIdentifiers(ControllerService,
processGroupId).find {
      cs -> lookup.getControllerServiceName(cs) == 'MySQLConnectionPool'
    }
    def conn = lookup.getControllerService(dbcpServiceId)?.getConnection()
  }

Hope this helps. I will think some more on how to make everything
fluid and legit -- Mark Payne, could use your help here :)

Regards,
Matt

On Tue, Nov 14, 2017 at 6:13 AM, Eric Chaves <e...@uolet.com> wrote:
> Hi Folks,
>
> I need to get an instance of DBCPService inside my ScriptedLookupService and
> for that I'm following Matt's post
> http://funnifi.blogspot.com.br/2016/04/sql-in-nifi-with-executescript.html
>
> In my groovy class I've overrided the initialize method and performing the
> lookup there but I'm getting the following error:
>
> java.lang.UnsupportedOperationException: Cannot obtain Controller Service
> Identifiers for service type interface
> org.apache.nifi.controller.ControllerService without providing a Process
> Group Identifier
>
>
> @Override
>   void initialize(ControllerServiceInitializationContext context) throws
> InitializationException {
>     log = context.logger
>     /* Get sql-connection */
>     def lookup = context.controllerServiceLookup
>     def dbcpServiceId =
> lookup.getControllerServiceIdentifiers(ControllerService).find {
>       cs -> lookup.getControllerServiceName(cs) == 'MySQLConnectionPool'
>     }
>     conn = lookup.getControllerService(dbcpServiceId)?.getConnection()
>     log.info("sql conn {}", conn)
>   }
>
> Is there other way to find service identifiers?
>
> Regards,

Reply via email to