The mrJar Plugin v0.0.16 has been released — JPMS Modules Made Easy

TL;DR - To resolve the java.lang.module.FindException: Module java.lang.module.InvalidModuleDescriptorException: not found failure you’re getting @Graou74, edit the build.gradle of that project from this…

 ...
 implementation "org.openjfx:javafx-base:13:$platform"
 implementation "org.openjfx:javafx-graphics:13:$platform"
 implementation "org.openjfx:javafx-controls:13:$platform"
 ...	

to this…

 ...
 implementation "org.openjfx:javafx-base:11:$platform"
 implementation "org.openjfx:javafx-graphics:11:$platform"
 implementation "org.openjfx:javafx-controls:11:$platform"
 ....

The details

I was able to reproduce your java.lang.module.FindException: Module java.lang.module.InvalidModuleDescriptorException: not found failure by changing my $JAVA_HOME from JDK 13 (my Linux box’s default) to JDK 11. Then I repeated the steps you listed:

  1. I just downloaded the project
  2. removed the com.lingocoder plugin from the Gradle cache
  3. imported the project into Eclipse
  4. made a “Refresh Gradle Project”
  5. and then “Run As / 1 Gradle test”

Doing the edit I describe in the TL;DR above made the error go away in my Linux environment.

My apologies for not pointing that out sooner. Up in comment #25 - where I first linked to the MP4 video the other day - I neglected to transcribe any of these points from that video into text…

  • at 1:22 and at 4:00, it shows: Java home directory: /home/lingocoder/.sdkman/candidates/java/13.0.1-zulu
  • at 3:09, the Java Build Path property page shows: JRE System Library [JavaSE-13]
  • at 5:00, the Java Build Path property page shows: java-fx-{...}-13-linux... in the module path drop-down
  • at 15:19, the MyTestApplication run shows: Hello, @Graou74, from JavaFX 13, running Java 13.0.1...
  • at 16:17, the MyTestApplication run shows: Hello, @Lingocoder, from JavaFX 13, running Java 13.0.1...
  • at 18:38-18:48, I double-click on the JavaFX dependencies coordinates in build.gradle to point out that that project is using JavaFX 13

Forgive me for not elaborating on those points in detail the other day. I didn’t because: a) I was too lazy previously :blush: And b) I assumed: A picture is worth a thousand words.

Regarding the optional sub-step of adding --refresh-dependencies to the Buildship wizard’s Program Arguments section that I recommended earlier. If you go that route, be sure that after the initial import has completed, you remove --refresh-dependencies from the arguments. Otherwise, Gradle will redownload all the projects dependencies everytime you execute any task.

To remove that after the initial import…

  1. Go to the project’s property dialog
  2. Go to the Gradle properties tab
  3. Remove --refresh-dependencies from the Program Arguments section
  4. Click Apply and Close

Please let me know if any of that helps? Or not? TIA :+1:

Same behavior with or without --refresh-dependencies. The test is done faster without.

Or there is an altenative which is the virtual machine. I have never tested Mac under PC but the opposite yes and it works very well. In any case, for components as is the case here that do not use very specific drivers it is very satisfactory.
In my case, my PC is down so I naturally turned to the virtual machine to test my application on PC. But no luck, it happens that precisely the main tool on which the application is based is not supported by VirtualBox.:crazy_face:

Bummer.

Incidentally, If you don’t mind me asking: What will your application be used for?

Yup! The Linux you see in my recording is running in VirtualBox actually. That is why everything in that recording looks like it exists in a quantum field made of black strap molasses :blush:

I have had „Install a Mac VirtualBox Guest“ on my TO-DO list for four or five years now. I’ll get around to it any day now, I’m sure :wink:

Right. The idea to remove --refresh-dependencies was only to improve the speed at which tasks complete; not their outcome (SUCCESSFUL or FAILED) as such.

To make sure I understand you correctly — and to avoid making any unneccesary changes to the mrJar code — please confirm that the previously-proposed solution of editing the JavaFX version in the build.gradle from 13 to 11 does not solve the java.lang.module.FindException: Module java.lang.module.InvalidModuleDescriptorException: not found failure on Mac? TIA :+1:

No, it does not change anything. The first “Run As / 1 Gradle test” fails but then the following ones work.
Looks like whatever I do now in the test sequences, whether I forget a phase or not (like not erasing com.lingocoder from the Grade cache), the behavior remains the same.
I wonder if it’s worth it to change the mrJar code. It may be a problem specific to my current environment.

It should be used to model 3D objects and the tool that is not supported by VirtualBox is Vulkan.

I was able to reproduce the InvalidModuleDescriptorException failure on Linux. But only that one time. I tried to reproduce it again so that I could get more insight and try to determine what I need to refactor in the mrJar code. But no matter what I do, I cannot reproduce it a second time :confused:

I have tried several combinations of ways of starting completely from scratch:

  • delete the project’s build folder
  • delete the project’s .gradle folder
  • delete the project’s .settings folder
  • delete the .classpath file
  • delete the .project file
  • add the --refresh-dependencies argument
  • set the Buildship wizard’s Gradle user home field to a brand new, empty location (redownloading/regenerating every single dependency)
  • $JAVA_HOME = JDK 11
  • Eclipse’s JRE System Library = [JavaSE-11]
  • JavaFX version in build.gradle = 13
  • fresh Buildship import

Each time I run your steps…

  1. I just downloaded the project
  2. removed the com.lingocoder plugin from the Gradle cache
  3. imported the project into Eclipse
  4. made a “Refresh Gradle Project”
  5. and then “Run As / 1 Gradle test”

…the :test outcomes are BUILD SUCCESSFUL. They succeed even if Eclipse’s JRE System Library = [JavaSE-11] and the JavaFX version in build.gradle is 13.

The one time I was able to reproduce the InvalidModuleDescriptorException failure, I had a hunch about what code in mrJar might most likely be involved. But even if my hunch was correct, if I can’t reproduce the failure again, there is no way for me to know what in the code to change; I wouldn’t know what specifically to make the refactored code do or what to make it stop doing.

Since you are able to reproduce the failure at will on the Mac, could you — whenever you have a spare five minutes — help narrow down what mrJar code may need refactoring by following these steps? Please?

  1. Edit your settings.gradle to this

    ...
    plugins {
        id "com.gradle.enterprise" version "3.1"
    }
    rootProject.name = 'Graou74'
    
  2. Add this block to the bottom of your build.gradle

    ...
    
    buildScan {
        termsOfServiceUrl = 'https://gradle.com/terms-of-service'
        termsOfServiceAgree = 'yes'
    } 
    
  3. Open Run — Run Configurations — Gradle Test — LibraryTest — Project Settings

    • to the Program Arguments section, add --debug, --stacktrace and --scan
  4. Do whatever steps you do to produce the failure

    • that should dump a ton of output to the console and the stack trace will probably go to Eclipse’s Error log
    • please copy all of that to file(s)?
    • upload them to me?

That would be a tremendous help, @Graou74, if you could. TIA :+1:

Hello again @regrog. I hope you don’t mind me reaching out to you after a month and a half.

But I’m curious to learn your feedback on the solution I proposed for your multiproject question. Please?

If v0.0.15 did the trick for you (or even if it didn’t) mrJar v0.0.16 has been improved majorly since we last spoke. Please, try it out and let me know if it works for you or not?

And if you have any questions, complaints or suggestions for other improvements please get in touch and share your thoughts. TIA :+1:

I do not know if it’s enough as I never registered for Gradle Scan.

console.rtf.zip (12.7 KB)

It is not necessary to register to use build scans. The only thing you needed to do, is add that license agreement acceptance block that I pasted in the steps. Thanks anyway for trying though, @Graou74 :+1:

All is not lost however :slight_smile: How about removing the --scan argument then? It’s important that you also do your „remove the com.lingocoder plugin from the Gradle cache“ step this time.

The --debug argument should result in there being some important debug entries from mrJar printed to the console. Those will provide super valuable insight into what specificallly might need to be refactored in mrJar.

The --stacktrace argument will result in the exception that’s produced by the :test run being dumped to Eclipse’s Error Log.

Sharing both of those via a simple .txt file would be awesome. Please, @Graou74? TIA.

Incidentally @Graou74, before you sent your build scan file, I had done some more analysis.

The TL;DR of that analysis only confirmed the usual suspects…

  • An extraordinarily elusive, practically-impossible-to-reproduce bug in mrJar?
  • An extraordinarily elusive, practically-impossible-to-reproduce bug in Gradle?
  • Something peculiar and exclusive to your end only — eg:
    • your unique Mac environment?
    • ???something else???

That analysis didn’t result in any solutions, I’m afraid. Just questions sans answers. Which hopefully, the requested --debug and --stacktrace output will provide. TIA.

Wow, this time it worked the first time (and the next ones too). yet at the previous test I had also removed com.lingocoder from the Gradle cache.

console.txt.zip (123.1 KB)

1 Like

AWESOME! Thank you from the bottom of my heart, @Graou74, for making time to run the test!

Earlier, I said: „That analysis didn’t result in any solutions“. But that’s not the full story. I did follow that hunch I mentioned before, actually. So I did add a single conditional to mrJar to test for that suspcious-looking java.lang.module.InvalidModuleDescriptorException: so-called „module“; the code simply does nothing if that case tests positive.

But that’s not really a solution in my opinion — so much as a band-aid or a work-around to help troubleshoot the real problem.

The --debug output has confirmed what I suspected from analysis: the root cause of that java.lang.module.InvalidModuleDescriptorException: is that one of your dependencies has a module descriptor that: „is found to be malformed or otherwise cannot be interpreted as a module descriptor“.

Because of the multi-threading of the logger, however, I couldn’t conclusively pinpoint precisely which dependency is the problem one. But I’m like ninety-eight percent certain that it is the project’s myApplication.jar. You could help me confirm that with these steps:

  1. Do most of the same steps exactly as you do to reproduce the failure; except
  2. Do not do the :Run As Gradle Test step; instead
  3. Do the :assemble task in its place…
    • either from the command line or from Buildship’s Gradle Tasks view
  4. Upload the resulting build/libs/myApplication.jar to me

The real conclusive solution would be to find out why the problem dependency has an invalid module descriptor in the first place. And to then correct/prevent that. I have another hunch about what that most likely is.

There you go

myApplication.jar.zip (2.1 KB)

1 Like

Super Thanks, Graou74!

The jar you uploaded does check out with my 11 and 13 runtimes as having a valid module descriptor :+1:

However, given all of the other evidence considered as a whole (the debug output, the results of my experiments in Linux, etc) my certainty approaches 100% that your local java.lang.module.InvalidModuleDescriptorException: failure is caused by your local instance of myApplication.jar having been corrupted — somehow.

An InvalidModuleDescriptorException can be caused by several different things. My hunch — based on my recent Googling and experiments — is that one way or another the project’s jar was compiled by javac with a high value for --release (13, say). But then the java runtime that ran the :test task was lower than that value (11, say).

So what do I propose as that real conclusive solution I referred to earlier then? It’s an easy one fortunately: Make sure you check, double and triple check even, that the JDK your project is compiled with is exactly the same as the runtime you expect it to be executed in.

I’m super-duper grateful to you, @Graou74, for you taking the time to help me troubleshoot this. Muy appreciado!

I have attached the printscreens settings.
Java-versions.zip (1015.6 KB)

I am happy to have humbly contributed to your project.

Hello!
I’m really sorry because I can’t keep on trying your plugin these days.
Switching to java 9 modules isn’t so easy because Gradle does not provide a good implementation of it as you can see https://guides.gradle.org/building-java-9-modules/
I remember that your plugin had a clash with Eclipse build folder and that could be a problem using eclipse as IDE.
Because of other dependencies, I can’t update my project and use models, my company can’t do that now. We will schedule this switch as soon as the conditions change.
Thanks a lot for your help, I’ll check your plugin when the times comes.

Thanks for that @Graou74. The more evidence, the better :+1:

This is probably one of those cases where we might never know with absolute 100% certainty what the root cause is - because of the intermittent nature of it.

But if the work-around unblocks the correct functioning of the project under test, then I’m thrilled either way.

It is probably fair to put the implementing of a JPMS-architected library or application into the Advanced category.

It’s probably also fair to say that not every project is advanced enough to make JPMS worth the effort.

Or the knowledge/experience of the developer(s) might not be at an advanced enough level to tackle the inevitable advanced challenges that JPMS will certainly present.

So I can totally see what you mean when you say you’re not ready yet. I sincerely appreciate that kind of candid feedback. Thanks :+1:

You can see from the lengthy exchange above between @Graou74 and myself, that the mrJar plugin does not clash in any way whatsoever with Eclipse’s build folder.

I point that out, not to persuade you to change your mind, but only to make you aware of a clearly observable fact that you might simply have overlooked.

Thanks again for the feedback, @regrog. And good luck with your project. mrJar will be here for you when you are ready :slight_smile:

Hey @Graou74? I would love to test your application on my PC. Just say the word!

Hi Lingocoder,
Thank you for this proposal but it will not be necessary.

First because my application is again in its infancy since the transition from OpenGL to Vulkan required a radical change in technology. I took the opportunity to make a global overhaul of the architecture.

Then because I need to do a small part of the development on the OS first because even if Vulkan is cross-platform, it is a bit dependent on the OS.

And finally I got a desktop PC three days ago but the graphics card is integrated and does not support Vulkan.
By cons this PC allowed me to make a boot disk (which I did not manage to do with the Mac) to be able to access again to an old gaming PC that I had loaned and which we could not find anymore the password.
Right now the graphics card is not recognized by Vulkan, I need to check if there is a new driver for this old card.

And if there is none, there are recycled PCs for not too expensive.

Anyway I just became aware even if OpenGL is a bit old (soon no longer supported on Mac), Vulkan is a bit young so I will have to implement both technologies.
I had not planned that.:crazy_face:

I thought turning the gradle-module-plugin into a JPMS module was the most advanced project mrJar was applied in. Well it was, up until I ported a three-module JAX-RS/DropWizard RESTFul AuthN API to its SpringBoot equivalent with mrJar tying it all together.

All three of those projects were excellent functional tests for mrJar v0.0.12, v0.0.13 and v0.0.15. Getting mrJar to work in them meant the plugin had to up its game for each one. Which improved the overall functionality of the plugin amazingly.

That same usage-driven development process also paid off handsomely with this most recent super productive functional testing iteration informed by @Graou74’s 3D modelling application.

I stumbled across mrJar’s latest most advanced functional test case so far in this Stackoverflow question. @Emily describes the problem she’s seeking a solution to, as: „migration of a large code base from Java 8 to modular (JPMS) Java 11“.

mrJar handled the JPMS migration of such „a large code base“ with such relative ease that even I was surprised at how little time and effort it took!

Not so surprising though is that, just like the other functional test projects, @Emily’s presented some technical requirements that would never have occurred to me if I’d never come across her Li Song Mech Lab project.

So, sincere thanks to all of those projects (@tlinkowski, @siordache, et al) for helping mrJar improve.