Consume Spring HATEOAS Rest API using JQuery Ajax example | Spring Boot

Consume Spring HATEOAS Rest API using JQuery Ajax example _ Spring Boot

In this tutorial, JavaSampleApproach shows you a Spring Boot example that consumes Spring HATEOAS Rest API using JQuery Ajax.

Related Post: Spring HATEOAS Rest API + JQuery Ajax POST/GET example | Spring Boot

I. Overview

1. Goal

We’ll build a Spring Boot Application in that:
HATEOAS REST Service provides interface for interacting with Customer Database.
– Client calls API by using JQuery Ajax GET, retrieves and displays:
+ Customer Data (Id, Name) with HATEOAS Links by CustomerId.
+ Order Data for Customer above.

2. Technology

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.4.RELEASE
– Spring Boot: 1.5.4.RELEASE

3. Project Structure

consume-spring-hateoas-ajax-structure

HATEOAS REST Service:
+ Customer class extends Spring HATEOAS ResourceSupport.
+ CustomerRepository provides repository methods and custom finder methods for CustomerController to interact with Customer database.
+ CustomerController is a REST Controller which has request mapping methods for RESTful requests such as:
/{id}, /{id}/orders, /getcustomer/{id}
+ Response class defines structure for returned data of HTTP GET.

For more details about creating HATEOAS REST Service, please visit:
How to start Spring HATEOAS RestAPI with Spring Boot

JQuery Ajax:
+ home.jsp contains elements for GET request and display results.
+ ajax() GET methods in get.js Javascript file.
+ WebController maps url to home.jsp page.

For more simple example about JQuery Ajax POST/GET, please visit:
How to integrate JQuery Ajax POST/GET & Spring MVC | Spring Boot

– Configuration for JSP page and static resources in application.properties
– Dependencies for Spring HATEOAS, WEB MVC, Tomcat in pom.xml

To know how to make application work with JSP page and static resources, please visit:
How to start with JSP page and static resource in Spring Boot

II. Practice

1. Create Spring Boot project

– Using Spring Tool Suite/Eclipse to create Project (WAR packaging), ServletInitializer and SpringBootApplication class will be created automatically.
– Add Dependencies to pom.xml file:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-tomcat</artifactId>
	<scope>provided</scope>
</dependency>

<dependency>
	<groupId>org.apache.tomcat.embed</groupId>
	<artifactId>tomcat-embed-jasper</artifactId>
	<scope>provided</scope>
</dependency>

2. Create Data Model Classes


package com.javasampleapproach.consumehateoas.model;

public class Order {

	private Long id;
	private String name;

	public Order(Long id, String name) {
		this.id = id;
		this.name = name;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

package com.javasampleapproach.consumehateoas.model;

import java.util.ArrayList;
import java.util.List;

import org.springframework.hateoas.ResourceSupport;

public class Customer extends ResourceSupport {

	private Long customerId;
	private String name;

	private List orders;

	public Customer() {
	}

	public Customer(Long customerId, String name, ArrayList orders) {
		this.customerId = customerId;
		this.name = name;
		this.orders = new ArrayList(orders);
	}

	public Long getCustomerId() {
		return customerId;
	}

	public void setCustomerId(Long customerId) {
		this.customerId = customerId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List getOrders() {
		return orders;
	}

	public void setOrders(List orders) {
		this.orders = orders;
	}

}

3. Create Message Model Class


package com.javasampleapproach.consumehateoas.message;

public class Response {
	private String status;
	private Object data;

	public Response() {

	}

	public Response(String status, Object data) {
		this.status = status;
		this.data = data;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}
}

4. Create Repository Class


package com.javasampleapproach.consumehateoas.repo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.stereotype.Repository;

import com.javasampleapproach.consumehateoas.model.Customer;
import com.javasampleapproach.consumehateoas.model.Order;

@Repository
public class CustomerRepository {

	private final List customers = new ArrayList<>();

	public CustomerRepository() {
		this.customers.add(new Customer(1L, "Jack",
				new ArrayList(Arrays.asList(new Order(1L, "SmartPhone A"), new Order(2L, "Tablet B")))));
		this.customers.add(new Customer(2L, "Adam",
				new ArrayList(Arrays.asList(new Order(3L, "SmartPhone C"), new Order(4L, "Tablet D")))));
		this.customers.add(new Customer(3L, "Kim",
				new ArrayList(Arrays.asList(new Order(5L, "SmartPhone E"), new Order(6L, "Tablet F")))));
	}

	public List findAll() {
		return this.customers;
	}

	public Customer findOne(Long id) {

		for (Customer customer : this.customers) {
			if (customer.getCustomerId().equals(id)) {
				return customer;
			}
		}
		return null;
	}
}

5. Create Controller Classes


package com.javasampleapproach.consumehateoas.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.javasampleapproach.consumehateoas.message.Response;
import com.javasampleapproach.consumehateoas.model.Customer;
import com.javasampleapproach.consumehateoas.model.Order;
import com.javasampleapproach.consumehateoas.repo.CustomerRepository;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;

import java.util.List;

@RestController
public class CustomerController {

	@Autowired
	private CustomerRepository repository;

	@RequestMapping(path = "/{id}")
	public Response getCustomerById(@PathVariable Long id) {

		Customer customer = this.repository.findOne(id);
		
		Response response = new Response("Done", customer);
		return response;
	}

	@RequestMapping(path = "/{id}/orders")
	public Response getOrdersForCustomer(@PathVariable Long id) {

		List orders = this.repository.findOne(id).getOrders();
		
		Response response = new Response("Done", orders);
		return response;
	}

	@RequestMapping(value = "/getcustomer/{id}", method = RequestMethod.GET)
	public Response getResource(@PathVariable Long id) {

		Customer customer = this.repository.findOne(id);
		
		customer.removeLinks();
		customer.add(linkTo(CustomerController.class).slash(customer.getCustomerId()).withSelfRel());
		customer.add(linkTo(methodOn(CustomerController.class).getOrdersForCustomer(customer.getCustomerId()))
				.withRel("allOrders"));

		Response response = new Response("Done", customer);
		return response;
	}
}

package com.javasampleapproach.consumehateoas.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class WebController {

	@RequestMapping("/")
	ModelAndView home(ModelAndView modelAndView) {

		modelAndView.setViewName("home");

		return modelAndView;
	}
}

6. Configuration for JSP Page and Static Resources

Add these lines to application.properties file:


spring.mvc.view.prefix = /WEB-INF/jsps/
spring.mvc.view.suffix = .jsp

7. Add JSP Page and Javascript File

Under src/main/webapp/WEB-INF/jsps folder, add:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
	<title>Spring Boot HATEOAS - POST-GET AJAX Example</title>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<meta name="viewport" content="width=device-width, initial-scale=1" />
	<script	src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
	<script src="/js/get.js"></script>
	<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" />
</head>
<body>
	<div class="container">
		<h1>AJAX - consume HATEOAS</h1>      
	    <div id="getdiv" class="row">
	        <label>Customer ID</label>
	        <input type="text" id="customerid_get" class="form-control" style="width:100px;"/>
	        <br/>
	        <button id="getBtn">Get Customer</button>
	    </div>
	    <div id="getCustomerResultDiv" class="row"></div>
	    <div id="getOrderResultDiv" class="row">
	    	<h2 id="order-title"></h2>
	    	<ul class="list-group"></ul>
	    </div>
	    
	</div>
</body>
</html>

Under src/main/webapp/js folder, add:


$( document ).ready(function() {
	
	var url = window.location;
	
	// GET REQUEST
	$("#getBtn").click(function(event){
		event.preventDefault();
		ajaxGet();
	});
	
	// DO GET
	function ajaxGet(){
		
    	var customerId = $("#customerid_get").val();
    	var links;
		
		$.ajax({
			type : "GET",
			url : url + "getcustomer/" + customerId,
			success: function(result){
				if(result.status == "Done"){
					console.log("url: ", url);
					links = result.data.links;
					
					$.ajax({
						type : "GET",
						url : links[0].href,
						success: function(result1){
							if(result1.status == "Done"){
								
								$("#getCustomerResultDiv").html(
										"

Customer Information

" + "" + "Customer: ID = " + result1.data.customerId + " , " + "Name = " + result1.data.name + "" + "
" ); $.each(links, function(i, link){ var _link = result1.data.links[i].rel + ": " + result1.data.links[i].href + "
"; $("#getCustomerResultDiv").append(_link) }); console.log("Customer Information Success: ", result1); } else { $("#getCustomerResultDiv").html("Error"); console.log("Fail: ", result1); } }, error : function(e) { $("#getCustomerResultDiv").html("Error"); console.log("ERROR: ", e); } }); $.ajax({ type : "GET", url : links[1].href, success: function(result2){ if(result2.status == "Done"){ $("#order-title").html("Order Information"); $('#getOrderResultDiv .list-group').empty(); $.each(result2.data, function(i, order){ var _order = "Order " + i + ":
ID = " + order.id + "
Name = " + order.name; $('#getOrderResultDiv .list-group').append('
  • '+ _order +'

  • ') }); } else { $("#getOrderResultDiv").html("Error"); console.log("Fail: ", result2); } console.log("Order Information Success: ", result2); }, error : function(e) { $("#getCustomerResultDiv").html("Error"); console.log("ERROR: ", e); } }); } else { $("#getResultDiv").html("Error"); console.log("Fail: ", result); } }, error : function(e) { $("#getResultDiv").html("Error"); console.log("ERROR: ", e); } }); } })

    8. Run & Check Result

    – Config maven build:
    clean install
    – Run project with mode Spring Boot App.
    – Open Browser, enter URL:
    http://localhost:8080/
    consume-spring-hateoas-ajax-request

    – Fill customerID & press Get Customer button.
    Customer information with Links and Order Information will appear:
    consume-spring-hateoas-ajax-result

    III. Source Code

    SpringBootAjaxConsumeHATEOAS

    One thought on “Consume Spring HATEOAS Rest API using JQuery Ajax example | Spring Boot”

    1. Hi,
      I have follow your tutorial,
      but the result is always showing

      Whitelabel Error Page

      This application has no explicit mapping for /error, so you are seeing this as a fallback.
      Tue Apr 03 14:12:01 ICT 2018
      There was an unexpected error (type=Not Found, status=404).
      No message available

      please I need your advice
      Thank you

    Leave a Reply

    Your email address will not be published. Required fields are marked *