HttpEntity<T> is a helper object which encapsulates header and body of an HTTP request or response. It can be used as a handler method parameter.
To get header and body information,the following methods are used:
public HttpHeaders getHeaders()
public T getBody()
The usage of HttpEntity is an alternative to using the two parameter: @RequestHeader HttpHeaders and @RequestBody String/backing type
HttpEntity can be used to return response as well. The additional advantage in this case, when comparing with @ResponseBody is, it can include the headers in the response as well.
Example
In the following example we are going to demonstrate the use of HttpEntity with JUnit tests.
Handling headers and body as String
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@Controller
@RequestMapping
public class MyController {
@PostMapping
public HttpEntity<String> handleRequest (HttpEntity<String> requestEntity) {
System.out.println("request body: " + requestEntity.getBody());
HttpHeaders headers = requestEntity.getHeaders();
System.out.println("request headers " + headers);
HttpEntity<String> responseEntity =
new HttpEntity<String>("my response body", headers);
return responseEntity;
}
.............
}
Unit Test
package com.logicbig.example;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import org.springframework.web.context.WebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitWebConfig(MyWebConfig.class)
public class ControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvcTester mockMvcTester;
@BeforeEach
public void setup() {
this.mockMvcTester = MockMvcTester.from(this.wac);
}
@Test
public void testController() {
assertThat(this.mockMvcTester.post().uri("/")
.header("testHeader",
"headerValue")
.content("test body")
.exchange())
.hasStatusOk()
.bodyText().isEqualTo("my response body");
assertThat(this.mockMvcTester.post().uri("/")
.header("testHeader",
"headerValue")
.content("test body")
.exchange())
.hasHeader("testHeader", "headerValue");
}
.............
}
mvn clean test -Dtest="ControllerTest#testController" Output$ mvn clean test -Dtest="ControllerTest#testController" [INFO] Scanning for projects... [WARNING] [WARNING] Some problems were encountered while building the effective model for com.logicbig.example:spring-http-entity:war:1.0-SNAPSHOT [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-war-plugin is missing. @ line 43, column 21 [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. [WARNING] [INFO] [INFO] --------------< com.logicbig.example:spring-http-entity >--------------- [INFO] Building spring-http-entity 1.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ war ]--------------------------------- [INFO] [INFO] --- clean:3.2.0:clean (default-clean) @ spring-http-entity --- [INFO] Deleting D:\example-projects\spring-mvc\spring-http-entity\target [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ spring-http-entity --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\example-projects\spring-mvc\spring-http-entity\src\main\resources [INFO] [INFO] --- compiler:3.5.1:compile (default-compile) @ spring-http-entity --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 4 source files to D:\example-projects\spring-mvc\spring-http-entity\target\classes [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ spring-http-entity --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\example-projects\spring-mvc\spring-http-entity\src\test\resources [INFO] [INFO] --- compiler:3.5.1:testCompile (default-testCompile) @ spring-http-entity --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to D:\example-projects\spring-mvc\spring-http-entity\target\test-classes [INFO] [INFO] --- surefire:3.2.5:test (default-test) @ spring-http-entity --- [INFO] Using auto detected provider org.apache.maven.surefire.junit4.JUnit4Provider [WARNING] file.encoding cannot be set as system property, use <argLine>-Dfile.encoding=...</argLine> instead [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running com.logicbig.example.ControllerTest request body: test body request headers {testHeader=[headerValue], Content-Length=[9]} [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.509 s -- in com.logicbig.example.ControllerTest [INFO] [INFO] Results: [INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 18.145 s [INFO] Finished at: 2026-07-26T20:05:10+08:00 [INFO] ------------------------------------------------------------------------
Using Backing/Command Object
package com.logicbig.example;
public class User {
private String name;
private String emailAddress;
.............
}
The Controller
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@Controller
@RequestMapping
public class MyController {
.............
@PostMapping("/user")
public HttpEntity<String> handleUserRequest (HttpEntity<User> requestEntity) {
User user = requestEntity.getBody();
System.out.println("request body: " + user);
System.out.println("request headers " + requestEntity.getHeaders());
HttpHeaders headers = new HttpHeaders();
headers.put("Cache-Control", Arrays.asList("max-age=3600"));
HttpEntity<String> responseEntity = new HttpEntity<>("user= "+user.getName(),
headers);
return responseEntity;
}
}
Unit Test
package com.logicbig.example;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import org.springframework.web.context.WebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitWebConfig(MyWebConfig.class)
public class ControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvcTester mockMvcTester;
@BeforeEach
public void setup() {
this.mockMvcTester = MockMvcTester.from(this.wac);
}
.............
@Test
public void testUserController() {
String userInJson = createUserInJson("joe",
"joe@example.com");
assertThat(this.mockMvcTester.post().uri("/user")
.header("testHeader",
"headerValue")
.contentType(MediaType.APPLICATION_JSON)
.content(userInJson)
.exchange())
.hasStatusOk()
.bodyText().isEqualTo("user= joe");
assertThat(this.mockMvcTester.post().uri("/user")
.header("testHeader",
"headerValue")
.contentType(MediaType.APPLICATION_JSON)
.content(userInJson)
.exchange())
.hasHeader("Cache-Control", "max-age=3600");
}
private static String createUserInJson(String name,
String email) {
return "{ \"name\": \"" + name + "\", " +
"\"emailAddress\":\"" + email + "\"}";
}
}
mvn clean test -Dtest="ControllerTest#testUserController" Output$ mvn clean test -Dtest="ControllerTest#testUserController" [INFO] Scanning for projects... [WARNING] [WARNING] Some problems were encountered while building the effective model for com.logicbig.example:spring-http-entity:war:1.0-SNAPSHOT [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-war-plugin is missing. @ line 43, column 21 [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. [WARNING] [INFO] [INFO] --------------< com.logicbig.example:spring-http-entity >--------------- [INFO] Building spring-http-entity 1.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ war ]--------------------------------- [INFO] [INFO] --- clean:3.2.0:clean (default-clean) @ spring-http-entity --- [INFO] Deleting D:\example-projects\spring-mvc\spring-http-entity\target [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ spring-http-entity --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\example-projects\spring-mvc\spring-http-entity\src\main\resources [INFO] [INFO] --- compiler:3.5.1:compile (default-compile) @ spring-http-entity --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 4 source files to D:\example-projects\spring-mvc\spring-http-entity\target\classes [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ spring-http-entity --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\example-projects\spring-mvc\spring-http-entity\src\test\resources [INFO] [INFO] --- compiler:3.5.1:testCompile (default-testCompile) @ spring-http-entity --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to D:\example-projects\spring-mvc\spring-http-entity\target\test-classes [INFO] [INFO] --- surefire:3.2.5:test (default-test) @ spring-http-entity --- [INFO] Using auto detected provider org.apache.maven.surefire.junit4.JUnit4Provider [WARNING] file.encoding cannot be set as system property, use <argLine>-Dfile.encoding=...</argLine> instead [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running com.logicbig.example.ControllerTest request body: User{name='joe', emailAddress='joe@example.com'} request headers {testHeader=[headerValue], Content-Type=[application/json], Content-Length=[50]} [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.354 s -- in com.logicbig.example.ControllerTest [INFO] [INFO] Results: [INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 15.366 s [INFO] Finished at: 2026-07-26T20:10:49+08:00 [INFO] ------------------------------------------------------------------------
Example ProjectDependencies and Technologies Used: - spring-webmvc 7.0.6 (Spring Web MVC)
Version Compatibility: 3.2.9.RELEASE - 7.0.6 Version compatibilities of spring-webmvc with this example: Versions in green have been tested.
- spring-test 7.0.6 (Spring TestContext Framework)
- jakarta.servlet-api 6.1.0 (Jakarta Servlet API documentation)
- junit-jupiter-engine 6.0.3 (Module "junit-jupiter-engine" of JUnit)
- jackson-databind 3.0.0 (General data-binding functionality for Jackson: works on core streaming API)
- hamcrest 3.0 (Core API and libraries of hamcrest matcher framework)
- assertj-core 3.26.3 (Rich and fluent assertions for testing in Java)
- JDK 25
- Maven 3.9.11
|