Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ It currently consists of
# Release Notes
BOAT is still under development and subject to change.

## 0.18.1
* Spring generator: fixed `@ExampleObject` rendering in `api.mustache` by unwrapping escaped quotes in example payloads.
* Added `unwrapEscapedQuotes` lambda to `boat-spring` generator templates to prevent malformed annotation values (for example `value = "\"{...}"`).
* Added a regression test to verify generated Spring API interfaces include valid `@ExampleObject` annotation values and remain parseable Java code.

## 0.18.0
* openapi-generator `7.20.0` baseline (Spring Boot 4, Jackson 3)
* moved Java and JavaSpring templates to `7.20.0` adding remaing custom features
Expand Down
2 changes: 1 addition & 1 deletion boat-engine/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.oss</groupId>
<artifactId>backbase-openapi-tools</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>
<artifactId>boat-engine</artifactId>
<packaging>jar</packaging>
Expand Down
2 changes: 1 addition & 1 deletion boat-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.oss</groupId>
<artifactId>backbase-openapi-tools</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>
<artifactId>boat-maven-plugin</artifactId>

Expand Down
2 changes: 1 addition & 1 deletion boat-quay/boat-quay-lint/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.oss</groupId>
<artifactId>boat-quay</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>

<artifactId>boat-quay-lint</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion boat-quay/boat-quay-rules/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.oss</groupId>
<artifactId>boat-quay</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>

<artifactId>boat-quay-rules</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion boat-quay/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.oss</groupId>
<artifactId>backbase-openapi-tools</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>


Expand Down
4 changes: 2 additions & 2 deletions boat-scaffold/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.oss</groupId>
<artifactId>backbase-openapi-tools</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>

<artifactId>boat-scaffold</artifactId>
Expand Down Expand Up @@ -102,7 +102,7 @@
<dependency>
<groupId>com.backbase.oss</groupId>
<artifactId>boat-trail-resources</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class BoatSpringCodeGen extends SpringCodegen {

public static final String ADD_SERVLET_REQUEST = "addServletRequest";
public static final String ADD_BINDING_RESULT = "addBindingResult";
public static final String UNWRAP_ESCAPED_QUOTES = "unwrapEscapedQuotes";

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

Expand Down Expand Up @@ -147,6 +148,23 @@ protected String postProcessLine(String line) {
}
}

static class UnwrapEscapedQuotes implements Mustache.Lambda {

@Override
public void execute(Fragment frag, Writer out) throws IOException {
Comment thread
jjjasper marked this conversation as resolved.
String text = frag.execute();
if (text == null) {
return;
}
String normalized = text.replace("\\\\\"", "\\\"");
if (normalized.length() >= 4 && normalized.startsWith("\\\"") && normalized.endsWith("\\\"")) {
out.write(normalized.substring(2, normalized.length() - 2));
return;
}
out.write(normalized);
}
}

/**
* Adds a HttpServletRequest object to the API definition method.
*/
Expand Down Expand Up @@ -332,6 +350,7 @@ public void processOpts() {
this.additionalProperties.put("newLine8", new NewLineIndent(8, " "));
this.additionalProperties.put("toOneLine", new FormatToOneLine());
this.additionalProperties.put("trimAndIndent4", new TrimAndIndent(4, " "));
this.additionalProperties.put(UNWRAP_ESCAPED_QUOTES, new UnwrapEscapedQuotes());
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion boat-scaffold/src/main/templates/boat-spring/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public interface {{classname}} {
{{#examples}}
@ExampleObject(
name = "{{{exampleName}}}",
value = "{{{exampleValue}}}"
value = "{{#unwrapEscapedQuotes}}{{{exampleValue}}}{{/unwrapEscapedQuotes}}"
){{^-last}},{{/-last}}
{{/examples}}
{{#-last}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -48,14 +49,17 @@
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.UnhandledException;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenOperation;
Expand Down Expand Up @@ -97,6 +101,20 @@ void newLineIndent() throws IOException {
assertThat(output.toString(), equalTo(String.format("__%n__Good%n__ morning,%n__ Dave%n")));
}

@ParameterizedTest
@MethodSource("unwrapEscapedQuotesCases")
void unwrapEscapedQuotes_execute_shouldHandleAllScenarios(String input, String expectedOutput) throws IOException {
final BoatSpringCodeGen.UnwrapEscapedQuotes lambda = new BoatSpringCodeGen.UnwrapEscapedQuotes();
final StringWriter output = new StringWriter();
final Fragment frag = mock(Fragment.class);

when(frag.execute()).thenReturn(input);

lambda.execute(frag, output);

assertThat(output.toString(), equalTo(expectedOutput));
}

@Test
void addServletRequestTestFromOperation(){
final BoatSpringCodeGen gen = new BoatSpringCodeGen();
Expand Down Expand Up @@ -139,6 +157,45 @@ void multipartWithFileAndObject() throws IOException {
assertThat(filesParam.getTypeAsString(), equalTo("List<MultipartFile>"));
}

@Test
void shouldGenerateValidExampleObjectAnnotation() throws IOException {
var codegen = new BoatSpringCodeGen();
var input = new File("src/test/resources/openapi-with-examples/openapi-with-multiple-permissions.yaml");
codegen.setLibrary("spring-boot");
codegen.setInterfaceOnly(true);
codegen.setSkipDefaultInterface(true);
codegen.setOutputDir(TEST_OUTPUT + "/example-object");
codegen.setInputSpec(input.getAbsolutePath());
codegen.additionalProperties().put(SpringCodegen.USE_SPRING_BOOT3, Boolean.TRUE.toString());

var openApiInput = new OpenAPIParser().readLocation(input.getAbsolutePath(), null, new ParseOptions())
.getOpenAPI();
var clientOptInput = new ClientOptInput();
clientOptInput.config(codegen);
clientOptInput.openAPI(openApiInput);

List<File> files = new DefaultGenerator().opts(clientOptInput).generate();

File apiFile = files.stream()
.filter(file -> file.getName().endsWith("Api.java"))
.filter(file -> {
try {
return Files.readString(file.toPath()).contains("@ExampleObject(");
} catch (IOException e) {
throw new UnhandledException(e);
}
})
.findFirst()
.orElseThrow();

String apiContent = Files.readString(apiFile.toPath());
assertTrue(apiContent.contains("@ExampleObject("));
assertTrue(apiContent.contains("Value Exceeded. Must be between {min} and {max}."));
assertTrue(apiContent.contains("Bad Request"));
assertFalse(apiContent.contains("value = \"\\\"{"));
StaticJavaParser.parse(apiFile);
}

@Test
void testReplaceBeanValidationCollectionType() {
var codegen = new BoatSpringCodeGen();
Expand Down Expand Up @@ -552,4 +609,12 @@ private static void assertMethodCollectionReturnType(MethodDeclaration method, S
.getTypeArguments().get().getFirst().get();
assertEquals(itemType, collectionItemType.getName().toString());
}

static Stream<Arguments> unwrapEscapedQuotesCases() {
return Stream.of(
Arguments.of((String) null, ""),
Arguments.of("\\\"{\\\"message\\\":\\\"Bad Request\\\"}\\\"", "{\\\"message\\\":\\\"Bad Request\\\"}"),
Arguments.of("prefix\\\\\"quoted\\\\\"suffix", "prefix\\\"quoted\\\"suffix"),
Arguments.of("\\\"", "\\\""));
}
}
2 changes: 1 addition & 1 deletion boat-trail-resources/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.oss</groupId>
<artifactId>backbase-openapi-tools</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>

<artifactId>boat-trail-resources</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>com.backbase.oss</groupId>
<artifactId>backbase-openapi-tools</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>

<packaging>pom</packaging>
<description>Backbase Open Api Tools is a collection of tools to work with Open API</description>
Expand Down
2 changes: 1 addition & 1 deletion tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.oss</groupId>
<artifactId>backbase-openapi-tools</artifactId>
<version>0.18.0-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>

<artifactId>tests</artifactId>
Expand Down