question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Documented method of using Wrapper types fails with Java 17 library target

See original GitHub issue

I have created a minimal reproduction of this issue here:

https://github.com/mglazer/repro-javaseventeen-immutables

The crux of the issue, is that when using Java 17 as a library target, if you have a Wrapper type, using:

@Value.Style(
        typeAbstract = "*Wrapper",
        typeImmutable = "*",
        visibility = Value.Style.ImplementationVisibility.PUBLIC,
        defaults = @Value.Immutable(builder = false, copy = false))
public @interface Wrapped {}

and:

import com.fasterxml.jackson.annotation.JsonValue;
import org.immutables.value.Value;

public abstract class Wrapper<T> {
    @JsonValue
    @Value.Parameter
    abstract T value();

    @Override
    public final String toString() {
        return value().toString();
    }
}

And then attempt to use that construction, only with Java 17 will you get compilation errors:

> Task :repro-javaseventeen-immutables-core:compileJava FAILED
Round 1:
	input files: {com.palantir.reprojavaseventeenimmutables.UseRepro, com.palantir.reprojavaseventeenimmutables.Wrapper, com.palantir.reprojavaseventeenimmutables.Wrapped, com.palantir.reprojavaseventeenimmutables.ReproIssueWrapper}
	annotations: [org.immutables.value.Value.Immutable, com.fasterxml.jackson.annotation.JsonValue, org.immutables.value.Value.Parameter, java.lang.Override, org.immutables.value.Value.Style, com.palantir.reprojavaseventeenimmutables.Wrapped]
	last round: false
Processor org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor matches [/org.immutables.value.Value.Immutable] and returns false.
Processor org.gradle.api.internal.tasks.compile.processing.SupportedOptionsCollectingProcessor matches [/com.palantir.reprojavaseventeenimmutables.Wrapped, /com.fasterxml.jackson.annotation.JsonValue, java.base/java.lang.Override, /org.immutables.value.Value.Immutable, /org.immutables.value.Value.Parameter, /org.immutables.value.Value.Style] and returns false.
warning: Was unable to read source file for com.palantir.reprojavaseventeenimmutables.UseRepro[com.sun.tools.javac.code.Symbol$ClassSymbol.class]: java.io.FileNotFoundException: com/palantir/reprojavaseventeenimmutables/UseRepro.java
Round 2:
	input files: {com.palantir.reprojavaseventeenimmutables.ImmutableUseRepro, com.palantir.reprojavaseventeenimmutables.ReproIssue}
	annotations: [org.immutables.value.Generated, java.lang.SuppressWarnings, javax.annotation.ParametersAreNonnullByDefault, javax.annotation.processing.Generated, javax.annotation.concurrent.Immutable, javax.annotation.CheckReturnValue, javax.annotation.concurrent.NotThreadSafe, javax.annotation.Nullable, com.google.errorprone.annotations.CanIgnoreReturnValue, java.lang.Override]
	last round: false
warning: Was unable to read source file for com.palantir.reprojavaseventeenimmutables.UseRepro[com.sun.tools.javac.code.Symbol$ClassSymbol.class]: java.io.FileNotFoundException: com/palantir/reprojavaseventeenimmutables/UseRepro.java

Processor org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor matches [] and returns false.
Processor org.gradle.api.internal.tasks.compile.processing.SupportedOptionsCollectingProcessor matches [/javax.annotation.concurrent.NotThreadSafe, /javax.annotation.Nullable, /com.google.errorprone.annotations.CanIgnoreReturnValue, /javax.annotation.CheckReturnValue, java.compiler/javax.annotation.processing.Generated, /javax.annotation.concurrent.Immutable, /org.immutables.value.Generated, java.base/java.lang.SuppressWarnings, java.base/java.lang.Override, /javax.annotation.ParametersAreNonnullByDefault] and returns false.
Round 3:
	input files: {}
	annotations: []
	last round: true
error: warnings found and -Werror specified
1 error
1 warning
error: warnings found and -Werror specified

The most noticeable error which occurs when verbose processor logging is disabled is the:

warning: Was unable to read source file for com.palantir.reprojavaseventeenimmutables.UseRepro[com.sun.tools.javac.code.Symbol$ClassSymbol.class]: java.io.FileNotFoundException: com/palantir/reprojavaseventeenimmutables/UseRepro.java

Otherwise, I have been unable to find anything that sticks out from the compilation messages.

I have attempted this with both Immutables 2.8.8 and 2.9.0 and it reproduces on both.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:3
  • Comments:16 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
carterkozakcommented, Sep 21, 2022

Oh gosh, I see the difference between the command-line and javac cases: running within idea, we’re missing some exports that are necessary for immutables, so despite both using javac, running within idea uses the SourceExtractor.DefaultExtractor while on the command line we get the SourceExtractor.JavacSourceExtractor` due to:

java.lang.IllegalAccessError: class org.immutables.value.internal.$generator$.$Compiler (in unnamed module @0x732ce05b) cannot access class com.sun.tools.javac.code.Symbol$ClassSymbol (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.code to unnamed module @0x732ce05b
	at org.immutables.value.internal.$generator$.$Compiler.detectCompilers($Compiler.java:38)
	at org.immutables.value.internal.$generator$.$Compiler.<clinit>($Compiler.java:31)
	..etc

Why does this only occur in the IDE? A gradle plugin in my default template uses error-prone static analysis, which requires some compiler exports to function, which allow the SourceExtractor code to work correctly in jdk-17. 🌶️ The plugin doesn’t apply error-prone when it detects intellij for historical reasons 🌶️

I’ve pushed a commit to my repro which opts out of error-prone, allowing a repro from the command line. I suspect we may want to bring back the compiler warning where we can recommend adding exports to support the annotation processor.

1reaction
elucashcommented, Sep 21, 2022

The using TwoTuple is a key difference. When compiling One {... TwoTuple issue(), the class/interface TwoTuple is known to compiler, it knows the package it comes from, full name/path etc. In the generated code all imports are processed properly. But when using One {... Two issue(), the compiler says to us (to Immutables processor), “— look, here’s some broken and not available type called Two, I wash my hands”, then processor says to itself, “— Oki-doki, we’ll use this type anyway in case it will be generated, but if it comes from another package we’re busted, only if there would be source code available, we could try to parse imports from there…”, and the annotation processor uses ~dark magic~ javac/ecj specific ways to access the underlying source code and if it succeeds and founds import from another package for Two it will put such an import into generated file, but if it’s not – then type name Two copied into the generated code as is (if it’s happens to be generated in the same package – that will work, but will fail for another package).

Read more comments on GitHub >

github_iconTop Results From Across the Web

java.util (Java SE 17 & JDK 17) - Oracle Help Center
A Red-Black tree based NavigableMap implementation. A NavigableSet implementation based on a TreeMap . Unchecked exception thrown when an unknown conversion is ...
Read more >
Building Java & JVM projects - Gradle User Manual
Gradle uses a convention-over-configuration approach to building JVM-based projects that borrows several conventions from Apache Maven.
Read more >
Java project in Eclipse: The type java.lang.Object cannot be ...
The solution I found was to remove the project from Eclipse (not from disk), remove the project's Eclipse files from the disk, and...
Read more >
Building a Native Executable - Quarkus
This means that you may see the following error when using gu : ... the application code, required libraries, Java APIs, and a...
Read more >
Spring Boot Reference Documentation
You can use Spring Boot in the same way as any standard Java library. To do so, include the appropriate spring-boot-*.jar files on...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found