Building a Java application in Visual Studio Code

An IDE (Integrated Development Environment) allows you to quickly program applications by providing multiple utilities for code development, testing, debugging features, etc. Given the increasing popularity of Visual Studio Code as a universal IDE, you can easily develop your first Java project by installing the Oracle Java Platform Extension.  

Setup

The Oracle Java Platform Extension is available on Visual Studio Code Marketplace. You can install it directly from Visual Studio Code by going through the Code menu: Code > Settings > Extensions.

Leverage the command palette to create a new project View > Command Palette > Java: New Project or open a folder with existing Maven (pom.xml) or Gradle project files (build.gradle, gradle.properties). Let's create a new Maven project by going through the menu View > Command Palette >Java: New Project and selecting the Java with Maven option. You will see a prompt asking you to specify a directory where you wish to save your project (eg: concatenate) and then enter a package name.

Package name

The extension will create a basic pom.xml and a default directory structure for a Maven project with the source folder defined. The pom.xml file is a single configuration file that contains the majority of information required to build the project.

If no JDK is present in your system then the extension can help you obtain one. In the Visual Studio Code menu select View > Command Palette > Download, install, and Use JDK and choose to install one of the JDKs listed there or point the extension to the binaries of an existing JDK on your operating system. This action will update your user settings. When you would like to use a different JDK, access View > Command Palette > Preferences:Open User Settings (JSON) and manually update the jdk.jdkhome setting.

JDK downloader


NOTE

The extension requires a minimum of JDK 11.


You can build, run, and debug your project with the same JDK that runs the Oracle Java Platform extension. The extension searches for a JDK in the following locations:

  • jdk.jdkhome
  • java.home
  • JDK_HOME environment variable
  • JAVA_HOME environment variable
  • current system path

Next, let's explore the generated project.

 

Project Explorer

You can visualize your project in Visual Studio Code's explorer. The goal of the concatenate project is to provide the intersection of 2 lists. Your program should receive the lists as arguments and calculate their intersection. Let's add the following code to achieve that in the Concatenate.java class:

public class Concatenate {

    public static void main(String[] args) {

        if (args.length < 2) {
            System.out.println("You need to provide 2 lists as arguments. You provided " + args.length);
            throw new UnsupportedOperationException("You need to provide 2 lists as arguments");
        }

        List<Integer> firstSeries = List.of(args[0].split(",")).stream()
                .map(Integer::valueOf).collect(Collectors.toList());

        List<Integer> secondSeries = List.of(args[1].split(",")).stream()
                .map(Integer::valueOf).collect(Collectors.toList());


        List<Integer> elements = extractCommonElements(firstSeries, secondSeries);
        System.out.println(elements);

    }

    public static List<Integer> extractCommonElements(List<Integer> list1, List<Integer> list2) {
        Set<Integer> intersection = new HashSet<>(list1);

        intersection.retainAll(list2);
        if (list1.get(0).equals(list2.get(0))) {
            intersection.add(list1.get(0));
        }
        if (list1.get(list1.size() - 1).equals(list2.get(list2.size() - 1))) {
            intersection.add(list1.get(list1.size() - 1));
        }

        return intersection.stream().toList();
    }
}

In addition to Visual Studio Code's explorer, the Oracle Java Platform extension offers Project Explorer that contains an overview of the project structure. This feature aims to simplify Java package structure navigation.

Project Explorer

You can use it to clean, compile, test, debug, and execute your Maven/Gradle Java projects.

 

Debugger and Launch Configurations

The Oracle Java Platform Extension launch configuration supports debugging and running Java applications using JDK11 or newer. You can invoke the launch configuration/debugger when you select Run main | Debug main code lense or from the Run and Debug activity panel.

Run main

Both launch and debugger configurations support the following actions:

  • Pause
  • Step over
  • Step into
  • Step out
  • Restart
  • Stop/Disconnect

In the Run and Debug view you can customize your launch configurations by choosing Java+ from the dropdown list and then click the run icon.

Launch configurations

Default launch configurations are available in launch.json file. You can attach debugger actions by selecting either from available processes or enter the port to connect to the JVM running with JDWP. On Windows operating system you can also select Attach to Shared Memory.

Attach to port & attach to process

Go to the Run Configuration panel of the Explorer view to modify the program arguments, VM options, environment variables, or set the working directory. For example, you can run your application with arguments by adding "31,20,15,17" "20,19,17,45" to the Program Arguments.

Run configuration

 

Code Refactoring

Maintaining a Java application usually involves improving internal code by making many small changes without altering its functional requirements. For example, if you are using JDK 21 or newer, you can select .get(0), right click Change all occurrences to use SequencedCollection method getFirst().

Change all occurences

Similarly, you can refactor all occurrences of get(list1.size() - 1) to SequencedCollection method getLast(). The code of extractCommonElements method becomes:

// works with JDK >= 21
public static List<Integer> extractCommonElementsAlternative(List<Integer> list1, List<Integer> list2) {
        Set<Integer> intersection = new HashSet<>(list1);

        intersection.retainAll(list2);

        if (list1.getFirst().equals(list2.getFirst())) {
            intersection.add(list1.getFirst());
        }
        if (list1.getLast().equals(list2.getLast())) {
            intersection.add(list1.getLast());
        }

        return intersection.stream().toList();
}

To speed up development, you can generate methods for your class via the Source Action context menu.

Source action menu

The Source Action context menu offers support for organizing imports in Java sources. Moreover, you can enhance the import optimization strategy by going to VSCode View > Command Palette > Preferences:Open User Settings > Extensions > Java and searching for jdk to set the Jdk > Java > Imports options:

  • Count For Using Star Import - Class count to use a star-import, having 999 as the default value.
  • Count For Using Static Star Import - Members count to use a static star-import, having 999 as the default value.
  • Groups - Groups of import statements (specified by their package prefixes) and their sorting order. Import statements within a group are ordered alphabetically.

Organize imports

You can choose to organize imports action when you save a document via View > Command Palette > Preferences:Open User Settings > Extensions > Java > On Save: Organize Imports and tick the checkbox.

More refactoring suggestions are available via the Show code lightbulb and Refactor context menu. You can achieve more complex refactorings, such as changing the parameters of a method via a dedicated form that allows you to change, add, move, remove method parameters.

Change method parameters

In case you decide to move members from one class to another, you can do so from the Refactor > Move context menu:

Move members

In addition, the extension also supports the following refactorings:

  • Refactoring of constructor and method arguments
  • Generating hashCode/equals and toString()
  • Assigning an expression to a local variable
  • Extracting an expression to a local variable
  • Splitting into declaration and assignment
  • Pulling a class member up or down
  • Inlining a redundant variable
  • Moving a class to a different package
  • Extracting an interface/method
  • Replacing import a constant/method by converting to a static import
  • Refactoring of for/try-catch/switch()/while() blocks

While refactoring is a process aimed to improve software quality without breaking the functionality for end-users, tests help you gain confidence that you are building bug-free applications.

 

Test Code

You can generate a test via the Show code lightbulb and select the Create Test Class option.

Test

The generated test class will contain methods that are either empty or failing. Your goal is to have tests that assess the actions in each method of your class, so you can add the @Disabled annotation to exclude/skip execution of some of those generated methods. Let's modify one of the generated tests to validate the extractCommonElements method:

import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class ConcatenateTest {

    /**
     * Test of extractCommonElements method, of class Concatenate.
     */
    @org.junit.jupiter.api.Test
    public void testExtractCommonElements() {
        System.out.println("extractCommonElements");
        List<Integer> list1 = Arrays.asList(31,20,15,17);
        List<Integer> list2 = Arrays.asList(20,19,17,45);
        List<Integer> expResult = Arrays.asList(17, 20);
        List<Integer> result = Concatenate.extractCommonElements(list1, list2);
        assertEquals(expResult, result);
    }
}

The extension provides Test Explorer view which allows to run all tests in a project, examine the results, go to source code and run particular test.

Test Explorer

 

Document Code

The Oracle Java Platform extension can assist you when writing documentation by suggesting to insert preformatted and prepopulated JavaDoc comments. Type /** above a method signature and the IDE will offer to complete the JavaDoc. The action creates a JavaDoc comment with all arguments prepared.

Javadoc assistant

The generated javadoc will be similar to this:

    /**
     *
     * @param list1
     * @param list2
     * @return
     */
    public static List<Integer> extractCommonElements(List<Integer> list1, List<Integer> list2) {}

 

Evolving the project

In case you have a project running on different Java versions, you can associate a profile for each runtime version you use. Once the profile is created, you can customize its settings.json and define the jdk.jdkhome value.

Like your own projects, the Oracle Java Platform Extension will continue to improve and evolve. As this is an open-source project, community contributions and feedback are welcome. Check the contribution guide and join our effort to offer a smooth developer experience with Java.

Last update: April 22, 2024


Back to Tutorial List