Gunnar Morling

Gunnar Morling

Random Musings on All Things Software Engineering

Gunnar Morling

Gunnar Morling

Random Musings on All Things Software Engineering

Getting Started With Java Development in 2023 — An Opinionated Guide

Posted at Jan 15, 2023

27 years of age, and alive and kicking — The Java platform regularly comes out amongst the top contenders in rankings like the TIOBE index. In my opinion, rightly so. The language is very actively maintained and constantly improved; its underlying runtime, the Java Virtual Machine (JVM), is one of, if not the most, advanced runtime environments for managed programming languages.

There is a massive eco-system of Java libraries which make it a great tool for a large number of use cases, ranging from command-line and desktop applications, over web apps and backend web services, to datastores and stream processing platforms. With upcoming features like support for vectorized computations (SIMD), light-weight virtual threads, improved integration with native code, value objects and user-defined primitives, and others, Java is becoming an excellent tool for solving a larger number of software development tasks than ever before.

The immense breadth of Java and its ecosystem, having grown and matured over nearly three decades, can also be challenging though for folks just starting their careers as a Java developer. Which Java version should you use? How to install it? Which build tool and IDE are the right ones? For all these, and many other questions, there are typically a number of options, which can easily overwhelm you if you are new to Java. As the platform has evolved, tools have come and gone, things which were hugely popular years ago have fallen into obsolescence since then. As related information can still be found on the internet, it can be hard to identify what’s still relevant and what not.

The idea for this blog post is to provide an opinionated guide for folks getting started with Java development in 2023, helping you with your very first steps with that amazing platform. Note I’m not saying that the things I’m going to recommend are the best ones for each and every situation. The focus is on providing a good getting-started experience. Some of the recommended tools or approaches may make less sense to use as you get more experienced and other choices might be better suited for you then, based on the specific situation and its requirements.

Also, very importantly, there is a notion of personal taste and preference to these things, those are my recommendations, and those of others might look different, which is perfectly fine.

Java — What is What?

As you make your first steps with Java, it might be confusing to understand what even Java is. Indeed "Java" refers to several things, which can even trip up more experienced folks. Here’s a list of key terms and concepts:

The Java programming language

A general-purpose statically-typed object-oriented programming language (with some functional flavors); it is compiled into portable byte code which can be executed on a wide range of platforms

The Java platform

"A suite of programs that facilitate developing and running programs written in the Java programming language", with key elements being the Java compiler (javac), the Java virtual machine, and the Java standard class library. Focus of this post is the Java Standard Edition (SE), other platforms like Java Micro Edition (ME), and Jakarta Enterprise Edition (EE) are not discussed here. A large number of languages other than Java (the language) itself can run on Java SE (the platform), for instance Kotlin, Groovy, and Scala; they are also out of scope for this article, though

The Java virtual machine (JVM)

A virtual machine for executing Java programs (or more precisely, byte code), e.g. taking care of tasks like loading byte code and verifying its correctness, compiling it into platform-specific machine code using a just-in-time compiler (JIT), automated memory management via garbage collection, ensuring isolation between different components, providing runtime diagnostics, etc.; multiple JVM implementations exist, including HotSpot and OpenJ9

The Java Development Kit (JDK)

A distribution of tools for developing and running Java applications

OpenJDK

An open-source implementation of Java SE and related projects; also the name of the open-source community creating this implementation

The Java Community Process (JCP)

A mechanism for developing specifications in the Java space, including those defining the different Java versions

📦 Distribution

The Java platform is maintained by the OpenJDK open-source project. Similar to Linux, multiple vendors provide binary distributions for this project, including Amazon, the Eclipse Foundation, Microsoft, Oracle, or Red Hat. These distributions differ in aspects like availability of commercial support and duration of the same, supported platforms, extent of testing, certain features like available garbage collectors, potentially bug fixes, and others. So which one should you use?

For the beginning, the differences won’t matter too much, and I suggest choosing Eclipse Temurin. It is backed by Adoptium, a working group of companies like Google, Red Hat, Microsoft, Alibaba, Azul, and others. You can download and use it for free, it contains everything you’ll need, passes the test compatibility kit (TCK) of the JDK, and if needed, there is commercial support provided by different vendors.

📆 Version

A new version of Java is released every six months, with the current one at the time of writing this being Java 19. Specific releases are long-term support (LTS) releases, for which vendors provide maintenance for many years. The current LTS release is Java 17 and I recommend you to get started with this one.

While newer non-LTS releases may add useful new features, finding a sustainable update strategy can be a bit tricky, and many of the new features are preview or incubating features, meaning that you would not use them in production code anyways. I recommend you diving into those later on, once you’ve gained some experience with Java and its ecosystem.

If specific 3rd-party libraries don’t work seamlessly with Java 17 yet, you should use the previous LTS (Java 11). Don’t use non-LTS releases apart from the current one, as they are mostly unmaintained, i.e. you may open yourself to security issues and other bugs which won’t get fixed. Also don’t use Java 8 (alternatively named 1.8), which is the LTS before 11, as it’s really ancient by today’s standards.

🔧 Installation

There’s different ways for installing your chosen Java distribution. Usually, there’ll be a distribution package which you can download from the vendor’s website. Alternatively, package managers of the operating system allow you to install Java too.

For a simplified getting started experience, my recommendation is to take a look at SDKMan. This is a tool which allows you to install software development kits (SDKs) such as Java’s JDK. You can also update your installed SDK versions and easily switch between multiple versions.

If you have SDKMan installed, obtaining the current Eclipse Temurin build of Java 17 is as simple as running the following in your shell:

1
2
3
4
5
6
$ sdk install java 17.0.5-tem # Install
$ sdk use java 17.0.5-tem # Activate
$ java --version # Verify version

openjdk 17.0.5 2022-10-18
...
Installation in Windows

SDKMan is implemented in bash, so if you are on Windows, you’ll need to install either the Windows Subsystem for Linux (WSL) or Cygwin before you can use SDKMan. I’d recommend having either in any case, but if that’s not an option, you may install Java using the winget package manager or by downloading your distribution directly from its vendors website.

💡 Your First Java Program

Having installed Java, it’s time to write your first Java program. Java is first and foremost an object-oriented language, hence everything in a Java program is defined in the form of classes, which have fields (representing their state) and methods (the behavior operating on that state). The canonical "Hello World" example in Java looks like this:

1
2
3
4
5
public class HelloWorld { (1)
  public static void main(String... args) { (2)
    System.out.println("Hello world!"); (3)
  }
}
1 The class HelloWorld must be specified in a source file named HelloWorld.java
2 The main() method is the entry point into a Java program
3 The println() method prints the given text to standard out

Java source code is compiled into class files which then are loaded into the JVM and executed. Normally, this is done in two steps: first running the compiler javac, then executing the program using the java binary. For quick testing and exploring, both steps can be combined, so you can execute your "Hello World" program like this:

1
2
$ java HelloWorld.java
Hello world!

For exploring Java in a quick and iterative mode, it provides jshell, an interactive Read-Evaluate-Print Loop (REPL). You can use it for running expressions and statements without defining a surrounding method or class, simplifying "Hello World" quite a bit:

1
2
3
4
$ jshell

jshell> System.out.println("Hello World");
Hello World

Similar to jshell, but quite a bit more fancier is jbang, which for instance allows you to easily pull in 3rd party libraries into your single source file Java programs.

📚 Learning the Language

Providing an introduction to all the features of the Java programming language is beyond the scope of this blog post. To truly learn the language and all its details, my recommendation would be to get a good book, grab a coffee (or two, or three, …​) and work through its chapters, in order of your personal interests. A popular choice for getting started with Java is "Head First Java, 3rd Edition" by Kathy Sierra, Bert Bates, Trisha Gee, nicely complemented by The Well-Grounded Java Developer, 2nd Edition, by Benjamin Evans, Jason Clark, and Martijn Verburg. A must-read for honing your Java skills is "Effective Java, 3rd Edition", by Joshua Bloch. While this has been updated for Java 9 the last time, its contents are pretty much timeless and still apply to current Java versions.

If you don’t want to commit to buying a book just yet, check out the "Learn Java" section on dev.java, which has tons of material describing the Java language, key parts of the class library, the JVM and its most important tools, and more in great detail.

The authoritative resource on the Java language is the Java Language Specification, or JLS for short. The specification is written in a very concise and well understandable way, and I highly recommend you to take a look if you’d like to understand how specific details of the language exactly work. That being said, when you’re just about to get started with learning Java, you’ll be better off by studying the resources mentioned above.

If certifications are your thing, you might consider learning for and taking the exam for the "Oracle Certified Professional: Java SE 17 Developer" one. I’d only recommend doing so after having worked with Java at least for a year or so, as the exam actually is quite involved. You’ll certainly learn a lot about Java, including all kinds of corner cases and odd details; not everything will necessarily translate into your day-to-day work as a developer, though. So you should consciously decide whether you want to spend the time preparing for the certification or not.

👷‍♀️ Build Tool

Once you go beyond the basics of manually compiling and running a set of Java classes, you’ll need a build tool. It will not only help you with compiling your code, but also with managing dependencies (i.e. 3rd party libraries you are using), testing your application, assembling the output artifacts (e.g. a JAR file with your program), and much more. There are plug-ins for finding common bug patterns, auto-formatting your code, etc. Commonly used build tool options for Java include Apache Maven, Gradle, and Bazel.

My recommendation is to stick with Maven for the beginning; it’s the most widely used one, and in my opinion the easiest to learn. Installing it is as simple as running sdk install maven with SDKMan. While it defines a rather rigid structure for your project, that also frees you from having to think about many aspects, which is great in particular when getting started. Maven has support for archetypes, templates which you can use to quickly bootstrap new projects. For instance you can use the oss-quickstart archetype which I have built for creating new projects with a reasonable set of pre-configured plug-ins like so:

1
2
3
4
5
6
7
8
mvn archetype:generate -B \
  -DarchetypeGroupId=org.moditect.ossquickstart \
  -DarchetypeArtifactId=oss-quickstart-simple-archetype \
  -DarchetypeVersion=1.0.0.Alpha1 \
  -DgroupId=com.example.demos \
  -DartifactId=fancy-project \
  -Dversion=1.0.0-SNAPSHOT \
  -DmoduleName=com.example.fancy

A lesser known yet super-useful companion to Maven is the Maven Daemon, which helps you to drastically speed up your builds by keeping a daemon process running in the background, avoiding the cost of repeatedly launching and initializing the build environment. You can install it via SDKMan by running sdk install mvnd.

Alternative build tools like Gradle tend to provide more flexibility and interesting features like "compilation avoidance" (rebuilding only affected parts of large code bases after a change) or distributed build caches (increasing developer productivity in particular in large projects), but I’d wait with looking at those until you’ve gathered some experience with Java itself.

📝 Editor

Many Java developers love to fight over their favorite build tools, and it’s the same with editors and full-blown integrated development environments (IDEs). So whatever I’m going to say here, it’s guaranteed a significant number of people won’t like it ;)

My suggestion is to start with VSCode. It’s a rather light-weight editor, which comes with excellent Java developer support, e.g. for testing and debugging your code. It integrates very well with Maven-based projects and has a rich eco-system of plug-ins you can tap into.

As your needs grow, you’ll probably look for an IDE which comes with even more advanced functionality, e.g. when it comes to refactoring your code. While I’m personally a happy user of the Eclipse IDE, most folks tend to use IntelliJ IDEA these days and it’s thus what I’d recommend you to look into too. It comes with a feature-rich free community edition which will help you a lot with the day-to-day tasks you’ll encounter as a Java developer. Make sure to spend a few hours learning the most important keyboard short-cuts, it will save you lots of time later on.

🧱 Libraries

The ecosystem of 3rd party libraries is one of Java’s absolute super-powers: there is a ready-made library or framework available for pretty much every task you might think of, most of the times available as open-source.

Perhaps counter-intuitively, my recommendation here is to try and be conservative with pulling in libraries into your project, and instead work with what’s available in Java’s standard class library (which is huge and covers a wide range of functionality already). Next, check out what your chosen application framework (if you use one, see below) offers either itself or provides integrations for.

Adding a dependency to an external library should always be a conscious decision, as you might easily run into version conflicts between transitive dependencies (i.e. dependencies of dependencies) in different versions, more dependencies increase the complexity of your application (for instance, you must keep them all up-to-date), they may increase the attack surface of your application, etc. Sometimes, you might be better off by implementing something yourself, or maybe copy a bit of code from a 3rd party library into your own codebase, provided the license of that library allows for that.

That said, some popular libraries you will encounter in many projects include JUnit (for unit testing), slf4j (logging), Jackson (JSON handling), Hibernate (object-relational persistence, domain model validation, etc.), Testcontainers (integration testing with Docker), and ArchUnit (enforcing software architecture rules). The "awesome-java" list is a great starting point for diving into the ecosystem of Java libraries.

Most open-source dependencies are available via the Maven Central repository; All the build tools integrate with it, not only Maven itself, but also Gradle and all the others. The MVN Repository site is a good starting point for finding dependencies and their latest versions. If you want to distribute libraries within your own organization, you can do so by self-running repository servers like Nexus or Artifactory, or use managed cloud services such as AWS CodeArtifact.

🐢 Application Framework

Most Java enterprise applications are built on top of an application framework which provides support for structuring your code via dependency injection, seamlessly integrates with a curated set of 3rd party libraries in compatible versions, helps with configuring and testing your application, and much more.

Again, there’s plenty of options in Java here, such as Spring Boot, Quarkus, Jakarta EE, Micronaut, Helidon, and more. My personal recommendation here is to use Quarkus (it’s the one I’m most familiar with, having worked for Red Hat before, who are the company behind this framework), or alternatively Spring Boot.

Both are widely popular, integrate with a wide range of technologies (e.g. web frameworks and databases of all kinds), come with excellent developer tooling, and are backed by very active open-source communities.

🐳 Container Base Image

In particular when you are going to work on an enterprise application, chances are that you’ll publish your application in form of a container image, so people can run it on Docker or Kubernetes.

Sticking to the recommendation on using Eclipse Temurin as your Java distribution, I suggest to use the Temurin image as the base for your application images, e.g. eclipse-temurin:17 for Java 17. Just make sure to keep your image up to date, so you and your users benefit from updates to the base image.

One base image you should avoid is the OpenJDK one, which is officially deprecated and not recommended for production usage.

🔭 Next Steps

The points above hopefully can help you to embark onto a successful journey with the Java platform, but they only are a starting point. Depending on your specific needs and requirements, here is a number possible next topics to explore and learn about:

  • Exploring the tools which come with the JDK, for instance javadoc (for generating API documentation), jcmd (for sending diagnostic commands to a running Java application), or jpackage (for packaging self-contained Java applications)

  • Building native binaries using GraalVM, allowing for a fast start-up and low memory consumption; very useful for instance for building command-line tools or AWS Lambda functions

  • Analyzing the performance and runtime characteristics of your application using JDK Flight Recorder and JDK Mission Control

  • Setting up continuous integration (CI) workflows for automatically building and testing your application with GitHub Actions (the aforementioned Maven oss-quickstart archetype will generate a basic template for that automatically)

  • Publishing open-source libraries to Maven Central with JReleaser

Finally, a few resources which should help you to stay up-to-date with everything Java and learn what’s going on in the community include the Java News on dev.java, inside.java ("news and views from members of the Java team at Oracle") the JEP Search (for searching and filtering Java enhancement proposals, i.e. changes to the language and the platform) and Foojay (Friends of OpenJDK).

Many thanks to Nils Hartmann, Andres Almiray, and Oliver Zeigermann for their input and feedback while writing this post!