HATEOAS – JAX-RS 2.0 UriInfo, UriBuilder and Link Examples

Learn to build JAX-RS 2.0 HATEOAS links in REST resources using it’s javax.ws.rs.core.Link, javax.ws.rs.core.UriBuilder and javax.ws.rs.core.UriInfo classes. RESTEasy 3.1.2.Final is used as reference implementation for JAX-RS 2.0.

To build HATEOAS links, I am modifying the sourcecode of RESTEasy 3.1.2.Final with Servlet 3.0 Example. Please refer to linked tutorial to learn how overall example is build.
Table of Contents

Usage of UriInfo, UriBuilder and Link Classes
Add Link.JaxbAdapter in model classes
Injecting links in resource representations
Demo

Usage of UriInfo, UriBuilder and Link Classes

HATEOAS structure itself is under discussions in lots of forums and different people suggest different approaches to build links in REST resource representations. JAX-RS 2.0 also does not have any direct support to build these links. Though you can use it’s helper classes to build the links, the way you want.

  1. javax.ws.rs.core.UriBuilder

    The UriBuilder class allows you to construct a URI step by step using builder pattern. The values can contain template parameters i.e. /resource/{id}. Here id is template parameter.

    The build() methods create the actual URI. Before building the URI, though, any template parameters you have defined must be filled in.

  2. javax.ws.rs.core.UriInfo

    Many times you will not know the base URI or relative URI where your resource will be present. In this case, you can use UriInfo class.

    UriInfo instances are pre-initialized with the base URI and the URI used to invoke the current HTTP request.

  3. javax.ws.rs.core.Link

    JAX-RS 2.0 introduces Link class, which serves as a representation of Web Link defined in RFC 5988. It helps in implementing HATEOAS using JAX-RS 2.0. It’s parameters such as rel or type provide additional meta-data about link.

Add Link.JaxbAdapter in model classes

To add a link in resource representation, you need to add Link element in model class.

Configurations.java

@XmlRootElement(name = "configurations")
@XmlAccessorType(XmlAccessType.FIELD)
public class Configurations 
{
	@XmlAttribute
	private Integer size;
	
	@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
	@XmlElement
	private Link link;
	
	@XmlElement
	private List<Configuration> configurations;

	//Getters and Setters are removed for limiting the text. Add them when running the code.

Configuration.java

@XmlRootElement(name="configuration")
@XmlAccessorType(XmlAccessType.FIELD)
public class Configuration 
{
	@XmlAttribute
	private Integer id;

	@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
	@XmlElement
	private Link link;

	@XmlElement
	private String content;

	@XmlElement
	private Status status;

	//Getters and Setters are removed for limiting the text. 
}

Link.JaxbAdapter is an implementation of JAXB XmlAdapter that maps the JAX-RS Link type to a value that can be marshalled and unmarshalled by JAXB.

Injecting HATEOAS links in resource representations

Now, you need to build and inject the links in these resource representations or model classes.

package net.restfulapi.app.rest.service;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import net.restfulapi.app.dao.ConfigurationDB;
import net.restfulapi.app.rest.domain.Configuration;
import net.restfulapi.app.rest.domain.Configurations;
import net.restfulapi.app.rest.domain.common.Status;

@Path("/configurations")
@Produces("application/xml")
public class ConfigurationResource 
{
	@Context 
	UriInfo uriInfo;
	
	@GET
	public Configurations getConfigurations() {
		
		List<Configuration> list = ConfigurationDB.getAllConfigurations();
		
		Configurations configurations = new Configurations();
		configurations.setConfigurations(list);
		configurations.setSize(list.size());
		
		//Set link for primary collection
		Link link = Link.fromUri(uriInfo.getPath()).rel("uri").build();
		configurations.setLink(link);
		
		//Set links in configuration items
		for(Configuration c: list){
			Link lnk = Link.fromUri(uriInfo.getPath() + "/" + c.getId()).rel("self").build();
			c.setLink(lnk);
		}
		return configurations;
	}
	
	@GET
	@Path("/{id}")
	public Configuration getConfigurationById(@PathParam("id") Integer id){
		Configuration config = ConfigurationDB.getConfiguration(id);
		
		if(config != null){
			UriBuilder builder = UriBuilder.fromResource(ConfigurationResource.class)
					.path(ConfigurationResource.class, "getConfigurationById");
			Link link = Link.fromUri(builder.build(id)).rel("self").build();
			config.setLink(link);
		}
		
		return config;
	}
	
	static {
		ConfigurationDB.createConfiguration("Some Content", Status.ACTIVE);
		ConfigurationDB.createConfiguration("Some More Content", Status.INACTIVE);
	}
}

Demo

Hit the URL: http://localhost:8080/NetworkManagement/network-management/configurations

JAX-RS HATEOAS Example - Primary Collection
JAX-RS HATEOAS Example – Primary Collection

Hit the URL: http://localhost:8080/NetworkManagement/network-management/configurations/1

JAX-RS HATEOAS Example - Single Collection Element
JAX-RS HATEOAS Example – Single Collection Element

Drop me your questions in comments section.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

1 thought on “HATEOAS – JAX-RS 2.0 UriInfo, UriBuilder and Link Examples”

  1. A bit late to the party. Anyways: Have you dealt with doing that with JSON? Because the XML attributes that are being serialized won’t be properly translated to a JSON representation, it seems to me.

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.