Re: Loading an automatic module from an exploded directory

2020-04-09 Thread Eirik Bjørsnøs
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.


> It shouldn't be too hard to create your
> own ModuleFinder that finds modules under META-INF/modules. This would
> mean implementing ModuleFinder rather trying to use
> ModuleFinder.of(Path...).


This is what my implementation currently does.

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.

I assume you've found ModuleDescriptor.read to
> read/parse the module-info.class of explicit modules.


I don't actually need to read the explicit modules. I just check that they
have module-info.class and use let ModuleFinder.of do the rest of the job.


> You are right that
> it would require code to scan directory trees, at least the equivalent
> of automatic modules, maybe for explicit modules too. However, it
> shouldn't be too hard. Have you tried the zip file system provider? That
> would allow you to open the JAR file as a file system so you can use the
> file system API.
>
>
Yes, I'm opening a ZIP filesystem on the single-jar and using the file
system API to navigate it.


> > I have also identify an additional use case which is to allow
> hot-deploying
> > automatic modules during development from target/classes using a Maven
> > plugin.
> >
> I'm not sure how to interpret this but just to say that the unit of
> replacement is the module layer, you can't replace modules in a layer
> and/or dynamically change the set of packages in a loaded module.
>

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.

Cheers,
Eirik.


Re: Loading an automatic module from an exploded directory

2020-04-09 Thread Alan Bateman

On 09/04/2020 16:42, Eirik Bjørsnøs wrote:

The current implementation of automatic modules seems to assume that an
automatic module is always packaged as a jar file.

I'm working on a module runtime where this is not always the case, and the
limitation has become a bit of a challenge.

I want to package applications (modules + runtime) at build time into a
single jar for distribution.

The runtime loads modules from directories within its own jar.  This means
that ModuleFinder.of(Path..) receives module locations in the form:

jar:file:///path/to/single.jar!/META-INF/modules/module-1.0/

This works fine as long as modules are explicit. (With the unrelated
limitation that the multi-release feature also seem to assume jar files)
The only packaging format for automatic modules that Java SE defines is 
JAR files. The "Multi-release JAR files" feature is also JAR file only.


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. It shouldn't be too hard to create your 
own ModuleFinder that finds modules under META-INF/modules. This would 
mean implementing ModuleFinder rather trying to use 
ModuleFinder.of(Path...). I assume you've found ModuleDescriptor.read to 
read/parse the module-info.class of explicit modules. You are right that 
it would require code to scan directory trees, at least the equivalent 
of automatic modules, maybe for explicit modules too. However, it 
shouldn't be too hard. Have you tried the zip file system provider? That 
would allow you to open the JAR file as a file system so you can use the 
file system API.



:

I have also identify an additional use case which is to allow hot-deploying
automatic modules during development from target/classes using a Maven
plugin.

I'm not sure how to interpret this but just to say that the unit of 
replacement is the module layer, you can't replace modules in a layer 
and/or dynamically change the set of packages in a loaded module.


-Alan



Loading an automatic module from an exploded directory

2020-04-09 Thread Eirik Bjørsnøs
The current implementation of automatic modules seems to assume that an
automatic module is always packaged as a jar file.

I'm working on a module runtime where this is not always the case, and the
limitation has become a bit of a challenge.

I want to package applications (modules + runtime) at build time into a
single jar for distribution.

The runtime loads modules from directories within its own jar.  This means
that ModuleFinder.of(Path..) receives module locations in the form:

jar:file:///path/to/single.jar!/META-INF/modules/module-1.0/

This works fine as long as modules are explicit. (With the unrelated
limitation that the multi-release feature also seem to assume jar files)

Loading automatic modules this way is not as easy.

First, it requires duplicating non-trivial amounts of private, slightly
intricate code from ModulePath.deriveModuleDescriptor and friends.

Second, since deriveModuleDescriptor assumes jars on disk, it uses JarFile
scanning to find all packages to add to the automatic module. So the
scanning code must be rewritten to scan for class files (and
META-INF/services/ files) within the sub-directory in the main jar instead.

I have also identify an additional use case which is to allow hot-deploying
automatic modules during development from target/classes using a Maven
plugin.

These use cases are probably on the fringes of what the module system was
designed to support, but it did made me wonder if some small changes maybe
could make this easier.

Availability of some public API to create ModuleFinder for an automatic
module loaded in non-standard ways would be helpful.

The 'non-standardness' I have been able to identity in my case is:

1: The fallback name for the automatic module. In my case, there's no jar
file name to investigate, so instead I use the Maven artifactId directly
(after cleaning it)

2: The set of paths to use as input for identifying packages in the module
and the set of service files to use as input for defining 'provides'
attributes.

Here's a strawman API which I think would support my use case :

ModuleFinder auto = ModuleFinder.automatic(Path location, String
defaultName, Set packages, Set serviceNames)

Any feedback, ideas or similar experiences would be appreciated.

Cheers,
Eirik.


RE: RFR: 8242039: Improve jlink VersionPropsPlugin

2020-04-09 Thread Langer, Christoph
Hi Claes and Mark,

thanks again for your inputs.

I'll push this with Claes' review then.

Best regards
Christoph

> -Original Message-
> From: core-libs-dev  On Behalf
> Of Claes Redestad
> Sent: Mittwoch, 8. April 2020 00:12
> To: core-libs-...@openjdk.java.net
> Subject: Re: RFR: 8242039: Improve jlink VersionPropsPlugin
> 
> 
> 
> On 2020-04-03 15:36, Langer, Christoph wrote:
> > Eventually I came up with this result and then I also asked myself the
> question whether the new complexity was worth the benefit. I answered
> myself with a yes (though definitely not a clear one ), and that's why I
> proposed the change. After all, the new complexity isn't huge...
> 
> I don't mind the cleaned up patch[1].
> 
> It also gets rid of the constants being replaced, which I assume will
> otherwise be loaded and kept on the heap and in the string table
> forever. While unlikely to cause confusion, I'd argue that not finding
> the value replaced in heap dumps might be of some value.
> 
> /Claes
> 
> [1] http://cr.openjdk.java.net/~clanger/webrevs/8242039.1/