9

Following example project a:

project-a
-src/main/
         -java/
              -test/
                   -Test.java
              module-info.java
         -resources
...
pom.xml

pom.xml:

<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>test</groupId>
    <artifactId>test1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.json</groupId>
            <artifactId>javax.json-api</artifactId>
            <version>1.1.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.json</artifactId>
            <version>1.1.4</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <release>11</release>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

module-info.java:

module test1 {
    exports test;
    requires transitive java.json;
}

when I run eclipse [project > maven > update project], all dependencies are added to the classpath. but the artifact javax.json-api must be on the modulepath (the api is a module), the other on the classpath (the implementation of that api is not a module).

How do I do this?

(I am using Eclipse 2018-12, OpenJDK 11 and maven 3.6.0)

Example code of class Test:

package test;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonObjectBuilder;
import javax.json.JsonStructure;
import javax.json.JsonWriter;
import javax.json.JsonWriterFactory;
import javax.json.stream.JsonGenerator;

public class Test {

    public static void main(String[] args) {
        JsonObjectBuilder b = build("name", "FOO", "surname", "BAR");
        String s = toFormattedString(b.build());
        System.out.println(s);
    }

    public static String toFormattedString(JsonStructure json) {
        Map<String, Boolean> config = new HashMap<String, Boolean>();
        config.put(JsonGenerator.PRETTY_PRINTING, true);
        JsonWriterFactory writerFactory = Json.createWriterFactory(config);
        StringWriter writer = new StringWriter();
        JsonWriter jsonwriter = writerFactory.createWriter(writer);
        jsonwriter.write(json);
        return writer.getBuffer().toString();
    }

    public static JsonObjectBuilder build(Object... objs) {
        JsonObjectBuilder b = Json.createObjectBuilder();
        for (int i = 0; i < objs.length - 1; i += 2) {
            String name = (String) objs[i];
            Object obj = objs[i + 1];
            if (obj == null) {
                b.addNull(name);
            } else if (obj instanceof String) {
                b.add(name, (String) obj);
            } else if (obj instanceof Integer) {
                b.add(name, (int) obj);
            } else if (obj instanceof Double) {
                b.add(name, (double) obj);
            } else if (obj instanceof Long) {
                b.add(name, (long) obj);
            } else {
                throw new IllegalArgumentException("Value type not supported:" + obj + " [class=" + obj.getClass() + "]");
            }
        }
        return b;
    }
}
huidube
  • 390
  • 3
  • 15
  • You should build on plain command line with JDK 11 ...If you need a dependency as a module you should add it to `module-info.java` cause you already have it as a dependency ? – khmarbaise Jan 21 '19 at 10:39
  • 1
    I already added the dependency (java.json) to the module path. But the [maven >update project] puts all maven dependencies on the classpath. – huidube Jan 21 '19 at 10:53
  • The `java.jason` yes but what about your `javax.json-api` which is not in your `module-info.java` file.... – khmarbaise Jan 21 '19 at 10:54
  • the module of actifact `javax.json-api` is called `java.json`. the artifact `javax.json` of groupid `org.glassfish`, which implements the `javax-json-api`, is not a module, so i can't be added to the module-info/module-path. – huidube Jan 21 '19 at 11:07
  • What's your expectation? That some dependencies are on the module path and others on the classpath (but that wouldn't make sense)? – howlger Jan 21 '19 at 11:57
  • 2
    1. I just want ANY Maven dependency to be automatically set to the module path when the Maven project is updated in Eclipse. 2. why doesn't that make sense? Do you have another idea how to solve the problem? – huidube Jan 21 '19 at 12:42
  • 2
    @huidube All the extra effort required for JPMS is to define a subset of the system library with the goal to reduce the start time and/or to create a minimal customized JRE (via `jlink`). But this works only without any dependency on the classpath. Can you explain why you want to use JPMS? – howlger Jan 21 '19 at 17:04
  • @howlger we have a framework consisting of > 10 projects, which we use in different applications. Some have > 1000 classes. As out devs have very different skill levels, i thought it would be a good idea to restrict access to some subprojects. So i started testing things out. – huidube Jan 22 '19 at 09:09
  • @huidube JPMS adds complexity and only works under certain conditions (no default package, cross-module unique module and package names; see the [answer by ZhekaKozlov](https://stackoverflow.com/a/54304598/6505250)). To restrict access to some subprojects/dependencies use access rules (in the _Java Build Path_ tab _Libraries_ via editing the _Access rules_ subnodes) which works with and without JPMS. – howlger Jan 22 '19 at 10:58
  • @howlger Isn't it the future that everything in java becomes a module? – huidube Jan 22 '19 at 11:32
  • 2
    @huidube IMHO hopefully not as long as JPMS doesn't include semantic versioning and doesn't offer modules that can be started and stopped at runtime (as OSGi already can). But that's just my personal opinion. You must decide whether in your case the effort is worth the benefit that JPMS brings. Independent of this, you cannot yet use JPMS in your case because not all dependencies are ready for JPMS. – howlger Jan 22 '19 at 12:07

1 Answers1

4

I couldn't recreate your issue. In general, Eclipse puts modules on the module path which are required in module-info.java. So, most of the time you don't even need to care about this.

In your case, I see a different issue. Two jar files javax.json-api and javax.json have the same module name and share the same packages. javax.json-api is an explicit module (with module-info.java). javax.json is an automatic module (no module-info.java). I don't know how Java will handle this but this is not a good situation certainly. I recommend fixing this issue first (e.g. merge modules or use classpath instead of a module path).

ZhekaKozlov
  • 36,558
  • 20
  • 126
  • 155