Java 11 - ParameterizedTypeReference issue
It's not everyday when you run into a Java bug.🪲
Brief
Let's say we wanted to interact with a third-party service which returned data in the follow structure:
Implementation
First, we need to define the payload structure. We'll take the generic
route and define the models this way:
public class Car {
private String name;
}
public class Motorcycle {
private String type;
}
public class MetadataObject<T> {
private String metadata;
private List<T> data;
}
For simplicity purposes we'll use Spring's RestTemplate
to send the HTTP requests to the external service.
public class IntegrationClient {
RestTemplate restTemplate = new RestTemplate();
public Metadata<Car> getCars() {
String url = ...
ResponseEntity<MetadataObject<Car>> response = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<MetadataObject<Car>>(){});
return response.getBody();
}
public Metadata<Motorcycle> getMotorcycles() {
String url = ...
ResponseEntity<MetadataObject<Motorcycle>> response = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<MetadataObject<Motorcycle>>(){});
return response.getBody();
}
}
At this point, IntelliJ already suggested that I could drop the explicit generic type for ParameterizedTypeReference
because he's smart enough to infer it. So, as to many other times when IntelliJ suggestions came to help, I did just that.
ResponseEntity<MetadataObject<Car>> response = restTemplate.exchange(url, new ParameterizedTypeReference<MetadataObject<Car>>(){});
became
ResponseEntity<MetadataObject<Car>> response = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<>(){});
All good and well, until I wanted to run the application.
compiler message file broken: key=compiler.misc.msg.bug arguments=11.0.2, {1}, {2}, {3}, {4}, {5}, {6}, {7} java.lang.NullPointerException at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitApply(Flow.java:1235) at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1634) at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:398) at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitVarDef(Flow.java:989)
Didn't really understand what was the issue but after some Googling and Stackoverflowing I found out that this is actually a JDK bug 😱 .
The problem seems to be that when compiling the code, Java couldn't infer the arguments for the ParameterizedTypeReference
.
It got fixed in JDK 12 and also been backported al the way to JDK 11.0.4 .
Conclusion
If you find yourself in the same situation as me, you either keep the type between the diamond signs or even better, think about upgrading your JDK version, it's 2022 already..
Stay tuned! 🚀