I have already blogged about Gitpod, which allows you to spin up fresh development environments from your GitHub projects so that you can code with Visual Studio on the web (that’s just a very reductive definition, so you may want to look at its website for the complete set of features). I have already shown how to use it for Ansible and Molecule.
I honestly prefer to have my IDE (Eclipse) on my computer. However, Gitpod allows you to use an old or less powerful computer to develop applications and systems requiring much computing power and resources. I showed an example for the PineBook Pro: you can use Gitpod to develop Ansible roles and test them with Docker.
Today, I will show how to use Gitpod for Java/Maven projects. This is the first post of a series about Java, Maven, and Gitpod.
NOTE: Although the post focuses on Gitpod, most of the features we will see come from Visual Studio Code and the extensions we will install. Thus, the same mechanisms could be used also on a locally installed Visual Studio Code. In that respect, it is best to get familiar with the main keyboard shortcuts (these will be shown in Visual Studio Code when no editor is opened):
Gitpod provides an example for Java, but it relies on Spring Boot and is probably too complex, especially if you’re not interested in web applications.
In this post, instead, I’ll start with a very basic Java/Maven project. It is intended as a tutorial, so you might want to follow along doing these steps with your GitHub account.
I start by creating a Maven project with the quickstart archetype locally on my computer:
1 2 3 4 5 6 7 |
mvn archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DarchetypeVersion=1.4 \ -DgroupId=com.mycompany.app \ -DartifactId=my-app \ -DinteractiveMode=false |
I move it into another directory, for example:
1 2 |
mv my-app java-maven-gitpod-example cd java-maven-gitpod-example |
Create a standard “.gitignore”:
1 2 |
.DS_Store target |
Initialize the Git repository and create a first commit:
1 2 3 |
git init git add . git commit -m "created project" |
Finally, I create a new repository on GitHub and push my Git repository there (in this example: https://github.com/LorenzoBettini/java-maven-gitpod-example)
To access Gitpod easily from a GitHub repository, I installed the Gitpod browser extension.
Now, I can start Gitpod for this repository using the button (as I said, you need to use a browser extension; otherwise, you have to prefix the URL appropriately):
Let’s press the “Gitpod” button. (The first time you use Gitpod, you’ll have to accept a few authorizations.).
Press the “Continue with GitHub” button and wait for the workspace to be ready.
NOTE: I’m using the light theme of Visual Studio in Gitpod in this blog post.
Gitpod detected that this was a Maven project and automatically executed the command:
1 |
mvn install -DskipTests=false |
Note that it also created the file “.gitpod.yml”, which we’ll later tweak to customize the default command and other things:
Moreover, it offers to install the Java extension pack:
Of course, we accept it because we want to have a fully-fledged Java IDE (this is based on the Eclipse JDT Language Server Protocol; you might want to have a look at what a Language Server Protocol, LSP, is). We use the arrow to choose “Install Do not Sync” (we don’t want that in all Gitpod workspaces, and we’ll configure the extensions for this project later).
Once that’s installed (note also the recommended extension GitLens, which we might want to install later, let’s use the gear icon to add the extension to our “.gitpod.yml” so that the extension will be automatically installed and available the next time we open Gitpod on this project:
Unfortunately, the “.gitpod.yml” is a bit messed up now (maybe a bug?), and we have to adjust it so that it looks like as follows:
There’s also a warning on top of the file; by hovering, we can see a few warnings complaining that the transitive dependencies of the extension are not part of the file:
Let’s click on “Quick Fix…” and then apply the suggestions to add the extensions to the file (these are just warnings, but I prefer not to have warnings in my development environment):
In the end, the file should look like this:
1 2 3 4 5 6 7 8 9 10 11 |
tasks: - init: mvn install -DskipTests=false vscode: extensions: - vscjava.vscode-java-pack - redhat.java - vscjava.vscode-java-debug - vscjava.vscode-java-dependency - vscjava.vscode-java-test - vscjava.vscode-maven |
Note that we have “code lens” in the editor, and we can choose to let Gitpod validate this configuration:
TIP: another extension I always add is “eamodio.gitlens”.
This will rebuild the Docker image for our workspace (see the terminal view at the bottom):
This operation takes some time to complete, so you might want to avoid that for the moment. If you choose to do the operation, in the end, another browser tab will be opened with this new configuration. We can switch to the new browser tab (the “.gitpod.yml” is available in the new workspace, though we still haven’t committed that).
NOTE: I find “mvn install” an anti-pattern, and, especially in this context, it makes no sense to run the “install” phase and run the tests when the workspace starts. In fact, I changed the “init” task to a simpler “mvn test-compile”; this is enough to let Maven resolve the compile and test dependencies when the workspace starts. The Java LSP will not have to resolve them again and will find them in the local Maven cache.
We can take the chance to commit the file by using the corresponding tab in Visual Studio Code and then push it to GitHub (“Sync Changes”):
We could also close the Gitpod tabs and re-open Gitpod (the “.gitpod.yml” is now saved in the GitHub repository), but let’s continue on the open workspace.
Let’s now open a Java file in our project:
We get a notification that the IDE is loading the Java project (this might take a few seconds).
TIP: to quickly open a file knowing (part of) its name, press “Ctrl + P” (see the shortcuts above) and start typing:
We have a fully-fledged Java IDE with “code lens” for running/debugging and parameter names (see the argument passed to “System.out.println”):
For example, let’s use “Run” to run the application and see the output in the terminal view:
Though this project generated by the archetype is just a starting point, we also have a simple JUnit test. Let’s open it.
After a few seconds, the editor is decorated with some “code lens” that allows us to run all the tests or a single test (see the green arrow in the editor’s left ruler). Clicking on the arrow immediately runs the tests or a single test. Right-clicking on such arrows gives us more options, like debugging the test.
On the right pane, we can select the “Testing” tab (depicted as a chemical ampoule) that shows all the tests detected in the project (in this simple example, there’s a single one, but in more complex projects, we can see all the tests). We can run/debug them from there.
Let’s run them and see the results (in this case, it is a complete success); note the decorations showing the succeeded tests (in case of failures, the decorations will be different):
Of course, we could run the tests through Maven in the console, but this would be a more manual process, and the output would be harder to interpret in case of failures: we want to use an IDE to run the tests.
We could also run the tests by pressing “F1” and typing “Run tests” (we’ll then use the command “Java: Run Tests”): we need to do that when a JUnit test case is open in the editor.
Let’s hover on the “assertTrue”, which is a static method of the JUnit library. The IDE will resolve its Javadoc and will show it on a pop-up (the “code lens” for the parameter names is also updated):
We can use the menu “Go to definition” (or Ctrl+click) to jump to our project’s source code and libraries. For example, let’s do that on “assertTrue”. We can view the method’s source code in the class “Assert” of JUnit (note that this editor is read-only, and the name of the file ends with “.class”):
Note that the “JAVA PROJECTS” in the “Explorer” shows the corresponding file. In this case, it is a file in the referred test dependency “junit-4.11.jar” in the local Maven cache (see the POM where this dependency is explicit).
Of course, we have code completion by pressing “Ctrl+Space”; when the suggestions appear, we can start typing to filter them, and substring filtering works as well (see the screenshot below where typing “asE” shows completions matching):
With ENTER, we select the proposal. In this case, if we select one “assertEquals”, which is a static method of “Assert”, upon selection, we will also have the corresponding static import automatically added to the file.
That’s all for the first post! Stay tuned for more posts on Java, Maven, and Gitpod! 🙂