GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing javaaltaf.blogspot.com — Java Altaf - Spring Hibernate Realtime Challenging Problems Solution When we are working with REST services, it can be very useful for debugging to be able to log both the request and the response info. We can do this very easy just by adding an interceptor in our project. import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
traceRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
traceResponse(response);
return response;
}
private void traceRequest(HttpRequest request, byte[] body) throws IOException {
log.info("=========================== Request Begin ===========================");
log.info("URI : " + request.getURI());
log.info("Method : " + request.getMethod());
log.info("Headers : " + request.getHeaders());
log.info("Body : " + new String(body, "utf-8"));
log.info("============================ Request End ============================");
}
private void traceResponse(ClientHttpResponse response) throws IOException {
StringBuilder inputStringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "utf-8"));
String line = bufferedReader.readLine();
while (line != null) {
inputStringBuilder.append(line);
line = bufferedReader.readLine();
}
log.info("=========================== Response Begin ===========================");
log.info("Status code : {}", response.getStatusCode());
log.info("Status text : {}", response.getStatusText());
log.info("Headers : {}", response.getHeaders());
log.info("Body : {}", inputStringBuilder.toString());
log.info("============================ Response End ============================");
}
}
Now create a BeanConfig class to create RestTemplate object. import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import com.altafjava.misc.LoggingRequestInterceptor;
@Configuration
public class BeanConfig {
@Bean
public RestTemplate buildrestTemplate() {
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setInterceptors(Collections.singletonList(new LoggingRequestInterceptor()));
return restTemplate;
}
}
That's it! But you will run in a problem. Actually Response body is a stream and if we read it in the interceptor it won’t be available for RestTemplate to deserialize it into object model. In other words, when we call restTemplate.get..() we will always get back empty objects (even as we see the object in the response. Fortunately we can fix that by using org.springframework.http.client.BufferingClientHttpResponseWrapper class. But unfortunately, you cannot use this class because this class is not public. Hence we cannot create object of this class. Hence to solve this we need to manually create this class with public modifier. Hence to solve this finally lets follow some steps. Step 1 :- Step 2 :-First we should create a BufferingClientHttpResponseWrapper class which will copy the response from actual response. Now with this copied response we can use response.getBody() any time.
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;
public class BufferingClientHttpResponseWrapper implements ClientHttpResponse {
private final ClientHttpResponse response;
private byte[] body;
public BufferingClientHttpResponseWrapper(ClientHttpResponse response) {
this.response = response;
}
@Override
public InputStream getBody() throws IOException {
if (body == null) {
body = StreamUtils.copyToByteArray(response.getBody());
}
return new ByteArrayInputStream(body);
}
@Override
public HttpStatus getStatusCode() throws IOException {
return this.response.getStatusCode();
}
@Override
public int getRawStatusCode() throws IOException {
return this.response.getRawStatusCode();
}
@Override
public String getStatusText() throws IOException {
return this.response.getStatusText();
}
@Override
public HttpHeaders getHeaders() {
return this.response.getHeaders();
}
@Override
public void close() {
this.response.close();
}
}
Create a custom interceptor class ie LoggingRequestInterceptor which will implement ClientHttpRequestInterceptor class. This class will be responsible to print all the RestTemplate request & response logs.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
traceRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
response = traceResponse(response);
return response;
}
private void traceRequest(HttpRequest request, byte[] body) throws IOException {
log.info("=========================== Request Begin ===========================");
log.info("URI : " + request.getURI());
log.info("Method : " + request.getMethod());
log.info("Headers : " + request.getHeaders());
log.info("Body : " + new String(body, "utf-8"));
log.info("============================ Request End ============================");
}
private ClientHttpResponse traceResponse(ClientHttpResponse response) throws IOException {
ClientHttpResponse newCopiedResponse = new BufferingClientHttpResponseWrapper(response);
StringBuilder inputStringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(newCopiedResponse.getBody(), "UTF-8"));
String line = bufferedReader.readLine();
while (line != null) {
inputStringBuilder.append(line);
line = bufferedReader.readLine();
}
log.info("=========================== Response Begin ===========================");
log.info("Status code : {}", response.getStatusCode());
log.info("Status text : {}", response.getStatusText());
log.info("Headers : {}", response.getHeaders());
log.info("Response Body : {}", inputStringBuilder.toString());
log.info("============================ Response End ============================");
return newCopiedResponse;
}
}
Create a Bean configuration class which will create RestTemplate object. import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import com.altafjava.misc.LoggingRequestInterceptor;
@Configuration
public class BeanConfig {
@Bean
public RestTemplate buildrestTemplate() {
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setInterceptors(Collections.singletonList(new LoggingRequestInterceptor()));
return restTemplate;
}
}
Thats It! Happy Coding. For your reference you can the project in https://github.com/altafjava/log-resttemplate-req-resp |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |