This message was deleted.
# community-support
s
This message was deleted.
v
if an
implementation
dependency contains an automatic module (e.g., Undertow, XNIO), then AFAIK, Gradle does NOT include that module on the module path by default.
Yes and no. If your project is a JPMS module and you didn't disable the module-path inferring, then explicit modules and also automatic modules with an
Automatic-Module-Name
in the manifest are put on the module path. JARs that have no knowledge about JPMS at all and would just be automatic modules with a module id derived from the jar name are put on the classpath.
(And while I don't fully understand the reasons why, I can vaguely infer that this is the correct default behavior.)
That's highly disputable. Especially automatic modules without an explicit automatic module name are very problematic and should imho never be depended on from a proper JPMS module. You just need a different jar name and your definition breaks. Or a newer version is a proper module or gets an explicit automatic module name and your definiton breaks, .... For automatic modules without explicit automatic module name, I think putting them on the classpath is the better default choice.
But let's say that I want to include those two modules on the module path, so that my own module can require them. How do I do that?
Again, better don't do it. But if you really must, just configure it manually. Exclude them from the classpath and use a jvm arg or jvm argument provider to set the
--module-path
explicitly instead of letting Gradle infer it. Or you can use for example the plugin https://github.com/gradlex-org/extra-java-module-info to transform the non-JPMS jar to a proper module on-the-fly which might be the better option if you really need to do it.
m
I do worry that the practical effect here is just to discourage the usage of Java modules altogether. It's just not realistic to live in a world where all your dependencies use named modules. (E.g., any project that takes a dependency on Undertow or XNIO can't use modules.) I can provide a very simple example using Immutables:
Copy code
package org.example;

import org.immutables.value.Value;

@Value.Immutable
public interface Empty {}
If you have Guava as a dependency in your project, the generated code will use some annotations from the automatic module
jsr305
. (There are ways to work around it, but not anything I would expect the typical Immutables user to know.) If you put
requires jsr305;
in
module-info.java
, though, you will get a "module not found" compilation error. I just wish there was an easy way to say, "I'm OK including
jsr305
from
com.google.code.findbugs:jsr305
in the module path, even though it's an automatic module." Ditto if I want to require
undertow.core
or
xnio.api
. (Re: extra-java-module-info, it could work, but in practice, if you merely enable the plugin, you will immediately get a bunch of "Not a module and no mapping defined:" errors for transitive dependencies. Which isn't the ideal developer experience.)
(I also vaguely recall that Maven will include automatic modules in the module path by default, though I'm not 100% sure of that. Not saying it should be the default behavior, but it should be easy to override the default and put automatic modules on the module path, so that you don't get compilation errors when you require them.)
v
I just wish there was an easy way to say, "I'm OK including
jsr305
from
com.google.code.findbugs:jsr305
in the module path, even though it's an automatic module." Ditto if I want to require
undertow.core
or
xnio.api
.
I already told you two easy ways. 1. just define the module-path yourself instead of using the Gradle default 2. use the plugin I mentioned Both are easy to use ways. Gradle is convention-over-configuration with usually sane defaults, but providing the power to easily adapt to your needs, so just use that power. :-)
(Re: extra-java-module-info, it could work, but in practice, if you merely enable the plugin, you will immediately get a bunch of "Not a module and no mapping defined:" errors for transitive dependencies. Which isn't the ideal developer experience.)
Well, if that's the case, maybe open a feature request to that plugin to improve developer experience. 😉
I also vaguely recall that Maven will include automatic modules in the module path by default
Well, quite possible that it does. Wouldn't be the first non-sense default that Maven uses where Gradle learned from and did it better. 😉
but it should be easy to override the default and put automatic modules on the module path
It is, I told you two ways. Also, again, proper automatic modules are put on the module path by default. Just the implied automatic modules are not, as it does not make much sense and can also easily break the JARs logic. Due to the different handling of JARs on the classpath vs. module path, it can easily happen that it works on one but not on the other. What you ask for is to simply put everything on the module path and cross fingers that nothing breaks by doing that. And you can easily do that, just set the classpath to empty and put the wohle
runtimeClasspath
on the module path and you are done. Well, except for the finger-crossing that nothing breaks by doing that.
m
Easy in my mind would be, e.g., adding a plugin that requires very simple configuration in
buildSrc
...
Copy code
extraJavaModuleInfo {
    automaticModule("jsr305", "com.google.code.findbugs:jsr305")
}
...and then
requires jsr305;
would just work. (And ideally, some Gradle documentation would explain how you could shoot yourself in the foot if you do this.) (2) isn't easy for the reasons I explained; just enabling the plugin creates build errors for transitive dependencies. Which means you could also get new errors any time you add a dep... (1) I've tried but haven't gotten it to work; is it supposed to be like this in
buildSrc
? (I used this as a reference.)
Copy code
tasks.withType<JavaCompile> {
    doFirst {
        options.compilerArgs.addAll(listOf("--module-path", classpath.asPath))
        classpath = files()
    }
}
But when you're asking developers to manage the classpath and/or module path themselves, I also wouldn't call that an easy option. (Easy is written from the perspective of a typical Gradle user, not a Gradle expert.) Also, this option seems to be akin to giving developers a blowtorch which puts everything on the module path, as opposed to a scalpel which adds specific implied automatic modules to the module path.
v
Easy in my mind would be, e.g., adding a plugin that requires very simple configuration in
buildSrc
...
Which is exactly what the plugin I told you is doing. It even helps you finding all cases to define by erroring out for plain jars that do not have an automatic module name. This is imho very user-friendly as you cannot forget to define some. And I told you, if you think differently, open a feature request to that plugin to have the option to change that behavior.
And ideally, some Gradle documentation would explain how you could shoot yourself in the foot if you do this.
That's not in the scope of Gradle documentation, but in the scope of JPMS documentation.
(2) isn't easy for the reasons I explained; just enabling the plugin creates build errors for transitive dependencies. Which means you could also get new errors any time you add a dep...
Matter of point of view. The errors for transitive dependencies are imho good, because if you want to fully mularize your application, you should take care of all legacy JARs. By putting everything on the module-path regardless, you anyway do the same with a big hammer. But as I said, open a feature request to that plugin for a switch to disable that behavior.
(1) I've tried but haven't gotten it to work; is it supposed to be like this in
buildSrc
? (I used this as a reference.)
Don't change the configuration of a task during its execution time, that is a big no-go, can cause a lot of trouble, and also is not allowed with configuration cache if you ever hope to use it.
But when you're asking developers to manage the classpath and/or module path themselves, I also wouldn't call that an easy option.
I didn't ask you to do anything. I recommended to not depend on an implied automatic module, as it causes all sorts of trouble and you read everywhere not to do it. If you want to do it anyway, you shouldn't wonder that there is not an easy switch to shoot yourself in the foot. But at least Gradle gives you the power to easily shoot yourself if you insist, unlike for example Maven. And for more convenience, there are 3rd party plugins like the one I recommended.
Also, this option seems to be akin to giving developers a blowtorch which puts everything on the module path, as opposed to a scalpel which adds specific implied automatic modules to the module path.
Yes, that's exactly what you asked for. To put all automatic modules on the module path. Which means each and every jar. Because every jar that is not an explicit module can be an automatic module, simply by putting it on the module path. That might break it's behavior and make it unusable, but well, that's the risk you want to take. If you do not want to put everything on the module path, but only specific things, then just put the things you want on the module path there and keep the rest on the classpath. That's the benefit of the power Gradle gives you, you can decide how you want it. That this is not "easy for a Gradle noob", might be. But a Gradle noob should probably just live with the sane defaults and should not follow the very dangerous practice to depend on implied automatic modules. If someone is keen and savvy enough to decide to do that, he should also be able to configure Gradle to do what he wants, or otherwise rethink of whether it really makes sense what he tries there. Btw. the blowtorch-approach you tried should probably more be something like
Copy code
tasks.compileJava {
    classpath = files()
    options.compilerArgumentProviders.add(
        object : CommandLineArgumentProvider {
            @CompileClasspath
            val compileClasspath = sourceSets.main.map { it.compileClasspath }

            override fun asArguments() = listOf(
                "--module-path",
                compileClasspath.get().asPath
            )
        }
    )
}
Also, in the course of https://github.com/gradle/gradle/issues/25954 you might get an easily shoot-yourself-in-the-foot option for the blowtorch approach.
m
The blowtorch option seems to work if a Gradle module uses a Java module, but if a Gradle module doesn't use a Java module, it blows up. That's a non-starter if you're incrementally migrating multi-module Gradle builds to use Java modules. Maybe this isn't so easy after all... This is a case of missing the forest for the trees. Here's the forest: let's say that we have a module with three easily-met requirements: 1. It puts all the code in a Java module. 2. It uses Immutables to create some
@Value.Immutable
interfaces (and generate their implementations). 3. It needs Google Guava as a dependency. Here's a minimalistic Java file to test this out with (note that the generated code is different depending on whether Guava is present or not):
Copy code
package org.example;

import org.immutables.value.Value;

@Value.Immutable
public interface Empty {}
Here's the corresponding `module-info.java`:
Copy code
module org.example {
    requires static org.immutables.value;
    requires com.google.errorprone.annotations;
    requires jsr305;
}
Now I only have a passing knowledge of Maven (I let IntelliJ auto-generate the pom.xml file and hacked it from there), but it didn't take me very long to get this code to build with Maven (with the Guava dep included):
Copy code
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="<http://maven.apache.org/POM/4.0.0>"
         xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>"
         xsi:schemaLocation="<http://maven.apache.org/POM/4.0.0> <http://maven.apache.org/xsd/maven-4.0.0.xsd>">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>maven-module</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.immutables</groupId>
            <artifactId>value</artifactId>
            <version>2.10.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.2-jre</version>
        </dependency>
    </dependencies>
</project>
Maybe Maven is doing some "impure" things w.r.t. implied automatic modules, but it just works out-of-the-box. Now try getting that same code to compile with Gradle. It's a pain-in-the-ass to get this dead-simple example to work, much less a real-world project. I'm not saying that you don't have valid points on why Gradle's defaults are correct for implied automatic modules. But at some point, demanding the perfect solution--as opposed to making it dead-easy to add implied automatic modules to the module path--will just encourage people to either not use Java modules or to use Maven instead.
v
The blowtorch option seems to work with modules, but if a project doesn't have a module, it blows up.
Not sure what you mean by "blow up". But either way, also not sure why you should use that snippet if you don't want its effect. Just use it if you need it and you are fine - well as fine as that approach will work anyway.
That's a non-starter if you're incrementally migrating multi-module Gradle builds to use Java modules.
Then do not put it into the convention plugin you apply to all projects, but have a separate convention plugin for already modular projects where it is included. That's anyway how you use convention plugins. Or if you really don't like that, add a check for the presence of
module-info.java
in the source files and only do it if it is there for example.
as opposed to making it dead-easy to add implied automatic modules to the module path
Well, you should really never ever do that anyway, no matter whether you use Gradle, or Maven, or Ant, or Bazel, or plain javac, or whatever else. You will only get much problems with doing so, so just don't do it and you are fine. If people insist on doing that and for that reason decide to not use JPMS, that is then maybe the exact right decision. Because you try to use an outdated library that is not JPMS-compatible with JPMS. That is like when you try to put E10 gasoline into an oldtimer motor. That would be a very bad idea and not work out too well at all. It would be a much better decision not to use E10, but keep on using E5 even if E10 would generally be the better choice. Besides that, I already told you that such a "dead-easy shoot yourself in the head" switch is most probably coming with the linked issue.
It's a pain-in-the-ass to get this dead-simple example to work
Why? It cost me approximately 5 minutes to ramp up a working build. And most of that time was for creating files and copy&paste.
It's more or less a 1:1 translation from the Maven POM, with the blowtorch snippet added to switch to the non-sense default of Maven
Copy code
plugins {
    `java-library`
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compileOnly("org.immutables:value:2.10.0")
    annotationProcessor("org.immutables:value:2.10.0")
    implementation("com.google.guava:guava:32.1.2-jre")
}

tasks.compileJava {
    classpath = files()
    options.compilerArgumentProviders.add(
        object : CommandLineArgumentProvider {
            @CompileClasspath
            val compileClasspath = sourceSets.main.map { it.compileClasspath }

            override fun asArguments() = listOf(
                "--module-path",
                compileClasspath.get().asPath
            )
        }
    )
}
m
Again, "easy" should be from the perspective of the average Gradle user, not from an expert. When they run into the same issue for the first time, the average Gradle user won't instantly identify the problem and come up with the solution that you did in 5 minutes. It even took me a fair amount of time to debug the issue before I learned enough to ask the question that I did; in that same time, others would just walk away and use Maven instead, since it just works there. In any real-world project, it's simply not a realistic constraint to tell people that they can only take deps that use a named/explicit-automatic module if they want to use Java modules themselves. We have to manage the impurity of depending on implied automatic modules as best we can, rather than disallow the purity (or make it hard to use "impure" solutions). If I'm a more technical product manager that's choosing between build systems for a product that uses Java modules, the arguments in favor of Maven (or for abandoning Java modules) are pretty simple: a list of every useful dependency that doesn't produce a named/explicit-automatic module.
v
Again, "easy" should be from the perspective of the average Gradle user, not from an expert.
Also "again", it should imho not be easy, as you shoot yourself in the foot. It should not be done. If you need to use non-modular JARs, then don't write modules. If you want to write modules, use modular replacements or make the projects release modular jars instead. Besides that I already referred you multiple times to the issue that will make it dead simple to shoot your foot like hat in the future unfortunately.
When they run into the same issue for the first time, the average Gradle user won't instantly identify the problem
The question is not about the average Gradle user, because the average Gradle users does not write JPMS modules anyway. Be that good or not is a different topic. The question is about someone wanting to write a JPMS module. Someone wanting to write a JPMS module should have some knowledge about JPMS. Such a person should also be aware of the differences of classpath and module path. The average of such a person should usually also be able to understand where that error comes from, especially when he did the very questionable decision to depen on an implied automatic module, which usually should already be a sign that he even has above average knowledge of JPMS. And especially as Gradle clearly documents which JARs are put to the classpath and which are put to the module path.
and come up with the solution that you did in 5 minutes.
You said that you are not able to get it running, or that it is PITA, even after I gave you the code, which is just wrong.
In any real-world project, it's simply not a realistic constraint to tell people that they can only take deps that use a named/explicit-automatic module if they want to use Java modules themselves.
Sure it is, that is how JPMS is designed. That it has this emergency fallback for plain jars on the module path was in my eyes a great misdecision. Well, that decision was made and gives you the power to use it. But great power comes with great responsibility.
the arguments in favor of Maven (or for abandoning Java modules) are pretty simple: a list of every useful dependency that doesn't produce a named/explicit-automatic module.
And abandoning Java modules is the exact right way in that case. And in parallel encouraging those dependencies to make their jars JPMS modules. You also cannot just put any jar on the module path. If you for example have split packages, you cannot put the jar on the module path. If you use service loader mechanism, you cannot put the jar on the module path. If you use deep reflection, you cannot put the jar on the module path. ...... Well, I told you multiple ways how to mitigate the defaults you don't like. And also tried to explain to you why - in my opinion - the Gradle folks decided to do it like that and that it makes sense, even if you don't want to agree. I even told you that it will get easier to follow that horrible practice in the future. Our conversation ended up in a cycle where you just repeat yourself constantly, so I'll break the cycle now and just stop writing here unless something new is said. 🙂
m
A lot of these claims about the JPMS should be tagged with [citation needed]. They make arguing your position more convenient, but they are at odds with the very people who created Project Jigsaw. This is from the page for Project Jigsaw: "The module system is powerful enough to modularize the JDK and other large legacy code bases, yet is still approachable by all developers." (https://openjdk.org/projects/jigsaw/) • The module system is designed to be "approachable by *all developers*" (emphasis added); my whole point here has been that Gradle makes the JPMS unapproachable to the average developer. • If you want to "modularize...large legacy code bases", you are almost certainly going to be dealing with "impure" dependencies that use implied automatic modules as part of that migration. See also https://www.oracle.com/corporate/features/understanding-java-9-modules.html: "Modularity—the result of Project Jigsaw—helps developers at all levels be more productive as they build, maintain, and evolve software systems, especially large systems." (emphasis added)
v
Emphasizes are fine. They state the intended goal. But those goals are not achieved. Java beginners don't even know what JPMS is, or how to use it, so it is not approachable by all developers and it does not help developers at all levels. And besides that, Gradle makes JPMS very approachable by just working properly in the typical situation with the most useful defaults. Migrating a legacy project is not the typical situation, and for sure not something a beginner would do. A beginner when learing JPMS would use JPMS modules from his JPMS modules and that just works out-of-the-box. And a last time, it will be more easy to shoot your foot with that non-sense setup in the future that will most likely break a bigger legacy project anyway. And no, I do not need any citations for stating my opinion.
m
Well at least we can agree that these are your own personal opinions on the JPMS. (And not those of the people who created JPMS.) What you think are flaws with the JPMS are actually imperfect but rational tradeoffs. If you want a solution that both makes it easily to modularize pre-Java 9 code (or work with non-modular code) and is also approachable for all developers (both are good goals to pursue), some compromises are necessary. That's my whole critique here: that purity has become an obstacle to making rational tradeoffs. To use Undertow as an example, we need to weigh the actual, concrete harms of making it hard to include Undertow as a dependency against any potential future harms of including Undertow as a dependency. E.g., what are the odds that the JAR name for Undertow will change from one release to the next? (And even if it did happen, it wouldn't be that hard to fix.) In any case, I filed an issue for this: https://github.com/gradle/gradle/issues/26726
v
But why did you report that duplicate? I already gave you the link to the issue that will result in exactly what you ask for most probably as I already said before. o_O
m
The two issues may (or may not) converge on the same solution, but they seem to different problems. One is about how the service loader discovers services with modules, and the other is about adding a simple dependency for a modular project.
v
Nah, both are about how to configure what goes on the module path and what goes on the classpath. What you said are just the symptoms.
🤷‍♂️
m
What's the old Google saying? "Focus on the user and all else will follow." If the issue is one that just affects power-users who are writing services, then perhaps a solution for power-users would be more appropriate. But if the issue ALSO affects the average developer who just wants to, e.g., take a dependency on Undertow, that would suggest that we need a solution targeted at the average user.
v
Again, the "average" user should not put plain jars on the module path, so the default is perfectly fine for the average user. And again, there will be options in the future to more easily change this. So what are you arguing about actually? Let's please just stop here, I don't think it will lead anywhere.
m
Again, we've established that these are your own person opinions of the JPMS, not those of Project Jigsaw. I abide by the latter. You were the one who criticized me for filing a "duplicate" issue. I was just merely explaining why the two issues are distinct because they affect two distinct groups of users.
v
Again, we've established that these are your own person opinions of the JPMS, not those of Project Jigsaw. I abide by the latter.
That you shouldn't put those jars on the module path? That is not my opinion, that is established best practice that you can read everywhere. I've also seen that recommended multiple times in various places, and it just makes sense. If you personally do not agree, that's your decision. But it is also not the opinion of project Jigsaw that you should do so. That they purely provide the possibility does in no means mean that it is recommended to use it like that. There are many such examples too. There is
subprojects { ... }
,
allprojects { ... }
,
project(...) { ... }
,
afterEvaluate { ... }
and some other things in Gradle for example. But their pure existence does not mean it is recommended to use them. It is even officially discouraged to use them. Or there are
sun.*
classes in the JDK, but still it is discouraged to use them. ... So no, you are not following the opinion of Jigsaw, you just follow your own opinion of how to do things, even if they are against best practices ... and that is fine for you.
You were the one who criticized me for filing a "duplicate" issue
I didn't critize, I just asked you why you did it when I already gave you the other. Obviously, you do not agree that it is a duplicate. But honestly, I don't care too much, that's not my cup of tea. We will see how the Gradle folks decide. I just try to avoid waisting their time with needing to care about duplicates, as their resources are already constrained enough sadly.
m
This is about tradeoffs. Tradeoffs. Tradeoffs. If we're talking about, e.g., overriding
equals()
but not `hashCode()`; the answer is simple: you should override both. There's no downside aside from a little extra work to implement
hashCode()
. Since no significant tradeoffs exist, you should just do the right thing. In the ideal world, yes, a modular project should not depend on an implied automatic module. In the real world, though, what do you do when many popular dependencies produce an implied automatic module? If we've established that the goal is that the JPMS "helps developers at all levels be more productive," per Oracle, what is the right set of tradeoffs?
v
You are comparing apples with pears. If you override
equals
you MUST override
hashCode
or you violate the contract. There is no should here, if you don't do it, that is simply a bug.
what do you do when many popular dependencies produce an implied automatic module?
If they are that popular, it shouldn't be a problem to make them proper modules or at least define an automatic module name if the jar otherwise is JPMS compatible, because then it is just a one-line change. If a dependency by now does not even have an automatic module name, it cannot be that popular, or is unmaintained and should thus not be used anyway. And besides that, again, for those insisting of depending on those from a module, they can configure Gradle to do what they want. And even if Jigsaw aims to help developers at all levels, this does not imply in any way that Gradle should do the same by having non-sense defaults like Maven does. 😉
m
To close the loop on this one, I eventually just switched that project from Gradle to Maven. Not saying that it's ideal--far from it--but it's the sadly the most viable path that doesn't involve abandoning the use of Java modules. (As for the workaround to put everything on the module path, it seemed to work from the command line, but it was not quite working for me in IntelliJ, which is a deal-breaker.) Honestly, Maven's behavior here is quite reasonable. Things just work there, but they will generate a warning like this:
Copy code
[WARNING] *********************************************************************************************************************************************************************************************************************
[WARNING] * Required filename-based automodules detected: [jsr305-3.0.2.jar, undertow-core-2.3.9.Final.jar, xnio-api-3.8.8.Final.jar, javax.inject-1.jar]. Please don't publish this project to a public artifact repository! *
[WARNING] *********************************************************************************************************************************************************************************************************************
If you search for "Required filename-based..." on Google, you will get some reasonable search results which will help educate you on that topic.
If they are that popular, it shouldn't be a problem to make them proper modules or at least define an automatic module name if the jar otherwise is JPMS compatible, because then it is just a one-line change.
If a dependency by now does not even have an automatic module name, it cannot be that popular, or is unmaintained and should thus not be used anyway.
This statement is so ridiculous and out-of-touch that it helped convince me to switch to Maven. Blaming developers because they didn't bend each and every one of their dependencies to your will is just a patently unrealistic expectation. Also, if you look at that warning, it includes
javax.inject
. So now you're telling me that
javax.inject
is a dependency that "should thus not be used anyway"? Not saying I'm a fan of Maven over Gradle, but that's a great way to advertise for Maven.
v
> Blaming developers because they didn't bend each and every one of their dependencies to your will is just a patently unrealistic expectation. Just because you are still not getting what I am saying it seems. If you have library A with version 1, that uses library B and is only compatible with version 2 of B, but breaks with version 3 of B. And in your project you want to use version 3 of library B because it has some functionality you need but is not present in version 2. You can then either • make the maintainer of A make it compatible with version 3 of library B • not use library A • use version 2 of library B yourself and not have the missing functionality • fork either of A or B and make it compatible for your situation And exactly the same situation you have here. A being a library without defined automatic module name B version 2 being putting the jar on the classpath B version 3 being putting the jar on the module path And you have exactly the same options • make maintainer of A make it compatible with JPMS • not use A • put your own stuff on the classpath • fork A and make it JPMS compatible yourself (could here be done on-the-fly with the plugin I mentioned) This is not ridiculous, but just the normal situation in the JVM ecosystem when different components use each other and not every version is compatible with all other versions. > Also, if you look at that warning, it includes
javax.inject
. So now you're telling me that
javax.inject
is a dependency that "should thus not be used anyway"? Well, you have at least the options described above. But yes, that artifact is 14 years old, so no wonder it knows nothing about JPMS. Fixing that would be trivial. But besides that, it is superseded by Jakarta Inject API anyway. And in this case it also is rather unproblematic anyway if you only annotate your code with these and not read them. You can simply
requires static ...
it, as you do not have a runtime dependency on them and there use the implied automatic module name after adding that to the module path, or an own one assigned by using the above described plugin. The real problems with implied automatic modules just start when you not have
requires static
but just
requires
or
requires transitive
. > but that's a great way to advertise for Maven. I don't know in which way my personal opinion on this topic has any influence to Gradle vs. Maven. This has nothing to do with Maven vs. Gradle. It is generally about putting implied automatic modules on the classpath or module path, no matter what build tool you use or wheter you use one at all.
m
I really don't care for talking points or proposed workarounds that sound nice in some hermetic bubble, but are not a realistic option in the real world. You're just repeatedly tossing options over the wall without any understanding of how realistic they are in the real-world, or how much extra work it would take to implement them. And when I try to explain how unrealistic they are, you just claim that I don't understand what you're saying. Yes, I do understand, but I also have to make real-world tradeoffs; I don't have the luxury of doing all this extra work to satisfy your desire for technical purity. And I've probably put way more effort into this than your typical developer would; a lot of developers would have switched to Maven (or abandoned Java modules) long before I did. E.g., it's not a realistic option to get
javax.inject:javax.inject
changed. But Dagger does not yet support jakarta; these sorts of migrations don't happen instantaneously in the real word. Sure, I guess I could fork Dagger (or not use Dagger, or do whatever other option you just toss over the wall). The problem there is not that I don't understand how to fork Dagger; the problem is if you're going to make me fork Dagger , I'll just switch to Maven, where things just work without a fork (though an appropriate warning is generated). Which is exactly what I did.
v
> I really don't care for talking points or proposed workarounds that sound nice in some hermetic bubble, but are not a realistic option in the real world. You're just repeatedly tossing options over the wall without any understanding of how realistic they are in the real-world, or how much extra work it would take to implement them. Why are you getting more and more personal? I just try to help you with a problem. You don't listen and insult me. And even with non-sense statements that just show that you don't know what you are talking about. I don't toss anything over a wall and I have pretty well understanding of realistic projects in the real world. I'm a professional developer since many years and all options I told you I already used in real-world projects depending on situation and all worked perfectly fine. That you cannot draw value from what I told you might be because you have a too narrow sight on what you think the world should work like. > And I've probably put way more effort into this than your typical developer would; a lot of developers would have switched to Maven (or abandoned Java modules) long before I did. I right away gave you the way how to do the same stupid and fragile non-sense Maven is doing with Gradle. That you don't take that one and put more effort in it, is not my fault. > the problem is if you're going to make me fork Dagger , I'll just switch to Maven, where things just work without a fork I don't make you anything, I just showed you what options you have. Also, if you are happier with Maven, by all means, do use Maven. To everyone his tool. If you prefer using a bad tool because it does what you exepect, be happy with it, why bothering with a better tool that does not fit your expectations. Anyway, I'll just stop responding in this conversation. I already wasted enough time trying to help you, and obviously you don't want to actually get help, but just insult me and bully around. 🤷‍♂️ 👋
m
> I right away gave you the way how to do the same stupid and fragile non-sense Maven is doing with Gradle. > That you don't take that one and put more effort in it, is not my fault. Except for the fact that your solution did not work. Earlier, I explicitly said, "(As for the workaround to put everything on the module path, it seemed to work from the command line, but it was not quite working for me in IntelliJ, which is a deal-breaker.)" This sadly is not the first time when you've given me your whole "I already gave you a solution" spiel after I explained why that solution did not work. So it's clear that you're not listening to me. On many occasions, when you think that I'm making "non-sense statements that just show that [I] don't know what [I am] talking about," what actually is happening is that you're not listening to me. (Especially whenever we get into the topic of tradeoffs.) And if you think that sort of professional criticism is a personal insult or a case of bullying, that's your problem, not mine... > I don't make you anything, I just showed you what options you have. > Also, if you are happier with Maven, by all means, do use Maven. > To everyone his tool. If you prefer using a bad tool because it does what you exepect, be happy with it, why bothering with a better tool that does not fit your expectations. For all your talk of being a professional developer, I really hope that you don't ever actually take this attitude in real life when a customer is frustrated with your product, and those frustrations cause them to switch to a competitor. I'm generally the type who likes to place product-savvy engineers closer to the customers, but I also understand why some product managers want to keep their engineers away from their customers...
v
after I explained why that solution did not work.
I'm sorry if I missed that, as you then directly skipped to other details. But here we talk about Gradle for which it works, not about IDE bugs that you should report to JetBrains. But actually you can just not do it during IntelliJ sync and it works as I wrote in the issue you created.
that sort of professional criticism is a personal insult or a case of bullying, that's your problem, not mine...
Of course professional and constructive criticism like "that does not work for me because ..." is not what I meant. But things like saying I'm living in a hermetic bubble and have no idea about realistic situations and real-world problems are pretty personal attacks and insults. If you don't see that, that is not my problem, but yours. 😉
when a customer is frustrated with your product, and those frustrations cause them to switch to a competitor
Gradle is not my product. I'm in no way affiliated to Gradle. I'm just a user like you, trying to help fellow Gradle users like you in my sparse spare time.