How in Eclipse project module java-9 have modulepath and classpath together?

Hello,

For my first contact with Gradle I created a java module project (OpenJDK-11) under Eclipse. The version of Eclipse is “2019-09 (4.13)” and I used the plugin “Buildship Gradle integration 3.0” to create the project.

I ended up figuring out how to set up the build.gradle file to integrate module path or class path dependencies but I do not see how to have both. So I can not have a configuration that recognizes main classes and test classes in the same project (in Eclipse).

The module-info.java file :

module myApplication {
   exports Application;
   requires yamlbeans;
}

The build.gradle file :

plugins {
    id ‘java-library’
}

repositories {
    jcenter()
}

dependencies {
    implementation group: ‘com.esotericsoftware.yamlbeans’, name: ‘yamlbeans’, version: ‘1.06’
}

apply plugin: ‘java’
apply plugin: ‘eclipse’

eclipse {
    classpath {

	//Necessary otherwise the library is not raised to the module level.
	containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
	
    file {
        whenMerged {
            entries.findAll { isConGradle(it) }.each {
            	it.entryAttributes['module'] = 'true'
            }
        }
    }
}

}

boolean isConGradle(entry) {
    entry.kind == ‘con’ && entry.path == ‘org.eclipse.buildship.core.gradleclasspathcontainer’
}

I saw that it was possible to add a container and place it at the classpath level but I do not see how to assign to this container library entries that would be declared in the block “dependencies” with for example “testImplementation (…)”.

Would anyone have an idea to do that?

My Eclipse 2019-06 with Buildship 3.1.0.v20190501-0832 shows a different module path than your setup shows, @Graou74:


As an experiment, I created a project using the build script you listed above. When I run the :test task in Eclipse — with the build script precisely how you wrote it above — I get this:

> Task :compileJava FAILED
.../Graou74/src/main/java/module-info.java:3: error: module not found: yamlbeans
    requires yamlbeans;
             ^
1 error

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.
...
BUILD FAILED in 2s
1 actionable task: 1 executed

When I make these very simple changes to build.gradle

plugins{
    id 'java-library'
    id 'eclipse'
    id 'com.lingocoder.mrjar' version '0.0.13'
}
...

…and then run the :test task in Eclipse again, I get this:

...
BUILD SUCCESSFUL in 5s
3 actionable tasks: 1 from cache, 2 up-to-date

I get the same result if I run :test from the command line. First using your original (it fails), then applying mrJar like above (it succeeds).

Give mrJar a try. Let me know if it works for you?

Thanks lingocoder for your answer.

I do not get the same result as you but it’s most likely because of an Eclipse/Buildship bug on Mac Osx. I guess the problem is associated with the OS because I have exactly the same problem with the same eclipse version as you (2019-06) but on Mac Osx :

Task :test
Caching disabled for task ':test' because:
  Build cache is disabled
Task ':test' is not up-to-date because:
  Task.upToDateWhen is false.
Finished generating test XML results (0.0 secs) into: /Users/.../TestGradleTest/build/test-results/test
Generating HTML test report...
Finished generating test html results (0.041 secs) into: /Users/.../TestGradleTest/build/reports/tests/test
:test (Thread[Execution worker for ':' Thread 2,5,main]) completed. Took 0.122 secs.

FAILURE: Build failed with an exception.

* What went wrong:
No matching tests found in any candidate test task.
    Requested tests:
        Test class TestGradleTest.LibraryTest

* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 905ms
3 actionable tasks: 1 executed, 2 up-to-date

When I run the test with command line, everything works perfectly :

Task :test
Caching disabled for task ':test' because:
  Build cache is disabled
Task ':test' is not up-to-date because:
  Value of input property 'filter.failOnNoMatchingTests' has changed for task ':test'
  Value of input property 'filter.includePatterns' has changed for task ':test'
Starting process 'Gradle Test Executor 4'. Working directory: /Users/.../TestGradleTest Command: /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/bin/java -Dorg.gradle.native=false @/private/var/folders/4t/wfx1sb3d2b7d82x56zmr3l1h0000gn/T/gradle-worker-classpath1860032888025482123txt -Xmx512m -Dfile.encoding=UTF-8 -Duser.country=FR -Duser.language=fr -Duser.variant -ea worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle Test Executor 4'
Successfully started process 'Gradle Test Executor 4'
Finished generating test XML results (0.001 secs) into: /Users/.../TestGradleTest/build/test-results/test
Generating HTML test report...
Finished generating test html results (0.001 secs) into: /Users/.../TestGradleTest/build/reports/tests/test
:test (Thread[Execution worker for ':',5,main]) completed. Took 0.378 secs.

BUILD SUCCESSFUL in 883ms
3 actionable tasks: 1 executed, 2 up-to-date

So I can not test your solution. I will create a ticket to Eclipse/Buildship.

However, my question was not yet at this level. It is based on the fact that when the “Project and external dependencies” container is at the “Modulepath” level (in “Java build path/Libraries”), the test classes are not recognized by the Eclipse editor:

Does your solution solve this problem too?

Have you tried upgrading to Buildship 3.1.0.v20190501-0832 or better?

By that, I gather you mean you’ve done something like this:


Is there a specific reason why you must do that? What is the reason why you cannot add JUnit to the module path the way that I showed you in the build script I uploaded for you?

I guess I have misunderstood the problem you are trying to solve. Sorry.

It would help my understanding though if you first please explain why you need to „assign to this container library entries“.

Aside from adding them to the IDE with the GUI like in my screenshots above, I know practically zero about Eclipse containers. But I presume that it is very likely possible to write some clever Groovy code in your build script that would do what you’re describing.

But if all you really want is to simply add test dependencies to the module path, then I would do it the simple way that I’ve exemplified in the script I’ve uploaded for you.

@Donat would most likely advise you to first upgrade Buildship to the latest and greatest, and see if that gets you any closer to whatever solution you’re after.

Before creating a ticket I wanted to test under Windows. I downloaded the latest version of eclipse for Windows, set the Java environment with the OpenJDK 11, Created the Gradle project with the Wizard, the most basic, without touching the code. Then I ran the Gradle test from Eclipse and I have exactly the same problem. The version of Buildship is “3.1.2.v20190903-1802” and that of Eclipse is “2019-09 R (4.13.0)”.

Following your remark I proceeded to the update of Buildship in Eclipse “Version: 2019-09 (4.13)” on Mac Osx and the last update Buildship becomes “3.1.2.v20190903-1802” (like the one of Windows). I am doing the same test that is done in Windows and I get exactly the same error.

I also tried the same thing in the 2019-06 version of Mac Osx hard eclipse (Buildship version “3.1.2.v20190903-1732”) and still the same error.

Here is the image of Mac and Windows versions for Eclipse 2019-09:


Do you think I should create a ticket or before I try to install the same Buildship version as you?

To summarize my initial expectation, it is simply to have a project Gradle Module Java-9 in Eclipse whose dependencies are recognized everywhere in the editors, as well as the Main as tests. As it happens for non-Java-9 Module projects.
And of course being able to run runs and tests :slightly_smiling_face: (which work on the command line).

I guess the solution exists by setting the Eclipse task with the right information. I searched this information a lot but without success (hence my post).
While waiting I will move towards a solution plan B (less elegant) which consists of dividing the project in two with a project Main and a project Test (for example here ZProject and ZProjectTest):

Thank you for your help Lingocoder.

Sorry I could not reply sooner.

The latest version is usually always better. That version I mentioned just happened to be what I had on my machine.

Actually, a (more elegant?) solution exists bundled inside that project zip file I uploaded for you yesterday. In it, you will find a gradle folder. In there is a script you should import into your build.gradle.

Follow These Steps

  1. Download and extract the project zip file I uploaded for you yesterday (link’s above)

  2. Delete or comment-out the existing elcipse{ } block from that project’s build.gradle

  3. Add this line at the top of that build.gradle

    ...
    apply( from: file( 'gradle/eclipse/modulefy.gradle' ) )
    ...
    
  4. If you’ve already imported the project in Eclipse, close and delete the project from Eclipse (don’t delete it from the file system)

  5. Open a terminal in the root folder of that project.

  6. Run: ./gradlew eclipse

  7. Open Eclipse and reimport as a Gradle project

Expected Result

It works for me…

…let me know if it works for you too? TIA :+1:

A big thank you Lingocoder, the eclipse block of the modulefy.gradle file exactly meets my expectations. This is precisely the behavior I wanted.

I wonder if I should not, once the Eclipse test run bug has been fixed, make a tutorial on this case.
I do not remember seeing this eclipse task script during my search on the web (or I should clean my glasses).
Anyway, I spent a lot of time on this problem (and you too) for finally something that I thought should have been plug & play.
I imagine that someone in my situation (new to Gradle and Java-9 modules) would be happy to find a ready-made solution.

Again thank you Lingocoder for your help, I will now be able to code in comfort.