Opened 6 years ago

Closed 5 years ago

#2027 closed enhancement (fixed)

Improve inter-communication between extensions

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

Description

Due to how classloading is implemented in Java, Tomcat and the BASE core the possibilities for communication between extensions is very limited. Actually, the extension system has been designed to make each extension as independent as possible from other extensions. This is something that among other things makes it possible to install and update extensions without having to restart Tomcat.

There are currently only a few possibilities for extensions to communicate:

  • Using a common class/interface defined by BASE. For example a Button instance can be passed between extensions since the Button class is defined by the BASE core. However, the Button can't be passed directly. It has to be passed via BASE as a middle-hand using the extensions API. It's doable but complicated and of limited use.
  • Using a Job and Plug-in. An extension can define a job for any plug-in, even plug-ins that are part of other extensions. Since #2026 it is even possible to execute the job without saving it to the database. The drawback is that parameters need to be passed using a few basic Java types (eg. strings, numbers, etc). This method is more or less just as complicated to use as the one above.
  • Using a Servlet. An extension can invoke any servlet that it wants. This is mostly useful when using the GUI from a browser and is already in use for Reggie/LabEnv integration (http://baseplugins.thep.lu.se/ticket/530). This method is of limited use from the server-side.

It would be nice to make it possible for extensions to directly use classes and methods defined by other extensions. In one sense it is not very complex to do. Simply make sure that the classloaders are linked so that one is the parent of the other. This information could for example be stored in the MANIFEST.MF file. In reality a lot of issues may arise:

  • What if one extension want to use functionality from two or more other extensions? Then it need multiple parents.
  • Updating extensions must still work. A new version of an extension must be picked up by dependencies without having to restart Tomcat.
  • Class collisions. There is already a chance that class collisions occur with classes that are shipped with BASE and classes that are shipped with an extension. It has been solved by stating that extensions should not duplicate classes that are shipped with BASE. The risk of collisions increases if one also has to consider dependencies between extensions. Extensions with multiple parents may create impossible situations.
  • Class loading search order. An extension may specify if the parent class loader is searched before or after searching it's own classloader. With dependencies on other extensions the search order may become even more important. A different search order may solve some types of class collisions.
  • And probably a lot more that I don't know about yet...

Change History (9)

comment:1 Changed 6 years ago by Nicklas Nordborg

(In [7190]) References #2027: Improve inter-communication between extensions

Prepared a test case where one extension (ExtensionThree.jar) is using classes from two other extensions (ExtensionOne.jar and ExtensionTwo.jar).

The idea is to specify the extensions that are needed in the MANIFEST.MF file with the X-Extension-Class-Path setting.

It should not be too hard to modify the JarClassLoader.loadClass() method so that it can delegate to the class loader for other extensions.

comment:2 Changed 6 years ago by Nicklas Nordborg

(In [7191]) References #2027: Improve inter-communication between extensions

This file should have been included in [7190].

comment:3 Changed 6 years ago by Nicklas Nordborg

(In [7192]) References #2027: Improve inter-communication between extensions

The original idea that X-Extension-Class-Path should specify extensions that are needed did not work. The extension system may load code (eg. ActionFactory and Action instances; see Three.java in this change) during the initialization of the extension system. The extensions are not registered until everything has been properly setup. If one extension then need to use another extension it will not be able to find it since it has not yet been registered.

The new approach is to simply only use the Class-Path attribute in the MANIFEST.MF file. If the referenced JAR file already exists it is no longer loaded immediately. Instead a proxy instance is created which will create the real class loader when needed. JAR files that are packages inside the META-INF/lib directory are not affected by this change. The code is still loaded before the extension system has been setup but since we now have the filename we do not have to ask the extension system to translate. The drawback is that extensions must be installed with the original filename.

This change also breaks the findResource() and hasChanged() methods which no longer searches the proxied JAR files.

comment:4 Changed 6 years ago by Nicklas Nordborg

(In [7193]) References #2027: Improve inter-communication between extensions

Adding a test to the TestJarClassLoader class. The new test works, but the new feature has broken the X-Delegate-First option since search order is now different.

Also noted that the JarPlugin.jar has a reference to an old hibernate JAR file. Don't know why it wasn't detected when switching to Hibernate 5 (#1979).

comment:5 Changed 6 years ago by Nicklas Nordborg

(In [7194]) References #2027: Improve inter-communication between extensions

Switches search order so that the parent class loader is searched last. Fixed path to Hibernate JAR file.

comment:6 Changed 6 years ago by Nicklas Nordborg

(In [7195]) References #2027: Improve inter-communication between extensions

Preparing a test case for loading resources from the JAR files using JarClassLoader.getResource() and JarClassLoader.getResources(). A bit messy in the build script to make sure that all files end up where they are needed.

comment:7 Changed 6 years ago by Nicklas Nordborg

(In [7196]) References #2027: Improve inter-communication between extensions

Fixed the findResource(), findResources() and hasChanged() methods so that they also search the proxied JAR files.

comment:8 Changed 5 years ago by Nicklas Nordborg

Owner: changed from everyone to Nicklas Nordborg
Status: newassigned

comment:9 Changed 5 years ago by Nicklas Nordborg

Resolution: fixed
Status: assignedclosed
Note: See TracTickets for help on using tickets.