I'm not entirely sure if this goes in the Thymeleaf project or the Spring Boot project. Spring Boot 2.5.4 Custom ErrorController
The template I have contains a number of large tables. At a certain point in the template, if I encounter an Exception I am no longer redirected to the Error Page I created. Instead, my Error Page is embedded inline with the partially rendered template. If I move me error back a few lines in the template, the Error Page displays as expected.
Here's my ErrorController
package com.csi.smartspooler.controllers;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.util.HtmlUtils;
import lombok.RequiredArgsConstructor;
@Controller
@RequiredArgsConstructor
public class MainErrorController implements ErrorController //
{
private static final Logger LOG = LogManager.getFormatterLogger();
private final BaseController base;
@RequestMapping("/error")
public String error(final HttpServletRequest request, final Model model) {
LOG.debug("handling error");
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
Integer statusCode = status == null ? -1
: Integer.valueOf(status.toString());
Object errorMessageObj = request
.getAttribute(RequestDispatcher.ERROR_MESSAGE);
Exception exception = (Exception) request
.getAttribute("javax.servlet.error.exception");
List<String> allErrors = new ArrayList<>();
String errsList = "";
if (exception != null) {
allErrors = getAllErrors(exception);
for (String err : allErrors) {
LOG.error("err [%s]", err);
errsList += "<br>" + HtmlUtils.htmlEscape(err);
}
LOG.error(exception);
}
String errorMessage = statusCode == HttpStatus.NOT_FOUND.value()
? "Not Found"
: (errorMessageObj == null ? "Unknown" : errorMessageObj.toString());
errorMessage = exception == null ? errorMessage
: String.format("%s<br>%s%s", //
(errorMessage == null || "".equals(errorMessage)) ? ""
: (errorMessage), //
exception.getClass().getName(), //
errsList);
Object requestURI = request
.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
Object requestQueryString = request
.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING);
Enumeration<String> attNames = request.getAttributeNames();
while (attNames.hasMoreElements()) {
String attName = attNames.nextElement();
Object attValue = request.getAttribute(attName);
LOG.debug(String.format("%s : '%s'", attName, attValue));
}
String requestedUrl = String.format("%s%s", requestURI,
(requestQueryString == null ? "" : ("?" + requestQueryString)));
LOG.error(String.format("requestedUrl %s, statusCode %s, errorMessage %s",
requestedUrl, statusCode, errorMessage));
model.addAttribute("requestedUrl", requestedUrl);
model.addAttribute("statusCode", statusCode);
model.addAttribute("errorMessage", errorMessage);
model.addAttribute("myVersion", base.versionService.getVersion());
model.addAttribute("title", "Error");
model.addAttribute("user", base.getUser());
return "error";
}
private List<String> getAllErrors(final Throwable exception) {
List<String> allErrors = new ArrayList<>();
allErrors.add(exception.getMessage());
Throwable cause = exception.getCause();
if (cause != null) {
List<String> errors = getAllErrors(cause);
for (String error : errors) {
if (!allErrors.contains(error)) {
allErrors.add(error);
}
}
}
return allErrors;
}
}
Here's my error template
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title th:text="'SmartSpooler Configuration v' + ${smartspoolerVersion}"></title>
<link th:replace="fragments :: ss-Header" />
</head>
<body>
<main role="main" class="container ss-Fill">
<div th:replace="fragments :: ss-Navbar"></div>
<h3>Error Page</h3>
<div>
Requested URL: <b th:text=${requestedURL}></b>
</div>
<div>
Status code: <b th:text=${statusCode}></b>
</div>
<div>
Error Message: <b th:utext=${errorMessage}></b>
</div>
</main>
<div th:replace="fragments :: ss-Footer"></div>
</body>
</html>
Here's the template with the error introduced to exercise this issue.
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
th:object="${lineConfig}">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title th:text="${title}"></title>
<link th:replace="fragments :: ss-Header" />
</head>
<body>
<main role="main" class="ss-Fill">
<div th:replace="fragments :: ss-Navbar"></div>
<div
th:replace="${sessionService.getAndRemoveAttribute('updated')} ? ~{fragments :: ss-Updated} : _"></div>
<div
th:replace="${#fields.hasAnyErrors()} ? ~{fragments :: ss-Errors} : _"></div>
<form action="#" th:action="@{/lineconfig}"
th:object="${lineConfig}" method="POST" id="myForm">
<input name="uuid" type="hidden" th:field="*{uuid}" />
<div class="bg-dark text-white"
style="padding-left: 8px; font-size: 1.5em;">Line
Parameters</div>
<table class="table table-striped table-sm"
style="table-layout: fixed; word-wrap: break-word;">
<thead class="thead-dark">
<tr>
<th scope="col" style="width: 25%"> </th>
<th scope="col" style="width: 25%">Current</th>
<th scope="col" style="width: 50%">New</th>
</tr>
</thead>
<tbody>
<tr
th:replace="fragments :: ss-ReadOnlyEnum(
title='Line Number',
fieldName='lineNumber',
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-ReadOnlyEnum(
title='MCCI Port',
fieldName='mcciPort',
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-ReadOnlyText(
title='Source Filename',
fieldName='sourceFilename',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.lineType()},
title='Line Type',
fieldName='lineType',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Transmit Channel ID',
fieldName='transmitChannelId',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Receive Channel ID',
fieldName='receiveChannelId',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='TCP Port (1-65535)',
fieldName='tcpPort',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='FDMP Block Size (64-1024)',
fieldName='fdmpBlockSize',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Checkbox(
title='Line Enabled',
fieldName='lineEnabled',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Checkbox(
title='Loopback',
fieldName='loopback',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.charSet()},
title='Character Set',
fieldName='serialCharacterSet',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.baudRate()},
title='Baud Rate',
fieldName='serialBaudRate',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.parity()},
title='Parity',
fieldName='serialParity',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.dataBits()},
title='Data Bits',
fieldName='serialDataBits',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.stopBits()},
title='Stop Bits',
fieldName='serialStopBits',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.replacementCharacter()},
title='Parity Replacement Character',
fieldName='parityReplacementChar',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.replacementCharacter()},
title='Buffer Overrun Replacement Character',
fieldName='bufferOverrunReplacementChar',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.replacementCharacter()},
title='Framing Error Replacement Character',
fieldName='framingErrorReplacementChar',
formFields=${#fields},
origConfig=${origConfig})"></tr>
ERROR INTRODUCED HERE <!--
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.clockSource()},
title='Clock Source',
fieldName='clockSource',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.polarity()},
title='Clock Polarity',
fieldName='clockPolarity',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.polarity()},
title='Data Polarity',
fieldName='dataPolarity',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.polarity()},
title='DTR/CD Polarity',
fieldName='dtrCdPolarity',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.polarity()},
title='RTS/CTS Polarity',
fieldName='rtsCtsPolarity',
formFields=${#fields},
origConfig=${origConfig})"></tr>
</tbody>
</table>
<div class="table-responsive">
<div class="bg-dark text-white"
style="padding-left: 8px; font-size: 1.5em;">Parser
Parameters</div>
<table class="table table-striped table-sm"
style="table-layout: fixed; word-wrap: break-word;">
<thead class="thead-dark">
<tr>
<th scope="col" style="width: 25%"> </th>
<th scope="col" style="width: 25%">Current</th>
<th scope="col" style="width: 50%">New</th>
</tr>
</thead>
<tbody>
<tr
th:replace="fragments :: ss-ListSingleSelect(
title='Parser Name',
fieldName='parserName',
listSelections=${parserNamesList},
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Parser Timeout (0-60 secs)',
fieldName='parserTimeout',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Parser Max Size (1-6160 kilobytes)',
fieldName='parserMaxSize',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Parser Max Unresolved Size (bytes)',
fieldName='maxUnresolvedSize',
formFields=${#fields},
origConfig=${origConfig})"></tr>
</tbody>
</table>
</div>
<div class="table-responsive">
<div class="bg-dark text-white"
style="padding-left: 8px; font-size: 1.5em;">Wrapping
Parameters</div>
<table class="table table-striped table-sm"
style="table-layout: fixed; word-wrap: break-word;">
<thead class="thead-dark">
<tr>
<th scope="col" style="width: 25%"> </th>
<th scope="col" style="width: 25%">Current</th>
<th scope="col" style="width: 50%">New</th>
</tr>
</thead>
<tbody>
<tr
th:replace="fragments :: ss-Input(
title='LMF', fieldName='wrappingLMF',
formFields=${#fields}, origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.classification()},
title='Classification',
fieldName='wrappingClassification',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-ReadOnlyText(
title='Classification Prosign',
fieldName='wrappingClassificationProsign',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='CIC',
fieldName='wrappingCIC',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Subject',
fieldName='wrappingSubject',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Account Code',
fieldName='wrappingAccountCode',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='OPS Signals',
fieldName='wrappingOpsSignals',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='OSRI',
fieldName='wrappingOSRI',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='TRC',
fieldName='wrappingTRC',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='From PLA',
fieldName='wrappingFromPLA',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='DSRIs',
fieldName='wrappingDSRIs',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='ALTRI',
fieldName='wrappingALTRI',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Security Words',
fieldName='wrappingSecurityWords',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='XMT PLAs',
fieldName='wrappingXmtPLAs',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Action PLAs',
fieldName='wrappingActionPLAs',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-Input(
title='Info PLAs',
fieldName='wrappingInfoPLAs',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.precedence()},
title='Action Precedence',
fieldName='wrappingActionPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-NullableEnumSingleSelect(
values=${@domainService.precedence()},
title='Info Precedence',
fieldName='wrappingInfoPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.precedence()},
title='CCOMS High Action Precedence',
fieldName='wrappingCCOMSHighActionPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-NullableEnumSingleSelect(
values=${@domainService.precedence()},
title='CCOMS High Info Precedence',
fieldName='wrappingCCOMSHighInfoPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.precedence()},
title='CCOMS Normal Action Precedence',
fieldName='wrappingCCOMSNormalActionPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-NullableEnumSingleSelect(
values=${@domainService.precedence()},
title='CCOMS Normal Info Precedence',
fieldName='wrappingCCOMSNormalInfoPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.precedence()},
title='ID High Action Precedence',
fieldName='wrappingIDHighActionPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-NullableEnumSingleSelect(
values=${@domainService.precedence()},
title='ID High Info Precedence',
fieldName='wrappingIDHighInfoPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-EnumSingleSelect(
values=${@domainService.precedence()},
title='ID Normal Action Precedence',
fieldName='wrappingIDNormalActionPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
<tr
th:replace="fragments :: ss-NullableEnumSingleSelect(
values=${@domainService.precedence()},
title='ID Normal Info Precedence',
fieldName='wrappingIDNormalInfoPrecedence',
formFields=${#fields},
origConfig=${origConfig})"></tr>
</tbody>
</table>
</div>
<span th:replace="fragments :: ss-Buttons"></span>
</form>
</main>
<div th:replace="fragments :: ss-Footer"></div>
<script th:replace="fragments :: ss-FormScripts"></script>
</body>
</html>
And finally here's the fragments template
<!-- FRAGMENT :: ss-Header -->
<div th:fragment="ss-Header" th:remove="tag">
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="stylesheet"
href="webjars/bootstrap/4.3.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="ssWeb.css" />
</div>
<!-- FRAGMENT :: ss-Header -->
<div th:fragment="ss-Navbar" class="bg-dark ss-Fill"
style="display: inline-block; clear: right;">
<div class="bg-dark">
<div class="float-left">
<h3 style="margin-left: 10px; margin-top: 5px;"
class="bg-dark text-white" th:text="${title}">REPLACE -
TITLE</h3>
</div>
<div class="float-right" style="margin-right: 10px;">
<p>
<a th:unless="${hideHomeLink}"
style="font-size: 1em; margin-top: 1px;"
class="float-right text-white" href="/">Main Menu</a> <a
th:if="${hideHomeLink}"
style="opacity: 0; font-size: 1em; margin-top: 1px;"
class="float-right text-white text-decoration-none" href="/"> </a>
</p>
<p class="mb-0 float-right text-white"
style="font-size: 0.7em; margin-top: 3px; padding-bottom: 3px;"
th:text="'v-' + ${myVersion}">REPLACE - VERSION</p>
</div>
</div>
</div>
<!-- FRAGMENT :: ss-Updated -->
<h4 th:fragment="ss-Updated" class="text-success ss-Fill"
style="display: inline-block; clear: right; text-align: center;">SUCCESSFULLY
UPDATED</h4>
<!-- FRAGMENT :: ss-Errors -->
<h4 th:fragment="ss-Errors" class="text-danger ss-Fill"
style="display: inline-block; clear: right; text-align: center;">--
PLEASE FIX ERRORS --</h4>
<!-- FRAGMENT :: ss-NullableEnumSingleSelect -->
<tr
th:fragment="ss-NullableEnumSingleSelect (values, title, fieldName, formFields, origConfig)">
<th scope="row">
<div th:text="${title}">REPLACE - TITLE</div>
</th>
<td>
<div
th:style="${origConfig.__${fieldName}__} == null ? 'font-weight: bold;' : _"
th:text="${origConfig.__${fieldName}__} == null ? '-- NOT CONFIGURED --' : ${origConfig.__${fieldName}__.getDisplayValue()}">REPLACE
- CURRENT VALUE</div>
</td>
<td><select
th:classappend="${formFields.hasErrors('__${fieldName}__')} ? 'is-invalid' : _"
th:id="${fieldName}" class="ss-singleSelect ss-W90 form-control"
th:field="*{__${fieldName}__}">
<option value="">-- NOT CONFIGURED --</option>
<option th:each="enum : ${values}" th:value="${enum}"
th:text="${enum.displayValue}"></option>
</select>
<!--/* ERRORS */-->
<div th:if="${formFields.hasErrors('__${fieldName}__')}"
style="clear: left;" class="text-danger float-left"
th:errors="*{__${fieldName}__}"></div></td>
</tr>
<!-- FRAGMENT :: ss-EnumSingleSelect -->
<tr
th:fragment="ss-EnumSingleSelect (values, title, fieldName, formFields, origConfig)">
<th scope="row">
<div th:text="${title}">REPLACE - TITLE</div>
</th>
<td>
<div
th:style="${origConfig.__${fieldName}__} == null ? 'font-weight: bold;' : _"
th:text="${origConfig.__${fieldName}__} == null ? '-- NOT CONFIGURED --' : ${origConfig.__${fieldName}__.getDisplayValue()}">REPLACE
- CURRENT VALUE</div>
</td>
<td><select th:id="${fieldName}"
class="ss-singleSelect ss-W90 form-control"
th:field="*{__${fieldName}__}">
<option th:each="enum : ${values}" th:value="${enum}"
th:text="${enum.displayValue}"></option>
</select></td>
</tr>
<!-- FRAGMENT :: ss-ListSingleSelect -->
<tr
th:fragment="ss-ListSingleSelect (title, fieldName, listSelections, formFields, origConfig)">
<th scope="row">
<div th:text="${title}">REPLACE - TITLE</div>
</th>
<td>
<div th:text="${origConfig.__${fieldName}__}">REPLACE -
CURRENT VALUE</div>
</td>
<td><select th:id="${fieldName}"
class="ss-singleSelect ss-W90 form-control"
th:field="*{__${fieldName}__}">
<option th:each="listSelection : ${listSelections}"
th:value="${listSelection}" th:text="${listSelection}"></option>
</select></td>
</tr>
<!-- FRAGMENT :: ss-Input -->
<tr th:fragment="ss-Input (title, fieldName, formFields, origConfig)">
<th scope="row">
<div th:text="${title}">REPLACE - TITLE</div>
</th>
<td>
<div
th:style="${origConfig.__${fieldName}__} == null ? 'font-weight: bold;' : _"
th:text="${origConfig.__${fieldName}__} == null ? '-- NOT CONFIGURED --' : ${origConfig.__${fieldName}__}">REPLACE
- CURRENT VALUE</div>
</td>
<td><input
th:classappend="${formFields.hasErrors('__${fieldName}__')} ? 'is-invalid' : _"
class="ss-W90 form-control" type="text"
th:field="*{__${fieldName}__}" />
<!--/* ERRORS */-->
<div th:if="${formFields.hasErrors('__${fieldName}__')}"
style="clear: left;" class="text-danger float-left"
th:errors="*{__${fieldName}__}"></div></td>
</tr>
<!-- FRAGMENT :: ss-Checkbox -->
<tr th:fragment="ss-Checkbox (title, fieldName, formFields, origConfig)">
<th scope="row">
<div th:text="${title}">REPLACE - TITLE</div>
</th>
<td>
<div th:text="${origConfig.__${fieldName}__.booleanValue()} ? 'YES' : 'NO'">REPLACE
- CURRENT VALUE</div>
</td>
<td><div>
<input class="ss-Checkbox" th:name="${fieldName}" th:id="${fieldName}"
type="checkbox" th:checked="*{__${fieldName}__.booleanValue()}" />
</div></td>
</tr>
<!-- FRAGMENT :: ss-ReadOnlyText -->
<tr
th:fragment="ss-ReadOnlyText (title, fieldName, formFields, origConfig)">
<th scope="row">
<div th:text="${title}">REPLACE - TITLE</div>
</th>
<td>
<div th:text="${origConfig.__${fieldName}__}">REPLACE -
CURRENT VALUE</div>
</td>
<td>NOT EDITABLE <input type="hidden"
th:field="*{__${fieldName}__}" />
</td>
</tr>
<!-- FRAGMENT :: ss-ReadOnlyEnum -->
<tr
th:fragment="ss-ReadOnlyEnum (title, fieldName, origConfig)">
<th scope="row">
<div th:text="${title}">REPLACE - TITLE</div>
</th>
<td>
<div th:text="${origConfig.__${fieldName}__.getDisplayValue()}">REPLACE
- CURRENT VALUE</div>
</td>
<td>NOT EDITABLE <input type="hidden"
th:field="*{__${fieldName}__}" /></td>
</tr>
<!-- FRAGMENT :: ss-Buttons -->
<span th:fragment="ss-Buttons" th:remove="tag">
<hr> <a type="submit" href="#"
onclick="document.getElementById('myForm').submit()"
style="width: 100px; margin: 4px 2px; cursor: default;"
class="btn btn-primary" role="button">Submit</a> <a
style="width: 100px; margin: 4px 2px; cursor: default;"
th:href="${session.resetURL}" class="btn btn-primary" role="button">Reset</a>
</span>
<!-- FRAGMENT :: ss-Footer -->
<div th:fragment="ss-Footer" th:remove="tag">
<script type="text/javascript"
src="webjars/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript"
src="webjars/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</div>
<!-- FRAGMENT :: ss-FormScripts -->
<script th:fragment="ss-FormScripts" type="text/javascript">
document.onkeypress = keyPress;
function keyPress(e) {
var x = e || window.event;
var key = (x.keyCode || x.which);
if (key == 13 || key == 3) {
tagName = document.activeElement.tagName;
console.log(tagName);
if (tagName != 'TEXTAREA') {
document.getElementById('myForm').submit();
}
}
}
</script>
Comment From: philwebb
I suspect this is a buffering issue where a flush has occurred before the exception happens. You could try adding spring.thymeleaf.servlet.produce-partial-output-while-processing=false
to your application.properties
to see if that solves the problem.
If that doesn't work, please provide a sample application as a GitHub project or a zip file so we can debug things.
Comment From: mdwheaton
Yep, that was it. Looks like I need to read these default options much more carefully. Thank you!
On Fri, Aug 27, 2021 at 5:25 PM Phil Webb @.***> wrote:
I suspect this is a buffering issue where a flush has occurred before the exception happens. You could try adding spring.thymeleaf.servlet.produce-partial-output-while-processing=false to your application.properties to see if that solves the problem.
If that doesn't work, please provide a sample application as a GitHub project or a zip file so we can debug things.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/spring-projects/spring-boot/issues/27828#issuecomment-907507123, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAP2IZZYIF5J4AHZUJTSSFTT7AGHNANCNFSM5C6IBFSA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
Comment From: mdwheaton
Yep, that was it. Looks like I need to read these default options much more carefully.