It feels to me like JPMS just plainly breaks the informal industry standard of the Maven project layout we have all been using for a million years.
In addition, how is one supposed to test package private code if a test jar tests a main jar where all packages are now different? This seems like a problem whether the test code is in the same Maven module or not. Or am I missing something? Am I the only one feeling like JPMS what developed in a vaccum? Gary On Tue, Jun 22, 2021, 14:16 Robert Scholte <[email protected]> wrote: > If I understand correctly you want both log4j-core main classes and test > classes be distributed as modularized jars. > To me with JPMS you should move the modularized test-classes to a separate > Maven module as a first citizen artifact. > That should make it a lot easier. > It should also make the separation more clear: classes under > target/test-classes are there to unittest its main classes. > Whereas this new module contains reusable (main) code for testing (which > should be tested too ;) ) > I understand that this will change the GA(-classifier) for the testing > module, but to me for a good reason. > > Even with your very small reduction of steps to simplify the process, it > doesn't fit in the default lifecycle unless you write you introduce a new > lifecycle-binding or write a new extension. > > Robert > > On 22-6-2021 07:02:59, Ralph Goers <[email protected]> wrote: > Sorry for posting again. I really need to proof-read better. Please ignore > the prior email. > > I have recently had quite an adventure modifying several of Log4j’s Maven > modules to > implement JPMS on our master branch. It was an adventure due to a few > issues: > > 1. https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8265826 . > This bug has been fixed in Java 17 but Log4j uses Java 11 to build. > 2. Log4j-plugins builds an annotation processor, packages it with the > annotations > and classes necessary to build and run plugins, creates and test jar and > runs unit tests. > 3. It is not possible to compile an annotation processor with a > module-info.java present. > The compile will fail because it can’t find the annotation processor > “service” when > compiling module-info.java. > 4. It is very difficult to compile an annotation processor and then use it > in the same Maven > module. JPMS expects the annotation processor to either be on the > classpath or specified > with the processorpath option. When a module-info.java is present, Maven > automatically > moves everything to the module path. Maven only supports using coordinates > to specify the > processor path, which don’t exist when the processor is in the same > module. The only way > to solve this is to compile all the classes with proc=only without a > module-info.java present. > 5. Although number 4 might seem bad, it really doesn’t matter because > javac will fail if a > module-info.java is present because module-info.java will have a reference > to the service > class being generated by the annotation processor and for some reason > module-info.java > is resolved before the annotation processor runs. > 6. If the main set of classes are compiled with a module-info.java every > other compile > in the Maven module must also be modularized. Likewise, if the main module > does > not contain a module-info.java no other compile can either. > 7. JPMS requires that every module have its own package space with no > overlap > with any other JPMS module. > > So while generating the log4j-plugins module is quite painful, generating > log4j-core isn’t > much better. That is actually the primary focus for this list. > > Log4j-core consists of the main classes packaged in the jar, a test jar > that is used by > downstream Maven modules, and the unit tests. Prior to JPMS one would just > create > the main jar and then package all the test classes and unit tests in a > test jar. This can > no longer be done with JPMS. > > When a project publishes a test jar along with the main jar, just like any > other JPMS > module. the test jar cannot use the package space of the main classes. > Log4j core > uses org.apache.logging.log4j.core so I placed all the test utility > classes under > org.apache.logging.log4j.core.test. However, the unit tests all need to be > packaged > in the main package space since its module-info.java “extends” the main > module and > several unit tests are required to be in the same main package so that > they can access > package private methods specifically provided for testing. > > In order to get this to work I had to perform the following steps: > > • Compile all the main classes except module-info.java with the Plugin > annotation processor. > • Compile the main module-info.java. > • Compile the test classes used by other modules with module-info.java and > using the plugin preprocessor. > • Package these test classes in a test jar. > • Delete the module-info and generated source for the test classes. > • Move the main module-info to a temp location. > • Compile the unit test classes without module-info.java. > • Move the main module-info back to the classes directory. > • Compile module-info.java for unit tests. > • Run the unit tests. > • Create the main jar if the unit tests pass. > > Were it not for JDK-8265826 I believe this could have been simplified > somewhat to: > > • Compile all the main classes except module-info.java with the Plugin > annotation processor. > • Compile the main module-info.java. > • Compile the test classes used by other modules with its module-info.java > and > using the plugin preprocessor. > • Package these test classes in a test jar. > • Delete the module-info and generated source for the test classes. > • Compile the unit test classes with its module-info.java. > • Compile module-info.java for unit tests. > • Run the unit tests. > • Create the main jar if the unit tests pass. > > So the gist of this entire email is pretty simple. Is there a way Maven > could be modified > to better support creating test jars with JPMS? > > Ralph
