Debugging a REST service with VSCode
If you are looking to debug a REST service with VSCode then follow along!
In 6 steps you will learn how to start debugging the REST service. They are:
- Create the Maven POM file
- Add the application class
- Add the endpoint
- Add the VSCode tasks.json file
- Add the VSCode launch.json file
- Debug the application
Create the Maven POM file
Create an empty directory to store your Maven project. Inside of that directory
create the pom.xml
file with the content as below.
<?xml version="1.0" encoding="UTF-8"?>
<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>cloud.piranha.guides.coreprofile</groupId>
<artifactId>vscode-debug</artifactId>
<version>24.10.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Piranha Core Profile - Debugging a REST service with VSCode</name>
<properties>
<jakartaee.version>10.0.0</jakartaee.version>
<java.version>17</java.version>
<junit.version>5.10.0-M1</junit.version>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>3.0.0</maven-failsafe-plugin.version>
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
<piranha.version>23.6.0</piranha.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-core-api</artifactId>
<version>${jakartaee.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>rest</finalName>
<plugins>
<plugin>
<groupId>cloud.piranha.maven.plugins</groupId>
<artifactId>piranha-maven-plugin</artifactId>
<version>${piranha.version}</version>
<executions>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>debug</id>
<build>
<plugins>
<plugin>
<groupId>cloud.piranha.maven.plugins</groupId>
<artifactId>piranha-maven-plugin</artifactId>
<version>${piranha.version}</version>
<configuration>
<jvmArguments>-Xdebug -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9009</jvmArguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Note the POM file contains a debug
profile in the profiles section that
we will leverage later on to activate the VSCode debugging.
Add the application class
Add the Application class in the src/main/java
directory, which allows you to
set the application path using the @ApplicationPath annotation.
package rest;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
@ApplicationPath("")
public class RestApplication extends Application {
}
Add the endpoint
And we are adding a simple ‘Hello World’ endpoint that is listening on the
/helloworld
path.
package rest;
import jakarta.enterprise.context.RequestScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/helloworld")
@RequestScoped
public class HelloWorldBean {
@GET
public String helloWorld() {
return "Hello World!";
}
}
Add the VSCode tasks.json file
To integrate debugging into VSCode we'll need a tasks.json file that will
trigger the proper Maven goals BEFORE we start the debugger. For that
lets first create the .vscode
directory in the root directory of your
Maven project (if it does not exist). And then we will create the
tasks.json
file in the .vscode
directory. It should contain the content
as below.
{
"version": "2.0.0",
"tasks": [
{
"label": "Start",
"type": "shell",
"command": "mvn -Pdebug package pre-integration-test",
"isBackground": true,
"problemMatcher": "$tsc-watch",
}
]
}
Add the VSCode launch.json file
The next step is to configure the launch.json
file to allow it to
attach to the REST service after it gets started by means of the
Start
entry in the tasks.json
file.
For that we will create the tasks.json
file in the .vscode
directory
with the content as below.
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Debug",
"preLaunchTask": "Start",
"request": "attach",
"hostName": "localhost",
"port": "9009"
}
]
}
Debug the application
Open the HelloWorldBean.java
file and set a breakpoint on the line where
the Hello World
response is returned.
Then on your left bar click on the Debug
icon.
And make sure that Debug
is selected and click the run icon to the left of it.
Then browse to http://localhost:8080/rest/helloworld/
.
Now you'll see it hit your breakpoint.
Conclusion
Setting up debugging for VSCode requires a little bit of plumbing, but once
the Maven profile, the VSCode tasks.json
and launch.json
files are in
place it all comes together nicely!