On 09/04/2020 19:23, Eirik Bjørsnøs wrote:
Alan,
If I read your mail correctly, you are creating "multi-module JAR
files"
where the modules are "exploded" under /META-INF/modules in
${NAME}-${VERSION} directories.
Correct.
Do they need to be "exploded"? If the dependences are automatic modules
then I assume putting the JAR files (without unpacking) into
META-INF/modules should just work without needing a new ModuleFinder
implementation or implementing the exploded equivalent of multi-module
JAR files (or modular multi-release JAR files).
(The reason it should work is that the built-in implementation can work
with paths to locations in virtual file systems. It handles this by
copying the JAR files from the virtual file system to the default file
system so that it can be opened with the JarFile API. It does this in
order to support signed JARs as the zip file system provider doesn't
have any support for validating signatures. It's possible this approach
isn't very efficient, also we haven't looked into interactions with the
cron jobs that clean tmpfs so there may be a bit more work needed here).
To achieve this, I had to copy / replicate quite a bit of code from
the ModulePath class which is not accessible outside java.base.
It wasn't all that hard, I just wasn't happy with the amount of
classes / methods I had to copy from java.base only to slightly modify
them
This includes:
Code to create / build the ModuleDescriptor (stolen from
deriveModuleDescriptor)
Code to clean the artifactId used to produce the automatic name
(Stolen from cleanModuleName, Patterns and Checks)
Duplication of ExplodedModuleReader which also dragged in Resources.
Understood although you probably don't need a deep copy of everything as
there is a lot in exploded module reader related to potential security
and traversal on the default file system that is less interesting in JAR
files.
:
The runtime loads a graph of module layers, each containing one or
more modules. Layers may depend on other layers, forming a DAG with
corresponding class loader delegation.
When the runtime detects that a module needs to be redeployed, the
transitive closure of depending layers is removed from the graph and
new module layers are created and added to the graph.
Services are bound using dependency injection, so there's also a DAG
of service dependencies. This allows restarting services which are
affected by the redeploy, either because they are provided from
updated modules or because they consume services from updated modules.
So not really hot-deploying in the JVM sense, but still pretty fast
and developer-friendly.
My demo has a module which provides a JAX-RS resource which is
consumed by a Jersey module which provides an HttpServlet which is
again consumed by a Jetty module which deploys the servlet in a
servlet context.
Redeploying the module containing the JAX-RS resource takes something
like 50ms IIRC.
This sounds very interesting. I'm sure there are several people here
that would be interesting in seeing a write-up or demo of this. I'm
curious if the service wiring make use of the existing uses/provides or
something else. I'm also curious if you've run into any issues with
multi-parent configurations as that is an area that might need attention
some day.
-Alan