Skip to content

Commit 362382a

Browse files
committed
fix: Fixed GH-3604, Add STErrorListener to StTemplateRenderer.
`StTemplateRenderer` uses `StringTemplate` as the template rendering engine. By default, StringTemplate use `org.stringtemplate.v4.misc.ErrorManager#DEFAULT_ERROR_LISTENER` as the error listener for rendering exceptions, which outputs errors via System.err.println. This may cause users to miss important information about rendering errors. This commit introduces a custom `STErrorListener` that logs exceptions to the application's logging system instead. Signed-off-by: Sun Yuhan <[email protected]>
1 parent 49df56c commit 362382a

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2023-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.template.st;
18+
19+
import org.slf4j.Logger;
20+
import org.slf4j.LoggerFactory;
21+
import org.stringtemplate.v4.STErrorListener;
22+
import org.stringtemplate.v4.misc.ErrorType;
23+
import org.stringtemplate.v4.misc.STMessage;
24+
25+
/**
26+
* An ErrorListener for the {@link StTemplateRenderer} rendering exceptions.
27+
* <p>
28+
* By default, StringTemplate uses
29+
* {@link org.stringtemplate.v4.misc.ErrorManager#DEFAULT_ERROR_LISTENER} as the exception
30+
* handler, which outputs exceptions via System.err.println. This can lead to a loss of
31+
* detailed exception logs from the user's perspective. The current ErrorListener retains
32+
* the behavior of the default handler but additionally outputs the exceptions through
33+
* logging mechanisms.
34+
* </p>
35+
*
36+
* @author Sun Yuhan
37+
*/
38+
public class StTemplateRenderErrorListener implements STErrorListener {
39+
40+
private final Logger logger = LoggerFactory.getLogger(StTemplateRenderErrorListener.class);
41+
42+
@Override
43+
public void compileTimeError(STMessage msg) {
44+
logger.error(msg.toString());
45+
}
46+
47+
@Override
48+
public void runTimeError(STMessage msg) {
49+
if (msg.error != ErrorType.NO_SUCH_PROPERTY) { // ignore these
50+
logger.error(msg.toString());
51+
}
52+
}
53+
54+
@Override
55+
public void IOError(STMessage msg) {
56+
logger.error(msg.toString());
57+
}
58+
59+
@Override
60+
public void internalError(STMessage msg) {
61+
logger.error(msg.toString());
62+
}
63+
64+
}

spring-ai-template-st/src/main/java/org/springframework/ai/template/st/StTemplateRenderer.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.slf4j.Logger;
2626
import org.slf4j.LoggerFactory;
2727
import org.stringtemplate.v4.ST;
28+
import org.stringtemplate.v4.STGroup;
2829
import org.stringtemplate.v4.compiler.Compiler;
2930
import org.stringtemplate.v4.compiler.STLexer;
3031

@@ -49,6 +50,7 @@
4950
* is shared between threads.
5051
*
5152
* @author Thomas Vitale
53+
* @author Sun Yuhan
5254
* @since 1.0.0
5355
*/
5456
public class StTemplateRenderer implements TemplateRenderer {
@@ -112,7 +114,9 @@ public String apply(String template, Map<String, Object> variables) {
112114

113115
private ST createST(String template) {
114116
try {
115-
return new ST(template, this.startDelimiterToken, this.endDelimiterToken);
117+
STGroup group = new STGroup(this.startDelimiterToken, this.endDelimiterToken);
118+
group.setListener(new StTemplateRenderErrorListener());
119+
return new ST(group, template);
116120
}
117121
catch (Exception ex) {
118122
throw new IllegalArgumentException("The template string is not valid.", ex);

0 commit comments

Comments
 (0)