Skip to main content

This guide shows you how to use Jakarta EE to make a
RESTful web service.

To create a RESTful web service using Jakarta EE, we will begin by
summarizing what we want to build.

We will build a service that will accept an HTTP GET1
request at http://localhost:8080/restfulservice/hello.

It will respond with the following JSON payload, as the following listing
shows:

{"text": "Hello from Jakarta EE"}

We can then further customize and improve it according to our needs.

OK, now that we have specified our requirements, you will need to follow these
steps:

Set up your development environment:

  • Install a Java Development Kit (JDK). Please make sure you have Java SE 8 or
    higher (we have tested with Java SE 8, Java SE 11 and Java SE 17). You can
    choose any vendor distribution of your choice from Adoptium
    as well.
  • Install an application server that supports Jakarta EE. Download any of the
    Jakarta EE compatible products.
  • Install Maven 3 or higher.

To install all of these, we can use the SDKMan. We can go
through the steps mentioned in the how-to guide.

How to complete this guide

In this getting started guide, you may start using Eclipse Starter for Jakarta
EE, finish each step, or skip fundamental setup stages that you already know.
You can also begin with an IDE or choose a project structure from well-known
Maven archetypes.

Create a new project with Eclipse Starter for Jakarta EE

To use Eclipse Starter for Jakarta EE, we need to take the following steps:

  1. Navigate to start.jakarta.ee. This service will set up all the essential
    dependencies for an application. The current version of the Starter only
    supports Maven. In the future, we may be able to choose between Gradle and
    Maven.
    A screenshot of the Generate a Jakarta EE Project form with fields filled out. More details on how to go through the form below.
  2. Select the desired version of Jakarta EE from the available options. As of
    now, the options include Jakarta EE 8, Jakarta 9.1, and Jakarta 10. You may
    choose the Jakarta EE profile from Platform, Core, or Web. However, for most
    options, you may safely stick with the defaults.
  3. Then specify the Group, Artifact and Version for your new project.
  4. Once you have done this, the following box will let you copy a command. Copy
    the command, open your terminal, paste it, and run it.
mvn archetype:generate -DarchetypeGroupId=org.eclipse.starter -DarchetypeArtifactId=jakartaee10-minimal -DarchetypeVersion=1.1.0 -DgroupId=org.eclipse.rest -DartifactId=rest-service -Dprofile=web-api -Dversion=1.0.0-SNAPSHOT -DinteractiveMode=false

This will give us the project structure and sample code, which we can then
build and run.

Let’s explore the code structure

When we unpack the generated code, we will have the following code structure:

.
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── org
    │           └── eclipse
    │               └── restfulservice
    │                   ├── ApplicationConfig.java
    │                   └── resources
    │                       ├── Hellorecord.java
    │                       └── RestResource.java
    ├── resources
    │   └── META-INF
    │       └── beans.xml
    └── webapp

In this code structure, along with other classes and configurations, we are
interested in two classes in particular: RestResource.java and
HelloRecord.java.

Let’s open the RestResource.java file first.

package org.eclipse.restfulservice.resources;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;

@Path("hello")
public class RestResource {
    
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public HelloRecord hello(){
        return new HelloRecord("Hello from Jakarta EE");
    }
}

This defines a RESTful web service that returns a JSON representation of a
RestResource when a GET request is made to the "/hello" endpoint.

The jakarta.ws.rs.Path annotation establishes a connection between the URL
given by the user and the Java class responsible for handling the request. The
jakarta.ws.rs.GET annotation tells us we must use the HTTP GET method to
access our endpoint. The jakarta.ws.rs.Produces annotation allows you to
specify the format of the response. In our case, it will produce a
JSON2 response by converting the
object of HelloRecord.

The method hello() is defined to return a HelloRecord. This is the new
record class that was released in Java 16.

package org.eclipse.restfulservice.resources;

public record HelloRecord(String text) {
}

But if you use a lower version of Java, you can change it to a traditional
POJO3 .

package org.eclipse.restfulservice.resources;

public final class HelloRecord {
  private final String text;

  public HelloRecord(String text) {
    this.text = text;
  }

  public String text() {
    return text;
  }
}

Let’s run the project from the CLI

The project structure was generated without having a runtime associated with
it. The merit of it is that we can choose from a multitude of runtimes. A list
of compatible Jakarta EE can be found here.

We will use WildFly in this tutorial.

To do that, we need to add an additional plugin to the pom.xml file.

<plugin>
  <groupId>org.wildfly.plugins</groupId>
  <artifactId>wildfly-maven-plugin</artifactId>
  <version>2.1.0.Beta1</version>
  <executions>
    <execution>
      <phase>install</phase>
      <goals>
        <goal>deploy</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Include the above plugin in the plugins sections of the pom.xml.

The wildfly-maven-plugin is used to deploy, redeploy, undeploy or run the
Jakarta EE application. There is also the ability to execute CLI commands. The
whole configuration of this plugin can be found here:
WildFly Maven Plugin – Introduction.

There are multiple ways you can configure a local instance of WildFly. Some
configurations can be found here:
WildFly Maven Plugin – Run Example.

However, in this tutorial, we can leave all the configurations as they are, as
we will use the default, and that’s enough for us.

In particular, we are interested in wildfly:run CLI command. Let’s run the
following command from the command line:

mvn clean package wildfly:run

The command above will build the app and put it on Wildfly. If Wildfly is not
installed, it will download and run it, and then the war file will be deployed.

Once the application runs, we will get the following output in the terminal:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------in< org.eclipse:restfulservice >---------------------
[INFO] Building restfulservice 1.0.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
.....
skipped the log for brevity 
.....
03:35:02,323 INFO  [org.jboss.resteasy.resteasy_jaxrs.i18n] (ServerService Thread Pool -- 32) RESTEASY002225: Deploying jakarta.ws.rs.core.Application: class org.eclipse.restfulservice.ApplicationConfig
03:35:02,346 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 32) WFLYUT0021: Registered web context: '/restfulservice' for server 'default-server'
03:35:02,365 INFO  [org.jboss.as.server] (management-handler-thread - 1) WFLYSRV0010: Deployed "restfulservice.war" (runtime-name : "restfulservice.war")

Let’s test the Service

Now that the service is running let’s visit http://localhost:8080/restfulservice/hello.
It should return:

{ "text": "Hello from Jakarta EE" }

Alternatively, we can curl from the command line:

curl -v http://localhost:8080/restfulservice/hello

*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /restfulservice/hello HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.86.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: application/json
< Content-Length: 32
< Date: Sun, 18 Dec 2022 08:45:51 GMT
<
* Connection #0 to host localhost left intact
{"text":"Hello from Jakarta EE"}%      

Let us have a look at the URL structure.

http://<hostname>:<port>/<context-root>/<REST-config>/<resource-config>

Let’s unpack the URL pattern here:

Hostname: the name of the machine on which WildFly Server is installed.

Port: The WildFly Server’s listening port for incoming HTTP requests. This is
port 8080 by default, but it can be configured.

Context-root: The context root to which the deployed application has been
assigned. By default, this is the filename (without the extension) of the WAR
file that is being deployed. But it can be changed when the file is being
deployed.

REST-config: The value we have defined for the @ApplicationPath
annotation in our project. By default, it is empty, which is indicated simply
by /. We can easily configure it in our ApplicationConfig class.

Resource-config: the value defined in the @Path annotation on the Java
class defines an endpoint. In our case, "/hello" is handled by the
RestResource class.

If we want to change the REST-config part, for example, to "/api", we can
change the value in the @ApplicationPath annotation like this:

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("/api")
public class ApplicationConfig extends Application {    
}

After making this change, if we run again, we have to change the curl command
to consume the service as follows:

curl -v http://localhost:8080/restfulservice/api/hello

Conclusion

Congratulations! You have just learned how to develop a RESTful web service
using Jakarta EE.


  1. HTTP GET is a request method supported by HTTP used by the World Wide Web. It requests a representation of the specified resource. Its general form is: GET /path/to/resource HTTP/1.1
  2. JSON - It stands for JavaScript Object Notation. JSON is a text format for storing and transporting data
  3. POJO - Plain Old Java Object