diff --git a/docs/generators/spring.md b/docs/generators/spring.md index 13d7bf229e7..51e46424f06 100644 --- a/docs/generators/spring.md +++ b/docs/generators/spring.md @@ -48,6 +48,7 @@ sidebar_label: spring |interfaceOnly|Whether to generate only API interface stubs without the server files.| |false| |delegatePattern|Whether to generate the server files using the delegate pattern| |false| |singleContentTypes|Whether to select only one produces/consumes content-type by operation.| |false| +|skipDefaultInterface|Whether to generate default implementations for java8 interfaces| |false| |async|use async Callable controllers| |false| |reactive|wrap responses in Mono/Flux Reactor types (spring-boot only)| |false| |responseWrapper|wrap the responses in given type (Future,Callable,CompletableFuture,ListenableFuture,DeferredResult,HystrixCommand,RxObservable,RxSingle or fully qualified type)| |null| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index 0946fc271c1..4b8373004f7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -52,6 +52,7 @@ public class SpringCodegen extends AbstractJavaCodegen public static final String DELEGATE_PATTERN = "delegatePattern"; public static final String SINGLE_CONTENT_TYPES = "singleContentTypes"; public static final String VIRTUAL_SERVICE = "virtualService"; + public static final String SKIP_DEFAULT_INTERFACE = "skipDefaultInterface"; public static final String JAVA_8 = "java8"; public static final String ASYNC = "async"; @@ -79,6 +80,7 @@ public class SpringCodegen extends AbstractJavaCodegen protected boolean async = false; protected boolean reactive = false; protected String responseWrapper = ""; + protected boolean skipDefaultInterface = false; protected boolean useTags = false; protected boolean useBeanValidation = true; protected boolean performBeanValidation = false; @@ -119,6 +121,7 @@ public class SpringCodegen extends AbstractJavaCodegen cliOptions.add(CliOption.newBoolean(DELEGATE_PATTERN, "Whether to generate the server files using the delegate pattern", delegatePattern)); cliOptions.add(CliOption.newBoolean(SINGLE_CONTENT_TYPES, "Whether to select only one produces/consumes content-type by operation.", singleContentTypes)); updateJava8CliOptions(); + cliOptions.add(CliOption.newBoolean(SKIP_DEFAULT_INTERFACE, "Whether to generate default implementations for java8 interfaces", skipDefaultInterface)); cliOptions.add(CliOption.newBoolean(ASYNC, "use async Callable controllers", async)); cliOptions.add(CliOption.newBoolean(REACTIVE, "wrap responses in Mono/Flux Reactor types (spring-boot only)", reactive)); cliOptions.add(new CliOption(RESPONSE_WRAPPER, "wrap the responses in given type (Future,Callable,CompletableFuture,ListenableFuture,DeferredResult,HystrixCommand,RxObservable,RxSingle or fully qualified type)")); @@ -234,6 +237,10 @@ public class SpringCodegen extends AbstractJavaCodegen this.setSingleContentTypes(Boolean.valueOf(additionalProperties.get(SINGLE_CONTENT_TYPES).toString())); } + if (additionalProperties.containsKey(SKIP_DEFAULT_INTERFACE)) { + this.setSkipDefaultInterface(Boolean.valueOf(additionalProperties.get(SKIP_DEFAULT_INTERFACE).toString())); + } + if (additionalProperties.containsKey(ASYNC)) { this.setAsync(Boolean.valueOf(additionalProperties.get(ASYNC).toString())); //fix for issue/1164 @@ -393,6 +400,7 @@ public class SpringCodegen extends AbstractJavaCodegen if (this.java8) { additionalProperties.put("javaVersion", "1.8"); + additionalProperties.put("jdk8-default-interface", !this.skipDefaultInterface); if (!SPRING_CLOUD_LIBRARY.equals(library)) { additionalProperties.put("jdk8", true); } @@ -414,6 +422,7 @@ public class SpringCodegen extends AbstractJavaCodegen // Some well-known Spring or Spring-Cloud response wrappers if (isNotEmpty(this.responseWrapper)) { additionalProperties.put("jdk8", false); + additionalProperties.put("jdk8-default-interface", false); switch (this.responseWrapper) { case "Future": case "Callable": @@ -716,6 +725,8 @@ public class SpringCodegen extends AbstractJavaCodegen this.singleContentTypes = singleContentTypes; } + public void setSkipDefaultInterface(boolean skipDefaultInterface) { this.skipDefaultInterface = skipDefaultInterface; } + public void setJava8(boolean java8) { this.java8 = java8; } public void setVirtualService(boolean virtualService) { this.virtualService = virtualService; } diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache index c1c1d9ab86e..067c32dbbdf 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache @@ -66,7 +66,7 @@ import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture @VirtualService {{/virtualService}} public interface {{classname}} { -{{#jdk8}} +{{#jdk8-default-interface}} {{^isDelegate}} {{^reactive}} @@ -81,7 +81,7 @@ public interface {{classname}} { return new {{classname}}Delegate() {}; } {{/isDelegate}} -{{/jdk8}} +{{/jdk8-default-interface}} {{#operation}} {{#virtualService}} @@ -109,13 +109,13 @@ public interface {{classname}} { produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}} consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}} method = RequestMethod.{{httpMethod}}) - {{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{^hasMore}}{{#reactive}}, {{/reactive}}{{/hasMore}}{{/allParams}}{{#reactive}}ServerWebExchange exchange{{/reactive}}){{^jdk8}};{{/jdk8}}{{#jdk8}}{{#unhandledException}} throws Exception{{/unhandledException}} { + {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{^hasMore}}{{#reactive}}, {{/reactive}}{{/hasMore}}{{/allParams}}{{#reactive}}ServerWebExchange exchange{{/reactive}}){{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}}{{#unhandledException}} throws Exception{{/unhandledException}} { {{#delegate-method}} return {{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}); } // Override this method - {{#jdk8}}default {{/jdk8}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}MultipartFile{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}ServerWebExchange exchange{{/reactive}}) { + {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}MultipartFile{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}ServerWebExchange exchange{{/reactive}}) { {{/delegate-method}} {{^isDelegate}} {{>methodBody}} @@ -123,8 +123,8 @@ public interface {{classname}} { {{#isDelegate}} return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}); {{/isDelegate}} - }{{/jdk8}} + }{{/jdk8-default-interface}} {{/operation}} } -{{/operations}} \ No newline at end of file +{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache index 76bc71fbb33..15a51ceb99e 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache @@ -39,22 +39,22 @@ import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture */ {{>generatedAnnotation}} public interface {{classname}}Delegate { -{{#jdk8}} +{{#jdk8-default-interface}} default Optional getRequest() { return Optional.empty(); } -{{/jdk8}} +{{/jdk8-default-interface}} {{#operation}} /** * @see {{classname}}#{{operationId}} */ - {{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}MultipartFile{{/isFile}} {{paramName}}{{#hasMore}}, + {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}MultipartFile{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, - {{/hasParams}}ServerWebExchange exchange{{/reactive}}){{^jdk8}};{{/jdk8}}{{#jdk8}} { + {{/hasParams}}ServerWebExchange exchange{{/reactive}}){{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} { {{>methodBody}} - }{{/jdk8}} + }{{/jdk8-default-interface}} {{/operation}} }