[JAVA] Unable to get resources when using modules in Gradle and IntelliJ

environment

Java

openjdk 11 2018-09-25

Gradle

Gradle 4.10.2

IntelliJ

IntelliJ IDEA 2018.2.4 (Community Edition)
Build #IC-182.4505.22, built on September 18, 2018

OS

Windows 10

Problems that occur

Project structure

|-build.gradle
`-src/main/
  |-java/
  | |-module-info.java
  | `-foo/
  |   `-Foo.java
  `-resources/
    `-resource.txt

code

build.gradle


apply plugin: "application"

sourceCompatibility = 11
targetCompatibility = 11

compileJava.options.encoding = "UTF-8"
mainClassName = "foo/foo.Foo"

compileJava {
    doFirst {
        options.compilerArgs = [
            "--module-path", classpath.asPath
        ]
        classpath = files()
    }
}

run {
    doFirst {
        jvmArgs = [
            "--module-path", classpath.asPath,
            "--module", mainClassName
        ]
        classpath = files()
    }
}

module-info.java


module foo {
    exports foo;
}

Foo.java


package foo;

import java.net.URL;

public class Foo {

    public static void main(String[] args) throws Exception {
        URL resource = Foo.class.getResource("/resource.txt");
        System.out.println("resource=" + resource);
    }
}

Execution result

> gradle run
resource=null

-- /resource.txt cannot be obtained and becomes null --Same result when imported into IntelliJ --By the way, you can get it without any problem with Eclipse (Photon).

Cause (probably)

--In Gradle and IntelliJ, the build results of src / main / java and src / main / resources are output to different directories.

gradle build result


|-build
: |-classes/java/main/
: | `-foo/
: |   `-Foo.class
: |
: |-resources/main/
: : `-resource.txt

IntelliJ build results


|-out/production/
: |-classes/
: | `-foo/
: |   `-Foo.class
: |
: `-resources/
:   `-resource.txt

--At this time, check how the module path is set.

Foo.java


package foo;

import java.net.URL;
import java.util.stream.Stream;

public class Foo {

    public static void main(String[] args) throws Exception {
        System.out.println("[jdk.module.path]");
        Stream.of(System.getProperty("jdk.module.path")
                .split(";"))
                .map(p -> "  " + p)
                .forEach(System.out::println);

        URL resource = Foo.class.getResource("/resource.txt");
        System.out.println("resource=" + resource);
    }
}

Gradle execution result


[jdk.module.path]
  ...\build\classes\java\main
  ...\build\resources\main
resource=null

IntelliJ execution result


[jdk.module.path]
  ...\out\production\classes
  ...\out\production\resources
resource=null

--Each is set in the module path --In other words, I feel that the resources directory is treated as a separate module from the foo module. --If you put a directory without module-info.class in the module path, will it be treated as an anonymous module? ?? ?? --In the case of a jar file, the module name is resolved from the file name and it is treated as an automatic module, but in the case of a directory, I do not know what happens. --And when you check the JavaDoc for Class.getResource (String), it explains:

If this class is in a named Module, ** this method will try to find resources in the module **. (Omitted) This method returns null ** if the resource is a non- ".class" resource in a package that is ** not open to the calling module **.

getResource(String) | Class | Java 10

--That is, Class.getResource (String) will only try to find the resources in the module to which the class belongs. --If the resource is another module, the package must be open (ʻopensspecified?) --Ifresourcesis treated as an anonymous module, I feel like I can't access the anonymous module from the named module. --At least the class is inaccessible --I don't know exactly if the resources are also inaccessible --By the way, in the case of Eclipse, bothsrc / main / java and src / main / resourcesare output underbin / main`.

Organize the story

--In case of Gradle, IntelliJ, files under src / main / resources directory are output to directory different from the compilation result under src / main / java. --The output destinations of src / main / java and src / main / resources will be specified in the module path as separate directories. --src / main / resources is treated as a different module than src / main / java (probably an anonymous module?) --Class.getResource (String) seems to basically only be able to access resources in the same module or in an open module --Therefore, files placed under src / main / resources cannot be read as resources.

Expected to the last.

Solution

Can't access resource with Java 10 – IDEs Support (IntelliJ Platform) | JetBrains

It seems that some people are in trouble with the same thing.

The final method explained here is that the output destination of src / main / resources should be the same as the output destination of src / main / java.

build.gradle


apply plugin: "application"
+ apply plugin: 'idea'

sourceCompatibility = 11
targetCompatibility = 11

compileJava.options.encoding = "UTF-8"
mainClassName = "foo/foo.Foo"

+ sourceSets {
+     main {
+         output.resourcesDir = java.outputDir
+     }
+ }
+ 
+ idea.module.outputDir file("out/production/classes")

compileJava {
    doFirst {
        options.compilerArgs = [
            "--module-path", classpath.asPath
        ]
        classpath = files()
    }
}

run {
    doFirst {
        jvmArgs = [
            "--module-path", classpath.asPath,
            "--module", mainClassName
        ]
        classpath = files()
    }
}

--Adjusting the output destination of IntelliJ and the output destination of Gradle respectively

Execution result

Gradle execution result


> gradle run
[jdk.module.path]
  ...\build\classes\java\main
resource=file:/.../build/classes/java/main/resource.txt

IntelliJ execution result


[jdk.module.path]
  ...\out\production\classes
resource=file:/.../out/production/classes/resource.txt

--Resources can now be accessed by aligning the output destinations of src / main / resources.

Recommended Posts

Unable to get resources when using modules in Gradle and IntelliJ
I summarized the points to note when using resources and resources in combination
Resolve "Cannot resolve symbol" in IntelliJ projects using Gradle
Things to keep in mind when using if statements
How to get the class name of the argument of LoggerFactory.getLogger when using SLF4J in Java
How to convert A to a and a to A using AND and OR in Java
How to test including images when using ActiveStorage and Faker
Get error information using DefaultErrorAttributes and ErrorAttributeOptions in Spring Boot 2.3
Set up Gradle multi-project in IntelliJ to build JAR file
How to dynamically switch JDK when building Java in Gradle
Contributed to Gradle and was named in the release notes
Things to keep in mind when using Sidekiq with Rails
Gradle to touch and remember
Ubuntu unable to log in
I can't log in to MySQL from Django when using docker-compose
In Java 10, when you do gradle eclipse and JavaSE-1.10 comes out, ...
How to POST JSON in Java-Method using OkHttp3 and method using HttpUrlConnection-
How to create a new Gradle + Java + Jar project in Intellij 2016.03
Things to note when using Spring AOP in Jersery resource classes
[jOOQ] How to CASE WHEN in the WHERE / AND / OR clause
How to get and add data from Firebase Firestore in Ruby
[Android] Convert Map to JSON using GSON in Kotlin and Java
How to solve the unknown error when using slf4j in Java
Conveniences I've been using since migrating from Eclipse to IntelliJ IDEA (in terms of search and Git)
Precautions when using checkboxes in Thymeleaf
Popular trends in gradle and maven
Do HelloWorld in Java / IntelliJ / Gradle
How to run Ant in Gradle
How to get parameters in Spark
Hello world in Java and Gradle
Enable log output to both file and console using log4j in Eclipse.
Things to keep in mind when combining if statements and logical operators
[Android] How to pass images and receive callbacks when sharing using ShareCompat
[Note] I want to get in reverse order using afterLast with JdbcTemplate
What to do and how to install when an error occurs in DXRuby 1.4.7
Try to get data from database using MyBatis in Micronaut + Kotlin project
Things to keep in mind when using Apache PDFBox® with AWS Lambda
I want to get the IP address when connecting to Wi-Fi in Java
Java --Introduce CheckStyle plugin to IntelliJ IDEA and reflect it in formatter
How to create your own annotation in Java and get the value
What to do if Command line is too long appears when building a gradle project in Intellij IDEA