eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

In this tutorial, we’ll introduce different methods for installing a JDK on Ubuntu. Then, we’ll briefly compare the methods. Finally, we’ll show how to manage multiple Java installations on an Ubuntu system.

As a prerequisite to each method, we need

  • an Ubuntu system
  • to be logged in as a non-root user with sudo privileges

The instructions described below have been tested on Ubuntu 18.10, 18.04 LTS, 16.04 LTS, and 14.04 LTS. For Ubuntu 14.04 LTS, there’re some differences, which are mentioned in the text.

Please note that both the packages you can download from OpenJDK and Oracle and the packages available in repositories are updated regularly. The exact package names will probably change within some months, but the basic methods of installation will remain the same.

2. Installing JDK 11

If we want to use the latest and greatest version of JDK, often manual installation is the way to go. This means downloading a package from the OpenJDK or the Oracle site and setting it up so that it adheres to the conventions of how apt sets up the JDK packages.

2.1. Installing OpenJDK 11 Manually

First of all, let’s download the tar archive of the recently released OpenJDK 11:

$ wget https://download.java.net/java/ga/jdk11/openjdk-11_linux-x64_bin.tar.gz

And we compare the sha256 sum of the downloaded package with the one provided on the OpenJDK site:

$ sha256sum openjdk-11_linux-x64_bin.tar.gz

Let’s extract the tar archive:

$ tar xzvf openjdk-11_linux-x64_bin.tar.gz

Next, let’s move the jdk-11 directory we’ve just extracted into a subdirectory of /usr/lib/jvm. The apt packages described in the next section also put their JDKs into this directory:

$ sudo mkdir /usr/lib/jvm
$ sudo mv jdk-11 /usr/lib/jvm/openjdk-11-manual-installation/

Now, we want to make the java and javac commands available. One possibility would be to create symbolic links for them, for example, in the /usr/bin directory. But instead, we’ll install an alternative for both of them. This way, if we ever wish to install additional versions of JDK, they will play nicely together:

$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/openjdk-11-manual-installation/bin/java 1
$ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/openjdk-11-manual-installation/bin/javac 1

Let’s verify the installation:

$ java -version

As we can see from the output, we’ve indeed installed the latest version of the OpenJDK JRE and JVM:

openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

Let’s have a look at the compiler version also:

$ javac -version
javac 11

2.2. Installing Oracle JDK 11 Manually

If we want to make sure to use the newest version of Oracle JDK, we can follow a similar manual installation workflow, as for OpenJDK. In order to download the tar archive for JDK 11 from the Oracle website, we must accept a license agreement first. For this reason, downloading via wget is a bit more complicated than for OpenJDK:

$ wget -c --header "Cookie: oraclelicense=accept-securebackup-cookie" \
http://download.oracle.com/otn-pub/java/jdk/11.0.1+13/90cf5d8f270a4347a95050320eef3fb7/jdk-11.0.1_linux-x64_bin.tar.gz

The example above downloads the package for 11.0.1 The exact download link changes for each minor version.

The following steps are the same as for OpenJDK:

$ sha256sum jdk-11.0.1_linux-x64_bin.tar.gz
$ tar xzvf jdk-11.0.1_linux-x64_bin.tar.gz
$ sudo mkdir /usr/lib/jvm
$ sudo mv jdk-11.0.1 /usr/lib/jvm/oracle-jdk-11-manual-installation/
$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/oracle-jdk-11-manual-installation/bin/java 1
$ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/oracle-jdk-11-manual-installation/bin/javac 1

The verification is also the same. But the output shows that this time, we’ve installed not OpenJDK but Java(TM):

$ java -version
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)

And for the compiler:

$ javac -version
javac 11.0.1

2.3. Installing Oracle JDK 11 from a PPA

Currently, Oracle JDK 11 is also available in a PPA (personal package archive). This installation involves 2 steps: adding the repository to our system and installing the package from the repository via apt:

$ sudo add-apt-repository ppa:linuxuprising/java
$ sudo apt update
$ sudo apt install oracle-java11-installer

The verifying steps should show the same result as after the manual installation in section 2.2.1.:

$ java -version
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)

And for the compiler:

$ javac -version
javac 11.0.1

On Ubuntu 14.04 LTS the add-apt-repository command isn’t available by default. In order to add a repository, first we need to install the software-properties-common package.

$ sudo apt update
$ sudo apt install software-properties-common

Afterward, we can continue with add-apt-repository, apt update and apt install as shown above.

3. Installing JDK 8

3.1. Installing OpenJDK 8 on Ubuntu 16.04 LTS and Newer

JDK 8 is an LTS version that has been around for a while. For this reason, we can find an up-to-date version of OpenJDK 8 in the “Main” repository on most of the supported Ubuntu versions. Of course, we can also head to the OpenJDK website, grab a package there, and install it the same way we’ve seen in the previous section.

But using the apt tooling and the “Main” repository provides some benefits. The “Main” repository is available by default on all Ubuntu systems. It’s supported by Canonical — the same company that maintains Ubuntu itself.

Let’s install OpenJDK 8 from the “Main” repository with apt:

$ sudo apt update
$ sudo apt install openjdk-8-jdk

Now, let’s verify the installation:

$ java -version

The result should list a Runtime Environment and a JVM:

openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-0ubuntu0.18.04.1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

Let’s check that the javac executable is available as well:

$ javac -version

Now we should see the same version number as shown above:

javac 1.8.0_181

3.2. Installing OpenJDK 8 on Ubuntu 14.04 LTS

On Ubuntu 14.04 LTS, the OpenJDK packages aren’t available in the “Main” repository, so we’ll install them from the openjdk-r PPA. As we’ve seen in section 2.3 above, the add-apt-repository command isn’t available by default. We need the software-properties-common package for it:

$ sudo apt update
$ sudo apt install software-properties-common
$ sudo add-apt-repository ppa:openjdk-r/ppa
$ sudo apt update
$ sudo apt install openjdk-8-jdk

3.3. Installing Oracle JDK 8 from a PPA

The “Main” repository does not contain any proprietary software. If we want to install Oracle Java with apt, we’ll have to use a package from a PPA. We’ve already seen how to install Oracle JDK 11 from the linuxuprising PPA. For Java 8, we can find the packages in the webupd8team PPA.

First, we need to add the PPA apt repository to our system:

$ sudo add-apt-repository ppa:webupd8team/java

Then we can install the package the usual way:

$ sudo apt update
$ sudo apt install oracle-java8-installer

During the installation, we have to accept Oracle’s license agreement. Let’s verify the installation:

$ java -version

The output shows a Java(TM) JRE and JVM:

java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

We can also verify that the compiler has been installed:

$ javac -version
javac 1.8.0_181

4. Installing JDK 10

The versions Java 10 and Java 9 aren’t supported anymore. You can install them manually, following similar steps as in section 2. You can grab the packages from:

Both sites contain the same warning:

These older versions of the JDK are provided to help developers debug issues in older systems. They are not updated with the latest security patches and are not recommended for use in production.

4.1.  Installing OpenJDK 10 Manually

Let’s see how to install OpenJDK 10.0.1:

$ wget https://download.java.net/java/GA/jdk10/10.0.1/fb4372174a714e6b8c52526dc134031e/10/openjdk-10.0.1_linux-x64_bin.tar.gz
$ sha256sum openjdk-10.0.1_linux-x64_bin.tar.gz
$ tar xzvf openjdk-10.0.1_linux-x64_bin.tar.gz
$ sudo mkdir /usr/lib/jvm
$ sudo mv jdk-10.0.1 /usr/lib/jvm/openjdk-10-manual-installation/
$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/openjdk-10-manual-installation/bin/java 1
$ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/openjdk-10-manual-installation/bin/javac 1
$ java -version
$ javac -version

4.2. Installing Oracle JDK 10 Manually

As we’ve seen in section 2.2., in order to download a package from the Oracle website, we must accept a license agreement first. Contrary to the supported versions, we can’t download the older Oracle JDKs via wget and a cookie. We need to head to https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase10-4425482.html and download the tar.gz file. Afterward, we follow the familiar steps:

$ sha256sum jdk-10.0.2_linux-x64_bin.tar.gz
$ tar xzvf jdk-10.0.2_linux-x64_bin.tar.gz
$ sudo mkdir /usr/lib/jvm
$ sudo mv jdk-10.0.2 /usr/lib/jvm/oracle-jdk-10-manual-installation/
$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/oracle-jdk-10-manual-installation/bin/java 1
$ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/oracle-jdk-10-manual-installation/bin/javac 1
$ java -version
$ javac -version

5. Installing JDK 9

5.1. Installing OpenJDK 9 Manually

Just like we saw above with OpenJDK 10.0.1, we download the OpenJDK 9 package via wget and set it up according to the conventions:

$ wget https://download.java.net/java/GA/jdk9/9.0.4/binaries/openjdk-9.0.4_linux-x64_bin.tar.gz
$ sha256sum openjdk-9.0.4_linux-x64_bin.tar.gz
$ tar xzvf openjdk-9.0.4_linux-x64_bin.tar.gz
$ sudo mkdir /usr/lib/jvm
$ sudo mv jdk-9.0.4 /usr/lib/jvm/openjdk-9-manual-installation/
$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/openjdk-9-manual-installation/bin/java 1
$ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/openjdk-9-manual-installation/bin/javac 1
$ java -version
$ javac -version

5.2. Installing Oracle JDK 9 Manually

Once again, we use the same method as for JDK 10. We need to head to https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase9-3934878.html and download the tar.gz file. Afterward, we follow the familiar steps:

$ sha256sum jdk-9.0.4_linux-x64_bin.tar.gz
$ tar xzvf jdk-9.0.4_linux-x64_bin.tar.gz
$ sudo mkdir /usr/lib/jvm
$ sudo mv jdk-9.0.4 /usr/lib/jvm/oracle-jdk-9-manual-installation/
$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/oracle-jdk-9-manual-installation/bin/java 1
$ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/oracle-jdk-9-manual-installation/bin/javac 1
$ java -version
$ javac -version

6. Comparison

We’ve seen three different ways of installing a JDK on Ubuntu. Let’s have a quick overview of each of them, pointing out the advantages and disadvantages.

6.1. “Main” Repository

This is the “Ubuntu native” way of installation. A big advantage is that we update the packages via the “usual apt workflow” with apt update and apt upgrade.

Furthermore, the “Main” repository is maintained by Canonical, which provides reasonably fast (if not immediate) updates. For example, OpenJDK versions 10.0.1 and 10.0.2 were both synced within a month of release.

6.2. PPA

PPAs are small repositories maintained by an individual developer or a group. This also means that the update frequency depends on the maintainer.

Packages from PPAs are considered riskier than the packages in the “Main” repository. First, we have to add the PPA explicitly to the system’s repository list, indicating that we trust it. Afterward, we can manage the packages via the usual apt tooling (apt update and apt upgrade).

6.3. Manual Installation

We download the package directly from the OpenJDK or Oracle site. Although this method offers a great deal of flexibility, updates are our responsibility. If we want to have the latest and greatest JDK, this is the way to go.

7. Exploring Other Versions of JDKs

The examples in sections 2 and 3 reflect the current status on Ubuntu 18.04 LTS. Keep in mind that the JDKs and the corresponding packages are updated regularly. Thus it’s useful to know how to explore our current possibilities.

In this section, we’ll focus on surveying the OpenJDK packages in the “Main” repository. If we’ve already added a PPA with add-apt-repository, we can explore it in a similar manner with apt list and apt show.

To discover which PPAs are available, we can head to https://launchpad.net/. If we don’t find what we’re looking for in the “Main” repository and in the PPAs, we’ll have to fall back to manual installation.

If we’d like to use an unsupported version, even that can be difficult. As of this writing, we didn’t find any packages for Java 9 or Java 10 on the OpenJDK and Oracle websites.

Let’s see which other JDK packages exist in the “Main” repository:

$ apt list openjdk*jdk

On Ubuntu 18.04 LTS, we can choose between the two current LTS Java versions:

Listing... Done
openjdk-11-jdk/bionic-updates,bionic-security,now 10.0.2+13-1ubuntu0.18.04.2 amd64 [installed,automatic]
openjdk-8-jdk/bionic-updates,bionic-security 8u181-b13-0ubuntu0.18.04.1 amd64

It’s also worth noting that although the package is called openjdk-11-jdk, as of this writing, it actually installs version 10.0.2. This is likely to change soon. We can see that if we inspect the package:

$ apt show openjdk-11-jdk

Let’s have a look at the “Depends” section of the output. Note that these packages (e.g. a JRE) also get installed alongside openjdk-11-jdk:

Depends: openjdk-11-jre (= 10.0.2+13-1ubuntu0.18.04.2),
openjdk-11-jdk-headless (= 10.0.2+13-1ubuntu0.18.04.2),
libc6 (>= 2.2.5)

Let’s explore which other packages we have at our disposal besides the default jdk package:

$ apt list openjdk-11*
Listing... Done
openjdk-11-dbg/bionic-updates,bionic-security 10.0.2+13-1ubuntu0.18.04.2 amd64
openjdk-11-demo/bionic-updates,bionic-security 10.0.2+13-1ubuntu0.18.04.2 amd64
openjdk-11-doc/bionic-updates,bionic-updates,bionic-security,bionic-security 10.0.2+13-1ubuntu0.18.04.2 all
openjdk-11-jdk/bionic-updates,bionic-security 10.0.2+13-1ubuntu0.18.04.2 amd64
openjdk-11-jdk-headless/bionic-updates,bionic-security 10.0.2+13-1ubuntu0.18.04.2 amd64
openjdk-11-jre/bionic-updates,bionic-security,now 10.0.2+13-1ubuntu0.18.04.2 amd64 [installed,automatic]
openjdk-11-jre-headless/bionic-updates,bionic-security,now 10.0.2+13-1ubuntu0.18.04.2 amd64 [installed,automatic]
openjdk-11-jre-zero/bionic-updates,bionic-security 10.0.2+13-1ubuntu0.18.04.2 amd64
openjdk-11-source/bionic-updates,bionic-updates,bionic-security,bionic-security 10.0.2+13-1ubuntu0.18.04.2 all

We may find some of these packages useful. For example, openjdk-11-source contains source files for the classes of the Java core API, while openjdk-11-dbg contains the debugging symbols.

Besides the openjdk-* family, there’s the default-jdk package, that is worth exploring:

$ apt show default-jdk

At the end of the output, the description says:

“This dependency package points to the Java runtime, or Java compatible development kit recommended for this architecture…”

In the case of Ubuntu 18.04 LTS, it’s the package openjdk-11-jdk at the moment.

8. Overview: Java Versions and Packages

Now, let’s have a look at how different versions of Java could be installed on Ubuntu 18.04 LTS as of this writing:

Version OpenJDK Oracle Java
11 manual installation manual installation

oracle-java11-installer in the linuxuprising PPA

10 manual installation – not supported manual installation – not supported
9 manual installation – not supported manual installation – not supported
8 openjdk-8-jdk in the “Main” repository oracle-java8-installer in the webupd8team PPA

9. Multiple Java Versions on an Ubuntu System

The standard way for managing multiple versions of the same software on Ubuntu is via the Debian Alternatives System. Most of the time we create, maintain and display alternatives via the update-alternatives program.

When apt installs a JDK package, it automatically adds the entries for the alternatives. In the case of manual installation, we’ve seen how to add the alternatives for java and javac respectively.

Let’s have a look at our alternatives:

$ update-alternatives --display java

On our test system, where we’ve installed two different versions of OpenJDK, the output lists both alternatives with their respective priorities:

java - auto mode
link best version is /usr/lib/jvm/java-11-openjdk-amd64/bin/java
link currently points to /usr/lib/jvm/java-11-openjdk-amd64/bin/java
link java is /usr/bin/java
slave java.1.gz is /usr/share/man/man1/java.1.gz
/usr/lib/jvm/java-11-openjdk-amd64/bin/java - priority 1101
slave java.1.gz: /usr/lib/jvm/java-11-openjdk-amd64/man/man1/java.1.gz
/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java - priority 1081
slave java.1.gz: /usr/lib/jvm/java-8-openjdk-amd64/jre/man/man1/java.1.gz

Now that we’ve seen our alternatives, we can also switch between them:

$ sudo update-alternatives --config java

Additionally, we get an interactive output, where we can switch between the alternatives via the keyboard:

There are 2 choices for the alternative java (providing /usr/bin/java).

Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1101 auto mode
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1101 manual mode
2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 manual mode

Press <enter> to keep the current choice[*], or type selection number:

If we’re working on multiple applications written in different versions of Java, chances are we’ll also need different versions of other software (e.g. Maven, some application server). In that case, we may want to consider using greater abstractions such as Docker containers.

10. Conclusion

To summarize, in this article, we’ve seen examples of installing a JDK from the “Main” repository, from a PPA, and manually. We’ve briefly compared these three installation methods.

And finally, we’ve seen how to manage multiple Java installations on Ubuntu system with update-alternatives.

As a next step, it may be useful to set the JAVA_HOME environment variable.

Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – LS – NPI (cat=Java)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)