Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

To be Reviewed By: August 20th27th, 2020

Authors: Patrick Johnson

...

Many of Geode's sub-projects depend on one another. In the world of the of ClassLoader Isolation work, those dependencies are explicitly defined when modules are loaded and linked to one another. For the most part, this is fine as JBoss is designed to handle dependencies between modules. However, some modules have JBoss Modules supports dependencies between modules by linking them to each other when they are loaded. To link modules, we explicitly define which modules a given module depends on when we define it. While this works for most relationships, it is insufficient for some types of bidirectional dependencies (A dependents on B and B depends on A). Explicit bidirectional dependencies, where A declares that it depends on B and B declares it depends on A, while supported by JBoss, are not allowed by Gradle–it would complain about them when building. What we see instead is something like:

A depending on B because B defines an interface that A implements and B doesn't explicitly depend on A, but assumes that A is on the classpath when trying to load implementations of the interface.

An example of this is logging; geode-log4j explicitly depends on geode-logging, and geode-logging, while it doesn't state it, requires geode-log4j to be on the classpath. There is also a similar relationship between geode-core and geode-http-service. Normally, this is these kinds of relationships are fine because everything is on the classpath, but when modularized, modules like geode-logging won't be able to access modules like geode-log4j unless it explicitly depends on it, but if that were the case, there would be a cyclical dependency, which is not allowedthat they don't explicitly depend on. We need a way to resolve these bidirectional dependencies to allow modules to access the resources they need.

Anti-Goals

This proposal is only intended to solve the problems of allowing bidirectional dependencies between modules and the loading/unloading of modules without having to reload all modules and is unconcerned with...

...

The proposed solution is to introduce a linking module, which will contain no code and instead consist only of dependencies. This linking module will depend on every other module and every other module will depend on it, as shown below.

Gliffy Diagram
size600
namelinking-module
pagePin3

This creates a path between all modules so because any module can access any other module via the linking module, allowing bidirectional relationships can to be resolved. This will have a similar effect to having everything on the classpath , but differs in that but prevents conflicts because modules will look inside themselves first before getting classes from other modules. This allows modules to access whatever they need, without allowing version conflicts, like we would get with everything on the classpathand only look outside when they reference a type that they don't define or are explicitly loading implementations of an interface.


The linking module will link to other modules by creating/recreating itself each time a module is loaded/unloaded. All modules will be made to depend on the linking module when they are created. The linking module will then unload and unregister itself, get the updated list of loaded modules, and reregister itself with dependencies on all current modules. Because the linking module's name stays the same, the modules that depend on it will still be able to find it after it refreshes itself.

Changes and Additions to Public Interfaces

...

No backward compatibility impact.

Prior Art

Break An alternative would be to break all bidirectional dependencies between sub-projects.

...