Opened 4 years ago

Closed 4 years ago

#2041 closed enhancement (fixed)

Support for extension points within extensions

Reported by: Nicklas Nordborg Owned by: everyone
Priority: major Milestone: BASE 3.10
Component: core Version:
Keywords: Cc:

Description

It would be nice if we could get this to work. In theory the concept is not very complicated. An extension may define additional extension points that are then extended by other extensions. In practice we get a lot of problems with initialization and class loading. Problems found so far:

  • The extension points are not loaded at startup. The core Application class will only load extensions points defined by the net.sf.basedb.core package and the web client will only load extension points defined by the net.sf.basedb.clients.web package. To enable the extension points a server admin must go to the "Administrate -> Plugins & Extensions -> Overview" page and re-install the extension. We could of course require other extensions to use those packages as well, but it would be better to fix the issue so that extension points are loaded at startup.
  • Updating a modified extension results in a ClassCastException:
    Action 'net.sf.basedb.opengrid.test.TestJobCompletionHandlerFactory@61a3083f' 
    created by extension 'net.sf.basedb.opengrid.test-job-complete' 
    is not of the expected class 
    'net.sf.basedb.opengrid.service.JobCompletionHandler'
    
    java.lang.ClassCastException:
    net.sf.basedb.opengrid.test.TestJobCompletionHandlerFactory@61a3083f -> net.sf.basedb.opengrid.service.JobCompletionHandler
      at net.sf.basedb.util.extensions.ActionIterator.validActions(ActionIterator.java:231)
      at net.sf.basedb.util.extensions.ActionIterator.hasNext(ActionIterator.java:114)
      at net.sf.basedb.util.extensions.ExtensionsInvoker.render(ExtensionsInvoker.java:167)
    ...
    

I guess that somewhere in BASE there is something that is not thrown out when the new class loader is created for the updated jar file.

  • The above class cast problem happened when both the extension point and extension was defined in the same JAR file. I have not tested to created extensions in separate JAR files. I guess that will be a bit more problematic.

Change History (9)

comment:1 Changed 4 years ago by Nicklas Nordborg

(In [7224]) References #2041: Support for extension points within extensions

Adding more debug-level logging to see what is going on when initializing the extension system. There is one step in the core that only load some extensions and one step in the web client that load other extensions. Everything that falls outside of that is not loaded at all (at least until a manual re-install is triggered from the web interface).

I think it should be safe to remove the filtering from the web client initialization and let it load all extensions. It seems like it should not touch already registered extensions.

Regarding the ClassCastException mentioned in the second point above I think it is a result of the Registry.RegisteredExtensionPoint.update() only is changing the classloader and not the action class.

comment:2 Changed 4 years ago by Nicklas Nordborg

(In [7225]) References #2041: Support for extension points within extensions

This seems to fix the ClassCastException when re-installing an updated extension/extension point in the same JAR file.

comment:3 Changed 4 years ago by Nicklas Nordborg

(In [7226]) References #2041: Support for extension points within extensions

Adding more debug logging to see what it going on when scanning for updated extensions.

If using the ExtensionsFile.wasModified() method instead of the ExtensionsFile.checkModified() method (which has already been called in the ExtensionsControl.scanForChanges() method) changes in one extension will automatically be detected in other extensions depending on the same JAR file (this was implemented in [7192] and [7196]).

However it only works once. If the server admin simply closes the extension installation wizard and then open it again, only the JAR file that was actually changed will be detected and not those that depend on it.

I'll need to set up a better test case. One idea is to add an example extension point to the "Example code package" (http://baseplugins.thep.lu.se/wiki/net.sf.basedb.examplecode) that we can use for testing purposes from other extensions.

comment:4 Changed 4 years ago by Nicklas Nordborg

comment:5 Changed 4 years ago by Nicklas Nordborg

(In [7227]) References #2041: Support for extension points within extensions

This should get rid of the problem that a scan for changes only once. The problem was that if a change was detected in a JAR file, the ExtensionsFile.validate() method was called which, as a side-effect, nullified the current JAR class loader. This caused a second scan to think that everyting was up to date. The class loader is no longer reset when validating, but only if a change has been detected and the getClassLoader() method is called.

comment:6 Changed 4 years ago by Nicklas Nordborg

(In [7228]) References #2041: Support for extension points within extensions

Implemented a better solution for re-installing an updated extension. The class loader is now reset as part of the re-installation process and not as part of the scanning-for-changes process. The existing ResetErrorFlagProcessor class has been deprecated and replaced with the more generic ResetProcessor which is able to reset the error flag, class loader and any other things we might need to reset in the future when doing a re-installation.

comment:7 Changed 4 years ago by Nicklas Nordborg

(In [7229]) References #2041: Support for extension points within extensions

Removing the filter that prevents extensions not in the "net.sf.basedb.clients.web" package from loading at startup.

comment:8 Changed 4 years ago by Nicklas Nordborg

(In [7230]) References #2041: Support for extension points within extensions

Updating documentation to refer to the new implementation.

comment:9 Changed 4 years ago by Nicklas Nordborg

Resolution: fixed
Status: newclosed

The tests in the example code seems to work.

Note: See TracTickets for help on using tickets.