Opened 8 years ago
Closed 8 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 theButton
class is defined by the BASE core. However, theButton
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 by , 8 years ago
comment:2 by , 8 years ago
comment:3 by , 8 years ago
(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 by , 8 years ago
(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 by , 8 years ago
comment:6 by , 8 years ago
comment:7 by , 8 years ago
comment:8 by , 8 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:9 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
(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
andExtensionTwo.jar
).The idea is to specify the extensions that are needed in the
MANIFEST.MF
file with theX-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.