Skip to content

Commit b87a351

Browse files
committed
[java][microprofile] Support useOneOfInterfaces
Route oneOf schemas to the shared oneof_interface template in the microprofile library's model.mustache, so useOneOfInterfaces=true renders a oneOf schema as a Java interface implemented by its subtypes, instead of an unrelated pojo. The microprofile library ships its own model.mustache (it overrides the base to support JSON-B and the jakarta/javax package split), which did not carry the oneOf-interface routing the base template has. Adding the routing lets the existing global oneof_interface template render the interface; children already implement it via x-implements. Scoped to serializationLibrary=jackson (the interface polymorphism annotations are Jackson-based). Adds a self-consistent oneof_interface_petstore.yaml fixture, a JavaClientCodegenTest case, and a microprofile-oneof-interface sample.
1 parent df45e93 commit b87a351

32 files changed

Lines changed: 1686 additions & 0 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
generatorName: java
2+
outputDir: samples/client/petstore/java/microprofile-oneof-interface
3+
library: microprofile
4+
inputSpec: modules/openapi-generator/src/test/resources/3_0/java/oneof_interface_petstore.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/Java
6+
additionalProperties:
7+
serializationLibrary: jackson
8+
artifactId: microprofile-oneof-interface
9+
useOneOfInterfaces: "true"
10+
microprofileRestClientVersion: "3.0"
11+
hideGenerationTimestamp: true

modules/openapi-generator/src/main/resources/Java/libraries/microprofile/model.mustache

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ import {{rootJavaEEPackage}}.validation.Valid;
5858

5959
{{/isEnum}}
6060
{{^isEnum}}
61+
{{#vendorExtensions.x-is-one-of-interface}}
62+
{{>oneof_interface}}
63+
{{/vendorExtensions.x-is-one-of-interface}}
64+
{{^vendorExtensions.x-is-one-of-interface}}
6165
{{>pojo}}
66+
{{/vendorExtensions.x-is-one-of-interface}}
6267

6368
{{/isEnum}}
6469
{{/model}}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4192,6 +4192,33 @@ public void givenOneOfUsesInterfacesAndLibraryNotJacksonWhenGenerateThenOneOfInt
41924192
TestUtils.assertFileNotContains(testModel.toPath(), "com.fasterxml.jackson");
41934193
}
41944194

4195+
@Test
4196+
public void oneOfInterfaceMicroprofileJackson() {
4197+
final Path output = newTempFolder();
4198+
final CodegenConfigurator configurator = new CodegenConfigurator()
4199+
.setGeneratorName(JAVA_GENERATOR)
4200+
.setLibrary(MICROPROFILE)
4201+
.setAdditionalProperties(Map.of(
4202+
USE_ONE_OF_INTERFACES, "true",
4203+
CodegenConstants.SERIALIZATION_LIBRARY, SERIALIZATION_LIBRARY_JACKSON
4204+
))
4205+
.setInputSpec("src/test/resources/3_0/java/oneof_interface_petstore.yaml")
4206+
.setOutputDir(output.toString().replace("\\", "/"));
4207+
4208+
new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
4209+
4210+
final Path model = output.resolve("src/main/java/org/openapitools/client/model");
4211+
// oneOf schema rendered as an interface (not a pojo); the discriminator getter resolves to the enum
4212+
assertFileContains(model.resolve("PetRequest.java"), "public interface PetRequest {");
4213+
assertFileContains(model.resolve("PetRequest.java"), "public PetType getPetType();");
4214+
// children implement the interface
4215+
assertFileContains(model.resolve("CatRequest.java"), "implements PetRequest");
4216+
assertFileContains(model.resolve("DogRequest.java"), "implements PetRequest");
4217+
// not sealed (useSealedOneOfInterfaces not set)
4218+
assertFileNotContains(model.resolve("PetRequest.java"), "sealed interface");
4219+
assertFileNotContains(model.resolve("CatRequest.java"), "public final class");
4220+
}
4221+
41954222
@DataProvider(name = "sealedInterfaceScenarios")
41964223
public static Object[][] sealedInterfaceScenarios() {
41974224
return new Object[][]{
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
openapi: 3.0.3
2+
info:
3+
title: oneOf interface petstore
4+
description: >
5+
A minimal, self-consistent oneOf-interface spec for the Java (microprofile) client generator.
6+
The oneOf container and the shared base both declare the discriminator property so the interface
7+
getter resolves to the enum type. Children inherit the base via allOf and only implement the
8+
generated interface.
9+
version: 1.0.0
10+
paths:
11+
/pets:
12+
post:
13+
operationId: createPet
14+
requestBody:
15+
required: true
16+
content:
17+
application/json:
18+
schema:
19+
$ref: '#/components/schemas/PetRequest'
20+
responses:
21+
'200':
22+
description: created
23+
content:
24+
application/json:
25+
schema:
26+
$ref: '#/components/schemas/PetRequest'
27+
components:
28+
schemas:
29+
PetType:
30+
type: string
31+
enum:
32+
- CAT
33+
- DOG
34+
description: Discriminator value identifying the type of pet
35+
36+
PetRequest:
37+
type: object
38+
properties:
39+
petType:
40+
$ref: '#/components/schemas/PetType'
41+
oneOf:
42+
- $ref: '#/components/schemas/CatRequest'
43+
- $ref: '#/components/schemas/DogRequest'
44+
discriminator:
45+
propertyName: petType
46+
mapping:
47+
CAT: '#/components/schemas/CatRequest'
48+
DOG: '#/components/schemas/DogRequest'
49+
50+
PetBase:
51+
type: object
52+
required:
53+
- petType
54+
- name
55+
properties:
56+
petType:
57+
$ref: '#/components/schemas/PetType'
58+
name:
59+
type: string
60+
61+
CatRequest:
62+
allOf:
63+
- $ref: '#/components/schemas/PetBase'
64+
- type: object
65+
required:
66+
- indoor
67+
properties:
68+
indoor:
69+
type: boolean
70+
71+
DogRequest:
72+
allOf:
73+
- $ref: '#/components/schemas/PetBase'
74+
- type: object
75+
required:
76+
- trained
77+
properties:
78+
trained:
79+
type: boolean
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
# The patterns follow closely to .gitignore or .dockerignore.
6+
7+
# As an example, the C# client generator defines ApiClient.cs.
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9+
#ApiClient.cs
10+
11+
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
12+
#foo/*/qux
13+
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14+
15+
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16+
#foo/**/qux
17+
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18+
19+
# You can also negate patterns with an exclamation (!).
20+
# For example, you can ignore all files in a docs folder with the file extension .md:
21+
#docs/*.md
22+
# Then explicitly reverse the ignore rule for a single file:
23+
#!docs/README.md
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
README.md
2+
docs/CatRequest.md
3+
docs/DefaultApi.md
4+
docs/DogRequest.md
5+
docs/PetBase.md
6+
docs/PetRequest.md
7+
docs/PetType.md
8+
pom.xml
9+
src/main/java/org/openapitools/client/RFC3339DateFormat.java
10+
src/main/java/org/openapitools/client/RFC3339InstantDeserializer.java
11+
src/main/java/org/openapitools/client/RFC3339JavaTimeModule.java
12+
src/main/java/org/openapitools/client/api/ApiException.java
13+
src/main/java/org/openapitools/client/api/ApiExceptionMapper.java
14+
src/main/java/org/openapitools/client/api/DefaultApi.java
15+
src/main/java/org/openapitools/client/model/CatRequest.java
16+
src/main/java/org/openapitools/client/model/DogRequest.java
17+
src/main/java/org/openapitools/client/model/PetBase.java
18+
src/main/java/org/openapitools/client/model/PetRequest.java
19+
src/main/java/org/openapitools/client/model/PetType.java
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7.24.0-SNAPSHOT
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# oneOf interface petstore - MicroProfile Rest Client & MicroProfile Server
2+
3+
A minimal, self-consistent oneOf-interface spec for the Java (microprofile) client generator. The oneOf container and the shared base both declare the discriminator property so the interface getter resolves to the enum type. Children inherit the base via allOf and only implement the generated interface.
4+
5+
6+
## Overview
7+
This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
8+
[MicroProfile Rest Client](https://github.com/eclipse/microprofile-rest-client) is a type-safe way of calling
9+
REST services. The generated client contains an interface which acts as the client, you can inject it into dependent classes.
10+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
3+
# CatRequest
4+
5+
6+
## Properties
7+
8+
| Name | Type | Description | Notes |
9+
|------------ | ------------- | ------------- | -------------|
10+
|**petType** | **PetType** | | |
11+
|**name** | **String** | | |
12+
|**indoor** | **Boolean** | | |
13+
14+
15+
## Implemented Interfaces
16+
17+
* PetRequest
18+
19+
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# DefaultApi
2+
3+
All URIs are relative to *http://localhost*
4+
5+
| Method | HTTP request | Description |
6+
|------------- | ------------- | -------------|
7+
| [**createPet**](DefaultApi.md#createPet) | **POST** /pets | |
8+
9+
10+
11+
## createPet
12+
13+
> PetRequest createPet(petRequest)
14+
15+
16+
17+
### Example
18+
19+
```java
20+
// Import classes:
21+
import org.openapitools.client.ApiClient;
22+
import org.openapitools.client.ApiException;
23+
import org.openapitools.client.Configuration;
24+
import org.openapitools.client.models.*;
25+
import org.openapitools.client.api.DefaultApi;
26+
27+
public class Example {
28+
public static void main(String[] args) {
29+
ApiClient defaultClient = Configuration.getDefaultApiClient();
30+
defaultClient.setBasePath("http://localhost");
31+
32+
DefaultApi apiInstance = new DefaultApi(defaultClient);
33+
PetRequest petRequest = new PetRequest(); // PetRequest |
34+
try {
35+
PetRequest result = apiInstance.createPet(petRequest);
36+
System.out.println(result);
37+
} catch (ApiException e) {
38+
System.err.println("Exception when calling DefaultApi#createPet");
39+
System.err.println("Status code: " + e.getCode());
40+
System.err.println("Reason: " + e.getResponseBody());
41+
System.err.println("Response headers: " + e.getResponseHeaders());
42+
e.printStackTrace();
43+
}
44+
}
45+
}
46+
```
47+
48+
### Parameters
49+
50+
51+
| Name | Type | Description | Notes |
52+
|------------- | ------------- | ------------- | -------------|
53+
| **petRequest** | [**PetRequest**](PetRequest.md)| | |
54+
55+
### Return type
56+
57+
[**PetRequest**](PetRequest.md)
58+
59+
### Authorization
60+
61+
No authorization required
62+
63+
### HTTP request headers
64+
65+
- **Content-Type**: application/json
66+
- **Accept**: application/json
67+
68+
69+
### HTTP response details
70+
| Status code | Description | Response headers |
71+
|-------------|-------------|------------------|
72+
| **200** | created | - |
73+

0 commit comments

Comments
 (0)