commit
84423082e2
@ -16,4 +16,5 @@ This module contains articles about core Spring functionality
|
||||
- [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations)
|
||||
- [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class)
|
||||
- [Guide to the Spring BeanFactory](https://www.baeldung.com/spring-beanfactory)
|
||||
- More articles: [[<-- prev]](/spring-core)
|
||||
- [Read HttpServletRequest Multiple Times](https://www.baeldung.com/spring-reading-httpservletrequest-multiple-times)
|
||||
- More articles: [[<-- prev]](/spring-core)
|
@ -0,0 +1,37 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
|
||||
|
||||
private byte[] cachedBody;
|
||||
|
||||
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
|
||||
super(request);
|
||||
InputStream requestInputStream = request.getInputStream();
|
||||
this.cachedBody = StreamUtils.copyToByteArray(requestInputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
return new CachedBodyServletInputStream(this.cachedBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
// Create a reader from cachedContent
|
||||
// and return it
|
||||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody);
|
||||
return new BufferedReader(new InputStreamReader(byteArrayInputStream));
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
|
||||
public class CachedBodyServletInputStream extends ServletInputStream {
|
||||
|
||||
private InputStream cachedBodyInputStream;
|
||||
|
||||
public CachedBodyServletInputStream(byte[] cachedBody) {
|
||||
this.cachedBodyInputStream = new ByteArrayInputStream(cachedBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
try {
|
||||
return cachedBodyInputStream.available() == 0;
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return cachedBodyInputStream.read();
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@Order(value = Ordered.HIGHEST_PRECEDENCE)
|
||||
@Component
|
||||
@WebFilter(filterName = "ContentCachingFilter", urlPatterns = "/*")
|
||||
public class ContentCachingFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
|
||||
System.out.println("IN ContentCachingFilter ");
|
||||
CachedBodyHttpServletRequest cachedBodyHttpServletRequest = new CachedBodyHttpServletRequest(httpServletRequest);
|
||||
filterChain.doFilter(cachedBodyHttpServletRequest, httpServletResponse);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
/**
|
||||
* To initialize the WebApplication, Please see
|
||||
* {@link org.baeldung.spring.config.MainWebAppInitializer}
|
||||
*/
|
||||
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = "org.baeldung.cachedrequest")
|
||||
public class HttpRequestDemoConfig implements WebMvcConfigurer {
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
public class Person {
|
||||
private String firstName;
|
||||
|
||||
private String lastName;
|
||||
|
||||
private int age;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String firstName, String lastName, int age) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", age=" + age + '}';
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class PersonController {
|
||||
|
||||
@PostMapping(value = "/person")
|
||||
@ResponseStatus(value = HttpStatus.NO_CONTENT)
|
||||
public void printPerson(@RequestBody Person person) {
|
||||
|
||||
System.out.println("In Demo Controller. Person " + "is : " + person);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/person")
|
||||
@ResponseStatus(value = HttpStatus.NO_CONTENT)
|
||||
public void getPerson() {
|
||||
|
||||
System.out.println("In Demo Controller get method.");
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
@Component
|
||||
@WebFilter(filterName = "printRequestContentFilter", urlPatterns = "/*")
|
||||
public class PrintRequestContentFilter extends OncePerRequestFilter {
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
|
||||
System.out.println("IN PrintRequestContentFilter ");
|
||||
InputStream inputStream = httpServletRequest.getInputStream();
|
||||
byte[] body = StreamUtils.copyToByteArray(inputStream);
|
||||
System.out.println("In PrintRequestContentFilter. Request body is: " + new String(body));
|
||||
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CachedBodyHttpServletRequestUnitTest extends TestCase {
|
||||
|
||||
private CachedBodyServletInputStream servletInputStream;
|
||||
|
||||
@After
|
||||
public void cleanUp() throws IOException {
|
||||
if (null != servletInputStream) {
|
||||
servletInputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGivenHttpServletRequestWithBody_whenCalledGetInputStream_ThenGetsServletInputStreamWithSameBody() throws IOException {
|
||||
// Given
|
||||
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||
MockHttpServletRequest mockeddHttpServletRequest = new MockHttpServletRequest();
|
||||
mockeddHttpServletRequest.setContent(cachedBody);
|
||||
CachedBodyHttpServletRequest request = new CachedBodyHttpServletRequest(mockeddHttpServletRequest);
|
||||
|
||||
// when
|
||||
InputStream inputStream = request.getInputStream();
|
||||
|
||||
// then
|
||||
assertEquals(new String(cachedBody), new String(StreamUtils.copyToByteArray(inputStream)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGivenHttpServletRequestWithBody_whenCalledGetReader_ThenGetBufferedReaderWithSameBody() throws IOException {
|
||||
// Given
|
||||
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||
MockHttpServletRequest mockeddHttpServletRequest = new MockHttpServletRequest();
|
||||
mockeddHttpServletRequest.setContent(cachedBody);
|
||||
CachedBodyHttpServletRequest request = new CachedBodyHttpServletRequest(mockeddHttpServletRequest);
|
||||
|
||||
// when
|
||||
BufferedReader bufferedReader = request.getReader();
|
||||
|
||||
// then
|
||||
String line = "";
|
||||
StringBuilder builder = new StringBuilder();
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
assertEquals(new String(cachedBody), builder.toString());
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CachedBodyServletInputStreamUnitTest extends TestCase {
|
||||
|
||||
private CachedBodyServletInputStream servletInputStream;
|
||||
|
||||
@After
|
||||
public void cleanUp() throws IOException {
|
||||
if (null != servletInputStream) {
|
||||
servletInputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGivenServletInputStreamCreated_whenCalledisFinished_Thenfalse() {
|
||||
// Given
|
||||
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||
|
||||
// when
|
||||
boolean finished = servletInputStream.isFinished();
|
||||
|
||||
// then
|
||||
assertFalse(finished);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGivenServletInputStreamCreatedAndBodyRead_whenCalledisFinished_ThenTrue() throws IOException {
|
||||
// Given
|
||||
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||
StreamUtils.copyToByteArray(servletInputStream);
|
||||
|
||||
// when
|
||||
boolean finished = servletInputStream.isFinished();
|
||||
|
||||
// then
|
||||
assertTrue(finished);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGivenServletInputStreamCreatedAndBodyRead_whenCalledIsReady_ThenTrue() throws IOException {
|
||||
// Given
|
||||
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||
|
||||
// when
|
||||
boolean ready = servletInputStream.isReady();
|
||||
|
||||
// then
|
||||
assertTrue(ready);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGivenServletInputStreamCreated_whenCalledIsRead_ThenReturnsBody() throws IOException {
|
||||
// Given
|
||||
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||
|
||||
// when
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
int len = 0;
|
||||
byte[] buffer = new byte[1024];
|
||||
while ((len = servletInputStream.read(buffer)) != -1) {
|
||||
byteArrayOutputStream.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
// then
|
||||
assertEquals(new String(cachedBody), new String(byteArrayOutputStream.toByteArray()));
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testGivenServletInputStreamCreated_whenCalledIsRead_ThenThrowsException() throws IOException {
|
||||
// Given
|
||||
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||
|
||||
// when
|
||||
servletInputStream.setReadListener(Mockito.mock(ReadListener.class));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ContentCachingFilterUnitTest extends TestCase {
|
||||
|
||||
@InjectMocks
|
||||
private ContentCachingFilter filterToTest;
|
||||
|
||||
@Test
|
||||
public void testGivenHttpRequest_WhenDoFilter_thenCreatesRequestWrapperObject() throws IOException, ServletException {
|
||||
// Given
|
||||
MockHttpServletRequest mockedRequest = new MockHttpServletRequest();
|
||||
MockHttpServletResponse mockedResponse = new MockHttpServletResponse();
|
||||
FilterChain mockedFilterChain = Mockito.mock(FilterChain.class);
|
||||
|
||||
// when
|
||||
filterToTest.doFilter(mockedRequest, mockedResponse, mockedFilterChain);
|
||||
|
||||
// then
|
||||
Mockito.verify(mockedFilterChain, Mockito.times(1))
|
||||
.doFilter(Mockito.any(CachedBodyHttpServletRequest.class), Mockito.any(MockHttpServletResponse.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.print.attribute.PrintRequestAttribute;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { HttpRequestDemoConfig.class, ContentCachingFilter.class, PrintRequestAttribute.class })
|
||||
@AutoConfigureMockMvc
|
||||
public class PersonControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
public void whenValidInput_thenCreateBook() throws IOException, Exception {
|
||||
// assign - given
|
||||
Person book = new Person("sumit", "abc", 100);
|
||||
|
||||
// act - when
|
||||
ResultActions result = mockMvc.perform(post("/person").accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(book)));
|
||||
|
||||
// assert - then
|
||||
result.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package org.baeldung.cachedrequest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PrintRequestContentFilterUnitTest extends TestCase {
|
||||
|
||||
@InjectMocks
|
||||
private PrintRequestContentFilter filterToTest;
|
||||
|
||||
@Test
|
||||
public void testGivenHttpRequest_WhenDoFilter_thenReadsBody() throws IOException, ServletException {
|
||||
// Given
|
||||
MockHttpServletRequest mockedRequest = new MockHttpServletRequest();
|
||||
MockHttpServletResponse mockedResponse = new MockHttpServletResponse();
|
||||
FilterChain mockedFilterChain = Mockito.mock(FilterChain.class);
|
||||
CachedBodyHttpServletRequest cachedBodyHttpServletRequest = new CachedBodyHttpServletRequest(mockedRequest);
|
||||
|
||||
// when
|
||||
filterToTest.doFilter(cachedBodyHttpServletRequest, mockedResponse, mockedFilterChain);
|
||||
|
||||
// then
|
||||
Mockito.verify(mockedFilterChain, Mockito.times(1))
|
||||
.doFilter(cachedBodyHttpServletRequest, mockedResponse);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user