1

I have two services being debugged from two instances of IntelliJ 2017.1.2. Service A submits a json request to Service B. Both services are Spring-Boot using REST calls.

Service A makes a post:

ResponseEntity<InvoiceResponse> response =
                            restTemplate.postForEntity(invoiceUrl, request, InvoiceResponse.class);

Service B had an endpoint:

 @RequestMapping(value = "/office/{officeId}/invoice", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity createInvoice(@RequestBody InvoiceRequest invoiceRequest, @PathVariable("officeId") long officeId) {
...}

But I get a JWT filter that intercepts the request, and processed it successfully (I have confirmed via breakpoint):

public class JwtAuthenticationTokenFilter extends GenericFilterBean {

 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
                    ServletException {
     HttpServletRequest httpRequest = (HttpServletRequest) request;
     String authToken = httpRequest.getHeader(this.tokenHeader);
     String username = jwtTokenUtil.getUsernameFromToken(authToken);
     if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
           if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                UsernamePasswordAuthenticationToken
                                authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        chain.doFilter(request, response);
    }

This seems to exit normally, as I don't see any errors in the logs. However, Service A in IntelliJ shows the message:

Could not read document: Unrecognized token 'Missing': was expecting ('true', 'false' or 'null') at [Source: java.io.PushbackInputStream@7d005eb; line: 1, column: 9] com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Missing': was expecting ('true', 'false' or 'null') at [Source: java.io.PushbackInputStream@7d005eb; line: 1, column: 9]

I don't have any stack traces and stepping thru the code doesn't show me the problem. I am trying to find a way to examine the JSON coming/leaving Service B so I can see what is being used since that appears to be causing issues with jackson. Is there anyway to view this in IntelliJ? If I could get the JSON being sent from Service A, I could recreate the call from Postman, but I can't seem to track the actual json leaving Service A either.

If it matters, I am using Spring-Boot 1.3.5 and Java 8 on OS X

UPDATE:

I added the following to Service A per Patrick Bay suggestions:

@Bean
public CommonsRequestLoggingFilter requestLoggingFilter() {
    CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
    loggingFilter.setIncludeClientInfo(true);
    loggingFilter.setIncludeQueryString(true);
    loggingFilter.setIncludePayload(true);
    return loggingFilter;
}

But I still don't see any json to help me see what is wrong with my request:

DEBUG 74188 --- [nio-8081-exec-3] o.s.web.client.RestTemplate
: Writing [com.common.invoice.InvoiceRequest@44471e8e] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@610fefeb] DEBUG 74188 --- [nio-8081-exec-3] o.s.web.client.RestTemplate
: POST request for "http://localhost:8998/office/1/invoice" resulted in 200 (null) DEBUG 74188 --- [nio-8081-exec-3] o.s.web.client.RestTemplate : Reading [class com..common.invoice.InvoiceResponse] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@610fefeb] ERROR 74188 --- [nio-8081-exec-3] c.finance.Connector : Could not read document: Unrecognized token 'Missing': was expecting ('true', 'false' or 'null')

I also tried inspecting the HttpRequest in my Service B JwtAuthenticationTokenFilter. I have tried navigating thru it, but I don't see the actual body that I am sending. I do see the correct url in the request, but once the filter successfull processes it, the actual endpoint ("/office/1/invoice") is never reached because I think Service B blows up

sonoerin
  • 5,015
  • 23
  • 75
  • 132

1 Answers1

0

To log the incoming requests you can use the CommonsRequestLoggingFilter see here for more details https://ivanursul.com/how-to-log-requests-and-their-payloads-in-spring/.

Add this to your Spring Configuration:

@Bean
public CommonsRequestLoggingFilter requestLoggingFilter() {
    CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
    loggingFilter.setIncludeClientInfo(true);
    loggingFilter.setIncludeQueryString(true);
    loggingFilter.setIncludePayload(true);
    return loggingFilter;
}

and this to your application properties file:

logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG  
Patrick Bray
  • 552
  • 2
  • 7
  • 20
  • You should also be able to inspect the request body when debugging your JwtAuthenticationTokenFilter by checking the httpRequest. – Patrick Bray May 25 '17 at 02:28
  • Also worth checking out this question https://stackoverflow.com/questions/7952154/spring-resttemplate-how-to-enable-full-debugging-logging-of-requests-responses – Patrick Bray May 25 '17 at 02:35
  • This doesn't actually show me the json request or response. I need to see that so i can see how my Jackson mapping is incorrect. – sonoerin May 25 '17 at 04:56
  • It should show the payload as long as it is < 50 characters in length. You can modify this max by setting: `loggingFilter.setMaxPayloadLength(1000);` As shown below `2017-05-25 17:42:00.581 DEBUG 86141 --- [nio-8080-exec-4] o.s.w.f.CommonsRequestLoggingFilter : After request [uri=/greet-post;client=0:0:0:0:0:0:0:1;payload={"In"}]` – Patrick Bray May 25 '17 at 07:44
  • Sorry for the confusion the CommonsRequestLoggingFilter filter should be applied on the server side. Service B in your example. Did you check out the linked question have you attempted to add a ClientHttpRequestInterceptor to Log the request and response from the RestTemplate in your client Service A? – Patrick Bray May 25 '17 at 23:40