Getting started with Jakarta REST Services 4.0

In this article, we will provide an overview of the upcoming Jakarta RESTful Web Services 4.0 features. We will show how to test the latest version of this API on WildFly and how to run some examples with it.

What’s New in Jakarta REST 4.0: Key Features and Enhancements

The latest Jakarta REST 4.0 release brings a host of exciting updates, aimed at enhancing integration with Jakarta EE technologies and improving overall functionality. Here’s a concise look at the key features and changes:

  • Integration with Jakarta EE Technologies: Jakarta REST 4.0 removes the @ManagedBean annotation support, integrating managed bean support fully into Contexts and Dependency Injection (CDI).
  • Clarified Java SE Publishing: The update refines specifications to clarify when developers must support the two alternative ways of publishing on Java SE.
  • Code Clean-Up: The API simplifies by removing the inner classes Link.JaxbLink and Link.JaxbAdapter.
  • New Methods for Enhanced Control:
    • Added the containsHeaderString() method to ClientRequestContext, ClientResponseContext, ContainerRequestContext, ContainerResponseContext, and HttpHeaders, allowing for more precise header management.
    • Introduced the getMatchedResourceTemplates() method to UriInfo to improve resource matching capabilities.
  • New Media Types: The update introduces APPLICATION_MERGE_PATCH_JSON and APPLICATION_MERGE_PATCH_JSON_TYPE to MediaType, supporting the JSON Merge Patch format.

These updates provide developers with more robust tools and clearer guidelines, ensuring a smoother and more efficient development experience with Jakarta REST.

Preparing WildFly for Jakarta REST 4.0

Firstly, you need a WildFly version which includes support for Jakarta REST 4.0. At the time of writing, you can do that by provisioning a server distribution including the resteasy-7.0 channel which supports Jakarta REST 4.0:

<plugin>
    <groupId>org.wildfly.plugins</groupId>
    <artifactId>wildfly-maven-plugin</artifactId>
    <version>5.0.0.Final</version>
    <executions>
        <execution>
            <id>server-provisioning</id>
            <phase>generate-test-resources</phase>
            <goals>
                <goal>provision</goal>
            </goals>
            <configuration>
                <feature-packs>
                    <feature-pack>
                        <groupId>org.wildfly</groupId>
                        <artifactId>wildfly-ee-galleon-pack</artifactId>
                    </feature-pack>
                </feature-packs>
                <channels>
                    <channel>
                        <manifest>
                            <groupId>org.wildfly.channels</groupId>
                            <artifactId>wildfly-ee</artifactId>
                        </manifest>
                    </channel>
                    <channel>
                        <manifest>
                            <groupId>dev.resteasy.channels</groupId>
                            <artifactId>resteasy-7.0</artifactId>
                        </manifest>
                    </channel>
                </channels>
            </configuration>
        </execution>
    </executions>
</plugin>

You can read more details about configuring WildFly channels in this article: Custom WildFly distributions using Channels

Then, to be able to build your applications, you need to include the following dependency:

<dependency>
    <groupId>jakarta.ws.rs</groupId>
    <artifactId>jakarta.ws.rs-api</artifactId>
    <scope>provided</scope>
    <version>4.0.0</version>
</dependency>

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <scope>provided</scope>
    <version>4.0.0</version>
</dependency>

Testing Jakarta 4.0 REST new features

One of the addition of this new API is the containsHeaderString() method to which is now available to ClientRequestContext, ClientResponseContext, ContainerRequestContext, ContainerResponseContext, and HttpHeaders.

This method simplifies working with request and response headers, specifically focusing on headers containing comma-separated values.

Currently, checking for specific values within headers that can appear multiple times (like Cache-Control) is cumbersome. Developers often resort to:

  • Regular Expressions: This can be slow as it concatenates the entire header string before splitting it.
  • Iterating through all values: This can be tedious and not very readable.

The following method allows a simple check on the no-store HTTP Header. It returns true if its value is “no-store” (ignoring the case):

@GET
@Path("header")
@Produces("text/plain")
public boolean getHeaderString(@Context HttpHeaders headers) {
		 
     return headers.containsHeaderString("cache-control", ",", "no-store"::equalsIgnoreCase);
}

Therefore:

jakarta rest 4.0 tutorial

Another new feature of Jakarta REST API 4.0 is the getMatchedResourceTemplate() method. This method provides the path template used to handle the request.

Traditionally, developers might rely on ResourceInfo to get the resource class and method serving the request. They could then use reflection to analyze @Path annotations and construct the route template. This approach becomes unreliable when sub-resources are involved, as it doesn’t capture the complete path hierarchy.

For example, the following example will return a Response (the reg expression itself), given that the Path matches the regular expression "[a-zA-Z][a-zA-Z_0-9]*

@GET
@Path("{name:[a-zA-Z][a-zA-Z_0-9]*}")
public Response get(@Context UriInfo info) {
    return Response.ok(info.getMatchedResourceTemplate()).build();
}

Therefore:

jakarta rest 4.0 step-by-step guide

Finally, Jakarta REST 4.0 also adds the JSON Merge Patch Media Type which is a way to describe changes to a JSON document. It assumes an existing JSON document (the original) that needs modifications.

You define a separate JSON document (the patch) that outlines the changes. This patch document uses a structure similar to the original document, but it specifies the modifications to be made. When you “apply” the patch to the original document, a new, modified JSON document is created.
Unlike JSON Patch, which uses specific operations (add, remove, replace), JSON Merge Patch describes the desired outcome directly within the patch document.

Here is some sample pseudo-code to give you an idea of how APPLICATION_MERGE_PATCH_JSON works:

@Path("/items/{id}")
@Consumes(MediaType.APPLICATION_MERGE_PATCH_JSON)  
public class ItemResource {
	
	  @Inject
	  private ItemController itemController;
	
	  @PATCH
	  public Response updateItem(@PathParam("id") String id, String patch) {
		itemController.updateItem(id, patch);
		return Response.ok().build();
	  }
}

Conclusion

This article provides an overview of the new Jakarta REST API 4.0 features, part of the upcoming Jakarta EE 11 specification. As soon as the specification is fully available, we will combine these snippets in a full quickstart demo. Stay tuned!

References: https://jakarta.ee/specifications/restful-ws/4.0/jakarta-restful-ws-spec-4.0