Skip to content

Commit ac958f0

Browse files
committed
chore: bump to 0.18.1-SNAPSHOT and fix spring example escaping
Update project versions to 0.18.1-SNAPSHOT, add 0.18.1 release notes, and fix boat-spring ExampleObject value rendering by unwrapping escaped quotes with regression coverage. Made-with: Cursor
1 parent 0ef46a4 commit ac958f0

13 files changed

Lines changed: 75 additions & 11 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ It currently consists of
1616
# Release Notes
1717
BOAT is still under development and subject to change.
1818

19+
## 0.18.1
20+
* Spring generator: fixed `@ExampleObject` rendering in `api.mustache` by unwrapping escaped quotes in example payloads.
21+
* Added `unwrapEscapedQuotes` lambda to `boat-spring` generator templates to prevent malformed annotation values (for example `value = "\"{...}"`).
22+
* Added a regression test to verify generated Spring API interfaces include valid `@ExampleObject` annotation values and remain parseable Java code.
23+
1924
## 0.18.0
2025
* openapi-generator `7.20.0` baseline (Spring Boot 4, Jackson 3)
2126
* moved Java and JavaSpring templates to `7.20.0` adding remaing custom features

boat-engine/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.backbase.oss</groupId>
77
<artifactId>backbase-openapi-tools</artifactId>
8-
<version>0.18.0-SNAPSHOT</version>
8+
<version>0.18.1-SNAPSHOT</version>
99
</parent>
1010
<artifactId>boat-engine</artifactId>
1111
<packaging>jar</packaging>

boat-maven-plugin/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.backbase.oss</groupId>
77
<artifactId>backbase-openapi-tools</artifactId>
8-
<version>0.18.0-SNAPSHOT</version>
8+
<version>0.18.1-SNAPSHOT</version>
99
</parent>
1010
<artifactId>boat-maven-plugin</artifactId>
1111

boat-quay/boat-quay-lint/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.backbase.oss</groupId>
77
<artifactId>boat-quay</artifactId>
8-
<version>0.18.0-SNAPSHOT</version>
8+
<version>0.18.1-SNAPSHOT</version>
99
</parent>
1010

1111
<artifactId>boat-quay-lint</artifactId>

boat-quay/boat-quay-rules/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.backbase.oss</groupId>
77
<artifactId>boat-quay</artifactId>
8-
<version>0.18.0-SNAPSHOT</version>
8+
<version>0.18.1-SNAPSHOT</version>
99
</parent>
1010

1111
<artifactId>boat-quay-rules</artifactId>

boat-quay/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.backbase.oss</groupId>
77
<artifactId>backbase-openapi-tools</artifactId>
8-
<version>0.18.0-SNAPSHOT</version>
8+
<version>0.18.1-SNAPSHOT</version>
99
</parent>
1010

1111

boat-scaffold/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.backbase.oss</groupId>
77
<artifactId>backbase-openapi-tools</artifactId>
8-
<version>0.18.0-SNAPSHOT</version>
8+
<version>0.18.1-SNAPSHOT</version>
99
</parent>
1010

1111
<artifactId>boat-scaffold</artifactId>
@@ -102,7 +102,7 @@
102102
<dependency>
103103
<groupId>com.backbase.oss</groupId>
104104
<artifactId>boat-trail-resources</artifactId>
105-
<version>0.18.0-SNAPSHOT</version>
105+
<version>0.18.1-SNAPSHOT</version>
106106
<scope>test</scope>
107107
</dependency>
108108
<dependency>

boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class BoatSpringCodeGen extends SpringCodegen {
4848

4949
public static final String ADD_SERVLET_REQUEST = "addServletRequest";
5050
public static final String ADD_BINDING_RESULT = "addBindingResult";
51+
public static final String UNWRAP_ESCAPED_QUOTES = "unwrapEscapedQuotes";
5152

5253
private static final String VENDOR_EXTENSION_NOT_NULL = "x-not-null";
5354

@@ -147,6 +148,23 @@ protected String postProcessLine(String line) {
147148
}
148149
}
149150

151+
static class UnwrapEscapedQuotes implements Mustache.Lambda {
152+
153+
@Override
154+
public void execute(Fragment frag, Writer out) throws IOException {
155+
String text = frag.execute();
156+
if (text == null) {
157+
return;
158+
}
159+
String normalized = text.replace("\\\\\"", "\\\"");
160+
if (normalized.length() >= 4 && normalized.startsWith("\\\"") && normalized.endsWith("\\\"")) {
161+
out.write(normalized.substring(2, normalized.length() - 2));
162+
return;
163+
}
164+
out.write(normalized);
165+
}
166+
}
167+
150168
/**
151169
* Adds a HttpServletRequest object to the API definition method.
152170
*/
@@ -332,6 +350,7 @@ public void processOpts() {
332350
this.additionalProperties.put("newLine8", new NewLineIndent(8, " "));
333351
this.additionalProperties.put("toOneLine", new FormatToOneLine());
334352
this.additionalProperties.put("trimAndIndent4", new TrimAndIndent(4, " "));
353+
this.additionalProperties.put(UNWRAP_ESCAPED_QUOTES, new UnwrapEscapedQuotes());
335354
}
336355

337356
@Override

boat-scaffold/src/main/templates/boat-spring/api.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public interface {{classname}} {
187187
{{#examples}}
188188
@ExampleObject(
189189
name = "{{{exampleName}}}",
190-
value = "{{{exampleValue}}}"
190+
value = "{{#unwrapEscapedQuotes}}{{{exampleValue}}}{{/unwrapEscapedQuotes}}"
191191
){{^-last}},{{/-last}}
192192
{{/examples}}
193193
{{#-last}}

boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import static org.hamcrest.Matchers.is;
77
import static org.hamcrest.Matchers.isA;
88
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertFalse;
910
import static org.junit.jupiter.api.Assertions.assertTrue;
1011
import static org.mockito.Mockito.mock;
1112
import static org.mockito.Mockito.when;
@@ -139,6 +140,45 @@ void multipartWithFileAndObject() throws IOException {
139140
assertThat(filesParam.getTypeAsString(), equalTo("List<MultipartFile>"));
140141
}
141142

143+
@Test
144+
void shouldGenerateValidExampleObjectAnnotation() throws IOException {
145+
var codegen = new BoatSpringCodeGen();
146+
var input = new File("src/test/resources/openapi-with-examples/openapi-with-multiple-permissions.yaml");
147+
codegen.setLibrary("spring-boot");
148+
codegen.setInterfaceOnly(true);
149+
codegen.setSkipDefaultInterface(true);
150+
codegen.setOutputDir(TEST_OUTPUT + "/example-object");
151+
codegen.setInputSpec(input.getAbsolutePath());
152+
codegen.additionalProperties().put(SpringCodegen.USE_SPRING_BOOT3, Boolean.TRUE.toString());
153+
154+
var openApiInput = new OpenAPIParser().readLocation(input.getAbsolutePath(), null, new ParseOptions())
155+
.getOpenAPI();
156+
var clientOptInput = new ClientOptInput();
157+
clientOptInput.config(codegen);
158+
clientOptInput.openAPI(openApiInput);
159+
160+
List<File> files = new DefaultGenerator().opts(clientOptInput).generate();
161+
162+
File apiFile = files.stream()
163+
.filter(file -> file.getName().endsWith("Api.java"))
164+
.filter(file -> {
165+
try {
166+
return Files.readString(file.toPath()).contains("@ExampleObject(");
167+
} catch (IOException e) {
168+
throw new UnhandledException(e);
169+
}
170+
})
171+
.findFirst()
172+
.orElseThrow();
173+
174+
String apiContent = Files.readString(apiFile.toPath());
175+
assertTrue(apiContent.contains("@ExampleObject("));
176+
assertTrue(apiContent.contains("Value Exceeded. Must be between {min} and {max}."));
177+
assertTrue(apiContent.contains("Bad Request"));
178+
assertFalse(apiContent.contains("value = \"\\\"{"));
179+
StaticJavaParser.parse(apiFile);
180+
}
181+
142182
@Test
143183
void testReplaceBeanValidationCollectionType() {
144184
var codegen = new BoatSpringCodeGen();

0 commit comments

Comments
 (0)