How to configure Lombok extension to play well with VSCode
Advocate for better developer's productivity and experience
Documenting my learnings and sharing it
26/7/22: Added VSCode Java July Update
15/1/22: Update to fix a typo
Update:
With the recent release of Language Support for Java(TM) by Red Hat 1.9, it now officially support lombok and Lombok Annotations Support for VS Code is no longer required.
Refer to VSCode Java July Update and VSCode Java Lombok Support for more information
Background
I was trying to figure out how to use an immutable object using Lombok @Value and @Jacksonized to play well with Jackson in spring-boot using VSCode
This is the sample code
@Value
@Builder
@Jacksonized
public class Flight {
private String id;
private String destination;
private int flightTime;
private int flightDuration;
}
@RestController
public class FlightController {
@PostMapping("/flights")
public Flight create(@RequestBody Flight flight) {
return Flight.builder()
.id(UUID.randomUUID().toString())
.destination(flight.getDestination())
.flightTime(flight.getFlightTime())
.flightDuration(flight.getFlightDuration())
.build();
}
}
However, I kept getting the following error which I should not be getting
2022-01-06 01:13:01.899 DEBUG 14672 --- [nio-8080-exec-2] o.s.web.method.HandlerMethod : Could not resolve parameter [0] in public com.trial.lombokjackson.Flight com.trial.lombokjackson.FlightController.create(com.trial.lombokjackson.Flight): Type definition error: [simple type, class com.trial.lombokjackson.Flight]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.trial.lombokjackson.Flight` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 2, column: 5]
2022-01-06 01:13:01.902 DEBUG 14672 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Failed to complete request: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.trial.lombokjackson.Flight]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.trial.lombokjackson.Flight` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 2, column: 5]
2022-01-06 01:13:01.907 ERROR 14672 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.trial.lombokjackson.Flight]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.trial.lombokjackson.Flight` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 2, column: 5]] with root cause
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.trial.lombokjackson.Flight` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 2, column: 5]
// omitted the rest of the stack trace
@Jacksonized is supposed to play well with @Builder as mentioned in the docs
It automatically configures the generated builder class to be used by Jackson's deserialization
Attempt to fix
I tried to fall back to use @JacksonDeserialize instead of @Jacksonized to see if works
@Value
@Builder
@JsonDeserialize(builder = Flight.FlightBuilder.class)
public class Flight {
private String id;
private String destination;
private int flightTime;
private int flightDuration;
@JsonPOJOBuilder(withPrefix = "")
public static class FlightBuilder { }
}
And Voilà! it works perfectly, the error wasn't there anymore, and it deserializes as expected.
What happened?
So what happened? Based on the documentation for @Jacksonized, it is supposed to reduce the boilerplate code, and replace @JsonDeserialize, @JsonPOJOBuilder, ... and play well with @Builder
After trying for hours, I still wasn't able to figure it out and so I posted on stackoverflow to see if I am missing out on anything obvious, and the first comment triggered me to look into vscode-lombok-extension. So I went to vscode-lombok-github-issues to search for any similar issue (which I should have done way earlier), and I came across this, this and some others
TLDR; vscode-lombok extension comes with v1.18.12 instead of the latest stable version (v1.18.22) and @Jacksonized was only added from v1.18.14 onwards
Solution
The fix was pretty straightforward once we know that it was caused by an older version of Lombok. There are a couple of ways to resolve this:
#1 Replace Lombok jar
This solution is the recommended one and should be the easiest, as it only involves replacing the jar file and restarting of VSCode
- Exit
VSCode - Download the latest stable version from lombok
- Navigate to
%userprofile%\vscode\extensions\gabrielbb.vscode-lombok-1.0.1\server- delete the existing
lombok.jar - copy the downloaded
lombok.jarinto the extension directory
- delete the existing
- Start
VSCode - Press
F1orCtrl + Shift + Pand selectJava: Clean Java Language Server Workspace - Restart
VSCodewhen prompted
Note that if the extension will to be updated, it might point to the older lombok version again, so you would have to repeat the same process again
#2 Configure java.jdt.ls.vmargs
This involves tweaking the current java.jdt.ls.vmargs configuration to point to the latest lombok jar file in another directory
- Open
.vscode/settings.jsonin the project directory - Add
"java.jdt.ls.vmargs": "-javaagent:/path/to/latest/lombok.jar - Restart
VSCodewhen prompted
If it does not work, you may need to run this step
- Press
F1orCtrl + Shift + Pand selectJava: Clean Java Language Server Workspace - Restart
VSCodewhen prompted
Note:
java.jdt.ls.vmargsconfiguration in the vscode global setting will also be updated to include the new setting
// original
"java.jdt.ls.vmargs": "-javaagent:\"c:\\Users\\Joseph\\.vscode\\extensions\\gabrielbb.vscode-lombok-1.0.1\\server\\lombok.jar\"",
// after
"java.jdt.ls.vmargs": "-javaagent:./server/lombok.jar -javaagent:\"c:\\Users\\Joseph\\.vscode\\extensions\\gabrielbb.vscode-lombok-1.0.1\\server\\lombok.jar\"",
However, if you removed the configuration from .vscode/settings.json, the global settings will not be updated to remove the path. If the file no longer exist in the path, you will encounter error message The Language Support for Java server crashed 5 times in the last 3 minutes. The server will not be restarted.. In that case, launch global settings and remove the added path to return to the original configuration
#3 Run via build tool (gradle/maven/java)
Start the application using the following command
./gradlew bootRunmvn spring-boot:runjava -jar myapp.jar
This will bypass the VSCode and launch as the application where the lombok version should be the latest. At the time of writing, I am using spring-boot-2.6.2 which comes with lombok-1.18.22
Lesson learned
Always remember to check the lombok version installed for the IDE when encountered with weird behavior especially using newer feature(s). This applies to Eclipse as well since lombok jar is also installed and using an outdated lombok would have caused the same issue




