Interface ControllerService

All Superinterfaces:
ConfigurableComponent
All Known Implementing Classes:
AbstractControllerService

public interface ControllerService extends ConfigurableComponent

This interface provides a mechanism for creating services that are shared among all Processors, ReportingTasks, FlowAnalysisRules, ParameterProviders and other ControllerServices.

ControllerServices are discovered using Java's ServiceLoader mechanism. As a result, all implementations must follow these rules:

  • The implementation must implement this interface.
  • The implementation must have a file named org.apache.nifi.controller.ControllerService located within the jar's META-INF/services directory. This file contains a list of fully-qualified class names of all ControllerServices in the jar, one-per-line.
  • The implementation must support a default constructor.

All implementations of this interface must be thread-safe.

Accessing Controller Services

A ControllerService is accessible only through its interface. The framework provides access to a ControllerService through two different mechanisms:

  • A PropertyDescriptor can be created via the PropertyDescriptor.Builder after calling the identifiesControllerService(Class) method and then the ControllerService is accessed via PropertyValue.asControllerService(Class) method.

    For example:

        public static final PropertyDescriptor MY_PROPERTY = new PropertyDescriptor.Builder()
         .name("My Property")
         .description("Example Property")
         .identifiesControllerService( MyControllerServiceInterface.class )
         .build();
    
        ...
        public void onTrigger(ProcessContext context, ProcessSessionFactory sessionFactory) throws ProcessException {
         // Obtain the user-selected controller service
         final MyControllerServiceInterface service = context.getProperty(MY_PROPERTY).asControllerService( MyControllerServiceInterface.class );
         ...
        }
    
     

  • A Controller Service can be obtained via a ControllerServiceLookup. This lookup may be obtained, for example, from the ProcessContext that is provided to a Processor's onTrigger method.

    For example:

        public void onTrigger(ProcessContext context, ProcessSessionFactory sessionFactory) throws ProcessException {
          final MyControllerServiceInterface service = (MyControllerServiceInterface) context.getControllerServiceLookup().getControllerService("service_identifier");
        }
     

Defining a Controller Service

Note in both of the examples above, that the Controller Service was accessed only by its interface, and this interface extends ControllerService. If we have an implementation named MyServiceImpl, for example, that implements MyControllerServiceInterface, we cannot, in either case, attempt to cast the ControllerService to the desired implementation. Doing so will result in a ClassCastException. This is by design and is done for the following reasons:

  • It is a good coding practice to implement such a service as an interface in general.
  • A Controller Service can be referenced from different NiFi Archives (NARs). This means that the Controller Service may be defined in one ClassLoader and referenced from another unrelated ClassLoader. In order to account for this, NiFi will change the current thread's ClassLoader as appropriate when entering the Controller Service's code and revert back to the previous ClassLoader after exiting the Controller Service's code.

Controller Services and NARs

Due to the fact that a Controller Service may be referenced from a different NAR than the one in which the implementation lives, it is crucial that both the Controller Service's interface and the code referencing the interface inherit from the same ClassLoader. This is accomplished by ensuring that the NAR that contains the Controller Service interface is the parent (or ancestor) of the NAR that references the Controller Service interface.

Typically, this is done by creating a NAR structure as follows:

   + my-services-api-nar
   +--- service-X-implementation-nar
   +--- service-Y-implementation-nar
   +--- service-Z-implementation-nar
   +--- processor-A-nar
   +--- processor-B-nar
 

In this case, the MyControllerServiceInterface interface, and any other Controller Service interfaces, will be defined in the my-services-api-nar NAR. Implementations are then encapsulated within the service-X-implementation-nar, service-Y-implementation-nar, and service-Z-implementation-nar NARs. All Controller Services and all Processors defined in these NARs are able to reference any other Controller Services whose interfaces are provided in the my-services-api-nar NAR.

For more information on NARs, see the NiFi Developer Guide.

  • Method Details

    • initialize

      Provides the Controller Service with access to objects that may be of use throughout the life of the service. This method will be called before any properties are set
      Parameters:
      context - of initialization
      Throws:
      InitializationException - if unable to init
    • isStateful

      default boolean isStateful(ConfigurationContext context)
      Indicates whether this controller service, configured with the given ConfigurationContext, stores state.
      Parameters:
      context - provides access to convenience methods for obtaining property values
      Returns:
      True if this controller service stores state
    • migrateProperties

      default void migrateProperties(PropertyConfiguration config)

      Allows for the migration of an old property configuration to a new configuration. This allows the Controller Service to evolve over time, as it allows properties to be renamed, removed, or reconfigured.

      This method is called only when a Controller Service is restored from a previous configuration. For example, when NiFi is restarted and the flow is restored from disk, when a previously configured flow is imported (e.g., from a JSON file that was exported or a NiFi Registry), or when a node joins a cluster and inherits a flow that has a new Controller Service. Once called, the method will not be invoked again for this Controller Service until NiFi is restarted.

      Parameters:
      config - the current property configuration