Re[2]: add-opens for dynamically created layers

2020-11-16 Thread Alex Orlov

Hello Alan,
 
Thank you very much for your help. With ModuleLayer.Controller I solved the 
problem.
Do I understand it correctly — it is impossible to get reference to boot layer 
controller,
isn’t it?
 
 
--
Best regards, Alex Orlov
 
  
>Понедельник, 16 ноября 2020, 22:27 +03:00 от Alan Bateman 
>:
> 
>On 16/11/2020 18:35, Alex Orlov wrote:
>> :
>>
>> When I start my application I get:
>>
>> java.lang.IllegalAccessError: class 
>> org.springframework.core.log.CompositeLog (in module spring.core) cannot 
>> access class org.apache.commons.logging.impl.NoOpLog (in module 
>> org.apache.commons.logging) because module org.apache.commons.logging does 
>> not export org.apache.commons.logging.impl to module spring.core.
>>
>> To fix it, I wanted in the Framework dynamically addOpens to module 
>> (module.addOpens(...)), however, I got
>>
>> Caused by: java.lang.IllegalCallerException: org.apache.commons.logging.impl 
>> is not open to module fw.module.
>>
>> To fix it I added jvm argument:
>>
>> --add-opens 
>> org.apache.commons.logging/org.apache.commons.logging.impl=fw.module \
>>
>> However, it didn’t help. It seems to me that jvm arguments add-opens works 
>> only when the module that must open
>> its package is in boot layer, but in my situation fw.module that is in boot 
>> layer knows nothing about web application modules. The static 
>> defineModules methods return a ModuleLayer.Controller
>that can be used to export or open any package of any module in the
>layer to any other module. It's the equivalent of using the
>--add-exports or --add-opens on the command line to export or open
>packages of modules in the boot layer. So in this case you should be
>able to use the ModuleLayer.Controller for (I assume) the "Web
>Application Layer" to export
>org.apache.commons.logging/org.apache.commons.logging.impl to
>spring.core. That can be a workaround using spring.core and
>org.apache.commons.logging agree sort out their differences on whether
>org.apache.commons.logging.impl is part of the supported API or not.
>
>-Alan.
 

add-opens for dynamically created layers

2020-11-16 Thread Alex Orlov

Hello all,
 
I have the following structure
 
I want to create the following layer structure:
 
+++
+ Boot Layer +
+++
       |
       +
       + Web Server Layer +
       +
                         |
                         
                         + Web Application Layer +
                         
 
In BootLayer I have a Framework that manages these layers.
 
In Web Application Layer I have Spring 5 and I need to direct its logs to 
slf4j, so I need to use jcl-over-slf4j
( 
https://github.com/qos-ch/slf4j/blob/v_1.8.0_beta2/jcl-over-slf4j/src/main/java/module-info.java
 ).
 
When I start my application I get:
 
java.lang.IllegalAccessError: class org.springframework.core.log.CompositeLog 
(in module spring.core) cannot access class 
org.apache.commons.logging.impl.NoOpLog (in module org.apache.commons.logging) 
because module org.apache.commons.logging does not export 
org.apache.commons.logging.impl to module spring.core.
 
To fix it, I wanted in the Framework dynamically addOpens to module 
(module.addOpens(...)), however, I got
 
Caused by: java.lang.IllegalCallerException: org.apache.commons.logging.impl is 
not open to module fw.module.
 
To fix it I added jvm argument:
 
--add-opens 
org.apache.commons.logging/org.apache.commons.logging.impl=fw.module \
 
However, it didn’t help. It seems to me that jvm arguments add-opens works only 
when the module that must open
its package is in boot layer, but in my situation fw.module that is in boot 
layer knows nothing about web application modules.
 
So, could anyone say how to fix this problem?
 
 
--
Best regards, Alex Orlov

Re: add-opens for dynamically created layers

2020-11-16 Thread Alan Bateman

On 16/11/2020 18:35, Alex Orlov wrote:

:
  
When I start my application I get:
  
java.lang.IllegalAccessError: class org.springframework.core.log.CompositeLog (in module spring.core) cannot access class org.apache.commons.logging.impl.NoOpLog (in module org.apache.commons.logging) because module org.apache.commons.logging does not export org.apache.commons.logging.impl to module spring.core.
  
To fix it, I wanted in the Framework dynamically addOpens to module (module.addOpens(...)), however, I got
  
Caused by: java.lang.IllegalCallerException: org.apache.commons.logging.impl is not open to module fw.module.
  
To fix it I added jvm argument:
  
--add-opens org.apache.commons.logging/org.apache.commons.logging.impl=fw.module \
  
However, it didn’t help. It seems to me that jvm arguments add-opens works only when the module that must open

its package is in boot layer, but in my situation fw.module that is in boot 
layer knows nothing about web application modules.
The static defineModules methods return a ModuleLayer.Controller 
that can be used to export or open any package of any module in the 
layer to any other module. It's the equivalent of using the 
--add-exports or --add-opens on the command line to export or open 
packages of modules in the boot layer. So in this case you should be 
able to use the ModuleLayer.Controller for (I assume) the "Web 
Application Layer" to export 
org.apache.commons.logging/org.apache.commons.logging.impl to 
spring.core. That can be a workaround using spring.core and 
org.apache.commons.logging agree sort out their differences on whether 
org.apache.commons.logging.impl is part of the supported API or not.


-Alan.


Re[2]: How to do “--add-modules” with dynamically created layer in JPMS?

2020-11-16 Thread Alex Orlov

Hello Alan,
 
Thank you for such detailed answer. I read it with attention, but still don’t 
know how to solve my situation.
Maybe may question didn’t provide all details, so here they are.
 
I want to create the following layer structure:
 
+++
+ Boot Layer +
+++
       |
       +
       + Web Server Layer +
       +
                         |
                         
                         + Web Application Layer +
                         
 
So, we have always one boot layer (it’s clear), one web server layer, and 
multiple web application layers. At
the same time all web application layers have one parent — web server layer. 
Boot layer doesn’t know and mustn’t know
about any child layer modules So it is impossible to add all modules to 
boot layer!
 
In web server layer I have servlet container (Jetty) and rest implementation 
(Jersey). When I create web server layer
 
Configuration cf = parentLayer.configuration().resolveAndBind(moduleFinder, 
ModuleFinder.of(), moduleNames);
ModuleLayer layer = parentLayer.defineModulesWithOneLoader(cf, 
parentClassLoader);
 
I add to it all modules of jetty, jersey and their dependencies. At the same 
time jetty knows nothing about jersey. When web server layer is created one of 
its modules starts Jetty.
 
So, when does jersey start? It starts only when web application layer is 
created with .war file that has web.xml with jersey servlet. For example:
 

    JerseyServlet
    
org.glassfish.jersey.servlet.ServletContainer

 
So, in such configuration, when web server layer is created no one can know if 
jersey will be used.
 
What what does JPMS do? It ignores all jersey modules including all its 
dependencies (including API). So, the question.
How to ask JPMS not to ignore modules that it must add to layer?
 
 
 
 
 
--
Best regards, Alex Orlov
 
  
>Понедельник, 16 ноября 2020, 11:20 +03:00 от Alan Bateman 
>:
> 
>On 15/11/2020 19:16, Alex Orlov wrote:
>> Hi all,
>>
>> I create JPMS layer this way:
>>
>> Configuration cf = parentLayer.configuration().resolveAndBind(moduleFinder, 
>> ModuleFinder.of(), moduleNames);
>> ModuleLayer layer = parentLayer.defineModulesWithOneLoader(cf, 
>> parentClassLoader);
>>
>> And I have a problem with adding implementation modules. These 
>> implementation modules are ignored by JPMS because classes from these 
>> modules are not used anywhere (it is clear, that classes from API modules 
>> are used). So, JPMS doesn't add these modules to layer.
>>
>> As I understand, if I spoke about implementation modules on boot layer, I 
>> could use --add-modules jvm argument. However, I couldn't find any 
>> information how to force JPMS load my module (even if its classes are not 
>> used) for dynamically created layers.
>>
>> Could anyone say how to do it? It would be useful if you could give an 
>> example of "implementation
>module". I can't tell if you mean a jdk.* module, a service provider
>module that doesn't export an API, or something else.
>
>In any case, I think the picture you are describing is a module that is
>observable, either in the run-time image or on module path. The module
>is not resolved at startup (and so is not in the boot layer) because the
>initial module that you specify with `java -m` doesn't transitively
>require it and it doesn't provide an implementation of a service that
>any of the other resolved modules use.
>
>The summary is a module layer is immutable and there isn't any way to
>add modules to a module layer once it has been created. For what you are
>doing then maybe `--add-modules ALL-SYSTEM` can be used as workaround.
>This will ensure that all system/platform modules are in the boot layer
>as these modules cannot be loaded into a child layer (Johannes's suggest
>to specify the module name to resolveAndBind will not work for java.*
>modules as they cannot be loaded into child layers, his suggestion may
>work for other modules).
>
>One other point to mention is that the original set of requirement
>envisaged some means to augment the set of platform modules at run-time.
>We didn't get to that requirement except for the limited scenario that
>is tools loading the JMX agent or a java agent into a running VM. These
>limited scenario involve loading the jdk.management.agent or
>java.instrument modules and that is some with a special child layer
>rather than augmenting the boot layer. This partial solution, along with
>`--add-modules ALL-SYSTEM`as a workaround for the general cases, has
>been sufficient to date.
>
>-Alan
 

Re: How to do “--add-modules” with dynamically created layer in JPMS?

2020-11-16 Thread Alan Bateman

On 16/11/2020 09:17, Alex Orlov wrote:

Hello Alan,
Thank you for such detailed answer. I read it with attention, but 
still don’t know how to solve my situation.

Maybe may question didn’t provide all details, so here they are.
I want to create the following layer structure:
+++
+ Boot Layer +
+++
       |
       +
       + Web Server Layer +
       +
                         |
                         
                         + Web Application Layer +
                         
So, we have always one boot layer (it’s clear), one web server layer, 
and multiple web application layers. At
the same time all web application layers have one parent — web server 
layer. Boot layer doesn’t know and mustn’t know
about any child layer modules So it is impossible to add all 
modules to boot layer!
In web server layer I have servlet container (Jetty) and rest 
implementation (Jersey). When I create web server layer
Configuration cf = 
parentLayer.configuration().resolveAndBind(moduleFinder, 
ModuleFinder.of(), moduleNames);
ModuleLayer layer = parentLayer.defineModulesWithOneLoader(cf, 
parentClassLoader);
I add to it all modules of jetty, jersey and their dependencies. At 
the same time jetty knows nothing about jersey. When web server layer 
is created one of its modules starts Jetty.
So, when does jersey start? It starts only when web application layer 
is created with .war file that has web.xml with jersey servlet. For 
example:


    JerseyServlet
org.glassfish.jersey.servlet.ServletContainer

So, in such configuration, when web server layer is created no one can 
know if jersey will be used.
What what does JPMS do? It ignores all jersey modules including all 
its dependencies (including API). So, the question.

How to ask JPMS not to ignore modules that it must add to layer?


Thanks for the diagram, and names, of the module layers.

If I read your mail correctly then you are saying that the Jersey module 
is observable when you create the configuration for "Web Server Layer". 
It is not resolved because it's not in the set of root modules that you 
specify to resolveAndBind. It is also not required by any of the modules 
that end up in the configuration. This should not be a surprise. If the 
intention for "Web Server Layer" to contain Jersey and other modules 
that web applications may need then you will need to add them to the set 
of root modules ("moduleNames" in your code fragment. If the modules are 
completely unrelated then you might want to scan them so that 
"moduleNames" has the names of the modules that export an API.


Does the .war file containing "JerseyServlet" have a module-info.class? 
I'm curious if it declares "requires Jersey" as I would expect that the 
resolve or resolveAndBind for the web application will fail if it 
requires Jersey and it is not observable or is not in the parent layer.


-Alan


Re: Re[2]: How to do “--add-modules” with dynamically created layer in JPMS?

2020-11-16 Thread Christian Stein
Hi Alex,

Perhaps a deeper look how Layrry works under the hood does help:
https://github.com/moditect/layrry
If I'm not mistaken, your use-case seems very similar to those Layrry tries
to cope with.

Cheers,
Christian


On Mon, Nov 16, 2020 at 10:17 AM Alex Orlov  wrote:

>
> Hello Alan,
>
> Thank you for such detailed answer. I read it with attention, but still
> don’t know how to solve my situation.
> Maybe may question didn’t provide all details, so here they are.
>
> I want to create the following layer structure:
>
> +++
> + Boot Layer +
> +++
>|
>+
>+ Web Server Layer +
>+
>  |
>  
>  + Web Application Layer +
>  
>
> So, we have always one boot layer (it’s clear), one web server layer, and
> multiple web application layers. At
> the same time all web application layers have one parent — web server
> layer. Boot layer doesn’t know and mustn’t know
> about any child layer modules So it is impossible to add all modules
> to boot layer!
>
> In web server layer I have servlet container (Jetty) and rest
> implementation (Jersey). When I create web server layer
>
> Configuration cf =
> parentLayer.configuration().resolveAndBind(moduleFinder, ModuleFinder.of(),
> moduleNames);
> ModuleLayer layer = parentLayer.defineModulesWithOneLoader(cf,
> parentClassLoader);
>
> I add to it all modules of jetty, jersey and their dependencies. At the
> same time jetty knows nothing about jersey. When web server layer is
> created one of its modules starts Jetty.
>
> So, when does jersey start? It starts only when web application layer is
> created with .war file that has web.xml with jersey servlet. For example:
>
> 
> JerseyServlet
>
> org.glassfish.jersey.servlet.ServletContainer
> 
>
> So, in such configuration, when web server layer is created no one can
> know if jersey will be used.
>
> What what does JPMS do? It ignores all jersey modules including all its
> dependencies (including API). So, the question.
> How to ask JPMS not to ignore modules that it must add to layer?
>
>
>
>
>
> --
> Best regards, Alex Orlov
>
>
> >Понедельник, 16 ноября 2020, 11:20 +03:00 от Alan Bateman <
> alan.bate...@oracle.com>:
> >
> >On 15/11/2020 19:16, Alex Orlov wrote:
> >> Hi all,
> >>
> >> I create JPMS layer this way:
> >>
> >> Configuration cf =
> parentLayer.configuration().resolveAndBind(moduleFinder, ModuleFinder.of(),
> moduleNames);
> >> ModuleLayer layer = parentLayer.defineModulesWithOneLoader(cf,
> parentClassLoader);
> >>
> >> And I have a problem with adding implementation modules. These
> implementation modules are ignored by JPMS because classes from these
> modules are not used anywhere (it is clear, that classes from API modules
> are used). So, JPMS doesn't add these modules to layer.
> >>
> >> As I understand, if I spoke about implementation modules on boot layer,
> I could use --add-modules jvm argument. However, I couldn't find any
> information how to force JPMS load my module (even if its classes are not
> used) for dynamically created layers.
> >>
> >> Could anyone say how to do it? It would be useful if you could give an
> example of "implementation
> >module". I can't tell if you mean a jdk.* module, a service provider
> >module that doesn't export an API, or something else.
> >
> >In any case, I think the picture you are describing is a module that is
> >observable, either in the run-time image or on module path. The module
> >is not resolved at startup (and so is not in the boot layer) because the
> >initial module that you specify with `java -m` doesn't transitively
> >require it and it doesn't provide an implementation of a service that
> >any of the other resolved modules use.
> >
> >The summary is a module layer is immutable and there isn't any way to
> >add modules to a module layer once it has been created. For what you are
> >doing then maybe `--add-modules ALL-SYSTEM` can be used as workaround.
> >This will ensure that all system/platform modules are in the boot layer
> >as these modules cannot be loaded into a child layer (Johannes's suggest
> >to specify the module name to resolveAndBind will not work for java.*
> >modules as they cannot be loaded into child layers, his suggestion may
> >work for other modules).
> >
> >One other point to mention is that the original set of requirement
> >envisaged some means to augment the set of platform modules at run-time.
> >We didn't get to that requirement except for the limited scenario that
> >is tools loading the JMX agent or a java agent into a running VM. These
> >limited scenario involve loading the jdk.management.agent or
> >java.instrument modules and that is some with a special child layer
> >rather than augmenting the boot layer. This partial solution, along with
> >`--add-modules ALL-SYSTEM`as a workaround for the 

Re: How to do “--add-modules” with dynamically created layer in JPMS?

2020-11-16 Thread Alan Bateman

On 15/11/2020 19:16, Alex Orlov wrote:

Hi all,
  
I create JPMS layer this way:
  
Configuration cf = parentLayer.configuration().resolveAndBind(moduleFinder, ModuleFinder.of(), moduleNames);

ModuleLayer layer = parentLayer.defineModulesWithOneLoader(cf, 
parentClassLoader);
  
And I have a problem with adding implementation modules. These implementation modules are ignored by JPMS because classes from these modules are not used anywhere (it is clear, that classes from API modules are used). So, JPMS doesn't add these modules to layer.
  
As I understand, if I spoke about implementation modules on boot layer, I could use --add-modules jvm argument. However, I couldn't find any information how to force JPMS load my module (even if its classes are not used) for dynamically created layers.
  
Could anyone say how to do it?
It would be useful if you could give an example of "implementation 
module". I can't tell if you mean a jdk.* module, a service provider 
module that doesn't export an API, or something else.


In any case, I think the picture you are describing is a module that is 
observable, either in the run-time image or on module path. The module 
is not resolved at startup (and so is not in the boot layer) because the 
initial module that you specify with `java -m` doesn't transitively 
require it and it doesn't provide an implementation of a service that 
any of the other resolved modules use.


The summary is a module layer is immutable and there isn't any way to 
add modules to a module layer once it has been created. For what you are 
doing then maybe `--add-modules ALL-SYSTEM` can be used as workaround. 
This will ensure that all system/platform modules are in the boot layer 
as these modules cannot be loaded into a child layer (Johannes's suggest 
to specify the module name to resolveAndBind will not work for java.* 
modules as they cannot be loaded into child layers, his suggestion may 
work for other modules).


One other point to mention is that the original set of requirement 
envisaged some means to augment the set of platform modules at run-time. 
We didn't get to that requirement except for the limited scenario that 
is tools loading the JMX agent or a java agent into a running VM. These 
limited scenario involve loading the jdk.management.agent or 
java.instrument modules and that is some with a special child layer 
rather than augmenting the boot layer. This partial solution, along with 
`--add-modules ALL-SYSTEM`as a workaround for the general cases, has 
been sufficient to date.


-Alan