Skip to content

[Micronaut] Add option to describe response wrappers #12186

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

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
2 changes: 2 additions & 0 deletions docs/generators/java-micronaut-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|parentGroupId|parent groupId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentVersion|parent version in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|reactive|Make the responses use Reactor Mono as wrapper| |true|
|requiredPropertiesInConstructor|Allow only to create models with all the required properties provided in constructor| |true|
|scmConnection|SCM connection in generated pom.xml| |scm:git:[email protected]:openapitools/openapi-generator.git|
|scmDeveloperConnection|SCM developer connection in generated pom.xml| |scm:git:[email protected]:openapitools/openapi-generator.git|
Expand All @@ -73,6 +74,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|title|Client service name| |null|
|useBeanValidation|Use BeanValidation API annotations| |true|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
|wrapInHttpResponse|Wrap the response in HttpResponse object| |false|

## SUPPORTED VENDOR EXTENSIONS

Expand Down
2 changes: 2 additions & 0 deletions docs/generators/java-micronaut-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|parentGroupId|parent groupId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentVersion|parent version in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|reactive|Make the responses use Reactor Mono as wrapper| |true|
|requiredPropertiesInConstructor|Allow only to create models with all the required properties provided in constructor| |true|
|scmConnection|SCM connection in generated pom.xml| |scm:git:[email protected]:openapitools/openapi-generator.git|
|scmDeveloperConnection|SCM developer connection in generated pom.xml| |scm:git:[email protected]:openapitools/openapi-generator.git|
Expand All @@ -75,6 +76,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useAuth|Whether to import authorization and to annotate controller methods accordingly| |true|
|useBeanValidation|Use BeanValidation API annotations| |true|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
|wrapInHttpResponse|Wrap the response in HttpResponse object| |false|

## SUPPORTED VENDOR EXTENSIONS

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,17 @@ public abstract class JavaMicronautAbstractCodegen extends AbstractJavaCodegen i
public static final String OPT_DATE_LIBRARY_JAVA8_LOCAL_DATETIME = "java8-localdatetime";
public static final String OPT_DATE_FORMAT = "dateFormat";
public static final String OPT_DATETIME_FORMAT = "datetimeFormat";
public static final String OPT_REACTIVE = "reactive";
public static final String OPT_WRAP_IN_HTTP_RESPONSE = "wrapInHttpResponse";

protected String title;
protected boolean useBeanValidation;
protected String buildTool;
protected String testTool;
protected boolean requiredPropertiesInConstructor = true;
protected String micronautVersion = "3.3.1";
protected String micronautVersion;
protected boolean reactive;
protected boolean wrapInHttpResponse;

public static final String CONTENT_TYPE_APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded";
public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json";
Expand All @@ -55,7 +59,6 @@ public JavaMicronautAbstractCodegen() {
buildTool = OPT_BUILD_ALL;
testTool = OPT_TEST_JUNIT;
outputFolder = "generated-code/java-micronaut-client";
templateDir = "java-micronaut/client";
apiPackage = "org.openapitools.api";
modelPackage = "org.openapitools.model";
invokerPackage = "org.openapitools";
Expand All @@ -64,6 +67,9 @@ public JavaMicronautAbstractCodegen() {
apiDocPath = "docs/apis";
modelDocPath = "docs/models";
dateLibrary = OPT_DATE_LIBRARY_JAVA8;
micronautVersion = "3.3.1";
reactive = true;
wrapInHttpResponse = false;

// Set implemented features for user information
modifyFeatureSet(features -> features
Expand Down Expand Up @@ -96,17 +102,19 @@ public JavaMicronautAbstractCodegen() {
cliOptions.add(new CliOption(OPT_MICRONAUT_VERSION, "Micronaut version, only >=3.0.0 versions are supported").defaultValue(micronautVersion));
cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations", useBeanValidation));
cliOptions.add(CliOption.newBoolean(OPT_REQUIRED_PROPERTIES_IN_CONSTRUCTOR, "Allow only to create models with all the required properties provided in constructor", requiredPropertiesInConstructor));
cliOptions.add(CliOption.newBoolean(OPT_REACTIVE, "Make the responses use Reactor Mono as wrapper", reactive));
cliOptions.add(CliOption.newBoolean(OPT_WRAP_IN_HTTP_RESPONSE, "Wrap the response in HttpResponse object", wrapInHttpResponse));

CliOption buildToolOption = new CliOption(OPT_BUILD, "Specify for which build tool to generate files").defaultValue(buildTool);
Map buildToolOptionMap = new HashMap<String, String>();
Map<String, String> buildToolOptionMap = new HashMap<>();
buildToolOptionMap.put(OPT_BUILD_GRADLE, "Gradle configuration is generated for the project");
buildToolOptionMap.put(OPT_BUILD_MAVEN, "Maven configuration is generated for the project");
buildToolOptionMap.put(OPT_BUILD_ALL, "Both Gradle and Maven configurations are generated");
buildToolOption.setEnum(buildToolOptionMap);
cliOptions.add(buildToolOption);

CliOption testToolOption = new CliOption(OPT_TEST, "Specify which test tool to generate files for").defaultValue(testTool);
Map testToolOptionMap = new HashMap<String, String>();
Map<String, String> testToolOptionMap = new HashMap<>();
testToolOptionMap.put(OPT_TEST_JUNIT, "Use JUnit as test tool");
testToolOptionMap.put(OPT_TEST_SPOCK, "Use Spock as test tool");
testToolOption.setEnum(testToolOptionMap);
Expand Down Expand Up @@ -163,6 +171,16 @@ public void processOpts() {
}
writePropertyBack(OPT_REQUIRED_PROPERTIES_IN_CONSTRUCTOR, requiredPropertiesInConstructor);

if (additionalProperties.containsKey(OPT_REACTIVE)) {
this.reactive = convertPropertyToBoolean(OPT_REACTIVE);
}
writePropertyBack(OPT_REACTIVE, reactive);

if (additionalProperties.containsKey(OPT_WRAP_IN_HTTP_RESPONSE)) {
this.wrapInHttpResponse = convertPropertyToBoolean(OPT_WRAP_IN_HTTP_RESPONSE);
}
writePropertyBack(OPT_WRAP_IN_HTTP_RESPONSE, wrapInHttpResponse);

// Get enum properties
if (additionalProperties.containsKey(OPT_BUILD)) {
switch ((String) additionalProperties.get(OPT_BUILD)) {
Expand Down Expand Up @@ -345,14 +363,14 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
allowableValues = (List<Object>) m.allowableValues.get("values");
}
example = getExampleValue(m.defaultValue, null, m.classname, true,
allowableValues, null, null, m.requiredVars, false);
allowableValues, null, null, m.requiredVars, false, false);
groovyExample = getExampleValue(m.defaultValue, null, m.classname, true,
allowableValues, null, null, m.requiredVars, true);
allowableValues, null, null, m.requiredVars, true, false);
} else {
example = getExampleValue(null, null, op.returnType, false, null,
op.returnBaseType, null, null, false);
op.returnBaseType, null, null, false, false);
groovyExample = getExampleValue(null, null, op.returnType, false, null,
op.returnBaseType, null, null, true);
op.returnBaseType, null, null, true, false);
}
op.vendorExtensions.put("example", example);
op.vendorExtensions.put("groovyExample", groovyExample);
Expand Down Expand Up @@ -421,7 +439,7 @@ protected String getParameterExampleValue(CodegenParameter p, boolean groovy) {
return getExampleValue(p.defaultValue, p.example, p.dataType, p.isModel, allowableValues,
p.items == null ? null : p.items.dataType,
p.items == null ? null : p.items.defaultValue,
p.requiredVars, groovy);
p.requiredVars, groovy, false);
}

protected String getPropertyExampleValue(CodegenProperty p, boolean groovy) {
Expand All @@ -430,12 +448,12 @@ protected String getPropertyExampleValue(CodegenProperty p, boolean groovy) {
return getExampleValue(p.defaultValue, p.example, p.dataType, p.isModel, allowableValues,
p.items == null ? null : p.items.dataType,
p.items == null ? null : p.items.defaultValue,
null, groovy);
null, groovy, true);
}

public String getExampleValue(
String defaultValue, String example, String dataType, Boolean isModel, List<Object> allowableValues,
String itemsType, String itemsExample, List<CodegenProperty> requiredVars, boolean groovy
String itemsType, String itemsExample, List<CodegenProperty> requiredVars, boolean groovy, boolean isProperty
) {
example = defaultValue != null ? defaultValue : example;
String containerType = dataType == null ? null : dataType.split("<")[0];
Expand Down Expand Up @@ -472,13 +490,19 @@ public String getExampleValue(
if (value == null || !allowableValues.contains(value)) {
value = allowableValues.get(0);
}
if (isProperty) {
dataType = importMapping.getOrDefault(dataType, modelPackage + '.' + dataType);
}
example = dataType + ".fromValue(\"" + value + "\")";
} else if ((isModel != null && isModel) || (isModel == null && !languageSpecificPrimitives.contains(dataType))) {
if (requiredVars == null) {
example = null;
} else {
if (requiredPropertiesInConstructor) {
StringBuilder builder = new StringBuilder();
if (isProperty) {
dataType = importMapping.getOrDefault(dataType, modelPackage + '.' + dataType);
}
builder.append("new ").append(dataType).append("(");
for (int i = 0; i < requiredVars.size(); ++i) {
if (i != 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import io.micronaut.http.client.annotation.Client;
import {{invokerPackage}}.auth.Authorization;
{{/configureAuth}}
import io.micronaut.core.convert.format.Format;
{{#reactive}}
import reactor.core.publisher.Mono;
{{/reactive}}
{{#wrapInHttpResponse}}
import io.micronaut.http.HttpResponse;
{{/wrapInHttpResponse}}
{{#imports}}import {{import}};
{{/imports}}
import javax.annotation.Generated;
Expand Down Expand Up @@ -63,9 +68,9 @@ public interface {{classname}} {
{{/authMethods}}
{{/configureAuth}}
{{!the method definition}}
{{#returnType}}Mono<{{{returnType}}}>{{/returnType}}{{^returnType}}Mono<Object>{{/returnType}} {{nickname}}({{^allParams}});{{/allParams}}{{#allParams}}
{{>common/operationReturnType}} {{nickname}}({{#allParams}}
{{>client/params/queryParams}}{{>client/params/pathParams}}{{>client/params/headerParams}}{{>client/params/bodyParams}}{{>client/params/formParams}}{{>client/params/cookieParams}}{{^-last}}, {{/-last}}{{#-last}}
);{{/-last}}{{/allParams}}
{{/-last}}{{/allParams}});
{{/operation}}
{{/operations}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ package {{package}}
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import spock.lang.Specification
import jakarta.inject.Inject
import reactor.core.publisher.Mono
import spock.lang.Ignore
{{#wrapInHttpResponse}}
import io.micronaut.http.HttpResponse
{{/wrapInHttpResponse}}
{{^fullJavaUtil}}
import java.util.Arrays
import java.util.ArrayList
import java.util.HashMap
import java.util.List
import java.util.Map
import java.util.HashSet
{{/fullJavaUtil}}


Expand All @@ -31,15 +36,23 @@ class {{classname}}Spec extends Specification {
* {{notes}}
{{/notes}}
*/
@Ignore("Not Implemented")
void '{{operationId}}() test'() {
given:
{{#allParams}}
{{{dataType}}} {{paramName}} = null
{{{dataType}}} {{paramName}} = {{{vendorExtensions.groovyExample}}}
{{/allParams}}
// {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).block()
// {{#returnType}}Mono<{{{returnType}}}>{{/returnType}}{{^returnType}}Mono<Object>{{/returnType}} asyncResponse = api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}})

expect:
when:
{{#wrapInHttpResponse}}
HttpResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> response = api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#reactive}}.block(){{/reactive}}{{#returnType}}
{{{returnType}}} body = response.body(){{/returnType}}
{{/wrapInHttpResponse}}
{{^wrapInHttpResponse}}
{{#returnType}}{{{returnType}}} body = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#reactive}}.block(){{/reactive}}
{{/wrapInHttpResponse}}

then:
true
// TODO: test validations
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ package {{package}};
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import jakarta.inject.Inject;
import reactor.core.publisher.Mono;

{{#wrapInHttpResponse}}
import io.micronaut.http.HttpResponse;
{{/wrapInHttpResponse}}
{{^fullJavaUtil}}
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.HashSet;
{{/fullJavaUtil}}


Expand All @@ -34,13 +38,24 @@ public class {{classname}}Test {
{{/notes}}
*/
@Test
@Disabled("Not Implemented")
public void {{operationId}}Test() {
// given
{{#allParams}}
{{{dataType}}} {{paramName}} = null;
{{{dataType}}} {{paramName}} = {{{example}}};
{{/allParams}}
// {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).block();
// {{#returnType}}Mono<{{{returnType}}}>{{/returnType}}{{^returnType}}Mono<Object>{{/returnType}} asyncResponse = api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
// TODO: test validations

// when
{{#wrapInHttpResponse}}
HttpResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> response = api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#reactive}}.block(){{/reactive}};{{#returnType}}
{{{returnType}}} body = response.body();{{/returnType}}
{{/wrapInHttpResponse}}
{{^wrapInHttpResponse}}
{{#returnType}}{{{returnType}}} body = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#reactive}}.block(){{/reactive}};
{{/wrapInHttpResponse}}

// then
// TODO implement the {{operationId}}Test()
}

{{/operation}}{{/operations}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{{!CLIENT CONFIGURATION}}
{{#client}}
base-path: "{{{basePath}}}/"
context-path: "{{{contextPath}}}/"

micronaut:
application:
Expand Down Expand Up @@ -56,13 +55,13 @@ micronaut:
{{/client}}
{{!SERVER CONFIGURATION}}
{{#server}}
context-path: "{{{contextPath}}}/"

micronaut:
application:
name: {{artifactId}}
server:
port: 8080
port: 8080{{#contextPath}}
context-path: "{{{contextPath}}}"{{/contextPath}}
security:
# authentication: bearer | cookie | session | idtoken
{{/server}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ dependencies {
implementation("io.micronaut.security:micronaut-security")
implementation("io.micronaut.security:micronaut-security-oauth2")
{{/useAuth}}
{{#reactive}}
implementation("io.micronaut.reactor:micronaut-reactor")
{{/reactive}}
implementation("io.swagger:swagger-annotations:1.5.9")
runtimeOnly("ch.qos.logback:logback-classic")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
{{#reactive}}
<dependency>
<groupId>io.micronaut.reactor</groupId>
<artifactId>micronaut-reactor</artifactId>
<scope>compile</scope>
</dependency>
{{/reactive}}
{{#useAuth}}
<dependency>
<groupId>io.micronaut.security</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{!begin reactive
}}{{#reactive}}Mono<{{/reactive}}{{!
begin wrapInHttpResponse
}}{{#wrapInHttpResponse}}HttpResponse<{{/wrapInHttpResponse}}{{!
return type
}}{{#returnType}}{{{returnType}}}{{/returnType}}{{!
no return type
}}{{^returnType}}{{#reactive}}Void{{/reactive}}{{^reactive}}{{#wrapInHttpResponse}}Void{{/wrapInHttpResponse}}{{/reactive}}{{^reactive}}{{^wrapInHttpResponse}}void{{/wrapInHttpResponse}}{{/reactive}}{{/returnType}}{{!
end wrapInHttpResponse
}}{{#wrapInHttpResponse}}>{{/wrapInHttpResponse}}{{!
end reactive
}}{{#reactive}}>{{/reactive}}
Loading