hgschmie commented on PR #227:
URL: 
https://github.com/apache/maven-javadoc-plugin/pull/227#issuecomment-1709311461

   This is the slightly longer (and a bit more winded) explanation of what that 
patch does:
   
   consider a project that spits out a module. This can be a defined module or 
an automatic module; it does not actually matter. What is important is that the 
maven tool chain considers it something where it will use the module path.
   
   let's consider this dependency graph: `project --> automatic module with 
manifest entry --> automatic module with file name based module id` (If that is 
too abstract for you, you can call those `jdbi3-guice -> guice-5.1.0 -> 
javax.inject-1`).
   
   - jdbi3-guice is a defined module (it contains a module-info.java file)
   - guice-5.1.0 is an automatic module that contains an entry in 
`META-INF/MANIFEST.MF`
   - javax.inject-1 is an automatic module that has no JPMS information, so it 
is treated as a filename based module.
   
   To run code that uses these three modules, it needs to do `--module-path 
jdbi3-guice.jar:guice-5.1.0.jar:javax.inject-1.jar`. This will work fine. The 
automatic modules open all their packages to the module path; there are no 
overlaps and the jdbi3-guice module can consume all the pieces that it needs.
   
   When the maven toolchain is trying to set up javadoc generation, it will 
inspect all three modules and come to the following conclusion:
   
   - jdbi3-guice --> `ModuleNameSource.MODULEDESCRIPTOR`
   - guice-5.1.0 --> `ModuleNameSource.MANIFEST`
   - javax.inject-1 --> `ModuleNameSource.FILENAME`
   
   (this is buried deep in the plexus-java component)
   
   Now, the javadoc plugin sees this and creates module and classpath:
   
   ```
   --add-modules ALL-MODULE-PATH
   --module-path 
'jdbi/guice/target/jdbi3-guice-3.41.0.jar:m2repo/guice-5.1.0.jar'
   --patch-module org.jdbi.v3.guice='m2repo/javax.inject-1.jar'
   ```
   
   because it treats the `ModuleNameSource.MANIFEST` *different* from 
`ModuleNameSource.FILENAME`
   
   So, everything cool? No. What happens now is that a class in the main module 
(`InternalBindingProvider`) implements a class in the guice module 
(`com.google.inject.Provider`) which in turn *extends* a class from 
javax.inject-1 (`javax.inject.Provider`). But the javax.inject-1 jar has *only 
been patched into the jdbi3-guice component*. So javadoc can not find it when 
the guice class says "I extend that" and that leads to:
   
   ```
   InternalImportBindingBuilder.java:88: error: cannot access Provider
       static final class InternalBindingProvider<T> implements Provider<T> {
                    ^
     class file for javax.inject.Provider not found
   1 error
   ```
   
   so the right fix is one of two things:
   
   - move all dependencies of the main artifact onto the module path. This 
sounds nice in theory but reality is that this only works for defined modules 
(those that have a module-info.java). Many of the other ones (especially the 
ones that simply tack an automatic module name into the jar after compile time) 
have dependencies with overlapping packages (e.g. jsr305 as the biggest 
offender) and short of inspecting every jar and keeping a list of exports, this 
option leads to more problems than actual solutions. It is, however, *the right 
solution* but, unless the rest of the tooling starts to differentiate between 
defined modules and automatic modules, not a viable solution.
   - patch *all* the automatic modules that are dependencies for the main 
artifact into the main artifact. IAW, don't differentiate between the two types 
of automatic modules (manifest and filename based).
   
   And that is what this patch does: It removes the differentiation between 
manifest and filename based dependencies.
   
   A more complete fix would do this:
   
   - plot the complete dependency graph
   - start from the root. Any dependency that is a defined module "infects" its 
full downstream tree. All of those dependencies need to go onto the module path
   - look at the remainder of the graph. Anything here needs to be patched into 
the main module.
   
   E.g.
   
   ```
   artifact --+--- defined module a --+-- defined module b-- +-- automatic 
module 1 --+ automatic module 2
                    |
                    +--- automatic module 4 --+-- automatic module 5
                    |
                    +--- automatic module 6 --+-- defined module c -+-- 
automatic module 5
   ```
   
   - defined module a goes onto the module path. As does defined module b, 
automatic module 1 and automatic module 2
   - defined module c goes onto the module path. This infects automatic module 
5.
   - automatic module 4 gets patched into the main module. its dependency has 
been forced onto the module path
   - automatic module 6 gets patched into the main module.
   
   So the result is
   
   ```
   --module-path defined module a:defined module b:defined module c:automatic 
module 1:automatic module 2:automatic module 5
   -- patch-module main.module=automatic module 4:automatic module 6
   ```
   
   Or in the case above, the chain `main artifact --> guice (automatic module) 
-> javax.inject (automatic module)` leads to both guice and javax.inject being 
patched into main artifact.
   
   If guice ever wises up and provides a module descriptor, it would be this 
scenario: `main artifact --> guice (defined module) -> javax.inject (automatic 
module)`
   
   Which would force guice onto the module path and its dependency 
(javax.inject) as well. That works as well as patching both. What does not work 
is move one of them onto the module path and patch the other one into the main 
module.
   
   I *would* implement that, except that AbstractJavadocMojo.java is a brittle 
6,100 lines (!) abomination littered with special cases, exceptions and 
dependencies on other components of unclear function. Also most mojos in the 
plugin share functionality here, all the way to the aggregation jar target. I 
did not dare to touch this and so I did the minimal invasive patch. 
   
   No, seriously, this thing needs to be refactored before any serious work can 
be done. Or better yet, thrown away and start over (maven-javadoc-next-plugin 
anyone?) 
   
   
   
   
   
   
   
   
   
   
   
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to