Skip to content

Commit d62e2eb

Browse files
committed
fix (JAVA): example in README for useOneOfInterfaces (#17419)
1 parent 197c047 commit d62e2eb

4 files changed

Lines changed: 77 additions & 1 deletion

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,9 @@ apiTemplateFiles are for API outputs only (controllers/handlers).
317317
// whether or not the oneOf imports machinery should add oneOf interfaces as imports in implementing classes
318318
protected boolean addOneOfInterfaceImports = false;
319319
protected List<CodegenModel> addOneOfInterfaces = new ArrayList<>();
320+
// set of all classnames that are oneOf interfaces (both synthetic property-level and component-level)
321+
// populated during preprocessOpenAPI(), used by setParameterExampleValue() to avoid "new InterfaceType()"
322+
protected Set<String> oneOfInterfaceNames = new HashSet<>();
320323

321324
// flag to indicate whether to only update files whose contents have changed
322325
protected boolean enableMinimalUpdate = false;
@@ -1123,6 +1126,7 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
11231126
} else {
11241127
// else this is a component schema, so we will just use that as the oneOf interface model
11251128
addOneOfNameExtension(s, n);
1129+
oneOfInterfaceNames.add(n);
11261130
}
11271131
} else if (ModelUtils.isArraySchema(s)) {
11281132
Schema items = ModelUtils.getSchemaItems(s);
@@ -8624,6 +8628,7 @@ public void addOneOfInterfaceModel(Schema cs, String type) {
86248628
cm.interfaceModels = new ArrayList<>();
86258629

86268630
addOneOfInterfaces.add(cm);
8631+
oneOfInterfaceNames.add(type);
86278632
}
86288633

86298634
public void addImportsToOneOfInterface(List<Map<String, String>> imports) {

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,13 @@ public void setParameterExampleValue(CodegenParameter p) {
17861786
example = type + ".fromValue(\"" + example + "\")";
17871787
} else if (!languageSpecificPrimitives.contains(type)) {
17881788
// type is a model class, e.g. User
1789-
example = "new " + type + "()";
1789+
// if useOneOfInterfaces is enabled and the type is a generated oneOf interface,
1790+
// we cannot instantiate it with 'new', so we use null instead
1791+
if (useOneOfInterfaces && oneOfInterfaceNames.contains(type)) {
1792+
example = "null";
1793+
} else {
1794+
example = "new " + type + "()";
1795+
}
17901796
}
17911797

17921798
if (example == null) {

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4480,4 +4480,33 @@ public void testOkHttpGsonClientWithUseOneOfInterfaceShouldntRegisterInterfaceAs
44804480
);
44814481
}
44824482

4483+
@Test(dataProvider = "allJavaClients")
4484+
public void testClientWithUseOneOfInterfaceShouldntInstantiateInterfaceInApiDoc_issue_17419(String client) {
4485+
// given
4486+
final Path output = newTempFolder();
4487+
final CodegenConfigurator configurator = new CodegenConfigurator()
4488+
.setGeneratorName("java")
4489+
.setLibrary(client)
4490+
.setAdditionalProperties(Map.of("useOneOfInterfaces", "true"))
4491+
.setInputSpec("src/test/resources/bugs/issue_17419_readme.yaml")
4492+
.setOutputDir(output.toString().replace("\\", "/"));
4493+
4494+
final ClientOptInput input = configurator.toClientOptInput();
4495+
4496+
// when
4497+
List<File> files = new DefaultGenerator().opts(input).generate();
4498+
4499+
// then
4500+
validateJavaSourceFiles(files);
4501+
4502+
// In every generated Markdown file (README.md, api_doc, etc.) the example for a
4503+
// oneOf interface parameter must not contain "new MyOperationRequest()" since
4504+
// interfaces cannot be instantiated with 'new'.
4505+
files.stream()
4506+
.filter(f -> f.getName().endsWith(".md"))
4507+
.forEach(f -> TestUtils.assertFileNotContains(f.toPath(),
4508+
"new MyOperationRequest()"
4509+
));
4510+
}
4511+
44834512
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
openapi: 3.0.0
2+
info:
3+
title: OneOf interface README bug
4+
version: '1.0'
5+
servers:
6+
- url: 'http://localhost:8080'
7+
paths:
8+
'/myapi/myendpoint':
9+
post:
10+
operationId: myOperation
11+
requestBody:
12+
required: true
13+
content:
14+
application/json:
15+
schema:
16+
$ref: '#/components/schemas/MyOperationRequest'
17+
responses:
18+
'200':
19+
description: OK
20+
components:
21+
schemas:
22+
MyOperationRequest:
23+
oneOf:
24+
- $ref: '#/components/schemas/VariantA'
25+
- $ref: '#/components/schemas/VariantB'
26+
VariantA:
27+
type: object
28+
properties:
29+
fieldA:
30+
type: string
31+
VariantB:
32+
type: object
33+
properties:
34+
fieldB:
35+
type: integer
36+

0 commit comments

Comments
 (0)