Open In App

Spring MVC – Content Negotiation

Last Updated : 05 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Content Negotiation is a mechanism in the Spring MVC Pattern. The Spring MVC is a Java Framework that is used for developing web applications it is built on a Model-View-Controller pattern and it provides all the basic features of Spring Boot. Like Dependency Injection, Inversion of Control, and other features. Content Negotiation is one of the mechanisms which is available in Spring MVC.

It can allow the client or user to specify the desired response format, and this can be possible using HTTP Request and Spring MVC will return a response in specified format. The content Negotiation mechanism is flexible and user-friendly while receiving information through HTTP. Through this Content Negotiation mechanism, we can handle the data in the format of JSON and XML data format. Through the article, we will learn how Content Negotiation is working in Spring MVC with examples for better understanding.

Different ways to configure Content Negotiation in Spring MVC

There are three different ways to configure content negotiation in Spring MVC those are:

  • Using URL suffixes
  • Using a URL parameter
  • Using the Accept header

Prerequisites

  • Spring Tools Suite for development
  • Basic Knowledge of Spring MVC pattern functionality
  • Basic Knowledge of APIs
  • Knowledge in Spring Boot Application Development
  • Knowledge of HTTP Basics
  • Basic Knowledge of Request Mapping in Spring Boot

These things you should know to understand this Content Negotiation Mechanism functionality in Spring MVC. Otherwise, it will be a little bit difficult to understand.

Project Creation

  • Create a Spring Stater Project with required dependencies.
  • After that create one controller class in the main package of the project In that develop the required logic. No need to worry about this I will explain it below.
  • Now Created one POJO class in main package of the project for handling the user details with Setters and Getters methods.
  • Once complete the development of required logic. After that Run this project as Spring Boot App.

Project Dependencies:

dependencies {

implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.16.1'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

Note: jackson-core is available in maven repository website not available in spring boot stater.

Project Folder Structure:
Project Structure

Now we will start development of types of strategies in Spring MVC for developing Content Negotiation Mechanism first we will start with URL suffixes after that URL parameter after that Accept header.

User POJO Class

The User POJO class is common for Content Negotiation Strategies This POJO class is used for Setting and Getting data by using Setters and Getters methods in POJO class. And It provides encapsulation to the data while data transformation.

Java




package com.gfg.articles;
  
public class User {
    private Long id;
    private String name;
    private String email;
  
    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;
    }
  
    public String getEmail() {
        return email;
    }
  
    public void setEmail(String email) {
        this.email = email;
    }
  
    public User(Long id, String name, String email) {
        super();
        this.id = id;
        this.name = name;
        this.email = email;
    }
  
    public User() {
        super();
    }
  
}


In other way also we can develop this pojo class by using lombok dependency in spring boot. We will provide that alternative way code in the below.

Java




package com.gfg.articles;
  
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
  
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private String email;
}


@Data, @AllArgsConstructor, @NoArgsConstructor these annotations are used for managing the Setters and Getters methods as well as also manage default and parameterized constructors.

URL Suffixes Strategy

It is one of the Strategy in Spring MVC for developing the Content Negotiation Mechanism. In this URL Suffixes we take url suffix value to validate the format of the data through HTTP Request. Actually, we can do this in two different data formats namely JSON and XML. In this Article we will learn JSON data format in all strategies. Now we will give the controller code for this URL Suffixes Strategy.

API Syntax:

http://localhost:8080/user/id.json

UserController.java:

Java




package com.gfg.articles;
  
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
  
@RestController
public class UserController{
  
    private static final Map<Long, User> userMap = new HashMap<>();
  
    // Dummy data for demonstration
    static {
        userMap.put(1L, new User(1L, "John Doe", "john.doe@example.com"));
        userMap.put(2L, new User(2L, "Jane Smith", "jane.smith@example.com"));
        userMap.put(3L, new User(3L, "Alice Johnson", "alice.johnson@example.com"));
        userMap.put(4L, new User(4L, "Bob Anderson", "bob.anderson@example.com"));
        userMap.put(5L, new User(5L, "Eva Williams", "eva.williams@example.com"));
    }
  
    @GetMapping(value = "/user/{id}.{format}")
    public ResponseEntity<User> getEmployeeById(@PathVariable long id, @PathVariable String format) {
  
        User user = userMap.get(id);
  
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
  
        if ("json".equalsIgnoreCase(format)) {
            return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
        } else {
            // Handle unsupported format
            return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).build();
        }
    }
}


In the above code, we have taken 5 persons dummy data for testing the logic. After that we have created one HTTP GET mapping,this is the API endpoint in that GET mapping we have provided this value = “/user/{id}.{format}” it can check the suffix of the URL of HTTP in url section. If the given API url have json as suffix then The logic validate the data request format. Once it is valid then user data will displayed on the HTML page This entire process is done by findbyid in this logic.

Users Dummy Data:

static {
userMap.put(1L, new User(1L, "John Doe", "john.doe@example.com"));
userMap.put(2L, new User(2L, "Jane Smith", "jane.smith@example.com"));
userMap.put(3L, new User(3L, "Alice Johnson", "alice.johnson@example.com"));
userMap.put(4L, new User(4L, "Bob Anderson", "bob.anderson@example.com"));
userMap.put(5L, new User(5L, "Eva Williams", "eva.williams@example.com"));
}

After this we develop logic of URL Suffixes Strategy within GET URL Mapping the UserController java class.

Java




@GetMapping(value = "/user/{id}.{format}")
    public ResponseEntity<User> getEmployeeById(@PathVariable long id, @PathVariable String format) {
  
        User user = userMap.get(id);
  
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
  
        if ("json".equalsIgnoreCase(format)) {
            return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
        } else {
            // Handle unsupported format
            return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).build();
        }
    }


This GET mapping is used for getting data by using find by id with URL Suffix method. And we will show output also for better understanding the concept. After running the application then I got output like this,

API URL:

http://localhost:8080/user/2.json

You can observe in above API URL we 2.json means we requested the API in the form of JSON. if you remove that json suffix we got an error.

Output:

With suffix as json in API URL with id:

suffix_json

We have already data of id 2. You can observe in users dummy data section for conformation.

Without suffix as json in API URL with id:
Without json suffix error

After hitting the API URL without JSON as Suffix URL, we got error like this. Means when we hit this url the back-end logic checks the requested data format of API request. If Request format is valid then we got data otherwise we got error as output.

URL Parameter Strategy

The URL parameter is another strategy in Spring MVC for Developing Content Negotiation Mechanism. In this strategy we provide type of the data format in form of parameter. If you don’t provide any any type also it given output. But we need follow the format for better understanding the concept. We will provide the syntax for it.

API Syntax:

http://localhost:8080/user/id?mediaType=json

In above syntax in place of is provide existing id then you the data which is related to that given id. Otherwise, it will show bad request like this id is not exist like that. Now we will provide the controller code below.

Java




package com.gfg.articles;
  
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
  
import java.util.HashMap;
import java.util.Map;
  
@RestController
public class UserController {
  
    private static final Map<Long, User> userMap = new HashMap<>();
  
    static {
        userMap.put(1L, new User(1L, "John Doe", "john.doe@example.com"));
        userMap.put(2L, new User(2L, "Jane Smith", "jane.smith@example.com"));
        userMap.put(3L, new User(3L, "Alice Johnson", "alice.johnson@example.com"));
        userMap.put(4L, new User(4L, "Bob Anderson", "bob.anderson@example.com"));
        userMap.put(5L, new User(5L, "Eva Williams", "eva.williams@example.com"));
    }
  
    @GetMapping(value = "/user/{id}", produces = { MediaType.APPLICATION_JSON_VALUE })
    public ResponseEntity<User> getEmployeeById(@PathVariable long id) {
        User user = userMap.get(id);
  
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
  
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
    }
}


For testing purpose, 5 users dummy data we have mentioned that data for better understanding the concept.

static {
userMap.put(1L, new User(1L, "John Doe", "john.doe@example.com"));
userMap.put(2L, new User(2L, "Jane Smith", "jane.smith@example.com"));
userMap.put(3L, new User(3L, "Alice Johnson", "alice.johnson@example.com"));
userMap.put(4L, new User(4L, "Bob Anderson", "bob.anderson@example.com"));
userMap.put(5L, new User(5L, "Eva Williams", "eva.williams@example.com"));
}

After this we have created one GET mapping for handling the URL parameter strategy. This handler logic can able check if the given request format is belonging to URL parameter strategy or not. If the requested format is valid then return the user data based on given otherwise It will shoe an error message.

URL parameter Handler:

Java




@GetMapping(value = "/user/{id}", produces = { MediaType.APPLICATION_JSON_VALUE, 
                                              MediaType.APPLICATION_XML_VALUE })
    public ResponseEntity<User> getEmployeeById(@PathVariable long id,
            @RequestHeader(name = "Accept", defaultValue = "application/json"
                                                String acceptHeader) {
  
        User user = userMap.get(id);
  
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
  
        if (acceptHeader.contains(MediaType.APPLICATION_JSON_VALUE)) {
            return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
        }
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
    }


This Handler code can able to check weather the requested url format is correct or wrong. If correct we get user data otherwise It will return an error message.

Output:

With correct URL parameter strategy:

URL Parameter

With Non-Existing User ID URL parameter strategy:

Non Existing User ID

Here we have provided id 102 which is not exist in user data, that’s why it shows an error message.

Accept Header Strategy

This another approach for developing Content Negotiation Mechanism in Spring MVC. In this Accept Header Strategy approach, we can provide user id as header as a accept. If the given id is existed, then return the user data otherwise it will give an error message. For this we have taken five users dummy data which is already mentioned in above. Again, same data we have used here.

UserController.java:

Java




package com.gfg.articles;
  
import java.util.HashMap;
import java.util.Map;
  
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
  
@RestController
public class UserController {
  
    private static final Map<Long, User> userMap = new HashMap<>();
  
    static {
        userMap.put(1L, new User(1L, "John Doe", "john.doe@example.com"));
        userMap.put(2L, new User(2L, "Jane Smith", "jane.smith@example.com"));
        userMap.put(3L, new User(3L, "Alice Johnson", "alice.johnson@example.com"));
        userMap.put(4L, new User(4L, "Bob Anderson", "bob.anderson@example.com"));
        userMap.put(5L, new User(5L, "Eva Williams", "eva.williams@example.com"));
    }
  
    @GetMapping(value = "/user/{id}", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
    public ResponseEntity<User> getEmployeeById(@PathVariable long id,
            @RequestHeader(name = "Accept", defaultValue = "application/json") String acceptHeader) {
  
        User user = userMap.get(id);
  
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
  
        if (acceptHeader.contains(MediaType.APPLICATION_JSON_VALUE)) {
            return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
        }
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
    }
}


For Handling Accept Header logic here I created one GET mapping end point. In that mapping I check the give data format is correct or not. If correct fetch the user data by using id. Otherwise It will an error.

Accept Header Handler:

Java




@GetMapping(value = "/user/{id}", produces = { MediaType.APPLICATION_JSON_VALUE,
                                              MediaType.APPLICATION_XML_VALUE })
    public ResponseEntity<User> getEmployeeById(@PathVariable long id,
            @RequestHeader(name = "Accept", defaultValue = "application/json"
                                                String acceptHeader) {
  
        User user = userMap.get(id);
  
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
  
        if (acceptHeader.contains(MediaType.APPLICATION_JSON_VALUE)) {
            return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
        }
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
    }


After running this application we get output as mentioned below.

Output of JSON Body:
Output Screen

Conclusion

Content Negotiation is one of the mechanisms in Spring MVC for handling the API request data format. The data format may be xml or json format. For Developing Content Negotiation mechanism in Spring MVC we have three different approaches. Which are handle the API request in different formats. This Content Negotiation is providing security for API URL Paths like If you send request in the form of unknown API request format, then this Content Negotiation mechanism will be able to check request format. If it is valid request format, then fetch data if exist. Otherwise, It will an error page. You can observe those error pages in above sections.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads