> On Apr 5, 2021, at 1:31 PM, Volkan Yazıcı <volkan.yaz...@gmail.com> wrote:
> 
>> ... this weird structure with two test source directories ...
> 
> doesn't seem okay to me. Please, don't get me wrong. Not that I know of
> JPMS or anything, though this sttructure doesn't resemble anything I have
> ever seen. I don't want to believe that every major Java library with JPMS
> support needs to have such ugly workarounds. Are we sure about this
> solution? Can we ask for a review from some other Apache fellow? (@Gary,
> how does Commons deal with this?)

I’m not sure who you would want to ask. AFAIK Commons hasn’t tackled JPMS yet 
and wouldn’t encounter this issue.  The only person I can think of would be 
Robert Scholte from the Maven project. He has worked closely with the OpenJDK 
guys to have Maven support JPMS.

That said, the problem is relatively simple.
Obviously, to create a JPMS module your code must have a module-info.java. 
Once you do Maven requires that everything in the module be a JPMS module - it 
looks for everything on the module path, not the class path.
Maven supports unit tests for JPMS modules by requiring that the test also have 
a module-info.java that opens the same module as the corresponding source.
Java annotation processors must be on the class path.
Log4j-api, Log4j-plugins and Log4j-core all publish test classes that 
downstream modules use for testing. Things like the LoggerContextRule, 
FileCleaner, etc.
Every JPMS module MUST have its own unique set of packages. 

All of these items cause some “interesting issues”.
The classes used for testing generally need to share the same package space as 
the classes they are testing. This isn’t really legal but Maven’s tooling 
allows it via the special module-info.java. It essentially creates a new module 
with both the source and test in it as far as I can tell.
Because the unit tests use the same package as the thing they are testing they 
cannot be package in a test jar for use by other modules.
The annotation processor has always had to be built by itself first, before the 
full module it resides in. That has to be followed by another compile to run 
the annotation processor to generate the Log4jPlugins.java file, followed by 
another compile to compile all of it with the Log4jPlugins class.

So what you end up with is almost a script that has to be run
Compile the main code without its module-info.java file so that the test 
classes can compile.
Compile the test classes that will be packaged in the test jar for other 
modules to use. These classes will reside in the target/test-classes directory.
Package the test jar.
Compile the main module-info.java.
Compile the unit tests - these will all go into the test-classes directory.

At this point you can run the unit tests. If they pass the main jar is created 
as normal. Both the test jar and main jar will be installed. 

Yes, this process could be done slightly differently. You could co-mingle the 
classes destined for the test jar with the unit tests and compile them all 
together. But then when you package the jar you would have to specify every 
class to be included in it. I simply didn’t like that option and chose to use 
the directory structure and build order to accomplish what is needed.

Note that all of this occurs ONLY because we are creating a test jar that will 
be used by other modules. As I said, this jar cannot have any classes in 
packages specified in the main module-info.java for the maven module. “Normal” 
modules will have a src/main and src/test just as they always have and both 
with have a module-info.java in them. 


> 
>> The test jars need to be installed in order for them to be used by the
> other log4j modules that follow. I see no reason they cannot be published.
> They contain some useful stuff that others could use for unit testing if
> they wanted.
> 
> I am really reluctant to make any internal goodie public without a tangible
> use case and (preferably) user request, given the backward compatibility
> burden we will need to carry for a decade afterwards.
> 

First, we publish the test jars because they have to be installed to be usable 
by downstream modules in Log4j. We have always published the test jars as part 
of our release distribution. Maven does that by default. We have never promised 
that they will remain compatible. 

Ralph

Reply via email to