title: Spring TemplateEngine process error on th:field
body: <p>I am developing a web application in Java using spring.</p>
  
  <p>This application includes Ajax calls in javascript which requests html code that is then inserted into the html document.</p>
  
  <p>In order to process a thymeleaf template into a String i'm using TemplateEngine process(..) method.</p>
  
  <p>I encountered an error when the thymeleaf template contains a form. </p>
  
  <p>My sample code:</p>
  
  <p>form.html:</p>
  
  <pre><code>&lt;form th:object="${customer}" xmlns:th="http://www.w3.org/1999/xhtml"&gt;
      &lt;label&gt;Name&lt;/label&gt;
      &lt;input type="text" th:field="*{name}" /&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>AjaxController.java:</p>
  
  <pre><code>package project;
  
  import com.fasterxml.jackson.core.JsonProcessingException;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Controller;
  import org.springframework.ui.Model;
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.ResponseBody;
  import org.thymeleaf.TemplateEngine;
  import org.thymeleaf.context.Context;
  
  @Controller
  public class AjaxController {
  
      @Autowired
      private TemplateEngine templateEngine;
      private ObjectMapper objectMapper = new ObjectMapper();
  
      @ResponseBody
      @GetMapping(value="/form1")
      public String form1() throws JsonProcessingException {
  
          Customer customer = new Customer("Burger King");
  
          Context templateContext = new Context();
          templateContext.setVariable("customer", customer);
  
          AjaxResponse response = new AjaxResponse();
          response.html = templateEngine.process("form", templateContext);
          response.additionalData = "ab123";
  
          return objectMapper.writeValueAsString(response);
      }
  
      @GetMapping(value="/form2")
      public String form2(Model model) throws JsonProcessingException {
  
          Customer customer = new Customer("Burger King");
  
          model.addAttribute("customer", customer);
  
          return "form";
      }
  
      class Customer {
          private String name;
  
          public Customer(String name) {
              this.name = name;
          }
  
          public String getName() {
              return name;
          }
  
          public void setName(String name) {
              this.name = name;
          }
      }
  
      class AjaxResponse {
          public String html;
          public String additionalData;
      }
  }
  </code></pre>
  
  <p>form1 is the one crashing, I'm trying to return the html code parsed by the thymeleaf template and also include additional data in this json response.
  It crashes on the line templateEngine.process("form", templateContext);</p>
  
  <p>form1 works when replacing form.html with:</p>
  
  <p>Customer name is: [[${customer.name}]]</p>
  
  <p>Which leads me to conclude that it is the form tag and th:object which causes this to crash.</p>
  
  <p>form2 works just as expected, but without any way to manipulate the thymeleaf return value. It proves that the thymeleaf template itself is valid.</p>
  
  <p>The whole error output is a bit too massive to paste in here but:</p>
  
  <pre><code>org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/form.html]")
  
  Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Cannot process attribute '{th:field,data-th-field}': no associated BindStatus could be found for the intended form binding operations. This can be due to the lack of a proper management of the Spring RequestContext, which is usually done through the ThymeleafView or ThymeleafReactiveView (template: "form" - line 3, col 21)
  </code></pre>
  
  <p>My question is: Is this a bug in the spring framework? or if not then what am i doing wrong?</p>
  
  <hr>
  
  <p>Update 1:
  Replacing th:field with th:value makes it work, seems that th:field inside a form when using TemplateEngine .process is what produces the error.</p>
  
  <p>Update 2:
  Okay so after a lot of detective work i've figured out a sort of hack to make this work temporarily. The problem is that thymeleaf requires IThymeleafRequestContext to process a template with a form, When TemplateEngine .process runs then this will not be created. It is possible to inject this into your model like following:</p>
  
  <pre><code>@Autowired
  ServletContext servletContext;
  
  private String renderToString(HttpServletRequest request, HttpServletResponse response, String viewName, Map&lt;String, Object&gt; parameters) {
      Context templateContext = new Context();
      templateContext.setVariables(parameters);
  
      RequestContext requestContext = new RequestContext(request, response, servletContext, parameters);
      SpringWebMvcThymeleafRequestContext thymeleafRequestContext = new SpringWebMvcThymeleafRequestContext(requestContext, request);
              templateContext.setVariable("thymeleafRequestContext", thymeleafRequestContext);
  
      return templateEngine.process(viewName, templateContext);
  }
  </code></pre>
  
  <p>and now you use this method like this:</p>
  
  <pre><code>@ResponseBody
  @GetMapping(value="/form1")
  public String form1(HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
  
      Customer customer = new Customer("Burger King");
      BindingAwareModelMap bindingMap = new BindingAwareModelMap();
      bindingMap.addAttribute("customer", customer);
      String html = renderToString(request, response, "form", bindingMap);
  
      AjaxResponse resp = new AjaxResponse();
      resp.html = html;
      resp.additionalData = "ab123";
  
      String json = objectMapper.writeValueAsString(resp);
      return json;
  }
  </code></pre>
  
  <p>I will not put down this as an answer as i don't see any reason of this being intended to be used this way. I'm in communication with the spring people to get a real fix for this.</p>