Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add configuration property to toggle workarounds for Asyn… #822

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ springwolf-bindings/springwolf-sqs-binding/build/
node_modules/

asyncapi.actual.json
asyncapi.actual.yaml

# Eclipse IDE
.classpath
Expand Down
1 change: 1 addition & 0 deletions springwolf-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {

implementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}"
implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jacksonVersion}"

implementation "org.slf4j:slf4j-api:${slf4jApiVersion}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,24 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties;
import io.swagger.v3.core.util.Yaml;

public class DefaultExampleYamlValueSerializer implements ExampleYamlValueSerializer {

private static final ObjectMapper yamlMapper = Yaml.mapper();
private final ObjectMapper yamlMapper;

public DefaultExampleYamlValueSerializer(SpringwolfConfigProperties springwolfConfigProperties) {
this.yamlMapper = Yaml.mapper();

if (springwolfConfigProperties.isStudioCompatibility()) {
// AsyncApi Studio has problems with missing quotes on dates, so we add quotes on every example
// see https://github.com/springwolf/springwolf-core/issues/820
((YAMLFactory) yamlMapper.getFactory()).disable(YAMLGenerator.Feature.MINIMIZE_QUOTES);
}
}

@Override
public String writeDocumentAsYamlString(JsonNode node) throws JsonProcessingException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.github.springwolf.core.asyncapi.components.examples.walkers.ExampleValueGenerator;
import io.github.springwolf.core.asyncapi.components.examples.walkers.PropertyExample;
import io.github.springwolf.core.asyncapi.components.examples.walkers.json.ExampleJsonValueGenerator;
import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import lombok.RequiredArgsConstructor;
Expand All @@ -24,6 +25,7 @@ public class ExampleYamlValueGenerator implements ExampleValueGenerator<JsonNode

private final ExampleJsonValueGenerator exampleJsonValueGenerator;
private final ExampleYamlValueSerializer exampleYamlValueSerializer;
private final SpringwolfConfigProperties springwolfConfigProperties;

@Override
public boolean canHandle(String contentType) {
Expand All @@ -39,9 +41,12 @@ public Optional<String> lookupSchemaName(Schema schema) {
public String prepareForSerialization(Schema schema, JsonNode exampleObject) {
final String name = schema.getName();
try {
// spec workaround to embedded yaml examples as string https://github.com/asyncapi/spec/issues/1038
schema.setType(OVERRIDE_SCHEMA.getType());
schema.setTypes(OVERRIDE_SCHEMA.getTypes());
if (springwolfConfigProperties.isStudioCompatibility()) {

// spec workaround to embedded yaml examples as string https://github.com/asyncapi/spec/issues/1038
schema.setType(OVERRIDE_SCHEMA.getType());
schema.setTypes(OVERRIDE_SCHEMA.getTypes());
}

return exampleYamlValueSerializer.writeDocumentAsYamlString(exampleObject);
} catch (JsonProcessingException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,17 @@ public SchemaWalker xmlSchemaWalker(ExampleXmlValueSerializer exampleXmlValueSer

@Bean
@ConditionalOnMissingBean
public ExampleYamlValueSerializer defaultExampleYamlValueSerializer() {
return new DefaultExampleYamlValueSerializer();
public ExampleYamlValueSerializer defaultExampleYamlValueSerializer(
SpringwolfConfigProperties springwolfConfigProperties) {
return new DefaultExampleYamlValueSerializer(springwolfConfigProperties);
}

@Bean
public SchemaWalker yamlSchemaWalker(ExampleYamlValueSerializer exampleYamlValueSerializer) {
return new DefaultSchemaWalker<>(
new ExampleYamlValueGenerator(new ExampleJsonValueGenerator(), exampleYamlValueSerializer));
public SchemaWalker yamlSchemaWalker(
ExampleYamlValueSerializer exampleYamlValueSerializer,
SpringwolfConfigProperties springwolfConfigProperties) {
return new DefaultSchemaWalker<>(new ExampleYamlValueGenerator(
new ExampleJsonValueGenerator(), exampleYamlValueSerializer, springwolfConfigProperties));
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ public enum InitMode {
*/
private boolean useFqn = true;

/**
* Feature toggle to enable/disable all workarounds for AsyncApi Studio
* to ensure a best-effort out-of-the-box experience.
* @see https://studio.asyncapi.com/
*/
private boolean studioCompatibility = true;

@Deprecated(forRemoval = true)
private Paths paths = new Paths();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ class DefaultYamlComponentsServiceTest {

private static final String CONTENT_TYPE_APPLICATION_YAML = "application/yaml";

private final ExampleYamlValueGenerator exampleYamlValueGenerator =
new ExampleYamlValueGenerator(new ExampleJsonValueGenerator(), new DefaultExampleYamlValueSerializer());
private final SpringwolfConfigProperties springwolfConfigProperties = new SpringwolfConfigProperties();
private final ExampleYamlValueGenerator exampleYamlValueGenerator = new ExampleYamlValueGenerator(
new ExampleJsonValueGenerator(),
new DefaultExampleYamlValueSerializer(springwolfConfigProperties),
springwolfConfigProperties);

private final SwaggerSchemaService schemaService = new SwaggerSchemaService(
List.of(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.github.springwolf.core.asyncapi.components.examples.walkers.json.ExampleJsonValueGenerator;
import io.github.springwolf.core.asyncapi.components.examples.walkers.yaml.DefaultExampleYamlValueSerializer;
import io.github.springwolf.core.asyncapi.components.examples.walkers.yaml.ExampleYamlValueGenerator;
import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.BinarySchema;
import io.swagger.v3.oas.models.media.BooleanSchema;
Expand All @@ -31,8 +32,11 @@

class DefaultSchemaWalkerYamlIntegrationTest {

private final ExampleYamlValueGenerator exampleYamlValueGenerator =
new ExampleYamlValueGenerator(new ExampleJsonValueGenerator(), new DefaultExampleYamlValueSerializer());
private final SpringwolfConfigProperties springwolfConfigProperties = new SpringwolfConfigProperties();
private final ExampleYamlValueGenerator exampleYamlValueGenerator = new ExampleYamlValueGenerator(
new ExampleJsonValueGenerator(),
new DefaultExampleYamlValueSerializer(springwolfConfigProperties),
springwolfConfigProperties);
private final DefaultSchemaWalker<JsonNode, String> jsonSchemaWalker =
new DefaultSchemaWalker<>(exampleYamlValueGenerator);

Expand Down Expand Up @@ -68,7 +72,7 @@ void build(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
string
"string"
""");
}

Expand Down Expand Up @@ -198,7 +202,7 @@ void type_string(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
string
"string"
""");
}

Expand All @@ -211,7 +215,7 @@ void type_string_example_set(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
custom-example-value
"custom-example-value"
""");
}

Expand All @@ -225,7 +229,7 @@ void type_string_from_enum(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
EnumItem1
"EnumItem1"
""");
}

Expand All @@ -238,7 +242,7 @@ void type_string_format_byte(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
YmFzZTY0LWV4YW1wbGU=
"YmFzZTY0LWV4YW1wbGU="
""");
}

Expand All @@ -264,7 +268,7 @@ void type_string_format_date(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
2015-07-20
"2015-07-20"
""");
}

Expand All @@ -277,7 +281,7 @@ void type_string_format_datetime(TestInfo testInfo) {

assertThat(actualString)
.isEqualTo("""
2015-07-20T15:49:04-07:00
"2015-07-20T15:49:04-07:00"
""");
}

Expand All @@ -289,7 +293,7 @@ void type_string_format_email(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
[email protected]
"[email protected]"
""");
}

Expand All @@ -301,7 +305,7 @@ void type_string_format_password(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
string-password
"string-password"
""");
}

Expand All @@ -314,7 +318,7 @@ void type_string_format_uuid(TestInfo testInfo) {

assertThat(actualString)
.isEqualTo("""
3fa85f64-5717-4562-b3fc-2c963f66afa6
"3fa85f64-5717-4562-b3fc-2c963f66afa6"
""");
}

Expand Down Expand Up @@ -360,7 +364,7 @@ void type_primitive_array(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(schema, emptyMap());

assertThat(actualString).isEqualTo("""
- string
- "string"
""");
}
}
Expand All @@ -383,7 +387,7 @@ void type_object_array(TestInfo testInfo) {
.isEqualTo(
"""
- b: true
s: string
s: "string"
""");
}

Expand All @@ -399,7 +403,7 @@ void composite_object_without_references(TestInfo testInfo) {
assertThat(actualString)
.isEqualTo("""
b: true
s: string
s: "string"
""");
}

Expand All @@ -423,8 +427,8 @@ void composite_object_with_references(TestInfo testInfo) {
"""
f:
b: true
s: string
s: string
s: "string"
s: "string"
""");
}

Expand All @@ -440,7 +444,7 @@ void object_with_anyOf(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(compositeSchema, Map.of("Nested", propertySchema));

assertThat(actualString).isEqualTo("""
anyOfField: string
anyOfField: "string"
""");
}

Expand All @@ -456,7 +460,7 @@ void object_with_oneOf(TestInfo testInfo) {
String actualString = jsonSchemaWalker.fromSchema(compositeSchema, Map.of("Nested", propertySchema));

assertThat(actualString).isEqualTo("""
oneOfField: string
oneOfField: "string"
""");
}

Expand All @@ -481,7 +485,7 @@ void object_with_allOf(TestInfo testInfo) {
.isEqualTo(
"""
allOfField:
field1: string
field1: "string"
field2: 1.1
""");
}
Expand All @@ -497,7 +501,7 @@ void schema_with_problematic_object_toString_example(TestInfo testInfo) {
assertThat(actualString)
.isEqualTo(
"""
Text with special character /\\\\'\\b\\f\\t\\r\\n.
"Text with special character /\\\\\\\\'\\\\b\\\\f\\\\t\\\\r\\\\n."
""");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SchemaWithOneOf$AllOf" : {
"type" : "string",
"examples" : [ "firstOne: string\nfirstTwo: 0\nsecondOne: string\nsecondTwo: true\n" ],
"examples" : [ "firstOne: \"string\"\nfirstTwo: 0\nsecondOne: \"string\"\nsecondTwo: true\n" ],
"allOf" : [ {
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SchemaWithOneOf$ImplementationOne"
}, {
Expand All @@ -10,7 +10,7 @@
},
"io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SchemaWithOneOf$AnyOf" : {
"type" : "string",
"examples" : [ "firstOne: string\nsecondOne: string\n" ],
"examples" : [ "firstOne: \"string\"\nsecondOne: \"string\"\n" ],
"anyOf" : [ {
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SchemaWithOneOf$ImplementationOne"
}, {
Expand All @@ -27,7 +27,7 @@
"type" : "string"
}
},
"examples" : [ "firstOne: string\nsecondOne: string\n" ]
"examples" : [ "firstOne: \"string\"\nsecondOne: \"string\"\n" ]
},
"io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SchemaWithOneOf$ImplementationTwo" : {
"type" : "string",
Expand All @@ -44,7 +44,7 @@
},
"io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SchemaWithOneOf$OneOf" : {
"type" : "string",
"examples" : [ "|\n firstOne: string\n secondOne: string\n" ],
"examples" : [ "\"firstOne: \\\"string\\\"\\nsecondOne: \\\"string\\\"\\n\"\n" ],
"oneOf" : [ {
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SchemaWithOneOf$ImplementationOne"
}, {
Expand All @@ -67,6 +67,6 @@
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SchemaWithOneOf$OneOf"
}
},
"examples" : [ "allOf: |\n firstOne: string\n firstTwo: 0\n secondOne: string\n secondTwo: true\nanyOf: |\n firstOne: string\n secondOne: string\nfield: string\noneOf: |\n |\n firstOne: string\n secondOne: string\n" ]
"examples" : [ "allOf: \"firstOne: \\\"string\\\"\\nfirstTwo: 0\\nsecondOne: \\\"string\\\"\\nsecondTwo: true\\n\"\nanyOf: \"firstOne: \\\"string\\\"\\nsecondOne: \\\"string\\\"\\n\"\nfield: \"string\"\noneOf: \"\\\"firstOne: \\\\\\\"string\\\\\\\"\\\\nsecondOne: \\\\\\\"string\\\\\\\"\\\\n\\\"\\n\"\n" ]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"type" : "string",
"description" : "The payload in the envelop",
"maxLength" : 10,
"examples" : [ "string\n" ]
"examples" : [ "\"string\"\n" ]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
}
}
},
"examples" : [ "flist:\n- b: true\n s: string\n" ]
"examples" : [ "flist:\n- b: true\n s: \"string\"\n" ]
},
"io.github.springwolf.core.asyncapi.components.DefaultYamlComponentsServiceTest$SimpleFoo" : {
"type" : "string",
Expand All @@ -21,6 +21,6 @@
"type" : "string"
}
},
"examples" : [ "b: true\ns: string\n" ]
"examples" : [ "b: true\ns: \"string\"\n" ]
}
}
Loading