I am currently migrating a project to JDK 11 and compiling it with Maven. However, Maven throws a wobbly over a single method reference (it doesn't have issues elsewhere). The method in question looks like this:
public class MyThing {
boolean something = true;
// ...
public boolean isSomething() {
return something;
}
// ...
}
And the call to the above method looks more or less like this:
return methodThatGetsOptionalDefinition(aString) // Optional<Definition>
.map(definition -> defenition.getMyThing(anotherString)) // Optional<MyThing>
.map(MyThing::isSomething) // Optional<Boolean>
.orElse(true);
Compiling this, Maven throws the following message:
> mvn clean install -Pdist-snapshot -DskipTests
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project XXXXX: Compilation failure
[ERROR] /D:/XXXXX.java:[63,38] incompatible types: invalid method reference
[ERROR] method isSomething in class XXXXX.MyThing cannot be applied to given types
[ERROR] required: no arguments
[ERROR] found: java.lang.Object
[ERROR] reason: actual and formal argument lists differ in length
[ERROR]
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
If I expand the method reference like so, it compiles without a problem:
return methodThatGetsOptionalDefinition(aString)
.map(definition -> defenition.getMyThing(anotherString))
.map(myThing -> myThing.isSomething())
.orElse(true);
Typing the Optional also works:
return methodThatGetsOptionalDefinition(aString)
.<MyThing>map(definition -> defenition.getMyThing(anotherString))
.map(myThing -> myThing.isSomething())
.orElse(true);
The same error occurs when compiling the project using IntelliJ with both Open JDK versions 11.0.1 and 11.0.2. Ironically, IntelliJ complains that the "Lambda can be replaced with method reference". The problem also occurs when using a different "language mode".
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
Does anyone have any idea why this might be happening?
Some of the specific implementation details have been obfuscated.
It has to do with the Type definition of the map method.
In order to provide a method reference, the method must have a matching Type definition. Stream map has a function method, but yours is a producer function.
Function = (T) -> R
Producer = () -> R
So, Method::isSomething() is not compatible with Stream.map, but your inline closure myThing -> myThing.isSomething() is..
Related
I would have a Scala question. I have the following code while using resilience4j library. The code works like a charm in Scala 12, but my project, a client library uses Scala-Cross compiling to Scala 11 also. When building it under Scala 11 I get the following error. Anyone has an idea how this should be written in Scala 11 to also compile?
import io.github.resilience4j.retry.Retry
import java.util.function.{Supplier, Function => JavaFunction}
val supplier: Supplier[List[Endpoint]] = () => getEndpoints
val decoratedSupplier = Retry.decorateSupplier(retry, supplier)
val result = io.vavr.control.Try.ofSupplier(decoratedSupplier)
.onSuccess { endpoints => endpoints }
.onFailure { failure =>
// handle failure
}.get()
In Scala 11 I get the following errors:
[Error] ServiceDiscoveryClient.scala:38: type mismatch;
found : () => List[Endpoint]
required: java.util.function.Supplier[List[Endpoint]]
[Error] ServiceDiscoveryClient.scala:41: missing parameter type
[Error] ServiceDiscoveryClient.scala:97: type mismatch;
found : () => List[Endpoint]
required: java.util.function.Supplier[List[Endpoint]]
four errors found
Any ideas? Thanks!
In Scala 2.11 you need -Xexperimental compiler option to support passing lambdas as SAM types such as java.util.function.Supplier. In 2.12 it's enabled by default. You can either add this option, or add scala-java8-compat dependency and
import scala.compat.java8.FunctionConverters._
...
val supplier: Supplier[List[Endpoint]] = (() => getEndpoints).asJava
(asJava may also be needed for lambdas used in result).
In my current project, i have this code:
for(Annotation annotation : field.getAnnotations()) {
String package = annotation.annotationType().getPackage().getName();
if(package.equals("com.loja.annotations.input_type"))
input.setAttribute("type", annotation.annotationType().getSimpleName());
}
when i try build the project, this code causes a compilation failure due to this error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project store: Compilation failure: Compilation failure:
[ERROR] /c:/Users/Kleber Mota/Documents/GitHub/app/src/main/java/com/loja/thymeleaf/processor/form/InputProcessor.java:[37,11] not a statement
[ERROR] /c:/Users/Kleber Mota/Documents/GitHub/app/src/main/java/com/loja/thymeleaf/processor/form/InputProcessor.java:[37,17] ';' expected
[ERROR] /c:/Users/Kleber Mota/Documents/GitHub/app/src/main/java/com/loja/thymeleaf/processor/form/InputProcessor.java:[38,14] illegal start of expression
[ERROR] /c:/Users/Kleber Mota/Documents/GitHub/app/src/main/java/com/loja/thymeleaf/processor/form/InputProcessor.java:[38,21] illegal start of expression
[ERROR] /c:/Users/Kleber Mota/Documents/GitHub/app/src/main/java/com/loja/thymeleaf/processor/form/InputProcessor.java:[38,28] ';' expected
[ERROR] /c:/Users/Kleber Mota/Documents/GitHub/app/src/main/java/com/loja/thymeleaf/processor/form/InputProcessor.java:[38,22] variable declaration not allowed here
anyone can see what's wrong here?
line 37 is: String package = annotation.annotationType().getPackage().getName(); and line 38 is if(package.equals("com.loja.annotations.input_type"))
you can try this..
annotation.annotationType().getName();
You can print out your "package" variable after line 37 (before if).
I wrote and ran the similar code and it worked for me. I created a custom annotation in my api package and line 37 returned "api".
I think everybody who has to work with Maven and Java8 knows of this bug that release builds suddenly fail for spelling mistakes in JavaDoc. As a company we decided to let some poor sap (aka me) work all of them out. Now I'm stuck with the following "error":
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.10.1:javadoc (default-cli) on project org.acme.project.demo: An error has occurred in JavaDocs report generation:
[ERROR] Exit code: 1 - C:\jenkins\workspace\Project 2.0\org.acme.project.demo\src\main\java\org\acme\project\demo\SomeClass.java:36: error: cannot access OtherClass
[ERROR] import org.acme.project.OtherClass;
[ERROR] ^
[ERROR] bad class file: C:\jenkins\workspace\Project 2.0\org.acme.project\target\org.acme.project-2.0.0-SNAPSHOT-v20150128-1503.jar(org/acme/project/OtherClass.class)
[ERROR] undeclared type variable: N
[ERROR] Please remove or make sure it appears in the correct subdirectory of the classpath.
I tried to clean it up a bit, but to summarize: Project B throws the exception when it tries to resolve a method call to Project A (yes, while generating JavaDoc!). The method in question looks like that:
public static <N extends Bean> void hookContinousImageFunction(final OtherClass<N> dialog,
final ImageGroup imageGroup, N model, final BiFunction<Image, N, ? extends Image> imageFunction) {
final Image original = imageGroup.getImage();
dialog.setOnCancelClick((notUsed) -> imageGroup.setImage(original));
model.addPropertyChangeListener(new ContinousImageFunctionListener<>(dialog, imageGroup, imageFunction));
dialog.setInitialModel(model);
}
It doesn't even have JavaDoc (not that any of this should matter when the generation of Project A's JavaDoc is already finished, and Maven is trying to generate JavaDoc for Project B).
As of now, we have this bug in multiple projects, about 1 out of 5. Project A (the one with a typed method / class like above) is more often than not in an entirely different build reactor and sometimes completely out of our control.
How do I fix this bug inside a bug?
(As a as a side note, the error occurs on the Jenkin's running with Java 1.8.0_31 and jdk1.8.0_40 or locally with 1.8.0_45, 1.8.0_60, but not locally with 1.8.0_20, but JavaDoc generation hasn't been that reliable, so I can't say for sure it has something to do with the Java version.)
I got the same kind of error message using a central build while having no problems in my local build. (Unfortunately I have no details about the central build environment.)
Adding a '#param ' explanation in the JavaDoc comment for the static method in question solved the issue. Adapted to the given example I did something like this:
/**
* #param <N> This is the class that ...
*/
public static <N extends Bean> void hookContinuousImageFunction(...)
Okay the answer is to a) downgrade Java to 1.8.0_20, or - if that is not possible - b) to use this code in the pom.xml to disable JavaDoc of the project until the Java people feel the need to fix the bug:
<properties>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
I'm writing unit tests for a web app and using the Java Play! (2.1.3) framework's FakeApplication class.
public class TagTest {
public static FakeApplication app;
...
// BeforeClass only runs once before any tests are run
#BeforeClass
public static void setUpBeforeClass() {
// Set up new FakeApplication before running any tests
app = Helpers.fakeApplication(Helpers.inMemoryDatabase());
Helpers.start(app);
}
...
}
I have the same setUpBeforeClass() method in all four of my test classes that test each of my four different models but when I run the play test command, all four test classes return a similar error:
[error] Test models.TagTest failed: java.lang.NullPointerException: null
[error] at Global.onStart(Global.java:59)
[error] at play.core.j.JavaGlobalSettingsAdapter.onStart(JavaGlobalSettingsAdapter.scala:17)
[error] at play.api.GlobalPlugin.onStart(GlobalSettings.scala:175)
[error] at play.api.Play$$anonfun$start$1$$anonfun$apply$mcV$sp$1.apply(Play.scala:68)
[error] at play.api.Play$$anonfun$start$1$$anonfun$apply$mcV$sp$1.apply(Play.scala:68)
[error] at scala.collection.immutable.List.foreach(List.scala:309)
[error] at play.api.Play$$anonfun$start$1.apply$mcV$sp(Play.scala:68)
[error] at play.api.Play$$anonfun$start$1.apply(Play.scala:68)
[error] at play.api.Play$$anonfun$start$1.apply(Play.scala:68)
[error] at play.utils.Threads$.withContextClassLoader(Threads.scala:18)
[error] at play.api.Play$.start(Play.scala:67)
[error] at play.api.Play.start(Play.scala)
[error] at play.test.Helpers.start(Helpers.java:354)
[error] at models.TagTest.setUpBeforeClass(TagTest.java:35)
Where line 35 is the line:
Helpers.start(app);
Is there something I'm doing wrong here?
Looks from the stack like the NPE is thrown on line 59 of your own Global class - inside your override of GlobalSettings.onStart()?
Look/debug there to see what the issue is. Hard to suggest any more without seeing your code - maybe check this out for a basic intro to Global and how it can be used.
By the way - just a couple of additional points
Why is app a static variable? It should probably be an instance variable of TagTest.
You didn't have to point out what code was on line 35 of TagTest - this can be seen on the second-last line of the stacktrace. The first line of the trace shows you the method in which the Exception was actually thrown - the rest just show the stack of calls which led up to that method call.
I have added the simple code write to a file into an open source project (Saiku) that before my changes builds and compiles cleanly.
The program compiles cleanly in Centos 5.3 Eclipse (no red X's).
However, when rerunning the maven build script, the compiler errors are generated (Exhibit 1):
Does Maven compile java projects differently from Eclipse?
Exhibit 1:
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[67,8] illegal start of type
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[67,11] ';' expected
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[70,14] <identifier> expected
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[70,15] illegal start of type
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[71,14] <identifier> expected
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[73,14] <identifier> expected
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[75,11] illegal start of type
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[79,2] invalid method declaration; return type required
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[130,15] class, interface, or enum expected
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[130,43] class, interface, or enum expected
[ERROR]
[ERROR] /usr/local/.m2/repository/saiku/saiku-core/saiku-service/src/main/java/org/saiku/olap/util/formatter/HierarchicalCellSetFormatter.java:[131,8] class, interface, or enum expected
[ERROR]
Exhibit 2:
import java.io.*; to the import section
try {
FileWriter fstream = new FileWriter("/usr/local/dailycandy/biserver.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write("Hello Java");
out.flush();
//Close the output stream
out.close();
}
catch (Exception e)
{
//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
The code that you have added is not within a method/constructor/block etc. This is not valid Java, and thus does not compile.
You need to surround this with something like follows:
public void doSomething
{
// Insert code here
}
Alternatively, you can place it in an existing method, or constructor, depending on when you need this code to execute.
Why Eclipse is not highlighting this error is beyond me. It would normally report this. Try refreshing your project or cleaning/rebuilding and you should see that it will fail to compile.