HOWTO: Java development environment on a Raspberry Pi
Stephan Klünker


System Environment
Operating System Preparations
Apache Ant and Ivy
Environemnt variables
IDE: Visual Studio Code
Java project in Visual Studio Code
Jetty 10 (standalone) Setup
Basic Servlet with Jetty 10 and Maven
Spring Boot (web application example)


This is a quick reference of how to establish a Java technology development environment on a Debian based Linux environment in general, and particularly focussed on Raspberry Pi OS, where system resources need to be used sustainably.

The page is thought to be for myself, for later re-use, however I don't see any reason for not publishing it, since it can be helpful for other developers too. For many subjects there are other solutions or alternative ways to go. I don't discuss them here, I just write down my personal preference.

I see myself as the collector of the contained solutions, not as the "author" or "inventor", a lot of contents is from other sources, which I cannot all mention or cite here, as I need to concentrate on my developer work, of which this page is a "side product".

System Environment

RaspberryPi 4, 4 GB memory, Raspberry Pi OS (Debian 10 buster), 64bit (aarch64)

Operating System Preparations

as a sudo user e.g. pi (or root): add a user (which is the developer):

      sudo adduser jade
      Lege Benutzer »jade« an ...
      Lege neue Gruppe »jade« (1002) an ...
      Lege neuen Benutzer »jade« (1002) mit Gruppe »jade« an ...
      Erstelle Home-Verzeichnis »/home/jade« ...
      Kopiere Dateien aus »/etc/skel« ...
      Geben Sie ein neues Passwort ein: 
      Geben Sie das neue Passwort erneut ein: 
      passwd: Passwort erfolgreich geändert
      Benutzerinformationen für jade werden geändert.
      Geben Sie einen neuen Wert an oder drücken Sie ENTER für den Standardwert
              Vollständiger Name []: Java Developer
	           Zimmernummer []: 
	           Telefon geschäftlich []: 
	           Telefon privat []: 
	           Sonstiges []: 
      Sind die Informationen korrekt? [J/n] J
The account is now ready for use, but needs to be added to the sudoers group:
      sudo visudo   
add the following line at the end of the edited file:
      jade ALL=(ALL) NOPASSWD: ALL
From now on everything every example command on this page is done by this user, unless explicitly mentioned. If superuser privileges are required, the command is running in sudo context.


- OpenJDK 8 (LTS)
- OpenJDK 11 (LTS)
- corresponding JREs (if needed)
- Operating System: Linux
- Architecture: aarch64


         cd /usr/local
         sudo mkdir java
         cd java
         sudo cp /path/to/downloaded/jdk_and_jre/OpenJDK8U-jdk_aarch64_linux_hotspot_8u302b08.tar.gz .
         sudo cp /path/to/downloaded/jdk_and_jre/OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.12_7.tar.gz .
         ... same with JRE packages if needed ...

         sudo tar -xzf ./OpenJDK8U-jdk_aarch64_linux_hotspot_8u302b08.tar.gz
         sudo tar -xzf ./OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.12_7.tar.gz
         ... same with JRE packages if needed ...

         sudo rm ./*.tar.gz
         ... set environment variables ... see Environment Variables

Apache Ant and Ivy

Download Ant:
Download Ivy:
- select Ivy "with dependencies" download package


      cd /usr/local
      sudo cp /path/to/downloaded/ant_package/apache-ant-1.10.11-bin.tar.gz .
      sudo cp /path/to/downloaded/ivy_package/apache-ivy-2.5.0-bin-with-deps.tar.gz .

      sudo tar -xzf ./apache-ant-1.10.11-bin.tar.gz
      sudo tar -xzf ./apache-ivy-2.5.0-bin-with-deps.tar.gz

      sudo mv apache-ant-1.10.11 ant
      sudo mv apache-ivy-2.5.0 ivy

      sudo rm ./*.tar.gz

      sudo cp ./ivy/ivy-2.5.0.jar ./ant/lib
      ... set environment variables ... see Environment Variables
Test the installation:
      mkdir project/ant_ivy_test
      cd project/ant_ivy_test
      vi build.xml (new file)      

      Buildfile: /home/user/project/ant_ivy_test/build.xml


      Total time: 1 second




      cd /usr/local
      sudo cp /path/to/downloaded/maven_package/apache-maven-3.8.1-bin.tar.gz .
      sudo tar -xzf ./apache-maven-3.8.1-bin.tar.gz
      sudo mv apache-maven-3.8.1 maven
      sudo rm ./*.tar.gz
      ... set environment variables ... see Environment Variables



         sudo apt install git
         git config --global "Java Developer"
         git config --global ""
         git config --global push.default simple
         git config --global branch.autosetuprebase always
         git config --global core.editor nano
         git config --global diff.tool vimdiff 
         git config --global merge.tool vimdiff
         - alternatively for diff.tool and merge.tool (requires graphic desktop):
            git config --global diff.tool meld 
            git config --global merge.tool meld
         git config --global color.ui true
         git config --global color.status auto
         git config --global color.branch auto

         check configuration
            git config --list
            git help
            git help -a 
            git help -g


            git --version         
Create a repository:
         cd projects
         mkdir sampleproject
         cd sampleproject

         vi readme.txt
         This is a sample Java project to be source controlled by Git.

         vi .gitignore

         git init
         >> Leeres Git-Repository in /home/stephan/project/sampleproject/.git/ initialisiert

         git add readme.txt
         git add .gitignore
         git commit -m "project initialized"

         cd .. (change to the projects folder)

         git clone --bare sampleproject sampleproject.git
         >> Klone in Bare-Repository 'sampleproject.git' ... Fertig.
Locate the repository on a server for cooperative work:
         scp -r sampleproject.git jade@reposerver:/gitrepo
         ssh jade@reposerver
         cd /gitrepo/sampleproject.git
         git init --bare --shared
         >> Reinitialized existing shared Git repository in /gitrepo/sampleproject.git/
- now every user in the same group / on the same (Unix) machine is able to use the repository.

         cd path/to/projects
         git clone jade@reposerver:/gitrepo/sampleproject         

Environment Variables

      sudo vi /etc/ (new file)
      - - -
      export JDK8_HOME="/usr/local/java/jdk8u302-b08"
      export JDK8_PATH="/usr/local/java/jdk8u302-b08/bin"
      export JRE8_HOME="/usr/local/java/jdk8u292-b10-jre"
      export JRE8_PATH="/usr/local/java/jdk8u292-b10-jre/bin"
      export JDK11_HOME="/usr/local/java/jdk-11.0.12+7"
      export JDK11_PATH="/usr/local/java/jdk-11.0.12+7/bin"
      export JRE11_HOME="/usr/local/java/jdk-11.0.11+9-jre"
      export JRE11_PATH="/usr/local/java/jdk-11.0.11+9-jre/bin"
      export JAVA_HOME=$JDK11_HOME
      export JAVA_PATH="$JDK11_PATH:$JRE11_PATH"
      export ANT_HOME="/usr/local/ant"
      export ANT_PATH=$ANT_HOME/bin
      export MVN_HOME="/usr/local/maven"
      export MVN_PATH=$MVN_HOME/bin      
      - - -

      sudo vi /etc/profile
      - - -
      # /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
      # and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

      . /etc/

      if [ "`id -u`" -eq 0 ]; then
      export PATH

      . . .
      - - -
       add the two bold lines to the existing /etc/profile.
       - adapt JAVA_HOME and JAVA_PATH to your needs in /etc/ (for example if you use Java 8 instead of Java 11).

IDE: Visual Studio Code (VSC)


      sudo apt install code
      sudo apt upgrade code

Create a workspace: File > Add folder to workspace
File > Save workspace as ... - e.g. [same name as project folder].code-workspace in project folder

Add Extensions:

Ctrl-Shift-P : Command Line for Extensions

Java settings: Settings > Extensions > Java
   edit java.configuration.runtimes and java.home in settings.json

            "java.home": "/usr/local/java/jdk-11.0.12+7",
            "java.configuration.runtimes": [
                  "name": "JavaSE-1.8",
                  "path": "/usr/local/java/jdk8u302-b08"
                  "name": "JavaSE-11",
                  "path": "/usr/local/java/jdk-11.0.12+7",
                  "default": true         
VSC uses the JDK/runtime where java.home is pointing to and where default=true, so settings must be changed both if a different JDK is to be used. Additionally, VSC is still sensitive towards the operating system environment, variables, so in order to change the JDK and JRE used in VSC, it ist necessary to also change the respective environemnt variables.

Java project in Visual Studio Code

The following section describes the initial generating of a new Java project using maven archetype. Since there are obviously no up-to-date archetypes, matching Java 11 or later, available, some refactoring needs do be done after generation. So it might be useful to keep the simple project, once it works, as a prototype for later projects, rather than using archetype generation again.
- Ctrl-Shift-P
- Create a Java Project
- Maven create from Archetype
- archetype-quickstart-JDK8     => this will create a basic Java project structure still suitable for JDK later than 8, however the generated pom.xml needs to be replaced.
- select a version: 2.0.0 (archetype version)
- Group ID: for example de.redeight
- Artifact ID: for example vsc_java
- Destination folder: for example /home/jade/projects (will create project folder vsc_java underneath /home/jade/projects )
    executing task: mvn org.apache.maven.plugins:maven-archetype-plugin:3.1.2:generate
- Interactions:
    Define value for property 'version' 1.0-SNAPSHOT: 0.1 (example)
    Package: de.redeight : Y
   [INFO] ----------------------------------------------------------------------------
   [INFO] Using following parameters for creating project from Archetype: archetype-quickstart-jdk8:2.0.0
   [INFO] ----------------------------------------------------------------------------
   [INFO] Parameter: groupId, Value: de.redeight
   [INFO] Parameter: artifactId, Value: vsc_java
   [INFO] Parameter: version, Value: 0.1
   [INFO] Parameter: package, Value: de.redeight
   [INFO] Parameter: packageInPathFormat, Value: de/redeight
   [INFO] Parameter: package, Value: de.redeight
   [INFO] Parameter: groupId, Value: de.redeight
   [INFO] Parameter: artifactId, Value: vsc_java
   [INFO] Parameter: version, Value: 0.1
   [INFO] Project created from Archetype in dir: /home/jade/projects/vsc_java
   [INFO] ------------------------------------------------------------------------
   [INFO] ------------------------------------------------------------------------
   [INFO] Total time: 49.867 s
   [INFO] Finished at: 2021-09-20T14:24:13+02:00
   [INFO] ------------------------------------------------------------------------
   Das Terminal wird von Aufgaben wiederverwendet, drücken Sie zum Schließen eine beliebige Taste.
- File > Add folder to Workspace ... => /home/jade/projects/vsc_java
- File > Save Workspace as ... => /home/jade/projects/vsc_java/vsc_java.code-workspace

The generated project file structure looks like this:

         |-- pom.xml
         |-- src
         |   |-- main
         |   |   `-- java
         |   |       `-- de
         |   |           `-- redeight
         |   |               `--
         |   `-- test
         |       `-- java
         |           `-- de
         |               `-- redeight
         |                   `--
         |-- target
         |   |-- classes
         |   |   `-- de
         |   |       `-- redeight
         |   |           `-- AppSample.class
         |   |-- test-classes
         |   |   `-- de
         |   |       `-- redeight
         |   |           `-- AppSampleTest.class
         |   `-- vsc_java-0.1.jar
         `-- vsc_java.code-workspace
- Replace the generated pom.xml to <project xmlns="" xmlns:xsi="" xsi:schemaLocation=""> <modelVersion>4.0.0</modelVersion> <groupId>de.redeight</groupId> <artifactId>vsc_java</artifactId> <version>0.1</version> <properties> <java.version>11</java.version> <commons.lang.version>2.6</commons.lang.version> <junit.version>5.6.0</junit.version> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> <maven-jar-plugin.version>3.1.0</maven-jar-plugin.version> <>UTF-8</> </properties> <dependencies> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>${commons.lang.version}</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <release>11</release> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>${maven-jar-plugin.version}</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>de.redeight.SampleVSCJ</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> </project> - Rename and refill the Java class files ( and according to your needs
- Update the project: in the Explorer right-click on the project (vsc_java in this example) under JAVA PROJECTS and select Update Project from the context menu
- build: in the Explorer
    - right-click on the project (vsc_java in this example) under JAVA PROJECTS and select Run Maven Command ... from the context menu
    - select Custom and enter clean package
- run the application:
    - from VSC: use the Run code lense function at the main method
    - from terminal: java -jar target/vsc_java.jar or mvn exec:java -Dexec.mainClass="de.redeight.SampleVSCJ"
... to be continued ...

Jetty 10 (standalone) Setup

- Download Jetty 10 from here:
su (root)
cd /opt
cp /path/to/jetty-home-10.0.6.tar.gz .
tar -xzf jetty-home-10.0.6.tar.gz
rm ./jetty-home-10.0.6.tar.gz
mv jetty-home-10.0.6/ jetty

mkdir jetty_base
vi /etc/
- - -
export JETTY_HOME="/opt/jetty"
export JETTY_BASE="/opt/jetty_base"
- - -

- Add required modules:
cd /opt/jetty_base/
java -jar $JETTY_HOME/start.jar --add-module=server,http,deploy

- to check installed modules:
java -jar $JETTY_HOME/start.jar --list-modules=*

The Jetty Base structure looks now like this:

         |-- resources
         |   `--
         |-- start.d
         |   |-- deploy.ini
         |   |-- http.ini
         |   `-- server.ini
         `-- webapps   
In /opt/jetty_base/ change jetty.http.port to (for example) 1080 to (later on) distinguish this to other Jetty instances.

- run the Jetty server:
cd /opt/jetty_base/
java -jar $JETTY_HOME/start.jar --list-modules=*

... to be continued ...

Basic Servlet with Jetty 10 and Maven

- Create the file system structure:

      cd /home/jade/projects
      mkdir basicservlet
      cd basicservlet
      mkdir -p src/main/java/de/redeight
      mkdir -p src/main/webapp/WEB-INF
      touch src/main/java/de/redeight/
      touch src/main/webapp/WEB-INF/web.xml
      touch ./pom.xml
- the resulting file system structure:
      |-- pom.xml
      `-- src
          `-- main
              |-- java
              |   `-- de
              |       `-- redeight
              |           `--
              `-- webapp
                  `-- WEB-INF
                      `-- web.xml
package de.redeight; import; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class BasicServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("<h1>Hello. This is a basic servlet running on Jetty 10!</h1>"); response.getWriter().println("session=" + request.getSession(true).getId()); } } - Deployment descriptor web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="" xmlns:xsi="" xsi:schemaLocation="" metadata-complete="false" version="3.1"> <servlet> <servlet-name>Basic Servlet on Jetty</servlet-name> <servlet-class>de.redeight.BasicServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Basic Servlet on Jetty</servlet-name> <url-pattern>/ident/*</url-pattern> </servlet-mapping> </web-app> - Maven - pom.xml:
<project xmlns="" xmlns:xsi="" xsi:schemaLocation=""> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>basicservlet</artifactId> <version>0.1-SNAPSHOT</version> <packaging>war</packaging> <name>Basic Servlet on Jetty</name> <properties> <jetty.version>10.0.6</jetty.version> <servlet.version>3.1.0</servlet.version> <maven-jar-plugin.version>3.1.0</maven-jar-plugin.version> <>UTF-8</> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <release>11</release> </configuration> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>${jetty.version}</version> </plugin> </plugins> </build> </project>

Spring Boot (web application example)

install Spring Boot Extension Pack
Spring Initializr: Create a Maven Project ...
- Spring Boot Version: 2.5.4
- Language: Java
- Input Group: de.redeight
- Input Artifact ID: sbwebsample
- Packaging Type: jar
- Java Version: 11
- Dependencies:
   - Spring Boot DevTools
   - Spring Web
- no further dependencies for now
- selected 2 dependencies > press ENTER to continue
- Dialog: Folder: ~/project ( select the (parent) project folder )
- - quit Dialog using [Generate to this folder]
- "successfully generated". Location: ~./project ==> [Open]
- [Add to Workspace]
- File > Save workspace as ... ~/project/sbwebsample/sbwebsample.code-workspace
- ... generating Java project(s) ...
- ... importing Java project(s) ... (VSC might prompt for this)

Generated project:

            |-- mvnw
            |-- mvnw.cmd
            |-- pom.xml
            |-- sbwebsample.code-workspace
            |-- src
            |   |-- main
            |   |   |-- java
            |   |   |   `-- de
            |   |   |       `-- redeight
            |   |   |           `-- sbwebsample
            |   |   |               `--
            |   |   `-- resources
            |   |       |--
            |   |       |-- static
            |   |       `-- templates
            |   `-- test
            |       `-- java
            |           `-- de
            |               `-- redeight
            |                   `-- sbwebsample
            |                       `--
            `-- target
                |-- classes
                |   |--
                |   `-- de
                |       `-- redeight
                |           `-- sbwebsample
                |               `-- SbwebsampleApplication.class
                `-- test-classes
                    `-- de
                        `-- redeight
                            `-- sbwebsample
                                `-- SbwebsampleApplicationTests.class         
- Add more dependencies (if needed) - Spring Initializr: Add Starters...

Edit Code - write a REST Controller: - in the VSC Explorer / JAVA PROJECTS view select the src/main/java folder
- right-click and select New Java Class from the context menu
- class name Intro (will create package and class)
            public class Intro {

               private final long id;
               private final String content;
               public Intro(long id, String content) {
         = id;
                  this.content = content;
               public long getId() {
                  return id;
               public String getContent() {
                  return content;
- Intro is a POJO class. Additionally a RestController class is needed
- once again right-click and select New Java Class from the context menu
- create the IntroController class. - add the @RestController annotation to the class
   - hereby use auto-completion to add the org.springframework.web.bind.annotation.RestController import
            package de.redeight.sbwebsample;

            import java.util.concurrent.atomic.AtomicLong;

            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.RequestParam;
            import org.springframework.web.bind.annotation.RestController;

            public class IntroController {
               private static final String template = "Hello, %s!";
	            private final AtomicLong counter = new AtomicLong();

	            public Intro intro(@RequestParam(value = "name", defaultValue = "World") String name) 
                  return new Intro(counter.incrementAndGet(), String.format(template, name));
- build and run the service (from VSC): use the Run code lense function at the main method:
- build and run the service (from the command line):
... change to the project folder run
    ./mvnw spring-boot:run
    ./mvnw clean package
    java -jar target/sbwebsample-0.0.1-SNAPSHOT.jar
- Service returns JSON format by default!

- Testing the service:
    - browse http://localhost:8080/intro => Hello, World
    - browse http://localhost:8080/intro?name=JADE => Hello, JADE

- Using embedded Jetty instead of Tomcat:
    - add the exclusion block around spring-boot-starter-tomcat
    - add the spring-boot-starter-jetty dependency
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> | <exclusions> | <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> | </exclusion> | </exclusions> </dependency> | <dependency> | <groupId>org.springframework.boot</groupId> | <artifactId>spring-boot-starter-jetty</artifactId> | </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>     - rebuild and run, that's all