[ 
https://issues.apache.org/jira/browse/NIFI-15365?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Bob Paulin updated NIFI-15365:
------------------------------
    Description: 
When Verifying configuration on a newly created DBCPConnectionPool (Controller 
Service) the user is presented with an error [1]

Driver Class found but not loaded: Apply configuration before verifying.

This is due to the StandardControllerServiceNode.verifyConfiguration method 
creating a new instance classloader [2] but still using the original controller 
service [3] that was loaded with the original ControllerService instance class 
loader any usage of Class.forName with in the controller service (or any 
included sdks) will not be able to see additional urls included in the new 
instance classloader [2].  

 

*Proposal* (patch in progress)

For this to work a new temporary controller service must be created with the 
new instance classloader and verify must be called on the temporary controller 
service.

Will look to model this after the component reload that takes the following 
actions (required or maybe required actions in this process bolded)

*1) get existing instance class loader* 
   *a) Save reference to original instance classloader to a variable*

    b)Close classloader and call on remove [We should not close the classloader 
as it is still needed or call on remove]
*2) Create new controller service.* 
 *A) Invoke build Controller service*
  *i) Create Instance Class loader.* 
  *ii) get raw class* 
  *iii) set thread context class loader as new detected instance class loader* 
  *iv) Subclass raw class as ControllerService* 
  *v) Invoke Declared Constructor on class to instantiate impl* 
  vi) Create invocation handler for implementation [No needed controller 
service will not be proxied]. 
  vii) Extract all interfaces to create proxy service [No needed controller 
service will not be proxied]  
  *viii) Build Initialization context with loggers, state managers, kerberos 
etc. Invoke initialization. [ Propose doing this with a mock. Risk does 
validation ever consider the original controller’s state management? 
Kerberos?]* 
  ix) Verify controller service references to prevent issues with instance 
class loading where service api and impls are in same nar but should not be [ 
Doesn’t matter should have already failed on initial controller creation] 
  x) Create new Controller Service Node and Validation context [Don’t need a 
new node just to validate] 
  *xi) Set controller service node name, logging context, [node name not 
needed…. Do we need the logging context? Maybe].* 
  xii) set Invocation handler service node as newly create service node. [ not 
needed proxy won’t be used] 
  *xiii) set thread context back to original thread context class loader* 
 *B) if first time invoke on configuration restored and on added [ Do we need 
controller service lifecycle called? Maybe but we definitely should not call 
any framework methods]* 
3) Put controller Service in process group [ Not needed we’ll be destroying 
after validation] 
4) Set invocation handler to existing node [ Not needed we’ll be destroying 
after validation] 
5) Create loggable components (implement and proxy) [ Not needed we’ll be 
destroying after validation] 
6) set luggable components into existing node and set extension missing [Not 
needed we’ll be destroying after validation] 
7) Refresh properties on existing node [ Not needed we’ll should be able to 
pass properties in directly to verify] 
8) Reset Validation State on existing node [ Not needed we’ll be destroying 
after validation] 
9) trigger validation on existing node. [ Not needed we’ll be destroying after 
validation] 

 

Note: This works fine if the Property defining the driver location is defined 
as a Parameter within a Parameter Context because the apply action in the UI 
reloads the controller service [4]

[1][https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-extension-bundles/nifi-extension-utils/nifi-dbcp-base/src/main/java/org/apache/nifi/dbcp/AbstractDBCPConnectionPool.java#L132C45-L132C117]

 

 
[2][https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java#L541]

[3] 
[https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java#L544]

[4] 
[https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ParameterUpdateManager.java#L368]

 

  was:
When Verifying configuration on a newly created DBCPConnectionPool (Controller 
Service) the user is presented with an error [1]

Driver Class found but not loaded: Apply configuration before verifying.

This is due to the StandardControllerServiceNode.verifyConfiguration method 
creating a new instance classloader [2] but still using the original controller 
service [3] that was loaded with the original ControllerService instance class 
loader any usage of Class.forName with in the controller service (or any 
included sdks) will not be able to see additional urls included in the new 
instance classloader [2].  

 

*Proposal* (patch in progress)

For this to work a new temporary controller service must be created with the 
new instance classloader and verify must be called on the temporary controller 
service.

Will look to model this after the component reload that takes the following 
actions (required or maybe required actions in this process bolded)

*1) get existing instance class loader and close calling on remove* 
*2) Create new controller service.* 
 *A) Invoke build Controller service*
  *i) Create Instance Class loader.* 
  *ii) get raw class* 
  *iii) set thread context class loader as new detected instance class loader* 
  *iv) Subclass raw class as ControllerService* 
  *v) Invoke Declared Constructor on class to instantiate impl* 
  vi) Create invocation handler for implementation [No needed controller 
service will not be proxied]. 
  vii) Extract all interfaces to create proxy service [No needed controller 
service will not be proxied]  
  *viii) Build Initialization context with loggers, state managers, kerberos 
etc. Invoke initialization. [ Propose doing this with a mock. Risk does 
validation ever consider the original controller’s state management? 
Kerberos?]* 
  ix) Verify controller service references to prevent issues with instance 
class loading where service api and impls are in same nar but should not be [ 
Doesn’t matter should have already failed on initial controller creation] 
  x) Create new Controller Service Node and Validation context [Don’t need a 
new node just to validate] 
  *xi) Set controller service node name, logging context, [node name not 
needed…. Do we need the logging context? Maybe].* 
  xii) set Invocation handler service node as newly create service node. [ not 
needed proxy won’t be used] 
  *xiii) set thread context back to original thread context class loader* 
 *B) if first time invoke on configuration restored and on added [ Do we need 
controller service lifecycle called? Maybe but we definitely should not call 
any framework methods]* 
3) Put controller Service in process group [ Not needed we’ll be destroying 
after validation] 
4) Set invocation handler to existing node [ Not needed we’ll be destroying 
after validation] 
5) Create loggable components (implement and proxy) [ Not needed we’ll be 
destroying after validation] 
6) set luggable components into existing node and set extension missing [Not 
needed we’ll be destroying after validation] 
7) Refresh properties on existing node [ Not needed we’ll should be able to 
pass properties in directly to verify] 
8) Reset Validation State on existing node [ Not needed we’ll be destroying 
after validation] 
9) trigger validation on existing node. [ Not needed we’ll be destroying after 
validation] 


 

Note: This works fine if the Property defining the driver location is defined 
as a Parameter within a Parameter Context because the apply action in the UI 
reloads the controller service [4]


[1][https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-extension-bundles/nifi-extension-utils/nifi-dbcp-base/src/main/java/org/apache/nifi/dbcp/AbstractDBCPConnectionPool.java#L132C45-L132C117]

 

 
[2][https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java#L541]

[3] 
[https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java#L544]

[4] 
[https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ParameterUpdateManager.java#L368]

 


> Classloader used during Controller Service Verify Configuration missing 
> additional resources
> --------------------------------------------------------------------------------------------
>
>                 Key: NIFI-15365
>                 URL: https://issues.apache.org/jira/browse/NIFI-15365
>             Project: Apache NiFi
>          Issue Type: Bug
>          Components: Core Framework
>    Affects Versions: 2.7.0
>            Reporter: Bob Paulin
>            Priority: Major
>
> When Verifying configuration on a newly created DBCPConnectionPool 
> (Controller Service) the user is presented with an error [1]
> Driver Class found but not loaded: Apply configuration before verifying.
> This is due to the StandardControllerServiceNode.verifyConfiguration method 
> creating a new instance classloader [2] but still using the original 
> controller service [3] that was loaded with the original ControllerService 
> instance class loader any usage of Class.forName with in the controller 
> service (or any included sdks) will not be able to see additional urls 
> included in the new instance classloader [2].  
>  
> *Proposal* (patch in progress)
> For this to work a new temporary controller service must be created with the 
> new instance classloader and verify must be called on the temporary 
> controller service.
> Will look to model this after the component reload that takes the following 
> actions (required or maybe required actions in this process bolded)
> *1) get existing instance class loader* 
>    *a) Save reference to original instance classloader to a variable*
>     b)Close classloader and call on remove [We should not close the 
> classloader as it is still needed or call on remove]
> *2) Create new controller service.* 
>  *A) Invoke build Controller service*
>   *i) Create Instance Class loader.* 
>   *ii) get raw class* 
>   *iii) set thread context class loader as new detected instance class 
> loader* 
>   *iv) Subclass raw class as ControllerService* 
>   *v) Invoke Declared Constructor on class to instantiate impl* 
>   vi) Create invocation handler for implementation [No needed controller 
> service will not be proxied]. 
>   vii) Extract all interfaces to create proxy service [No needed controller 
> service will not be proxied]  
>   *viii) Build Initialization context with loggers, state managers, kerberos 
> etc. Invoke initialization. [ Propose doing this with a mock. Risk does 
> validation ever consider the original controller’s state management? 
> Kerberos?]* 
>   ix) Verify controller service references to prevent issues with instance 
> class loading where service api and impls are in same nar but should not be [ 
> Doesn’t matter should have already failed on initial controller creation] 
>   x) Create new Controller Service Node and Validation context [Don’t need a 
> new node just to validate] 
>   *xi) Set controller service node name, logging context, [node name not 
> needed…. Do we need the logging context? Maybe].* 
>   xii) set Invocation handler service node as newly create service node. [ 
> not needed proxy won’t be used] 
>   *xiii) set thread context back to original thread context class loader* 
>  *B) if first time invoke on configuration restored and on added [ Do we need 
> controller service lifecycle called? Maybe but we definitely should not call 
> any framework methods]* 
> 3) Put controller Service in process group [ Not needed we’ll be destroying 
> after validation] 
> 4) Set invocation handler to existing node [ Not needed we’ll be destroying 
> after validation] 
> 5) Create loggable components (implement and proxy) [ Not needed we’ll be 
> destroying after validation] 
> 6) set luggable components into existing node and set extension missing [Not 
> needed we’ll be destroying after validation] 
> 7) Refresh properties on existing node [ Not needed we’ll should be able to 
> pass properties in directly to verify] 
> 8) Reset Validation State on existing node [ Not needed we’ll be destroying 
> after validation] 
> 9) trigger validation on existing node. [ Not needed we’ll be destroying 
> after validation] 
>  
> Note: This works fine if the Property defining the driver location is defined 
> as a Parameter within a Parameter Context because the apply action in the UI 
> reloads the controller service [4]
> [1][https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-extension-bundles/nifi-extension-utils/nifi-dbcp-base/src/main/java/org/apache/nifi/dbcp/AbstractDBCPConnectionPool.java#L132C45-L132C117]
>  
>  
> [2][https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java#L541]
> [3] 
> [https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java#L544]
> [4] 
> [https://github.com/apache/nifi/blob/09cfea2f5458474ec9f365370ca0b44741a65a93/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ParameterUpdateManager.java#L368]
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to