Explain Codes LogoExplain Codes Logo

Spring RestTemplate - how to enable full debugging/logging of requests/responses?

java
logging
debugging
rest-template
Alex KataevbyAlex Kataev·Oct 18, 2024
TLDR

Enable in-depth logging for Spring's RestTemplate with a ClientHttpRequestInterceptor. Here is an efficient interceptor for logging request/response details:

public class LoggingInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { // Alerting the headquarters about the coming request log("Request status", request.getMethod(), request.getURI(), new String(body, StandardCharsets.UTF_8)); // Carry on with the execution; keep calm and carry on! ClientHttpResponse response = execution.execute(request, body); // Response received, let the world know about it! log("Response status", response.getStatusCode(), response.getStatusText(), StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8)); return response; } private void log(String prefix, Object... payloads) { // Let's sekritly collect the logs System.out.println(prefix + Arrays.stream(payloads).map(Object::toString).collect(Collectors.joining(" | "))); } } // Debugging, RestTemplate's style! RestTemplate restTemplate = new RestTemplate(); restTemplate.getInterceptors().add(new LoggingInterceptor());

This compact piece of code outlines an interceptor logging HTTP method, URI, body for requests, status for responses, and glues it onto RestTemplate.

Advanced: In-depth debugging

While the Fast answer provides you with a head start, let's venture further to Advanced: logging techniques. These come only second to your coffee when it comes to easing your debugging mornings.

Buffering: Catch 'em all

Use BufferingClientHttpRequestFactory to read the response body multiple times. It’s like a Pokémon master, catching all info circulating in and out:

restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));

Log settings: Dial M for Monitoring

application.properties is your go-to place to Set. Debug. Go!:

logging.level.org.springframework.web.client.RestTemplate=DEBUG

Take it up a notch, log like a pro using log4j:

log4j.logger.httpclient.wire.header=DEBUG log4j.logger.httpclient.wire.content=DEBUG

Logging Inception: Library within libraries

In the world of libraries, spring-rest-template-logger is The One. Grapple it tight (add the dependency) and whisper the logging command (edit the properties):

<dependency> <groupId>com.github</groupId> <artifactId>spring-rest-template-logger</artifactId> <version>1.0.0</version> </dependency>
logging.level.spring-rest-template-logger=DEBUG

Refining the edges

Creating a masterpiece requires attention to detail. Let's brush up on some key attributes that will put us on the debugging pedestal.

Encoding: lost in translation

Without proper encoding identification, the log messages may seem like they're directed by Christopher Nolan:

new String(body, StandardCharsets.UTF_8)

Exception Handling: We'll Always Have Errors

Exception handling in your interceptors is as inevitable as encountering Ross' "We were on a break!" in every FRIENDS series. Try, catch, continue:

try { // Fingers crossed } catch (Exception e) { // Well, that happened throw e; }

Interplay: SLF4J & The Loggers

Master the art of managing SLF4J, Logback, and Log4j. Make them work together like The Avengers of logging.

curl-in-the-headlights

Extracting curl's verbose mode goodness for connection lifecycle and data exchange is a gamechanger:

logging.level.org.apache.http=DEBUG logging.level.org.apache.http.wire=DEBUG

Early riser: StringBuilder

For early risers (read: better memory management and performance), let the StringBuilder do the logging.

Plot Twists: Different scenarios

Different HTTP methods and content types have their plot twists, like a Shyamalan movie. Adapt your strategy; don't let POST and JSON surprise you.