Welcome to Chapter 15, future Java enterprise developers! So far, we’ve focused on “Standard Edition” Java (Java SE), building foundational skills that are crucial for any Java programmer. But what happens when you need to build applications that serve thousands or millions of users, handle complex transactions, integrate with various systems, and run reliably 24/7? That’s where Enterprise Java comes in!
In this chapter, we’re going to embark on an exciting journey into the world of Enterprise Java. We’ll explore what it is, why it’s essential for large-scale applications, and dive into the modern landscape, specifically understanding the crucial shift from javax to jakarta namespaces. This transition is a fundamental piece of knowledge for any modern Java developer working on enterprise systems. By the end, you’ll have a solid grasp of Jakarta EE’s role and even build your very first web application component.
Ready to level up your Java skills and start building applications that can truly scale? Let’s dive in!
Prerequisites
Before we jump into the enterprise world, make sure you’re comfortable with:
- Core Java Concepts: Classes, objects, interfaces, inheritance, basic exception handling.
- Maven Basics: Understanding how
pom.xmlworks for dependency management and project building (we covered this briefly in earlier chapters, but a refresher on how to create a simple Maven project might be helpful). - Command Line: Basic navigation and execution of commands.
Core Concepts: Understanding Enterprise Java and the Jakarta EE Shift
Let’s begin by demystifying “Enterprise Java” and understanding the big changes that have shaped its future.
What is Enterprise Java?
Imagine you’re building a simple calculator application. You use Java SE, and it runs perfectly on your desktop. Now, imagine you’re building an online banking system. This system needs to:
- Handle thousands of simultaneous users.
- Securely access and store sensitive customer data in a database.
- Process transactions reliably, even if parts of the system fail.
- Provide a web interface for users.
- Integrate with other banking systems.
This is where Enterprise Java (historically known as Java EE, now Jakarta EE) shines! It’s a collection of specifications and APIs built on top of Java SE, specifically designed to address the challenges of developing large-scale, multi-tiered, and distributed applications. It provides standardized ways to:
- Build web applications: Servlets, JavaServer Pages (JSP), RESTful web services (JAX-RS).
- Connect to databases: Java Persistence API (JPA).
- Manage transactions: Java Transaction API (JTA).
- Handle messaging: Java Message Service (JMS).
- Inject dependencies: Contexts and Dependency Injection (CDI).
- …and much more!
Think of Java SE as your basic toolkit, and Jakarta EE as a specialized workshop full of powerful, standardized tools for building robust, industrial-strength applications.
The Great Renaming: From javax to jakarta
This is perhaps the most critical concept to grasp for modern Enterprise Java development. You might have heard of “Java EE” (Enterprise Edition) in the past. It was originally developed and managed by Oracle. However, in 2017, Oracle decided to move Java EE to the Eclipse Foundation to foster a more open and agile development process.
This move came with a significant change: the package namespace had to be changed from javax.* to jakarta.*. Why? Because Oracle retained the javax trademark. So, to continue evolving the platform under the Eclipse Foundation, a new namespace was necessary.
What does this mean for you?
- Older Java EE applications (Java EE 8 and earlier): Use
javax.*packages (e.g.,javax.servlet.http.HttpServlet). - Modern Jakarta EE applications (Jakarta EE 9 and later): Use
jakarta.*packages (e.g.,jakarta.servlet.http.HttpServlet).
This is not just a cosmetic change; it’s a fundamental shift. When you’re working on a new project, you must ensure you’re using the jakarta namespace and compatible libraries. Mixing them will lead to compilation errors and runtime issues.
Current Version Information (as of 2025-12-04):
- Java Development Kit (JDK): We will be using Oracle JDK 25, which was released in September 2025. While Java 21 is the current Long-Term Support (LTS) release, JDK 25 is the latest stable version. You can find its documentation at docs.oracle.com/en/java/javase/25/.
- Jakarta EE: The latest stable version is Jakarta EE 11, released in May 2024. This version fully embraces the
jakartanamespace. - Application Server: To run Jakarta EE applications, we need an application server. For this chapter, we’ll use Apache Tomcat 11.0.x, which fully supports Jakarta EE 11 and its Servlet 6.1 specification.
Key Jakarta EE Specifications (A Glimpse)
Jakarta EE is a vast ecosystem, but a few core specifications are essential for building web applications:
- Jakarta Servlet: The cornerstone of web development in Java. Servlets are Java classes that extend the capabilities of servers, handling incoming HTTP requests and generating responses. They are the engine behind dynamic web pages.
- Jakarta Server Pages (JSP): A technology that allows developers to embed Java code into HTML pages. While still present, modern development often favors templating engines or frontend frameworks for UI.
- Jakarta RESTful Web Services (JAX-RS): A specification for building RESTful web services, which are widely used for communication between different applications over HTTP.
- Jakarta Contexts and Dependency Injection (CDI): A powerful mechanism for managing component lifecycles and injecting dependencies, simplifying application development and making code more modular.
- Jakarta Persistence (JPA): A standard for object-relational mapping (ORM), allowing you to interact with databases using Java objects instead of raw SQL.
For our first step, we’ll focus on the Jakarta Servlet API, as it’s the foundation of web applications in Enterprise Java.
Application Servers: The Home for Your Enterprise Apps
An application server (like Apache Tomcat, WildFly, GlassFish, or Open Liberty) is a specialized server that provides the runtime environment for Jakarta EE applications. It handles many underlying complexities, such as:
- HTTP request/response handling: Listening for web requests and routing them to the correct Servlet.
- Lifecycle management: Starting, stopping, and managing your application components.
- Concurrency: Handling multiple user requests simultaneously.
- Security: Providing mechanisms for authentication and authorization.
For development, we often use lightweight servers like Apache Tomcat. It’s excellent for running web applications built with Servlets and JSPs.
Step-by-Step Implementation: Your First Jakarta EE Web Application
Let’s get our hands dirty and build a very simple “Hello, Jakarta!” web application using a Servlet. We’ll use Maven to manage our project and dependencies.
Step 1: Set up Your Development Environment
Make sure you have the following installed:
Java Development Kit (JDK) 25:
- Download from Oracle’s official site: oracle.com/java/technologies/downloads/
- Install it and configure your
JAVA_HOMEenvironment variable to point to your JDK 25 installation directory. - Verify by opening your terminal/command prompt and typing:You should see something like
java -versionopenjdk version "25.0.1" 2025-09-16or similar.
Apache Maven 3.9.x or later:
- Download from Apache Maven project site: maven.apache.org/download.cgi
- Follow the installation instructions to set up your
M2_HOMEandPATHenvironment variables. - Verify by typing:You should see
mvn -versionApache Maven 3.9.x(or newer) and information about your Java version.
Apache Tomcat 11.0.x:
- Download the binary distribution (e.g., “zip” for Windows, “tar.gz” for Linux/macOS) from the Apache Tomcat website: tomcat.apache.org/download-11.cgi
- Unzip/untar it to a convenient location (e.g.,
C:\apache-tomcat-11.0.xor~/apache-tomcat-11.0.x). We’ll refer to this asTOMCAT_HOME. - We won’t start it manually yet, but have it ready!
Step 2: Create a New Maven Web Project
Open your terminal or command prompt and navigate to a directory where you want to create your project. Then, execute the following Maven command:
mvn archetype:generate \
-DgroupId=com.example.jakartaee \
-DartifactId=hello-jakarta \
-DarchetypeArtifactId=maven-archetype-webapp \
-DarchetypeVersion=1.4 \
-DinteractiveMode=false
What’s happening here?
mvn archetype:generate: This Maven command tells Maven to generate a project from an archetype (a project template).-DgroupId=com.example.jakartaee: Defines the base package name for your project.-DartifactId=hello-jakarta: Defines the name of your project. This will also be the name of your generated WAR file and the context path when deployed.-DarchetypeArtifactId=maven-archetype-webapp: Specifies that we want to use the standard Maven web application archetype.-DarchetypeVersion=1.4: Specifies the version of the archetype.-DinteractiveMode=false: Tells Maven to generate the project without asking for interactive input.
After running this, Maven will create a directory named hello-jakarta with a basic web project structure.
Step 3: Configure pom.xml for Jakarta EE 11
Navigate into your newly created hello-jakarta directory:
cd hello-jakarta
Now, open the pom.xml file in your favorite code editor. We need to make a few crucial changes to support Jakarta EE 11 and use JDK 25.
First, update the properties section. Find the <properties> block and modify it to specify Java 25 and the encoding:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
</properties>
Explanation:
maven.compiler.sourceandmaven.compiler.target: These tell Maven to compile your Java code using the language features of Java 25 and to target the Java 25 runtime environment.
Next, we need to add the Jakarta Servlet API dependency. This is where the javax to jakarta change is critical! We need the jakarta.servlet API, specifically version 6.1.0 for Jakarta EE 11.
Find the <dependencies> block and add the following:
<dependencies>
<!-- Jakarta Servlet API for Jakarta EE 11 -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Why scope=provided?
- This is very important for web applications. It tells Maven that the application server (like Tomcat) will provide this library at runtime. We don’t need to package it within our WAR file. If we didn’t do this, our WAR file would be unnecessarily larger, and we might run into class loading conflicts with the server’s own libraries.
Finally, let’s ensure the maven-war-plugin is configured correctly, especially for the web.xml version. The maven-archetype-webapp often generates an older web.xml. While modern Servlets can often be configured purely with annotations, it’s good practice to ensure the web.xml is aligned or to remove it if you plan to use only annotations. For now, let’s just make sure the maven-war-plugin is present and correctly configured within the <build> section.
If you don’t have a <build> section, add it. If you do, ensure the maven-war-plugin is there. It should look something like this (add it right after the <dependencies> block if it’s not present):
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version> <!-- Use a recent version -->
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version> <!-- Use a recent version -->
<configuration>
<!-- This tells the plugin to generate a web.xml if not present,
or to respect the existing one. For annotation-driven servlets,
it's less critical. -->
</configuration>
</plugin>
</plugins>
</build>
Your complete pom.xml should now look similar to this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.jakartaee</groupId>
<artifactId>hello-jakarta</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>hello-jakarta Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
</properties>
<dependencies>
<!-- Jakarta Servlet API for Jakarta EE 11 -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<!-- No specific configuration needed here for annotation-driven servlets -->
</configuration>
</plugin>
</plugins>
</build>
</project>
Step 4: Create Your First Jakarta Servlet
Now let’s create the Java class that will handle our web requests.
Delete the default
index.jsp: Themaven-archetype-webappcreates a defaultsrc/main/webapp/index.jsp. We won’t be using it for now, so you can safely deletesrc/main/webapp/index.jsp.Create the Servlet class: Navigate to
src/main/java/com/example/jakartaee/(you might need to create these subdirectories if they don’t exist undersrc/main/java). Inside this directory, create a new Java file namedHelloServlet.java.Add the following code to
HelloServlet.java:package com.example.jakartaee; // Make sure this matches your groupId import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; // This annotation maps our servlet to a URL path. // When a request comes to /hello, this servlet will handle it. @WebServlet("/hello") public class HelloServlet extends HttpServlet { // This method handles HTTP GET requests. @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Set the content type of the response. // This tells the browser what kind of content to expect (HTML in this case). response.setContentType("text/html"); // Get a PrintWriter object to write the response back to the client. PrintWriter out = response.getWriter(); // Write the HTML content to the response. out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println("<title>Hello Jakarta!</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello from Jakarta EE 11!</h1>"); out.println("<p>This is your first Jakarta Servlet.</p>"); out.println("</body>"); out.println("</html>"); // Close the writer (optional, but good practice). out.close(); } }
Let’s break down this code, line by line:
package com.example.jakartaee;: This declares the package your class belongs to. It should match thegroupIdyou used in Maven.import jakarta.servlet.ServletException;etc.: These are the import statements. Notice they all start withjakarta.– this is the crucial part for Jakarta EE 11 compatibility!HttpServlet: The base class for HTTP servlets. We extend this to create our own servlet.HttpServletRequest: An object representing the incoming HTTP request. It contains information like request parameters, headers, URL, etc.HttpServletResponse: An object representing the outgoing HTTP response. We use this to send data back to the client (browser).@WebServlet("/hello"): This is an annotation. It’s a modern way to configure servlets without needing aweb.xmlfile. It tells the application server: “Hey, when a request comes in for the/helloURL path, send it to thisHelloServletclass!”
public class HelloServlet extends HttpServlet {: Our classHelloServletinherits fromHttpServlet, giving it all the capabilities to handle HTTP requests.@Override protected void doGet(...): This method is overridden fromHttpServlet. ThedoGet()method is specifically designed to handle HTTP GET requests (e.g., when you type a URL into your browser or click a link). There are alsodoPost(),doPut(),doDelete(), etc., for other HTTP methods.response.setContentType("text/html");: Before writing any content, we tell the client (browser) what kind of content we’re sending. In this case, it’s HTML.PrintWriter out = response.getWriter();: We get aPrintWriterobject from theHttpServletResponse. ThisPrintWriteracts like a stream where we can write text that will be sent back to the client.out.println("<!DOCTYPE html>");…out.println("</html>");: We useout.println()to write standard HTML content directly into the response. The browser will receive this HTML and render it.
Step 5: Package Your Application
Now that our code is written, let’s package it into a deployable format.
From your hello-jakarta project directory, run the Maven package goal:
mvn clean package
What does mvn clean package do?
clean: Deletes thetargetdirectory, ensuring a fresh build.package: Compiles your Java code, runs any tests, and then packages your application into a Web Application Archive (WAR) file. This WAR file is a standard format for deploying web applications to application servers.
You should see a BUILD SUCCESS message. Inside your target directory, you’ll find hello-jakarta.war. This is the file we’ll deploy!
Step 6: Deploy to Apache Tomcat
Now, let’s deploy our hello-jakarta.war to Tomcat and see it in action!
Copy the WAR file: Copy the
hello-jakarta.warfile from yourhello-jakarta/targetdirectory to thewebappsdirectory inside your Tomcat installation (TOMCAT_HOME/webapps).- Example (Linux/macOS):
cp target/hello-jakarta.war /path/to/apache-tomcat-11.0.x/webapps/ - Example (Windows):
copy target\hello-jakarta.war C:\path\to\apache-tomcat-11.0.x\webapps\
- Example (Linux/macOS):
Start Tomcat: Navigate to the
bindirectory inside your Tomcat installation (TOMCAT_HOME/bin).- Linux/macOS:
./startup.sh - Windows:
startup.bat
You should see messages indicating that Tomcat is starting up. It will automatically detect and deploy your
hello-jakarta.warfile. You’ll likely see a new directory namedhello-jakartacreated insideTOMCAT_HOME/webapps, which is Tomcat unpacking your WAR file.- Linux/macOS:
Access Your Application: Open your web browser and navigate to:
http://localhost:8080/hello-jakarta/helloYou should see your “Hello from Jakarta EE 11!” message!
Breakdown of the URL:
http://localhost:8080: This is the default address and port for Tomcat./hello-jakarta: This is the context root of your application. It’s derived from the name of your WAR file (hello-jakarta.war)./hello: This is the URL pattern we defined in ourHelloServletusing the@WebServlet("/hello")annotation.
Congratulations! You’ve just built and deployed your first Jakarta EE web application!
Mini-Challenge: Personalize Your Greeting
Let’s make our HelloServlet a bit more interactive.
Challenge: Modify the HelloServlet to greet the user by name if a name parameter is provided in the URL.
- If the URL is
http://localhost:8080/hello-jakarta/hello?name=Alice, it should display “Hello, Alice from Jakarta EE 11!”. - If no
nameparameter is provided (e.g.,http://localhost:8080/hello-jakarta/hello), it should default to “Hello from Jakarta EE 11!”.
Hint:
Inside your doGet method, you can retrieve request parameters using request.getParameter("parameterName"). This method returns a String or null if the parameter isn’t present.
What to Observe/Learn: This challenge will help you understand how Servlets can read input from HTTP requests, making your web applications dynamic and responsive to user input. It’s a fundamental step in building interactive web experiences.
Take your time, try to solve it on your own. If you get stuck, peek at the solution below!
Click here for a hint if you're stuck!
You'll want to check if the `name` parameter is `null` or empty after retrieving it. If it is, use a default greeting. Otherwise, use the provided name. Remember to recompile and redeploy your WAR file after making changes!Click here for the solution if you're really stuck!
package com.example.jakartaee;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String userName = request.getParameter("name"); // Get the 'name' parameter
String greetingName;
if (userName != null && !userName.trim().isEmpty()) {
greetingName = userName;
} else {
greetingName = "from Jakarta EE 11"; // Default if no name is provided
}
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Hello Jakarta!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Hello, " + greetingName + "!</h1>"); // Use the name here
out.println("<p>This is your first Jakarta Servlet.</p>");
out.println("</body>");
out.println("</html>");
out.close();
}
}
Remember to save the file, run mvn clean package, copy the new hello-jakarta.war to TOMCAT_HOME/webapps, and restart Tomcat!
Common Pitfalls & Troubleshooting
Working with Enterprise Java, especially when dealing with version transitions, can have its quirks. Here are a few common issues you might encounter:
javaxvs.jakartaPackage Mix-up:- Symptom: You see compilation errors like “package
javax.servletdoes not exist” or “cannot find symbolHttpServlet” even though you have a servlet API dependency. - Cause: You’re either using an older
javax.servletdependency in yourpom.xmlwhile your code usesjakarta.servletimports, or vice-versa. Or, you might have mixed imports in your Java file (somejavax, somejakarta). - Solution: For new Jakarta EE 11 projects, ensure all your imports for Enterprise Java APIs start with
jakarta.*and that yourpom.xmlexplicitly referencesjakarta.servlet:jakarta.servlet-api(version6.1.0for Jakarta EE 11). Double-check yourpom.xmland your Javaimportstatements.
- Symptom: You see compilation errors like “package
Servlet Not Found (404 Error) or “The requested resource is not available”:
- Symptom: You deploy your WAR file, start Tomcat, but when you navigate to the URL, you get a 404 error or a similar “resource not available” message.
- Cause 1: Incorrect URL Path. You might be typing the wrong URL. Remember the full path:
http://localhost:8080/<YOUR_APP_NAME>/<SERVLET_PATH>. The app name is usually your WAR file name without.war. - Cause 2: Missing
@WebServletannotation or incorrectweb.xml(if used). The application server doesn’t know which class should handle the request for that URL. - Cause 3: Deployment Issue. The WAR file wasn’t copied correctly, or Tomcat failed to deploy it. Check Tomcat’s logs (in
TOMCAT_HOME/logs) for deployment errors. - Solution:
- Verify your URL.
- Ensure your
HelloServlethas@WebServlet("/hello")and the path matches what you’re typing. - Check Tomcat logs for errors during startup or deployment.
Unsupported major.minor versionError:- Symptom: Tomcat starts, but when you access your application, you get an error in the logs or browser related to “unsupported major.minor version”.
- Cause: This usually means your Java code was compiled with a newer JDK version than the one Tomcat is running with. For example, if you compiled with JDK 25 but Tomcat is configured to use an older JDK 11.
- Solution: Ensure that the
JAVA_HOMEenvironment variable used by Tomcat (or thejavaexecutable in itsPATH) points to JDK 25 or a compatible version. You can check Tomcat’s startup logs for the Java version it’s using.
Summary
Phew! You’ve covered a lot in this chapter, and you’ve taken a significant leap into the world of Enterprise Java. Let’s quickly recap the key takeaways:
- Enterprise Java (Jakarta EE): It’s a suite of specifications and APIs built on Java SE, designed for building large-scale, distributed, and robust applications.
javaxtojakartaTransition: This is a crucial change! Modern Jakarta EE applications (Jakarta EE 9 and later, including our Jakarta EE 11 example) use thejakarta.*package namespace instead ofjavax.*.- Key Specifications: We briefly touched upon Servlets, JSPs, JAX-RS, CDI, and JPA as core components of Jakarta EE.
- Application Servers: These are runtime environments (like Apache Tomcat 11.0.x) that host and manage Jakarta EE applications.
- First Servlet: You successfully created, compiled, packaged, and deployed a simple “Hello, Jakarta!” web application using the Jakarta Servlet API and Maven with JDK 25. You learned how Servlets handle HTTP GET requests and generate responses.
This chapter has provided you with the foundational understanding and practical experience to begin your journey into Enterprise Java. You’re now equipped to understand the modern landscape and start exploring more complex Jakarta EE technologies.
What’s Next?
In upcoming chapters, we’ll build upon this foundation. We might explore:
- More Servlet capabilities: Handling POST requests, form processing, session management.
- Introduction to CDI: Learning about dependency injection to build more modular applications.
- JAX-RS: Building powerful RESTful web services that can communicate with other applications.
- Introduction to Spring Framework: While Jakarta EE is a standard, Spring is a dominant framework that often runs on top of or alongside Jakarta EE technologies, offering even more powerful tools and conventions for enterprise development.
Keep practicing, keep building, and stay curious! The enterprise world of Java is vast and rewarding.