I use windows 10, Oracle JDK-11.0.2, Maven 3.6, Spring-boot 2.1.3.RELEASE
Hello. After #15810 fix module-info.class now place in root folder in fat-jar, but is broken jar running process. Before module-info.class was in /BOOT-INF/classes folder and jar was as automatic-module with name of jar. But now fat-jar is a normal module, but folder structure is not valid, and packages not found by JVM when you try running you jar as java --module-path
Comment From: wilkinsona
If you want your application to be an automatic module you should not have a module-info.class file. It was not causing a problem in the past as repackaging was incorrectly moving it to a location where it could not be found. That’s been fixed in 2.1.3. Deleting your module-info.java file should restore the behaviour you had with 2.1.2.
Comment From: revkov
@wilkinsona I don't want what my application will be a automatic module. I want a normal Java 11 spring boot application with module-info.class. How I can do that without removing module-info.class? If I remove module-info.class this is not correct Java 11 module. Please reopen and fix this. Or spring boot doesn't support this?
Comment From: revkov
It turns out that now modules which build with spring-boot are fully invalid and uselesses because has wrong structure and can't be running correctly or use as required for other modules. Maybe this is bug?
Comment From: thorntonrp
A Spring Boot jar is designed to package an application, not a module. It was never intended for use as a dependency that exports packages to other modules. As it is not a library or module jar, there is little, if anything, to be gained by having a module-info.java in the project.
Comment From: wilkinsona
I don't want what my application will be a automatic module
That’s what you had with 2.1.2. The module-info.class was moved to BOOT-INF/classes which effectively removed it and turned your jar into an automatic module.
If I remove module-info.class this is not correct Java 11 module. Please reopen and fix this. Or spring boot doesn't support this?
I don’t think there is anything more for us to fix. In 2.1.2 and earlier we moved the module-info.class file, effectively removing it. This made it impossible for a fat jar to be a module. In 2.1.3 it is now possible for a fat jar to be a module.
That said, I am not sure that there is much benefit in doing so. The entry point to the module will still have to be the JarLauncher (as specified in the main class attribute in the manifest) and the module won’t be able to export any of the packages in BOOT-INF/classes or in the jars in BOOT-INF/lib.
or use as required for other modules
A Spring Boot application is intended to be a self-contained unit, much like a war file. It is not intended to be used as a dependency on the classpath or on the module path. Please refer to the documentation about using an application as a dependency for further details.
Comment From: revkov
@wilkinsona
I don’t think there is anything more for us to fix. In 2.1.2 and earlier we moved the
module-info.classfile, effectively removing it. This made it impossible for a fat jar to be a module. In 2.1.3 it is now possible for a fat jar to be a module.
But now (in 2.1.3) it's not possible for a fat jar to be a module, because he has wrong structure and java doesn't recognize it. Try my application. I think you don't need move module-info.class to root folder because you got wrong java module + invalid fat spring-boot jar (not working). Maybe you need remove module-info.class at all on repackage ?
Comment From: wilkinsona
As a I tried to explain above, there’s little point in trying to make a Spring Boot fat jar be a module. If you still wish to do so, you’ll need to ensure that you provide module info that is compatible with a fat jar’s structure. That will require you to only reference Boot’s launcher and then rely on it to create a ClassLoader that can load classes from BOOT-INF/classes and from the jars in BOOT-INF/lib. I’m not even sure that this is possible given the module system’s current capabilities.
Let’s take a step back. You haven’t explained why you want your fat jar to be a module. What are you trying to achieve?
Comment From: revkov
Let’s take a step back. You haven’t explained why you want your fat jar to be a module. What are you trying to achieve?
I don't want what fat-jar be a module, i want what this is run correctly. if in documentation says what spring-boot jar is not a dependency, then it is not a module. I suggest remove module-info.class at all on repackage cycle. if i manually delete module-info.class from my project it works correctly, but received jar is not a java module (it's standalone unique spring-boot fat jar, we are undestatnd this). I think need rollback #15810 and remove module-info on repackage. This make our fat-jar works as designed by spring-boot, because spring-boot jar is not a module and doesn't contains any module-info.class.
Comment From: wilkinsona
I don't want what fat-jar be a module, i want what this is run correctly
If you don't want it to be a module, why do you have a module-info.java file?
I think need rollback #15810 and remove module-info on repackage
That would make it impossible for @swaechter to do what they were trying to do. You can achieve the same result by removing module-info.java and it won't cause problems for anyone else.
Comment From: revkov
That would make it impossible for @swaechter to do what they were trying to do. You can achieve the same result by removing
module-info.javaand it won't cause problems for anyone else.
They custom jre will not worked anyway, because module is corrupted! Try youself.
/usr/lib/jvm/jdk-12/bin/jlink --no-header-files --no-man-pages --compress=2 --module-path target/springmodule-1.0.0.jar --add-modules springmodule --launcher launch=springmodule/ch.swaechter.springmodule.SpringModule --output custom_jre:
Error: Error reading module: target\springmodule-1.0.0.jar !
Comment From: wilkinsona
This isn't going anywhere.
That command is incorrect. When you've built a fat jar and are trying to use it as a module, you can't launch its main class directly. As I said above, you need to launch it using the JarLauncher and that may not even be possible given the current capabilities of the module system.
We do not recommend trying to turn a fat jar into a module and we do not recommend using a Spring Boot application as a dependency. If you'd like me to spend any more time on this, can you please answer my question:
If you don't want it to be a module, why do you have a
module-info.javafile?
Comment From: revkov
Because I want write a correct Java modules code. Modules can be execute as standalone application how a default jar. java - jar spring-boot.jar - old way java - p spring-boot.jar - m mymodule - new way
Spring boot now does not support second way if I has a correct Java module. I think what #15810 solves nothing. All cases in this task never been running. It's fix only break fat jar and made it corrupted Java module. What you think?
Comment From: wilkinsona
We're still going round in circles.
Writing a module for the sake of writing a module doesn't make sense to me as there is no benefit to running a Spring Boot fat jar as a module. If that's your goal then, unfortunately, I can't justify spending any more time trying to help you. With 2.1.2 you were running your application as an automatic module. You can achieve exactly the same end result by removing module-info.java and run your application using the module path. Alternatively, you can simplify things even further by using java -jar instead.
It may make sense to try to use a module when building an image with jlink which is what #15810 is, hopefully, a step towards. You'll still need to use JarLauncher as the entry point which is essentially what happens when an automatic module is created. I'm still doubtful that there's much point in this either, but we're hopefully a little closer now. If we revert the change we'll be no closer there. I see no need to do so as, as explained above, you can get the exact same behaviour as you had with 2.1.2 by removing module-info.java and running your application as an automatic module.
Comment From: revkov
Ok. Thank you.
Comment From: Reginald-Yoeng-Lee
@wilkinsona Thank you for your patience. After reading the conversation above, I hope I'd have a chance to consult you about the JPMS.
First, let's say we just omit the module-info.java of the application of Spring Boot and run the application by using java -jar. The whole application will be treated as an unnamed module and it can access all public types exported by the dependencies. Everything works fine. However, in my opinion, this may not be the recommended way by official, since the unnamed module is like some kinds of compatibility solution, not a regular solution. (Correct me if I've misunderstood)
Or, we could add the module-info.java to the root directory of the application as the JPMS suggesting and append all the requires to the descriptor. We could sucessfully compile the source codes and build the fat jar as usual. So far so good.
Now we have two choices: run the application by using java -jar or by using java -m.
The former way works just fine, the application could run and behave normally. However, it seems like that in this way the JVM just ignore the module-info.class and something doesn't behave as expected as a module. For example, the Spring Boot can access our classes by reflection even we haven't append any open symbols to the module declaration. That is, this is not a pure module way running the application.
The latter way comes to some horrible problems. The JVM complains that the required modules can not be found if we don't specify the module path. But obviously it's impossible to specify the module path because all the dependent modules having been packed and been part of the fat jar. So, it seems like that we can't run the application in this way. (Again, correct me if I'm wrong)
So, here's the confusing part I'm curious, what's the recommended way of runing an application from Spring Boot official while working with the JPMS?
Comment From: wilkinsona
Unless you're building a custom JVM image using jlink, we don't recommend running a Spring Boot application using the module path as there is almost no benefit.
Comment From: swaechter
I fully agree with what Andy said. At some point we even gave jlink up and moved to GraalVM/native-image + upx for compression
Comment From: Reginald-Yoeng-Lee
Thank u so much. That really solves my question. Let me try to draw a conclusion. Compiling the source code with the module path so that we could meet the requirements of JPMS and indicate explicitly which modules the application relied on by writing the module-info.java file. Then we create the fat jar and run it by using java -jar. Or, we could even just ignore the module decleartion stuff and use it as Java 8.
BTW, one more question, do you think there are any benefits using the module stuff while compiling? Thanks for taking up your time agian.
Comment From: wilkinsona
do you think there are any benefits using the module stuff while compiling
No, not that I am aware of.
If you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.