My context is that I have written a java library that does something "useful" and this library is (as is common for libraries) to be used in other applications.
Among other things my library uses Antlr 4 to generate part of the code. Key thing here is that the Antlr versions of the generated code and the runtime must be identical.
I do not want to limit applications that want to use my library to only the specific Antlr version my code uses. So the Antlr runtime for my library must be present and hidden from the application than uses my library.
At this point I have solved this my using the maven-shade-plugin and relocate the antlr4 classes to a new package that is specific to my jar file. That way my code is modified to look for these classes in different packages and thus two different versions can exist side by side.
This works fine.
I have been experimenting with making my library a JPMS compliant module and there this all becomes very hard.
The key problem I'm facing is how can I isolate the Antlr runtime my library needs from the Antlr runtime the application needs when using the JPMS?
- If I create my library as a module then dependencies like the Antlr runtime remain "external" and thus there seems to be no way to enforce the specific version.
- If I simply shade them in you will get conflicts about packages existing in two modules and thus the maven-shade-plugin removes the module-info.class from the jar to avoid very nasty issues.
- If I shade and relocate the Antlr runtime then I think it should be possible. How ever the maven-shade-plugin still removes the module-info.class from the jar and the module-info.class that is created during the build. Because it is created during the build (before shading) it must include the Antlr runtime dependency ... which is no longer a dependency that is needed after the shading step (so the module-info.class seems incorrect to me).
- Tools like the moditect-maven-plugin seem to me like a quite brutal solution: A separate plugin to generate something the java compiler also generates.
So my question is what is the best/recommended solution for this kind of situation? I want my library to be usable in both JPMS and non-JPMS applications.