title: Spring Boot controller not responding to POST request
body: <p>I am working with a receipt printer that has a cloud function. It commuicates with a server specification which i am implementing. It polls a URL with POST requests every x seconds and when the POST response contains a certain piece of information, the printer sends a GET request to the same to URL get the information to print.</p>
  
  <p>I'm implementing the print server as a Spring Boot server and i'm getting some strange problems with the POST method that i need some help with. </p>
  
  <p>My problem is that the POST requests from the printer to the server never make it to the controller. However, i am able to send a POST request from Postman to the exact same URL and it gets handled by the controller.</p>
  
  <p>The URL is simply: <a href="https://www.[my-domain].com:[port-number]/cloudprint" rel="noreferrer">https://www.[my-domain].com:[port-number]/cloudprint</a></p>
  
  <p>Also, i have tried copying the controller method to another Spring (not Boot) application, running on a Tomcat instance behind Apache and there, the POST requests from the printer are handled by the controller method. I can see them in the Apache log and the Tomcat log. The polling frequency is currently at 10 seconds.</p>
  
  <p>Here's what the controller looks like:</p>
  
  <pre><code>package com.[my-domain].[application-name].controller;
  
  [a bunch of imports]
  
  @RestController
  @CrossOrigin
  public class PrintController {
      Logger logger = LoggerFactory.getLogger(PrintController.class);
  
      @RequestMapping(value="/cloudprint", method=RequestMethod.POST,
              headers={"Accept=application/json"})
      @ResponseStatus(HttpStatus.CREATED)
      public @ResponseBody String printPost() { 
          logger.debug("in printPost");
          return "OK";
      }
  
      @RequestMapping(value="/cloudprint", method=RequestMethod.GET,
              headers={"Accept=application/json"})
      @ResponseStatus(HttpStatus.OK)
      public @ResponseBody String printGet(HttpServletRequest request) {
          logger.debug("in printGet");
          return "OK";
      }
  
      @RequestMapping(value="/cloudprint", method=RequestMethod.DELETE,
              headers={"Accept=application/json"})
      @ResponseStatus(HttpStatus.OK)
      public @ResponseBody String printDelete() {
          logger.debug("in printDelete");
          return "OK";
      }
  }
  </code></pre>
  
  <p>What could be causing this? What can i test to solve this issue?</p>
  
  <p>---ADDED INFORMATION BELOW 2019-06-03 @13:21 cet---
  Since i have a regular Spring (non-boot) application that accepts the POST requests from the printer, i am able to log the information in the incoming request. So i did that.</p>
  
  <p>This is one of the POST requests from the printer, which is NOT accepted by the Spring boot oontroller:</p>
  
  <pre><code>auth type: null
  content type: application/json
  -- HEADERS --
  Header: host : dev.[our-domain-name].com
  Header: accept : */*
  Header: user-agent : Cente HTTPc
  Header: content-type : application/json
  Header: content-length : 303
  Header: connection : keep-alive
  QueryString: null
  -- PARAMETERS --
  END
  </code></pre>
  
  <p>This is one of the POST requests from Postman to the exact same URL, which IS accepted by the Spring boot oontroller:</p>
  
  <pre><code>auth type: null
  cotent type: application/json
  -- HEADERS --
  Header: content-type : application/json
  Header: cache-control : no-cache
  Header: Postman-Token : caf99fa1-4730-4193-aab3-c4874273661d
  Header: user-agent : PostmanRuntime/7.6.0
  Header: accept : */*
  Header: host : dev.[our-domain-name].com
  Header: accept-encoding : gzip, deflate
  Header: content-length : 0
  Header: connection : keep-alive
  QueryString: null
  -- PARAMETERS --
  END
  </code></pre>
  
  <p>Analysis:
  1. The user-agent headers differ.
  2. The content-length headers differ.
  3. The Postman request has three headers that the request from the cloud printer does not have. They are: cache-control, Postman-token and accept-encoding</p>
  
  <p>---ADDED INFORMATION BELOW 2019-06-03 @17:56 cet---
  OK, i figured out how to log the message body. It is a well-formatted json structure that is indeed 303 characters:</p>
  
  <pre><code>{"status": "29 a 0 0 0 0 0 0 0 0 0 0",
   "printerMAC": "00:11:62:1b:xx:xx",
   "statusCode": "200%20OK",
   "printingInProgress": false,
   "clientAction": null,
   "display": [
     {"name": "MainDisplay" ,
      "status": {"connected": false}}],
   "barcodeReader": [
     {"name": "MainBCR" ,
      "status": {"connected": false,"claimed": false}}]}
  </code></pre>
  
  <p>I created the corresponding classes and changed the POST method in the Boot application to this:</p>
  
  <pre><code>@RequestMapping(value="/cloudprint", method=RequestMethod.POST,
          headers={"Accept=application/json"})
  @ResponseStatus(HttpStatus.CREATED)
  public @ResponseBody String printPost(@RequestBody PrinterPostRequest printerPostRequest,
          HttpServletRequest request) {  
      HttpRequestLogger.log(request);
      return "OK";
  }
  </code></pre>
  
  <p>Still, it is not picking up the POST request from the printer. It picks up the Postman request and successfully marshals the request body json into the classes.</p>
  
  <p>---ADDED INFORMATION BELOW 2019-06-05 @10:16 cet---
  I had an idea. Using Spring RestTemplate, i sent a POST request to the Boot application with the same headers and same payload as the request the printer sends. I'm getting an org.springframework.web.client.ResourceAccessException with this message:</p>
  
  <pre><code>I/O error on POST request for "https://boot.[my-domain].com:8443/cloudprint":sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  </code></pre>