diff --git a/.github/workflows/samples-java-dubbo.yaml b/.github/workflows/samples-java-dubbo.yaml
new file mode 100644
index 00000000000..16842d995fc
--- /dev/null
+++ b/.github/workflows/samples-java-dubbo.yaml
@@ -0,0 +1,39 @@
+name: Samples Java Dubbo
+
+on:
+ push:
+ paths:
+ - 'samples/server/petstore/java-dubbo/**'
+ pull_request:
+ paths:
+ - 'samples/server/petstore/java-dubbo/**'
+
+jobs:
+ build:
+ name: Build Java Dubbo
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ sample:
+ # servers
+ - samples/server/petstore/java-dubbo
+ steps:
+ - uses: actions/checkout@v5
+ - uses: actions/setup-java@v5
+ with:
+ distribution: 'temurin'
+ java-version: 17
+ - name: Cache maven dependencies
+ uses: actions/cache@v4
+ env:
+ cache-name: maven-repository
+ with:
+ path: |
+ ~/.m2
+ key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
+ - name: Build
+ working-directory: ${{ matrix.sample }}
+ run: mvn clean package --no-transfer-progress -DskipTests
+ # add -DskipTests as the app compiles but fails to start
+ #run: mvn clean package --no-transfer-progress
diff --git a/README.md b/README.md
index 4e77eb2ad14..64893e4859c 100644
--- a/README.md
+++ b/README.md
@@ -1143,6 +1143,7 @@ Here is a list of template creators:
* Haskell Servant: @algas
* Haskell Yesod: @yotsuya
* Java Camel: @carnevalegiacomo
+ * Java Dubbo: @redoom
* Java MSF4J: @sanjeewa-malalgoda
* Java Spring Boot: @diyfr
* Java Undertow: @stevehu
diff --git a/bin/configs/java-dubbo-server.yaml b/bin/configs/java-dubbo-server.yaml
new file mode 100644
index 00000000000..1b285d67f70
--- /dev/null
+++ b/bin/configs/java-dubbo-server.yaml
@@ -0,0 +1,15 @@
+generatorName: java-dubbo
+outputDir: samples/server/petstore/java-dubbo
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/java-dubbo
+additionalProperties:
+ hideGenerationTimestamp: "true"
+ artifactId: openapi-dubbo-server-petstore
+ basePackage: "org.openapitools.example"
+ title: "OpenAPI Petstore"
+ serviceInterface: true
+ serviceImplementation: true
+ useTags: true
+ dubboVersion: "3.2.18"
+ javaVersion: "17"
+ registryAddress: "zookeeper://127.0.0.1:2181"
diff --git a/docs/generators.md b/docs/generators.md
index da5ce385155..710d2614290 100644
--- a/docs/generators.md
+++ b/docs/generators.md
@@ -106,6 +106,7 @@ The following generators are available:
* [haskell](generators/haskell.md)
* [haskell-yesod (beta)](generators/haskell-yesod.md)
* [java-camel](generators/java-camel.md)
+* [java-dubbo (beta)](generators/java-dubbo.md)
* [java-helidon-server (beta)](generators/java-helidon-server.md)
* [java-inflector](generators/java-inflector.md)
* [java-micronaut-server (beta)](generators/java-micronaut-server.md)
diff --git a/docs/generators/java-dubbo.md b/docs/generators/java-dubbo.md
new file mode 100644
index 00000000000..fa64f3d3595
--- /dev/null
+++ b/docs/generators/java-dubbo.md
@@ -0,0 +1,351 @@
+---
+title: Documentation for the java-dubbo Generator
+---
+
+## METADATA
+
+| Property | Value | Notes |
+| -------- | ----- | ----- |
+| generator name | java-dubbo | pass this to the generate command after -g |
+| generator stability | BETA | |
+| generator type | SERVER | |
+| generator language | Java | |
+| generator default templating engine | mustache | |
+| helpTxt | Generates a Java Apache Dubbo server application. | |
+
+## CONFIG OPTIONS
+These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
+
+| Option | Description | Values | Default |
+| ------ | ----------- | ------ | ------- |
+|additionalEnumTypeAnnotations|Additional annotations for enum type(class level annotations)| |null|
+|additionalModelTypeAnnotations|Additional annotations for model type(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)| |null|
+|additionalOneOfTypeAnnotations|Additional annotations for oneOf interfaces(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)| |null|
+|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
+|apiPackage|package for generated api classes| |org.openapitools.api|
+|artifactDescription|artifact description in generated pom.xml| |OpenAPI Java|
+|artifactId|artifactId in generated pom.xml. This also becomes part of the generated library's filename| |openapi-dubbo|
+|artifactUrl|artifact URL in generated pom.xml| |https://github.com/openapitools/openapi-generator|
+|artifactVersion|artifact version in generated pom.xml. This also becomes part of the generated library's filename. If not provided, uses the version from the OpenAPI specification file. If that's also not present, uses the default value of the artifactVersion option.| |1.0.0|
+|basePackage|base package (invokerPackage) for generated code| |org.openapitools|
+|bigDecimalAsString|Treat BigDecimal values as Strings to avoid precision loss.| |false|
+|booleanGetterPrefix|Set booleanGetterPrefix| |get|
+|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
+|configPackage|configuration package for generated code| |org.openapitools.configuration|
+|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
+|dateLibrary|Option. Date library to use|
**joda** Joda (for legacy app only) **legacy** Legacy java.util.Date **java8-localdatetime** Java 8 using LocalDateTime (for legacy app only) **java8** Java 8 native JSR310 (preferred for jdk 1.8+) |java8|
+|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
+|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
+|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|
+|developerOrganizationUrl|developer organization URL in generated pom.xml| |http://openapitools.org|
+|disableHtmlEscaping|Disable HTML escaping of JSON strings when using gson (needed to avoid problems with byte[] fields)| |false|
+|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|**false** The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications. **true** Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default. |true|
+|discriminatorCaseSensitive|Whether the discriminator value lookup should be case-sensitive or not. This option only works for Java API client| |true|
+|dubboVersion|Dubbo version| |3.2.18|
+|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
+|enumPropertyNaming|Naming convention for enum properties: 'MACRO_CASE', 'legacy' and 'original'| |MACRO_CASE|
+|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|**false** No changes to the enum's are made, this is the default option. **true** With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case. |false|
+|generateBuilders|Whether to generate builders for models| |false|
+|generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false|
+|groupId|groupId in generated pom.xml| |org.openapitools|
+|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |false|
+|ignoreAnyOfInEnum|Ignore anyOf keyword in enum| |false|
+|implicitHeaders|Skip header parameters in the generated API methods using @ApiImplicitParams annotation.| |false|
+|implicitHeadersRegex|Skip header parameters that matches given regex in the generated API methods using @ApiImplicitParams annotation. Note: this parameter is ignored when implicitHeaders=true| |null|
+|interfaceOnly|Whether to generate only API interface stubs without the server files.| |false|
+|invokerPackage|root package for generated code| |org.openapitools|
+|javaVersion|Java version| |17|
+|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|**true** The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document. **false** The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing. |true|
+|licenseName|The name of the license| |Unlicense|
+|licenseUrl|The URL of the license| |http://unlicense.org|
+|modelPackage|package for generated models| |org.openapitools.model|
+|openApiNullable|Enable OpenAPI Jackson Nullable library. Not supported by `microprofile` library.| |true|
+|parentArtifactId|parent artifactId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
+|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|
+|registry-address|Registry address (e.g., zookeeper://127.0.0.1:2181 or nacos://127.0.0.1:8848)| |zookeeper://127.0.0.1:2181|
+|scmConnection|SCM connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
+|scmDeveloperConnection|SCM developer connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
+|scmUrl|SCM URL in generated pom.xml| |https://github.com/openapitools/openapi-generator|
+|serializableModel|boolean - toggle "implements Serializable" for generated models| |false|
+|serviceImplementation|Generate service implementation| |true|
+|serviceInterface|Generate service interface| |true|
+|snapshotVersion|Uses a SNAPSHOT version.|**true** Use a SnapShot Version **false** Use a Release Version |null|
+|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
+|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
+|sourceFolder|source folder for generated code| |src/main/java|
+|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
+|title|API title name| |null|
+|useGenericResponse|Use generic response wrapper| |false|
+|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
+|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
+|useTags|use tags for creating interface and controller classnames| |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|
+
+## SUPPORTED VENDOR EXTENSIONS
+
+| Extension name | Description | Applicable for | Default value |
+| -------------- | ----------- | -------------- | ------------- |
+|x-discriminator-value|Used with model inheritance to specify value for discriminator that identifies current model|MODEL|
+|x-implements|Ability to specify interfaces that model must implements|MODEL|empty array
+|x-setter-extra-annotation|Custom annotation that can be specified over java setter for specific field|FIELD|When field is array & uniqueItems, then this extension is used to add `@JsonDeserialize(as = LinkedHashSet.class)` over setter, otherwise no value
+|x-tags|Specify multiple swagger tags for operation|OPERATION|null
+|x-accepts|Specify custom value for 'Accept' header for operation|OPERATION|null
+|x-content-type|Specify custom value for 'Content-Type' header for operation|OPERATION|null
+|x-class-extra-annotation|List of custom annotations to be added to model|MODEL|null
+|x-field-extra-annotation|List of custom annotations to be added to property|FIELD, OPERATION_PARAMETER|null
+
+
+## IMPORT MAPPING
+
+| Type/Alias | Imports |
+| ---------- | ------- |
+|Array|java.util.List|
+|ArrayList|java.util.ArrayList|
+|Arrays|java.util.Arrays|
+|BigDecimal|java.math.BigDecimal|
+|BigInteger|java.math.BigInteger|
+|Date|java.util.Date|
+|DateTime|org.joda.time.*|
+|File|java.io.File|
+|HashMap|java.util.HashMap|
+|HashSet|java.util.HashSet|
+|LinkedHashSet|java.util.LinkedHashSet|
+|List|java.util.List|
+|LocalDate|java.time.LocalDate|
+|LocalDateTime|java.time.LocalDateTime|
+|LocalTime|java.time.LocalTime|
+|Map|java.util.Map|
+|MultipartFile|org.springframework.web.multipart.MultipartFile|
+|OffsetDateTime|java.time.OffsetDateTime|
+|Set|java.util.Set|
+|Timestamp|java.sql.Timestamp|
+|URI|java.net.URI|
+|UUID|java.util.UUID|
+
+
+## INSTANTIATION TYPES
+
+| Type/Alias | Instantiated By |
+| ---------- | --------------- |
+|array|ArrayList|
+|map|HashMap|
+|set|LinkedHashSet|
+
+
+## LANGUAGE PRIMITIVES
+
+
+Boolean
+Double
+Float
+Integer
+List
+Long
+Map
+Object
+Set
+String
+boolean
+
+
+## RESERVED WORDS
+
+
+_
+abstract
+apiclient
+apiexception
+apiresponse
+assert
+boolean
+break
+byte
+case
+catch
+char
+class
+configuration
+const
+continue
+default
+do
+double
+else
+enum
+extends
+file
+final
+finally
+float
+for
+goto
+if
+implements
+import
+instanceof
+int
+interface
+list
+localdate
+localreturntype
+localtime
+localvaraccept
+localvaraccepts
+localvarauthnames
+localvarcollectionqueryparams
+localvarcontenttype
+localvarcontenttypes
+localvarcookieparams
+localvarformparams
+localvarheaderparams
+localvarpath
+localvarpostbody
+localvarqueryparams
+long
+native
+new
+null
+object
+offsetdatetime
+package
+private
+protected
+public
+return
+short
+static
+strictfp
+stringutil
+super
+switch
+synchronized
+this
+throw
+throws
+transient
+try
+void
+volatile
+while
+
+
+## FEATURE SET
+
+
+### Client Modification Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|BasePath|✓|ToolingExtension
+|Authorizations|✗|ToolingExtension
+|UserAgent|✗|ToolingExtension
+|MockServer|✗|ToolingExtension
+
+### Data Type Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Custom|✗|OAS2,OAS3
+|Int32|✓|OAS2,OAS3
+|Int64|✓|OAS2,OAS3
+|Float|✓|OAS2,OAS3
+|Double|✓|OAS2,OAS3
+|Decimal|✓|ToolingExtension
+|String|✓|OAS2,OAS3
+|Byte|✓|OAS2,OAS3
+|Binary|✓|OAS2,OAS3
+|Boolean|✓|OAS2,OAS3
+|Date|✓|OAS2,OAS3
+|DateTime|✓|OAS2,OAS3
+|Password|✓|OAS2,OAS3
+|File|✓|OAS2
+|Uuid|✗|
+|Array|✓|OAS2,OAS3
+|Null|✗|OAS3
+|AnyType|✗|OAS2,OAS3
+|Object|✓|OAS2,OAS3
+|Maps|✓|ToolingExtension
+|CollectionFormat|✓|OAS2
+|CollectionFormatMulti|✓|OAS2
+|Enum|✓|OAS2,OAS3
+|ArrayOfEnum|✓|ToolingExtension
+|ArrayOfModel|✓|ToolingExtension
+|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
+|ArrayOfCollectionOfModel|✓|ToolingExtension
+|ArrayOfCollectionOfEnum|✓|ToolingExtension
+|MapOfEnum|✓|ToolingExtension
+|MapOfModel|✓|ToolingExtension
+|MapOfCollectionOfPrimitives|✓|ToolingExtension
+|MapOfCollectionOfModel|✓|ToolingExtension
+|MapOfCollectionOfEnum|✓|ToolingExtension
+
+### Documentation Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Readme|✓|ToolingExtension
+|Model|✓|ToolingExtension
+|Api|✓|ToolingExtension
+
+### Global Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Host|✓|OAS2,OAS3
+|BasePath|✓|OAS2,OAS3
+|Info|✓|OAS2,OAS3
+|Schemes|✗|OAS2,OAS3
+|PartialSchemes|✓|OAS2,OAS3
+|Consumes|✓|OAS2
+|Produces|✓|OAS2
+|ExternalDocumentation|✓|OAS2,OAS3
+|Examples|✓|OAS2,OAS3
+|XMLStructureDefinitions|✗|OAS2,OAS3
+|MultiServer|✗|OAS3
+|ParameterizedServer|✗|OAS3
+|ParameterStyling|✗|OAS3
+|Callbacks|✗|OAS3
+|LinkObjects|✗|OAS3
+
+### Parameter Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Path|✓|OAS2,OAS3
+|Query|✓|OAS2,OAS3
+|Header|✓|OAS2,OAS3
+|Body|✓|OAS2
+|FormUnencoded|✓|OAS2
+|FormMultipart|✓|OAS2
+|Cookie|✗|OAS3
+
+### Schema Support Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Simple|✓|OAS2,OAS3
+|Composite|✓|OAS2,OAS3
+|Polymorphism|✓|OAS2,OAS3
+|Union|✗|OAS3
+|allOf|✗|OAS2,OAS3
+|anyOf|✗|OAS3
+|oneOf|✗|OAS3
+|not|✗|OAS3
+
+### Security Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|BasicAuth|✓|OAS2,OAS3
+|ApiKey|✓|OAS2,OAS3
+|OpenIDConnect|✗|OAS3
+|BearerToken|✗|OAS3
+|OAuth2_Implicit|✓|OAS2,OAS3
+|OAuth2_Password|✓|OAS2,OAS3
+|OAuth2_ClientCredentials|✓|OAS2,OAS3
+|OAuth2_AuthorizationCode|✓|OAS2,OAS3
+|SignatureAuth|✗|OAS3
+|AWSV4Signature|✗|ToolingExtension
+
+### Wire Format Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|JSON|✓|OAS2,OAS3
+|XML|✓|OAS2,OAS3
+|PROTOBUF|✗|ToolingExtension
+|Custom|✓|OAS2,OAS3
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaDubboServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaDubboServerCodegen.java
new file mode 100644
index 00000000000..5d28f7b0b55
--- /dev/null
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaDubboServerCodegen.java
@@ -0,0 +1,885 @@
+/*
+ * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law of or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openapitools.codegen.languages;
+
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import org.openapitools.codegen.*;
+
+import org.openapitools.codegen.meta.GeneratorMetadata;
+import org.openapitools.codegen.meta.Stability;
+import org.openapitools.codegen.meta.features.*;
+import org.openapitools.codegen.model.ModelMap;
+import org.openapitools.codegen.model.ModelsMap;
+import org.openapitools.codegen.model.OperationMap;
+import org.openapitools.codegen.model.OperationsMap;
+import org.openapitools.codegen.templating.mustache.TrimWhitespaceLambda;
+import org.openapitools.codegen.utils.ModelUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
+
+import org.openapitools.codegen.utils.CamelizeOption;
+
+import static org.openapitools.codegen.utils.StringUtils.camelize;
+
+
+public class JavaDubboServerCodegen extends AbstractJavaCodegen {
+ private final Logger LOGGER = LoggerFactory.getLogger(JavaDubboServerCodegen.class);
+
+ public static final String TITLE = "title";
+ public static final String CONFIG_PACKAGE = "configPackage";
+ public static final String BASE_PACKAGE = "basePackage";
+ public static final String INTERFACE_ONLY = "interfaceOnly";
+ public static final String USE_TAGS = "useTags";
+ public static final String DUBBO_VERSION = "dubboVersion";
+ public static final String JAVA_VERSION = "javaVersion";
+ public static final String SERVICE_INTERFACE = "serviceInterface";
+ public static final String SERVICE_IMPLEMENTATION = "serviceImplementation";
+ public static final String USE_GENERIC_RESPONSE = "useGenericResponse";
+ public static final String REGISTRY_ADDRESS = "registry-address";
+
+ @Setter
+ protected String title = null;
+ @Getter
+ @Setter
+ protected String configPackage = "org.openapitools.configuration";
+ @Getter
+ @Setter
+ protected String basePackage = "org.openapitools";
+
+ @Setter
+ protected boolean interfaceOnly = false;
+ @Setter
+ protected boolean useTags = true;
+ @Setter
+ protected String javaVersion = "17";
+ @Setter
+ protected String dubboVersion = "3.2.18";
+ @Setter
+ protected boolean serviceInterface = true;
+ @Setter
+ protected boolean serviceImplementation = true;
+ @Setter
+ protected boolean useGenericResponse = false;
+ @Setter
+ protected String registryAddress = "zookeeper://127.0.0.1:2181";
+
+ public JavaDubboServerCodegen() {
+ super();
+
+ modifyFeatureSet(features -> features
+ .includeDocumentationFeatures(DocumentationFeature.Readme)
+ .wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML, WireFormatFeature.Custom))
+ .securityFeatures(EnumSet.of(SecurityFeature.OAuth2_Implicit, SecurityFeature.OAuth2_AuthorizationCode,
+ SecurityFeature.OAuth2_ClientCredentials, SecurityFeature.OAuth2_Password,
+ SecurityFeature.ApiKey, SecurityFeature.BasicAuth))
+ .excludeGlobalFeatures(GlobalFeature.Callbacks, GlobalFeature.LinkObjects, GlobalFeature.ParameterStyling)
+ .includeSchemaSupportFeatures(SchemaSupportFeature.Polymorphism)
+ .excludeParameterFeatures(ParameterFeature.Cookie));
+
+ generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
+ .stability(Stability.BETA)
+ .build();
+
+ dateLibrary = "java8";
+
+ useBeanValidation = false;
+ serializableModel = true;
+ outputFolder = "generated-code/java-dubbo";
+ embeddedTemplateDir = templateDir = "java-dubbo";
+ invokerPackage = "org.openapitools";
+ apiPackage = invokerPackage + ".api";
+ modelPackage = invokerPackage + ".model";
+ artifactId = "openapi-dubbo";
+
+ additionalProperties.put("hideGenerationTimestamp", true);
+ additionalProperties.put("withXml", false);
+
+ importMapping.remove("ApiModel");
+ importMapping.remove("ApiModelProperty");
+
+ setDocumentationProvider(DocumentationProvider.NONE);
+ setAnnotationLibrary(AnnotationLibrary.NONE);
+
+ supportsInheritance = false;
+ supportsMixins = false;
+
+ importMapping.remove("ApiModel");
+ importMapping.remove("ApiModelProperty");
+ importMapping.remove("Schema");
+ importMapping.remove("io.swagger.annotations.ApiModel");
+ importMapping.remove("io.swagger.annotations.ApiModelProperty");
+ importMapping.remove("io.swagger.v3.oas.annotations.media.Schema");
+
+ typeMapping.clear();
+ typeMapping.put("integer", "Integer");
+ typeMapping.put("long", "Long");
+ typeMapping.put("float", "Float");
+ typeMapping.put("double", "Double");
+ typeMapping.put("boolean", "Boolean");
+ typeMapping.put("string", "String");
+ typeMapping.put("array", "List");
+ typeMapping.put("map", "Map");
+ typeMapping.put("object", "Object");
+ typeMapping.put("date", "LocalDate");
+ typeMapping.put("DateTime", "OffsetDateTime");
+ typeMapping.put("date-time", "OffsetDateTime");
+ typeMapping.put("number", "BigDecimal");
+ typeMapping.put("decimal", "BigDecimal");
+ typeMapping.put("binary", "byte[]");
+ typeMapping.put("file", "org.springframework.web.multipart.MultipartFile");
+ typeMapping.put("uuid", "UUID");
+ typeMapping.put("byte", "byte[]");
+ typeMapping.put("ByteArray", "byte[]");
+ typeMapping.put("binary", "byte[]");
+ typeMapping.put("password", "String");
+
+ languageSpecificPrimitives.clear();
+ languageSpecificPrimitives.add("String");
+ languageSpecificPrimitives.add("boolean");
+ languageSpecificPrimitives.add("Boolean");
+ languageSpecificPrimitives.add("Double");
+ languageSpecificPrimitives.add("Integer");
+ languageSpecificPrimitives.add("Long");
+ languageSpecificPrimitives.add("Float");
+ languageSpecificPrimitives.add("Object");
+ languageSpecificPrimitives.add("List");
+ languageSpecificPrimitives.add("Map");
+ languageSpecificPrimitives.add("Set");
+
+ importMapping.put("List", "java.util.List");
+ importMapping.put("Map", "java.util.Map");
+ importMapping.put("Set", "java.util.Set");
+ importMapping.put("ArrayList", "java.util.ArrayList");
+ importMapping.put("HashMap", "java.util.HashMap");
+ importMapping.put("HashSet", "java.util.HashSet");
+ importMapping.put("Date", "java.util.Date");
+ importMapping.put("Arrays", "java.util.Arrays");
+ importMapping.put("OffsetDateTime", "java.time.OffsetDateTime");
+ importMapping.put("LocalDate", "java.time.LocalDate");
+ importMapping.put("LocalTime", "java.time.LocalTime");
+ importMapping.put("LocalDateTime", "java.time.LocalDateTime");
+ importMapping.put("BigDecimal", "java.math.BigDecimal");
+ importMapping.put("BigInteger", "java.math.BigInteger");
+ importMapping.put("UUID", "java.util.UUID");
+ importMapping.put("MultipartFile", "org.springframework.web.multipart.MultipartFile");
+
+ typeMapping.put("List", "List");
+ typeMapping.put("Set", "Set");
+ typeMapping.put("Map", "Map");
+
+ updateOption(CodegenConstants.INVOKER_PACKAGE, this.getInvokerPackage());
+ updateOption(CodegenConstants.ARTIFACT_ID, this.getArtifactId());
+ updateOption(CodegenConstants.API_PACKAGE, apiPackage);
+ updateOption(CodegenConstants.MODEL_PACKAGE, modelPackage);
+
+ apiTestTemplateFiles.clear();
+
+ apiTemplateFiles.clear();
+ apiTemplateFiles.put("api.mustache", ".java");
+ apiTemplateFiles.put("apiDubbo.mustache", ".java");
+ apiTemplateFiles.put("apiController.mustache", ".java");
+ apiDocTemplateFiles.clear();
+
+ modelTemplateFiles.clear();
+ modelTemplateFiles.put("model.mustache", ".java");
+ modelDocTemplateFiles.clear();
+
+ additionalProperties.put("dubboVersion", dubboVersion);
+ additionalProperties.put("javaVersion", javaVersion);
+
+ cliOptions.add(new CliOption(TITLE, "API title name").defaultValue(title));
+ cliOptions.add(new CliOption(CONFIG_PACKAGE, "configuration package for generated code")
+ .defaultValue(this.getConfigPackage()));
+ cliOptions.add(new CliOption(BASE_PACKAGE, "base package (invokerPackage) for generated code")
+ .defaultValue(this.getBasePackage()));
+ cliOptions.add(CliOption.newBoolean(INTERFACE_ONLY,
+ "Whether to generate only API interface stubs without the server files.", interfaceOnly));
+ cliOptions.add(CliOption.newBoolean(USE_TAGS, "use tags for creating interface and controller classnames", useTags));
+ cliOptions.add(new CliOption(DUBBO_VERSION, "Dubbo version").defaultValue(dubboVersion));
+ cliOptions.add(new CliOption(JAVA_VERSION, "Java version").defaultValue(javaVersion));
+ cliOptions.add(CliOption.newBoolean(SERVICE_INTERFACE, "Generate service interface", serviceInterface));
+ cliOptions.add(CliOption.newBoolean(SERVICE_IMPLEMENTATION, "Generate service implementation", serviceImplementation));
+ cliOptions.add(CliOption.newBoolean(USE_GENERIC_RESPONSE, "Use generic response wrapper", useGenericResponse));
+ cliOptions.add(new CliOption(REGISTRY_ADDRESS, "Registry address (e.g., zookeeper://127.0.0.1:2181 or nacos://127.0.0.1:8848)")
+ .defaultValue(registryAddress));
+ }
+
+ @Override
+ public CodegenType getTag() {
+ return CodegenType.SERVER;
+ }
+
+ @Override
+ public String getName() {
+ return "java-dubbo";
+ }
+
+ @Override
+ public String getHelp() {
+ return "Generates a Java Apache Dubbo server application.";
+ }
+
+ private boolean isOutputFolderPointingToSourceDirectory() {
+ if (outputFolder == null) {
+ return false;
+ }
+
+ String normalizedPath = outputFolder.replace('\\', '/');
+ return normalizedPath.endsWith("/src/main/java") || normalizedPath.endsWith("src/main/java");
+ }
+
+ @Override
+ public String outputFolder() {
+ if (isOutputFolderPointingToSourceDirectory()) {
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+
+ for (StackTraceElement element : stackTrace) {
+ String methodName = element.getMethodName();
+ String className = element.getClassName();
+
+ if (className.equals("org.openapitools.codegen.DefaultGenerator")) {
+ if (methodName.equals("generateVersionMetadata") ||
+ methodName.equals("generateFilesMetadata")) {
+
+ return outputFolder + File.separator + ".." + File.separator + ".." + File.separator + "..";
+ }
+ }
+ }
+ }
+
+ return outputFolder;
+ }
+
+ public String getIgnoreFileOutputPath() {
+ if (isOutputFolderPointingToSourceDirectory()) {
+ return outputFolder + File.separator + ".." + File.separator + ".." + File.separator + "..";
+ }
+ return outputFolder;
+ }
+
+ @Override
+ public void processOpts() {
+ final List> configOptions =
+ additionalProperties.entrySet().stream()
+ .filter(e -> !Arrays.asList("hideGenerationTimestamp").contains(e.getKey()))
+ .filter(e -> cliOptions.stream().map(CliOption::getOpt).anyMatch(opt -> opt.equals(e.getKey())))
+ .map(e -> org.apache.commons.lang3.tuple.Pair.of(e.getKey(), e.getValue().toString()))
+ .collect(Collectors.toList());
+ additionalProperties.put("configOptions", configOptions);
+
+ super.processOpts();
+
+ supportingFiles.removeIf(sf -> sf.getDestinationFilename().equals(".openapi-generator-ignore"));
+
+ openapiGeneratorIgnoreList = new HashSet<>();
+ openapiGeneratorIgnoreList.add("# Dubbo generator explicitly disables .openapi-generator-ignore");
+
+ importMapping.remove("ApiModel");
+ importMapping.remove("ApiModelProperty");
+ importMapping.remove("io.swagger.annotations.ApiModel");
+ importMapping.remove("io.swagger.annotations.ApiModelProperty");
+ importMapping.remove("Schema");
+ importMapping.remove("io.swagger.v3.oas.annotations.media.Schema");
+
+ String userTitle = (String) additionalProperties.get(TITLE);
+ boolean userProvidedTitle = userTitle != null && !userTitle.equals("OpenAPI Dubbo");
+
+ if (userProvidedTitle) {
+ this.title = userTitle;
+ }
+
+ additionalProperties.put("userProvidedTitle", userProvidedTitle);
+
+ additionalProperties.put("title", this.title);
+
+ if (additionalProperties.containsKey(CONFIG_PACKAGE)) {
+ this.setConfigPackage((String) additionalProperties.get(CONFIG_PACKAGE));
+ }
+
+ if (additionalProperties.containsKey(BASE_PACKAGE)) {
+ String basePackageName = (String) additionalProperties.get(BASE_PACKAGE);
+ this.setBasePackage(basePackageName);
+ this.setInvokerPackage(basePackageName);
+
+ this.apiPackage = basePackageName + ".api";
+ this.modelPackage = basePackageName + ".model";
+
+ if (!additionalProperties.containsKey(CONFIG_PACKAGE)) {
+ this.configPackage = basePackageName + ".configuration";
+ }
+
+ updateOption(CodegenConstants.API_PACKAGE, this.apiPackage);
+ updateOption(CodegenConstants.MODEL_PACKAGE, this.modelPackage);
+ updateOption(CodegenConstants.INVOKER_PACKAGE, this.getInvokerPackage());
+ }
+
+ if (additionalProperties.containsKey(INTERFACE_ONLY)) {
+ this.interfaceOnly = Boolean.parseBoolean(additionalProperties.get(INTERFACE_ONLY).toString());
+ }
+
+ if (additionalProperties.containsKey(USE_TAGS)) {
+ this.useTags = Boolean.parseBoolean(additionalProperties.get(USE_TAGS).toString());
+ }
+
+ if (additionalProperties.containsKey(DUBBO_VERSION)) {
+ this.dubboVersion = (String) additionalProperties.get(DUBBO_VERSION);
+ }
+
+ if (additionalProperties.containsKey(JAVA_VERSION)) {
+ this.javaVersion = (String) additionalProperties.get(JAVA_VERSION);
+ }
+
+ if (additionalProperties.containsKey(SERVICE_INTERFACE)) {
+ this.serviceInterface = Boolean.parseBoolean(additionalProperties.get(SERVICE_INTERFACE).toString());
+ }
+
+ if (additionalProperties.containsKey(SERVICE_IMPLEMENTATION)) {
+ this.serviceImplementation = Boolean.parseBoolean(additionalProperties.get(SERVICE_IMPLEMENTATION).toString());
+ }
+
+ if (additionalProperties.containsKey(USE_GENERIC_RESPONSE)) {
+ this.useGenericResponse = Boolean.parseBoolean(additionalProperties.get(USE_GENERIC_RESPONSE).toString());
+ }
+
+ if (additionalProperties.containsKey(REGISTRY_ADDRESS)) {
+ this.registryAddress = (String) additionalProperties.get(REGISTRY_ADDRESS);
+ }
+
+ additionalProperties.put("title", this.title);
+ additionalProperties.put("configPackage", this.configPackage);
+ additionalProperties.put("basePackage", this.basePackage);
+ additionalProperties.put("apiPackage", this.apiPackage);
+ additionalProperties.put("modelPackage", this.modelPackage);
+ additionalProperties.put("invokerPackage", this.getInvokerPackage());
+ additionalProperties.put("interfaceOnly", interfaceOnly);
+ additionalProperties.put("useTags", useTags);
+ additionalProperties.put("dubboVersion", dubboVersion);
+ additionalProperties.put("javaVersion", javaVersion);
+ additionalProperties.put("serviceInterface", serviceInterface);
+ additionalProperties.put("serviceImplementation", serviceImplementation);
+ additionalProperties.put("useGenericResponse", useGenericResponse);
+ additionalProperties.put("registryAddress", registryAddress);
+
+ supportingFiles.clear();
+
+ if (isOutputFolderPointingToSourceDirectory()) {
+ String rootPath = ".." + File.separator + ".." + File.separator + "..";
+ supportingFiles.add(new SupportingFile("pom.mustache", rootPath, "pom.xml"));
+ supportingFiles.add(new SupportingFile("README.mustache", rootPath, "README.md"));
+
+ } else {
+ supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
+ supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
+ }
+
+ if (serviceImplementation && !interfaceOnly) {
+ String mainClassName;
+ boolean isUserTitle = (Boolean) additionalProperties.getOrDefault("userProvidedTitle", false);
+
+ if (isUserTitle) {
+ String titleName = (String) additionalProperties.get(TITLE);
+ mainClassName = (camelize(titleName.trim(), CamelizeOption.UPPERCASE_FIRST_CHAR) + "Application").replaceAll("\\s+", "");
+ ;
+ } else {
+ mainClassName = "OpenApiGeneratorApplication";
+ }
+
+ String testClassName = mainClassName + "Tests";
+ additionalProperties.put("mainClassName", mainClassName);
+ additionalProperties.put("testClassName", testClassName);
+
+ if (isOutputFolderPointingToSourceDirectory()) {
+ supportingFiles.add(new SupportingFile("mainApplication.mustache",
+ basePackage.replace(".", File.separator),
+ mainClassName + ".java"));
+
+ supportingFiles.add(new SupportingFile("applicationTest.mustache",
+ ".." + File.separator + ".." + File.separator + ".." + File.separator + "src" + File.separator + "test" + File.separator + "java" + File.separator + basePackage.replace(".", File.separator),
+ testClassName + ".java"));
+
+ supportingFiles.add(new SupportingFile("application.mustache",
+ ".." + File.separator + ".." + File.separator + ".." + File.separator + "src" + File.separator + "main" + File.separator + "resources",
+ "application.yml"));
+ } else {
+ supportingFiles.add(new SupportingFile("mainApplication.mustache",
+ (sourceFolder + File.separator + basePackage).replace(".", File.separator),
+ mainClassName + ".java"));
+
+ supportingFiles.add(new SupportingFile("applicationTest.mustache",
+ (testFolder + File.separator + basePackage).replace(".", File.separator),
+ testClassName + ".java"));
+
+ supportingFiles.add(new SupportingFile("application.mustache",
+ "src/main/resources".replace("/", File.separator),
+ "application.yml"));
+ }
+ }
+
+ additionalProperties.put("lambdaTrimWhitespace", new TrimWhitespaceLambda());
+
+ additionalProperties.put("documentationProvider", "none");
+ additionalProperties.put("annotationLibrary", "none");
+ additionalProperties.put("hideGenerationTimestamp", true);
+ additionalProperties.put("useBeanValidation", false);
+ additionalProperties.put("performBeanValidation", false);
+
+ }
+
+ private boolean isDubbo33OrHigher(String version) {
+ if (version == null || version.trim().isEmpty()) {
+ return false;
+ }
+
+ try {
+ String cleanVersion = version.split("-")[0];
+ String[] parts = cleanVersion.split("\\.");
+ if (parts.length >= 2) {
+ int major = Integer.parseInt(parts[0]);
+ int minor = Integer.parseInt(parts[1]);
+
+ return major > 3 || (major == 3 && minor >= 3);
+ }
+ } catch (NumberFormatException e) {
+ LOGGER.warn("Unable to parse Dubbo version: " + version);
+ }
+
+ return false;
+ }
+
+ @Override
+ public Map postProcessSupportingFileData(Map objs) {
+ generateYAMLSpecFile(objs);
+ objs = super.postProcessSupportingFileData(objs);
+
+ objs.put("interfacePackage", apiPackage + ".interfaces");
+ objs.put("consumerPackage", apiPackage + ".consumer");
+ objs.put("providerPackage", apiPackage + ".provider");
+
+ objs.put("registryAddress", registryAddress);
+
+ boolean isDubbo33Plus = isDubbo33OrHigher(dubboVersion);
+ objs.put("isDubbo33Plus", isDubbo33Plus);
+
+ boolean isZookeeperRegistry = registryAddress != null && registryAddress.startsWith("zookeeper://");
+ boolean isNacosRegistry = registryAddress != null && registryAddress.startsWith("nacos://");
+ objs.put("isZookeeperRegistry", isZookeeperRegistry);
+ objs.put("isNacosRegistry", isNacosRegistry);
+
+ String nacosClientVersion = isDubbo33Plus ? "2.5.0" : "2.2.4";
+ objs.put("nacosClientVersion", nacosClientVersion);
+
+ return objs;
+ }
+
+
+ @Override
+ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List allModels) {
+ OperationsMap results = super.postProcessOperationsWithModels(objs, allModels);
+
+ if (results.getImports() != null) {
+ boolean hasJavaUtilImports = false;
+ Iterator> importIterator = results.getImports().iterator();
+ while (importIterator.hasNext()) {
+ Map importMap = importIterator.next();
+ String importName = importMap.get("import");
+ if (importName != null && importName.startsWith("java.util.") &&
+ !importName.equals("java.util.*") &&
+ !importName.equals("java.util.UUID")) {
+ importIterator.remove();
+ hasJavaUtilImports = true;
+ }
+ }
+
+ if (hasJavaUtilImports) {
+ Map utilImport = new HashMap<>();
+ utilImport.put("import", "java.util.*");
+ utilImport.put("classname", "*");
+ results.getImports().add(utilImport);
+ }
+ }
+
+ OperationMap operations = results.getOperations();
+ if (operations != null) {
+ String baseName = (String) operations.get("baseName");
+ String originalClassName = (String) operations.get("classname");
+
+ if (baseName == null) {
+ baseName = originalClassName;
+ if (baseName != null && baseName.endsWith("Service")) {
+ baseName = baseName.substring(0, baseName.length() - 7).toLowerCase(java.util.Locale.ROOT);
+ } else if (baseName != null && baseName.endsWith("Api")) {
+ baseName = baseName.substring(0, baseName.length() - 3).toLowerCase(java.util.Locale.ROOT);
+ }
+ }
+
+ if (baseName != null) {
+ if ("ashares".equals(baseName)) {
+ operations.put("baseName", "a");
+ } else if ("usdata".equals(baseName)) {
+ operations.put("baseName", "us");
+ } else if ("kline".equals(baseName)) {
+ operations.put("baseName", "kline");
+ }
+ }
+
+ if (originalClassName != null) {
+ String serviceName = originalClassName;
+ if (serviceName.endsWith("Api")) {
+ serviceName = serviceName.replace("Api", "Service");
+ } else if (serviceName.endsWith("Service")) {
+ serviceName = originalClassName;
+ }
+ operations.put("serviceName", serviceName);
+ operations.put("serviceVarName", camelize(serviceName, LOWERCASE_FIRST_LETTER));
+
+ operations.put("servicePackage", apiPackage + ".interfaces");
+ operations.put("serviceImport", apiPackage + ".interfaces." + serviceName);
+ operations.put("interfacePackage", apiPackage + ".interfaces");
+ operations.put("consumerPackage", apiPackage + ".consumer");
+ operations.put("providerPackage", apiPackage + ".provider");
+ }
+
+ List ops = operations.getOperation();
+ for (CodegenOperation operation : ops) {
+ if (useGenericResponse) {
+ operation.vendorExtensions.put("x-generic-response", true);
+ }
+ }
+ }
+
+ results.put("interfacePackage", apiPackage + ".interfaces");
+ results.put("consumerPackage", apiPackage + ".consumer");
+ results.put("providerPackage", apiPackage + ".provider");
+
+ return results;
+ }
+
+ @Override
+ public String apiFileFolder() {
+ if (isOutputFolderPointingToSourceDirectory()) {
+ return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar);
+ } else {
+ return outputFolder + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator + apiPackage().replace('.', File.separatorChar);
+ }
+ }
+
+ public String getFileFolderForTemplate(String templateName) {
+ String baseFolder;
+ if (isOutputFolderPointingToSourceDirectory()) {
+ baseFolder = outputFolder + File.separator + apiPackage().replace('.', File.separatorChar);
+ } else {
+ baseFolder = outputFolder + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator + apiPackage().replace('.', File.separatorChar);
+ }
+
+ if ("api.mustache".equals(templateName)) {
+ return baseFolder + File.separator + "interfaces";
+ } else if ("apiController.mustache".equals(templateName)) {
+ return baseFolder + File.separator + "consumer";
+ } else if ("apiDubbo.mustache".equals(templateName)) {
+ return baseFolder + File.separator + "provider";
+ }
+
+ return baseFolder;
+ }
+
+ public String getPackageForTemplate(String templateName) {
+ if ("api.mustache".equals(templateName)) {
+ return apiPackage() + ".interfaces";
+ } else if ("apiController.mustache".equals(templateName)) {
+ return apiPackage() + ".consumer";
+ } else if ("apiDubbo.mustache".equals(templateName)) {
+ return apiPackage() + ".provider";
+ }
+ return apiPackage();
+ }
+
+ @Override
+ public String modelFileFolder() {
+ if (isOutputFolderPointingToSourceDirectory()) {
+ return outputFolder + File.separator + modelPackage().replace('.', File.separatorChar);
+ } else {
+ return outputFolder + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator + modelPackage().replace('.', File.separatorChar);
+ }
+ }
+
+
+ @Override
+ public String apiFilename(String templateName, String tag) {
+ String suffix = apiTemplateFiles().get(templateName);
+ if (suffix == null) {
+ return null;
+ }
+
+ String folder = getFileFolderForTemplate(templateName);
+ String filename;
+
+ String apiName = toApiName(tag);
+
+ if ("api.mustache".equals(templateName)) {
+ filename = apiName;
+ } else if ("apiDubbo.mustache".equals(templateName)) {
+ filename = apiName + "Impl";
+ } else if ("apiController.mustache".equals(templateName)) {
+ filename = apiName + "Controller";
+ } else {
+ filename = toApiFilename(tag);
+ }
+
+ return folder + File.separator + filename + suffix;
+ }
+
+ @Override
+ public String toApiName(String name) {
+ if (name.length() == 0) {
+ return "DefaultService";
+ }
+ name = sanitizeName(name);
+ String apiName = camelize(name, CamelizeOption.UPPERCASE_FIRST_CHAR);
+
+ if (!apiName.endsWith("Service")) {
+ apiName = apiName + "Service";
+ }
+
+ return apiName;
+ }
+
+ @Override
+ public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map> operations) {
+ if (useTags) {
+ String basePath = resourcePath;
+ if (basePath.startsWith("/")) {
+ basePath = basePath.substring(1);
+ }
+ int pos = basePath.indexOf("/");
+ if (pos > 0) {
+ basePath = basePath.substring(0, pos);
+ }
+
+ if (basePath.length() == 0) {
+ basePath = "default";
+ } else {
+ String subPath = resourcePath;
+ if (subPath.startsWith("/" + basePath)) {
+ subPath = subPath.substring(("/" + basePath).length());
+ }
+ if (subPath.isEmpty()) {
+ subPath = "/";
+ }
+ co.vendorExtensions.put("x-sub-path", subPath);
+ co.subresourceOperation = !subPath.equals("/");
+
+ co.vendorExtensions.put("x-base-path", "/" + basePath);
+
+ if ("a".equals(basePath)) {
+ basePath = "ashares";
+ } else if ("us".equals(basePath)) {
+ basePath = "usdata";
+ }
+ }
+ List opList = operations.computeIfAbsent(basePath, k -> new ArrayList<>());
+ opList.add(co);
+ co.baseName = basePath;
+ } else {
+ super.addOperationToGroup(tag, resourcePath, operation, co, operations);
+ }
+ }
+
+ @Override
+ public boolean isDataTypeString(String dataType) {
+ return "String".equals(dataType);
+ }
+
+ @Override
+ public String getTypeDeclaration(Schema p) {
+ if (ModelUtils.isArraySchema(p)) {
+ Schema inner = ModelUtils.getSchemaItems(p);
+ String innerType = getTypeDeclaration(inner);
+ return "List<" + innerType + ">";
+ } else if (ModelUtils.isMapSchema(p)) {
+ Schema inner = ModelUtils.getAdditionalProperties(p);
+ String innerType = getTypeDeclaration(inner);
+ return "Map";
+ }
+ return super.getTypeDeclaration(p);
+ }
+
+ @Override
+ public String getSchemaType(Schema p) {
+ String openAPIType = super.getSchemaType(p);
+ if (typeMapping.containsKey(openAPIType)) {
+ return typeMapping.get(openAPIType);
+ }
+ return openAPIType;
+ }
+
+
+ @Override
+ public Set defaultIncludes() {
+ return new HashSet(
+ Arrays.asList(
+ "double",
+ "int",
+ "long",
+ "short",
+ "char",
+ "float",
+ "String",
+ "boolean",
+ "Boolean",
+ "Double",
+ "Void",
+ "Integer",
+ "Long",
+ "Float")
+ );
+ }
+
+ @Override
+ public String toModelImport(String name) {
+ if ("ApiModel".equals(name) || "ApiModelProperty".equals(name)) {
+ return null;
+ }
+ if ("".equals(modelPackage())) {
+ return name;
+ } else {
+ return modelPackage() + "." + name;
+ }
+ }
+
+ @Override
+ public String getTypeDeclaration(String name) {
+ if ("ApiModel".equals(name) || "ApiModelProperty".equals(name)) {
+ return null;
+ }
+ return super.getTypeDeclaration(name);
+ }
+
+ @Override
+ public boolean needToImport(String type) {
+ if ("ApiModel".equals(type) ||
+ "ApiModelProperty".equals(type) ||
+ "io.swagger.annotations.ApiModel".equals(type) ||
+ "io.swagger.annotations.ApiModelProperty".equals(type) ||
+ "Schema".equals(type) ||
+ "io.swagger.v3.oas.annotations.media.Schema".equals(type)) {
+ return false;
+ }
+
+ if ("LocalDate".equals(type) ||
+ "LocalDateTime".equals(type) ||
+ "LocalTime".equals(type) ||
+ "OffsetDateTime".equals(type) ||
+ "BigDecimal".equals(type) ||
+ "BigInteger".equals(type) ||
+ "UUID".equals(type)) {
+ return true;
+ }
+
+ return super.needToImport(type);
+ }
+
+
+ @Override
+ public ModelsMap postProcessModels(ModelsMap objs) {
+ objs = super.postProcessModels(objs);
+
+ for (ModelMap modelMap : objs.getModels()) {
+ CodegenModel model = modelMap.getModel();
+ model.imports.remove("ApiModel");
+ model.imports.remove("ApiModelProperty");
+ model.imports.remove("io.swagger.annotations.ApiModel");
+ model.imports.remove("io.swagger.annotations.ApiModelProperty");
+ model.imports.remove("Schema");
+ model.imports.remove("io.swagger.v3.oas.annotations.media.Schema");
+
+ boolean hasJavaUtilImports = false;
+ Set javaUtilImports = new HashSet<>();
+ Iterator iterator = model.imports.iterator();
+ while (iterator.hasNext()) {
+ String importName = iterator.next();
+ if (importName.startsWith("java.util.") &&
+ !importName.equals("java.util.*") &&
+ !importName.equals("java.util.UUID")) {
+ javaUtilImports.add(importName);
+ iterator.remove();
+ hasJavaUtilImports = true;
+ }
+ }
+
+ if (hasJavaUtilImports) {
+ model.imports.add("java.util.*");
+ }
+
+ for (CodegenProperty var : model.vars) {
+ if (var.allowableValues != null && var.allowableValues.get("imports") != null) {
+ ((Set) var.allowableValues.get("imports")).remove("ApiModel");
+ ((Set) var.allowableValues.get("imports")).remove("ApiModelProperty");
+ ((Set) var.allowableValues.get("imports")).remove("io.swagger.annotations.ApiModel");
+ ((Set) var.allowableValues.get("imports")).remove("io.swagger.annotations.ApiModelProperty");
+ }
+ }
+ }
+
+ if (objs.getImports() != null) {
+ objs.getImports().removeIf(importMap -> {
+ String className = importMap.get("classname");
+ return "ApiModel".equals(className) || "ApiModelProperty".equals(className);
+ });
+
+ boolean hasJavaUtilImports = false;
+ Iterator> importIterator = objs.getImports().iterator();
+ while (importIterator.hasNext()) {
+ Map importMap = importIterator.next();
+ String importName = importMap.get("import");
+ if (importName != null && importName.startsWith("java.util.") &&
+ !importName.equals("java.util.*") &&
+ !importName.equals("java.util.UUID")) {
+ importIterator.remove();
+ hasJavaUtilImports = true;
+ }
+ }
+
+ if (hasJavaUtilImports) {
+ Map utilImport = new HashMap<>();
+ utilImport.put("import", "java.util.*");
+ utilImport.put("classname", "*");
+ objs.getImports().add(utilImport);
+ }
+ }
+
+ return objs;
+ }
+
+ @Override
+ public String toModelDocFilename(String name) {
+ return null;
+ }
+
+ @Override
+ public String toApiDocFilename(String name) {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
index 2167287cd58..345f9b2543b 100644
--- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
+++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
@@ -48,6 +48,7 @@ org.openapitools.codegen.languages.HaskellHttpClientCodegen
org.openapitools.codegen.languages.HaskellServantCodegen
org.openapitools.codegen.languages.HaskellYesodServerCodegen
org.openapitools.codegen.languages.JavaClientCodegen
+org.openapitools.codegen.languages.JavaDubboServerCodegen
org.openapitools.codegen.languages.JavaCXFClientCodegen
org.openapitools.codegen.languages.JavaHelidonClientCodegen
org.openapitools.codegen.languages.JavaHelidonServerCodegen
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/README.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/README.mustache
new file mode 100644
index 00000000000..2ca19131786
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/README.mustache
@@ -0,0 +1,347 @@
+# {{appName}}
+
+{{appDescription}}
+
+This is a microservice project based on Apache Dubbo, generated by [OpenAPI Generator](https://openapi-generator.tech).
+
+- API version: {{appVersion}}
+- Package version: {{packageVersion}}
+{{^hideGenerationTimestamp}}
+- Generator version: {{generatorVersion}}
+- Build date: {{generatedDate}}
+{{/hideGenerationTimestamp}}
+- Generator: {{generatorClass}}
+{{#externalDocumentationDescription}}
+For more information, please visit: [{{{externalDocumentationDescription}}}]({{{externalDocumentationURL}}})
+{{/externalDocumentationDescription}}
+
+## Technology Stack
+
+- **Framework**: Apache Dubbo {{dubboVersion}}
+{{#useSpringBoot}}
+- **Spring Boot**: {{#useSpringBoot3}}3.x{{/useSpringBoot3}}{{^useSpringBoot3}}2.x{{/useSpringBoot3}}
+{{/useSpringBoot}}
+- **Java**: {{#java8}}8+{{/java8}}{{^java8}}11+{{/java8}}
+- **Build Tool**: Maven 3.6+
+- **Registry**: {{registryAddress}}
+- **Serialization**: Jackson JSON
+
+## System Requirements
+
+Building and running this project requires:
+1. Java {{#java8}}8{{/java8}}{{^java8}}11{{/java8}}+
+2. Maven 3.6+
+3. Registry Center (Nacos or Zookeeper)
+
+## Quick Start
+
+### 1. Clone and Build Project
+
+```bash
+git clone
+cd {{artifactId}}
+mvn clean compile
+```
+
+### 2. Configure Registry Center
+
+#### Using Nacos (Recommended)
+```bash
+# Download and start Nacos
+wget https://github.com/alibaba/nacos/releases/download/2.2.4/nacos-server-2.2.4.tar.gz
+tar -xzf nacos-server-2.2.4.tar.gz
+cd nacos/bin
+# Linux/Mac
+./startup.sh -m standalone
+# Windows
+startup.cmd -m standalone
+```
+
+#### Using Zookeeper (Alternative)
+```bash
+# Download and start Zookeeper
+wget https://downloads.apache.org/zookeeper/zookeeper-3.8.2/apache-zookeeper-3.8.2-bin.tar.gz
+tar -xzf apache-zookeeper-3.8.2-bin.tar.gz
+cd apache-zookeeper-3.8.2-bin
+cp conf/zoo_sample.cfg conf/zoo.cfg
+bin/zkServer.sh start
+```
+
+### 3. Configure Application
+
+Edit the `src/main/resources/application.yml` file:
+
+```yaml
+# Dubbo Configuration
+dubbo:
+ application:
+ name: {{artifactId}}
+ registry:
+ # Using Nacos
+ address: nacos://127.0.0.1:8848
+ # Or using Zookeeper
+ # address: zookeeper://127.0.0.1:2181
+ protocol:
+ name: dubbo
+ port: 20880
+ provider:
+ timeout: 10000
+
+{{#useSpringBoot}}
+# Spring Boot Configuration
+server:
+ port: 8080
+
+spring:
+ application:
+ name: {{artifactId}}
+
+# Logging Configuration
+logging:
+ level:
+ com.alibaba.nacos: WARN
+ org.apache.dubbo: INFO
+ root: INFO
+{{/useSpringBoot}}
+```
+
+### 4. Start Application
+
+{{#useSpringBoot}}
+```bash
+# Using Spring Boot Maven plugin
+mvn spring-boot:run
+
+# Or build JAR and run
+mvn clean package
+java -jar target/{{artifactId}}-{{appVersion}}.jar
+```
+{{/useSpringBoot}}
+{{^useSpringBoot}}
+```bash
+# Build project
+mvn clean compile
+
+# Run main class
+mvn exec:java -Dexec.mainClass="{{package}}.Application"
+```
+{{/useSpringBoot}}
+
+## Project Structure
+
+```
+{{artifactId}}/
+├── src/main/java/{{package}}/
+{{#operations}}
+│ ├── api/
+│ │ ├── {{classname}}.java # Service Interface
+│ │ └── {{classname}}DubboImpl.java # Dubbo Service Implementation
+{{/operations}}
+{{#hasModel}}
+│ ├── model/ # Data Models
+{{#models}}
+{{#model}}
+│ │ └── {{classname}}.java
+{{/model}}
+{{/models}}
+{{/hasModel}}
+│ └── Application.java # Main Application Class
+├── src/main/resources/
+│ └── application.yml # Application Configuration
+├── pom.xml # Maven Configuration
+└── README.md # Project Documentation
+```
+
+## API Interfaces
+
+{{#apiDocumentationUrl}}
+For complete API documentation, please visit: [{{apiDocumentationUrl}}]({{apiDocumentationUrl}})
+{{/apiDocumentationUrl}}
+
+### Service Interfaces
+
+{{#operations}}
+#### {{classname}}
+{{#operation}}
+- **{{nickname}}**: {{summary}}
+ {{#notes}}
+ - Description: {{.}}
+ {{/notes}}
+{{/operation}}
+
+{{/operations}}
+
+## Development Guide
+
+### Implement Business Logic
+
+1. Implement specific business logic in the generated `*DubboImpl.java` classes
+2. Inject necessary business service dependencies
+3. Handle exceptions and error scenarios
+
+### Custom Configuration
+
+1. **Timeout Configuration**: Adjust `dubbo.provider.timeout` in `application.yml`
+2. **Thread Pool Configuration**: Configure `dubbo.provider.threads` and other parameters
+3. **Serialization Configuration**: Choose appropriate serialization method
+
+### Monitoring and Operations
+
+1. **Health Checks**: Dubbo provides built-in health check endpoints
+2. **Metrics Monitoring**: Integrate with Prometheus or other monitoring systems
+3. **Log Management**: Configure appropriate log levels and output formats
+
+## Testing
+
+```bash
+# Run unit tests
+mvn test
+
+# Run integration tests
+mvn integration-test
+```
+
+## Deployment
+
+### Development Environment
+```bash
+mvn spring-boot:run
+```
+
+### Production Environment
+```bash
+# Build production package
+mvn clean package -Pprod
+
+# Deploy using Docker
+docker build -t {{artifactId}}:{{appVersion}} .
+docker run -p 8080:8080 -p 20880:20880 {{artifactId}}:{{appVersion}}
+```
+
+## Generator Configuration Options
+
+This project supports the following OpenAPI Generator configuration options:
+
+### Basic Configuration
+- `title`: API service title name (Default: "OpenAPI Dubbo")
+- `basePackage`: Base package name (Default: "org.openapitools")
+- `configPackage`: Configuration class package name (Default: "org.openapitools.configuration")
+- `dubboVersion`: Dubbo version (Default: "3.2.0")
+
+### Generation Control
+- `interfaceOnly`: Generate interfaces only, no implementation classes (Default: false)
+- `serviceInterface`: Generate service interfaces (Default: true)
+- `serviceImplementation`: Generate service implementations (Default: true)
+- `async`: Use asynchronous methods (Default: false)
+- `useTags`: Use tags to create class names (Default: true)
+- `useGenericResponse`: Use generic response wrapper (Default: false)
+
+### Registry Configuration
+- `registry-address`: Registry address, supports full address format (Default: "zookeeper://127.0.0.1:2181")
+ - Zookeeper example: `zookeeper://127.0.0.1:2181`
+ - Nacos example: `nacos://127.0.0.1:8848`
+
+#### 📋 Automatic Dependency Adaptation by Version
+The generator automatically selects the correct dependencies based on Dubbo version:
+
+**Dubbo 3.2 and earlier versions**:
+- Zookeeper: `dubbo-dependencies-zookeeper` (Aggregation POM)
+- Nacos: `dubbo-registry-nacos` + `nacos-client:2.2.4`
+
+**Dubbo 3.3+ versions**:
+- Zookeeper: `dubbo-registry-zookeeper` + `dubbo-remoting-zookeeper-curator5`
+- Nacos: `dubbo-registry-nacos` + `nacos-client:2.5.0`
+
+### Date-Time Library Configuration
+- `dateLibrary`: Date-time library selection (Default: "java8")
+ - `java8`: Java 8 native JSR310 (Recommended, for JDK 1.8+)
+ - `java8-localdatetime`: Java 8 using LocalDateTime (For legacy applications only)
+ - `joda`: Joda time library (For legacy applications only)
+ - `legacy`: Traditional java.util.Date
+
+### Usage Examples
+
+#### 🔧 Dubbo 3.2 Version Example
+```bash
+# Using Zookeeper (3.2 version automatically uses dubbo-dependencies-zookeeper)
+java -jar openapi-generator-cli.jar generate \
+-i /Users/redoom/IdeaProjects/openapi.yaml \
+-g java-dubbo \
+-o /Users/redoom/IdeaProjects/openapi-test \
+--additional-properties=registry-address=zookeeper://127.0.0.1:2181 \
+--additional-properties=dubboVersion=3.2.0 \
+--additional-properties=dateLibrary=java8
+
+# Using Nacos (3.2 version uses nacos-client:2.2.4)
+java -jar openapi-generator-cli.jar generate \
+-i /Users/redoom/IdeaProjects/openapi.yaml \
+-g java-dubbo \
+-o /Users/redoom/IdeaProjects/openapi-test \
+--additional-properties=registry-address=nacos://127.0.0.1:8848 \
+--additional-properties=dubboVersion=3.2.0 \
+--additional-properties=dateLibrary=java8
+```
+
+#### 🚀 Dubbo 3.3+ Version Example
+```bash
+# Using Zookeeper (3.3+ version automatically uses new modular dependencies)
+java -jar openapi-generator-cli.jar generate \
+-i /Users/redoom/IdeaProjects/openapi.yaml \
+-g java-dubbo \
+-o /Users/redoom/IdeaProjects/openapi-test \
+--additional-properties=registry-address=zookeeper://127.0.0.1:2181 \
+--additional-properties=dubboVersion=3.3.0 \
+--additional-properties=dateLibrary=java8
+
+# Using Nacos (3.3+ version uses nacos-client:2.5.0)
+java -jar openapi-generator-cli.jar generate \
+-i /Users/redoom/IdeaProjects/openapi.yaml \
+-g java-dubbo \
+-o /Users/redoom/IdeaProjects/openapi-test \
+--additional-properties=registry-address=nacos://127.0.0.1:8848 \
+--additional-properties=dubboVersion=3.3.0 \
+--additional-properties=dateLibrary=java8
+```
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Registry Connection Failed**
+ - Check if the registry center is started
+ - Verify network connection and port configuration
+
+2. **Service Call Timeout**
+ - Adjust `dubbo.provider.timeout` settings
+ - Check network latency and service performance
+
+3. **Serialization Exception**
+ - Ensure all model classes implement `Serializable` interface
+ - Check Jackson configuration
+
+### Debug Logging
+
+Enable debug mode to see detailed logs:
+
+```yaml
+logging:
+ level:
+ org.apache.dubbo: DEBUG
+ {{package}}: DEBUG
+```
+
+## License
+
+This project is licensed under the [Apache License 2.0](LICENSE).
+
+## Contributing
+
+Issues and Pull Requests are welcome!
+
+## Contact
+
+{{#apiDocumentationUrl}}{{infoEmail}}{{/apiDocumentationUrl}}
+
+---
+
+> This project is automatically generated by OpenAPI Generator, based on Apache Dubbo microservice architecture.
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/api.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/api.mustache
new file mode 100644
index 00000000000..e5c25ec9e80
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/api.mustache
@@ -0,0 +1,45 @@
+package {{interfacePackage}};
+
+{{#imports}}import {{import}};
+{{/imports}}
+{{#hasModel}}
+import {{modelPackage}}.*;
+{{/hasModel}}
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+{{#async}}
+import java.util.concurrent.CompletableFuture;
+{{/async}}
+import javax.annotation.Generated;
+
+
+{{>generatedAnnotation}}
+{{#operations}}
+public interface {{serviceName}} {
+{{#operation}}
+
+ /**
+ * {{summary}}
+ * {{notes}}
+ *
+{{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
+{{/allParams}}
+ * @return {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}}
+ */
+{{#async}}
+ CompletableFuture<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}(
+{{/async}}
+{{^async}}
+ {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}(
+{{/async}}
+{{#allParams}}
+ {{{dataType}}} {{paramName}}{{^-last}},{{/-last}}
+{{/allParams}}
+ );
+{{/operation}}
+}
+{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/apiController.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/apiController.mustache
new file mode 100644
index 00000000000..6a7bdf751ae
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/apiController.mustache
@@ -0,0 +1,57 @@
+package {{consumerPackage}};
+
+{{#imports}}import {{import}};
+{{/imports}}
+{{#hasModel}}
+import {{modelPackage}}.*;
+{{/hasModel}}
+{{#operations}}
+import {{interfacePackage}}.{{serviceName}};
+{{/operations}}
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.web.bind.annotation.*;
+{{#async}}
+import java.util.concurrent.CompletableFuture;
+{{/async}}
+import javax.annotation.Generated;
+
+
+{{>generatedAnnotation}}
+{{#operations}}
+@RestController
+@RequestMapping("/{{baseName}}")
+public class {{classname}}Controller {
+
+ @DubboReference
+ private {{serviceName}} {{serviceVarName}};
+
+{{#operation}}
+ @RequestMapping(method = RequestMethod.{{httpMethod}}, value = "{{#vendorExtensions.x-sub-path}}{{{vendorExtensions.x-sub-path}}}{{/vendorExtensions.x-sub-path}}{{^vendorExtensions.x-sub-path}}/{{/vendorExtensions.x-sub-path}}")
+{{#async}}
+ public CompletableFuture<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}(
+{{/async}}
+{{^async}}
+ public {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}(
+{{/async}}
+{{#allParams}}
+ @RequestParam(name = "{{paramName}}"{{#defaultValue}}, defaultValue = "{{.}}"{{/defaultValue}}) {{{dataType}}} {{paramName}}{{^-last}},{{/-last}}
+{{/allParams}}
+ ) {
+{{#async}}
+ return {{serviceVarName}}.{{nickname}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+{{/async}}
+{{^async}}
+ {{#returnType}}return {{/returnType}}{{serviceVarName}}.{{nickname}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+{{/async}}
+ }
+{{^-last}}
+
+{{/-last}}
+{{/operation}}
+}
+{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/apiDubbo.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/apiDubbo.mustache
new file mode 100644
index 00000000000..bb78e6e2edc
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/apiDubbo.mustache
@@ -0,0 +1,66 @@
+package {{providerPackage}};
+
+{{#imports}}import {{import}};
+{{/imports}}
+{{#hasModel}}
+import {{modelPackage}}.*;
+{{/hasModel}}
+{{#operations}}
+import {{interfacePackage}}.{{serviceName}};
+{{/operations}}
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+{{#async}}
+import java.util.concurrent.CompletableFuture;
+{{/async}}
+import javax.annotation.Generated;
+
+
+{{>generatedAnnotation}}
+{{#operations}}
+@DubboService
+public class {{serviceName}}Impl implements {{serviceName}} {
+
+ private static final Logger logger = LoggerFactory.getLogger({{serviceName}}Impl.class);
+
+{{#operation}}
+ @Override
+{{#async}}
+ public CompletableFuture<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}(
+{{/async}}
+{{^async}}
+ public {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}(
+{{/async}}
+{{#allParams}}
+ {{{dataType}}} {{paramName}}{{^-last}},{{/-last}}
+{{/allParams}}
+ ) {
+ logger.info("Dubbo service method {{nickname}} called with parameters: {{#allParams}}{{paramName}}={}{{^-last}}, {{/-last}}{{/allParams}}"{{#allParams}}, {{paramName}}{{/allParams}});
+
+{{#async}}
+ return CompletableFuture.supplyAsync(() -> {
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ });
+{{/async}}
+{{^async}}
+ // TODO: Implement your business logic here
+{{#returnType}}
+ // Replace this with actual implementation
+ return null;
+{{/returnType}}
+{{/async}}
+ }
+{{^-last}}
+
+{{/-last}}
+{{/operation}}
+}
+{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/application.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/application.mustache
new file mode 100644
index 00000000000..17c5ff5c031
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/application.mustache
@@ -0,0 +1,20 @@
+spring:
+ application:
+ name: {{artifactId}}-provider
+
+dubbo:
+ application:
+ name: {{artifactId}}
+ logger: slf4j
+ registry:
+ address: {{registryAddress}}
+ # 协议配置
+ protocol:
+ name: tri
+ port: -1 # auto-increment port
+
+logging:
+ level:
+ root: INFO
+ org.apache.dubbo: INFO
+ {{invokerPackage}}: DEBUG
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/applicationTest.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/applicationTest.mustache
new file mode 100644
index 00000000000..49b3e127060
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/applicationTest.mustache
@@ -0,0 +1,13 @@
+package {{invokerPackage}};
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class {{testClassName}} {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/beanValidation.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/beanValidation.mustache
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/generatedAnnotation.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/generatedAnnotation.mustache
new file mode 100644
index 00000000000..4fc54c11ac0
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/generatedAnnotation.mustache
@@ -0,0 +1,6 @@
+@Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}, comments = "Generator version: {{generatorVersion}}")
+{{^hideGenerationTimestamp}}/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */{{/hideGenerationTimestamp}}
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/mainApplication.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/mainApplication.mustache
new file mode 100644
index 00000000000..d5ebe5af2f4
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/mainApplication.mustache
@@ -0,0 +1,15 @@
+package {{invokerPackage}};
+
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableDubbo(scanBasePackages = "{{invokerPackage}}")
+public class {{mainClassName}} {
+
+ public static void main(String[] args) {
+ SpringApplication.run({{mainClassName}}.class, args);
+ }
+
+}
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/model.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/model.mustache
new file mode 100644
index 00000000000..ba5efc7e40d
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/model.mustache
@@ -0,0 +1,92 @@
+package {{package}};
+
+{{#imports}}import {{import}};
+{{/imports}}
+import java.util.Objects;
+{{#serializableModel}}
+import java.io.Serializable;
+{{/serializableModel}}
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.Generated;
+import java.time.*;
+import java.math.*;
+{{#models}}
+{{#model}}
+{{>generatedAnnotation}}
+{{#description}}
+/**
+ * {{.}}
+ */
+{{/description}}
+public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{^parent}}{{#serializableModel}}implements Serializable{{/serializableModel}}{{/parent}} {
+{{#serializableModel}}
+ private static final long serialVersionUID = 1L;
+{{/serializableModel}}
+
+{{#vars}}
+{{#description}}
+ /**
+ * {{.}}
+ */
+{{/description}}
+ @JsonProperty("{{baseName}}")
+ private {{{dataType}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
+
+{{/vars}}
+{{#vars}}
+ /**
+ * {{description}}
+ * @return {{name}}
+ */
+ public {{{dataType}}} {{getter}}() {
+ return {{name}};
+ }
+
+ public void {{setter}}({{{dataType}}} {{name}}) {
+ this.{{name}} = {{name}};
+ }
+
+{{/vars}}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }{{#hasVars}}
+ {{classname}} {{classVarName}} = ({{classname}}) o;
+ return {{#vars}}Objects.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
+ {{/-last}}{{/vars}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
+ return true;{{/hasVars}}
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash({{#vars}}{{name}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}});
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class {{classname}} {\n");
+ {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}}
+ {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n");
+ {{/vars}}sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
+{{/model}}
+{{/models}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/pom.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/pom.mustache
new file mode 100644
index 00000000000..dbc9d340f53
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/pom.mustache
@@ -0,0 +1,141 @@
+
+
+ 4.0.0
+
+ {{groupId}}
+ {{artifactId}}
+ {{appVersion}}
+ jar
+
+ {{appName}}
+ {{appDescription}}
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.18
+
+
+
+
+ {{javaVersion}}
+ UTF-8
+ UTF-8
+ {{dubboVersion}}
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-starter
+ ${dubbo.version}
+
+
+
+
+ org.apache.dubbo
+ dubbo
+ ${dubbo.version}
+
+
+{{#isZookeeperRegistry}}
+
+{{#isDubbo33Plus}}
+
+
+ org.apache.dubbo
+ dubbo-registry-zookeeper
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-remoting-zookeeper-curator5
+ ${dubbo.version}
+
+{{/isDubbo33Plus}}
+{{^isDubbo33Plus}}
+
+
+ org.apache.dubbo
+ dubbo-dependencies-zookeeper
+ ${dubbo.version}
+ pom
+
+{{/isDubbo33Plus}}
+{{/isZookeeperRegistry}}
+
+{{#isNacosRegistry}}
+
+
+ org.apache.dubbo
+ dubbo-registry-nacos
+ ${dubbo.version}
+
+
+ com.alibaba.nacos
+ nacos-client
+ {{nacosClientVersion}}
+
+{{/isNacosRegistry}}
+
+{{^isZookeeperRegistry}}{{^isNacosRegistry}}
+
+{{#isDubbo33Plus}}
+
+
+ org.apache.dubbo
+ dubbo-registry-zookeeper
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-remoting-zookeeper-curator5
+ ${dubbo.version}
+
+{{/isDubbo33Plus}}
+{{^isDubbo33Plus}}
+
+
+ org.apache.dubbo
+ dubbo-dependencies-zookeeper
+ ${dubbo.version}
+ pom
+
+{{/isDubbo33Plus}}
+{{/isNacosRegistry}}{{/isZookeeperRegistry}}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ ${java.version}
+ ${java.version}
+ ${project.build.sourceEncoding}
+
+
+
+
+
diff --git a/modules/openapi-generator/src/main/resources/java-dubbo/returnValueExample.mustache b/modules/openapi-generator/src/main/resources/java-dubbo/returnValueExample.mustache
new file mode 100644
index 00000000000..7ba3df8ba1d
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/java-dubbo/returnValueExample.mustache
@@ -0,0 +1 @@
+{{#isString}}"示例字符串"{{/isString}}{{#isBoolean}}true{{/isBoolean}}{{#isInteger}}1{{/isInteger}}{{#isLong}}1L{{/isLong}}{{#isFloat}}1.0f{{/isFloat}}{{#isDouble}}1.0{{/isDouble}}{{#isBinary}}null{{/isBinary}}{{#isByteArray}}null{{/isByteArray}}{{#isDate}}null{{/isDate}}{{#isDateTime}}null{{/isDateTime}}{{#isArray}}null{{/isArray}}{{#isMap}}null{{/isMap}}{{#returnContainer}}null{{/returnContainer}}{{#isContainer}}null{{/isContainer}}{{^isPrimitiveType}}null{{/isPrimitiveType}}
diff --git a/samples/server/petstore/java-dubbo/.openapi-generator-ignore b/samples/server/petstore/java-dubbo/.openapi-generator-ignore
new file mode 100644
index 00000000000..0ace8df8597
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/.openapi-generator-ignore
@@ -0,0 +1,33 @@
+# IMPORTANT: this file is generated with the option `openapiGeneratorIgnoreList` enabled
+# (--openapi-generator-ignore-list in CLI for example) so the entries below are pre-populated based
+# on the input provided by the users and this file will be overwritten every time when the option is
+# enabled (which is the exact opposite of the default behaviour to not overwrite
+# .openapi-generator-ignore if the file exists).
+
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
+
+# The following entries are pre-populated based on the input obtained via
+# the option `openapiGeneratorIgnoreList` (--openapi-generator-ignore-list in CLI for example).
+# Dubbo generator explicitly disables .openapi-generator-ignore
diff --git a/samples/server/petstore/java-dubbo/.openapi-generator/FILES b/samples/server/petstore/java-dubbo/.openapi-generator/FILES
new file mode 100644
index 00000000000..d1e16c54bc4
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/.openapi-generator/FILES
@@ -0,0 +1,20 @@
+README.md
+pom.xml
+src/main/java/org/openapitools/example/OpenAPIPetstoreApplication.java
+src/main/java/org/openapitools/example/api/consumer/PetServiceController.java
+src/main/java/org/openapitools/example/api/consumer/StoreServiceController.java
+src/main/java/org/openapitools/example/api/consumer/UserServiceController.java
+src/main/java/org/openapitools/example/api/interfaces/PetService.java
+src/main/java/org/openapitools/example/api/interfaces/StoreService.java
+src/main/java/org/openapitools/example/api/interfaces/UserService.java
+src/main/java/org/openapitools/example/api/provider/PetServiceImpl.java
+src/main/java/org/openapitools/example/api/provider/StoreServiceImpl.java
+src/main/java/org/openapitools/example/api/provider/UserServiceImpl.java
+src/main/java/org/openapitools/example/model/Category.java
+src/main/java/org/openapitools/example/model/ModelApiResponse.java
+src/main/java/org/openapitools/example/model/Order.java
+src/main/java/org/openapitools/example/model/Pet.java
+src/main/java/org/openapitools/example/model/Tag.java
+src/main/java/org/openapitools/example/model/User.java
+src/main/resources/application.yml
+src/test/java/org/openapitools/example/OpenAPIPetstoreApplicationTests.java
diff --git a/samples/server/petstore/java-dubbo/.openapi-generator/VERSION b/samples/server/petstore/java-dubbo/.openapi-generator/VERSION
new file mode 100644
index 00000000000..5e528295308
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.16.0-SNAPSHOT
diff --git a/samples/server/petstore/java-dubbo/README.md b/samples/server/petstore/java-dubbo/README.md
new file mode 100644
index 00000000000..48ed7469f4c
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/README.md
@@ -0,0 +1,283 @@
+# OpenAPI Petstore
+
+This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+
+This is a microservice project based on Apache Dubbo, generated by [OpenAPI Generator](https://openapi-generator.tech).
+
+- API version: 1.0.0
+- Package version:
+- Generator: org.openapitools.codegen.languages.JavaDubboServerCodegen
+
+## Technology Stack
+
+- **Framework**: Apache Dubbo 3.2.18
+- **Java**: 8+
+- **Build Tool**: Maven 3.6+
+- **Registry**: zookeeper://127.0.0.1:2181
+- **Serialization**: Jackson JSON
+
+## System Requirements
+
+Building and running this project requires:
+1. Java 8+
+2. Maven 3.6+
+3. Registry Center (Nacos or Zookeeper)
+
+## Quick Start
+
+### 1. Clone and Build Project
+
+```bash
+git clone
+cd openapi-dubbo-server-petstore
+mvn clean compile
+```
+
+### 2. Configure Registry Center
+
+#### Using Nacos (Recommended)
+```bash
+# Download and start Nacos
+wget https://github.com/alibaba/nacos/releases/download/2.2.4/nacos-server-2.2.4.tar.gz
+tar -xzf nacos-server-2.2.4.tar.gz
+cd nacos/bin
+# Linux/Mac
+./startup.sh -m standalone
+# Windows
+startup.cmd -m standalone
+```
+
+#### Using Zookeeper (Alternative)
+```bash
+# Download and start Zookeeper
+wget https://downloads.apache.org/zookeeper/zookeeper-3.8.2/apache-zookeeper-3.8.2-bin.tar.gz
+tar -xzf apache-zookeeper-3.8.2-bin.tar.gz
+cd apache-zookeeper-3.8.2-bin
+cp conf/zoo_sample.cfg conf/zoo.cfg
+bin/zkServer.sh start
+```
+
+### 3. Configure Application
+
+Edit the `src/main/resources/application.yml` file:
+
+```yaml
+# Dubbo Configuration
+dubbo:
+ application:
+ name: openapi-dubbo-server-petstore
+ registry:
+ # Using Nacos
+ address: nacos://127.0.0.1:8848
+ # Or using Zookeeper
+ # address: zookeeper://127.0.0.1:2181
+ protocol:
+ name: dubbo
+ port: 20880
+ provider:
+ timeout: 10000
+
+```
+
+### 4. Start Application
+
+```bash
+# Build project
+mvn clean compile
+
+# Run main class
+mvn exec:java -Dexec.mainClass=".Application"
+```
+
+## Project Structure
+
+```
+openapi-dubbo-server-petstore/
+├── src/main/java//
+│ └── Application.java # Main Application Class
+├── src/main/resources/
+│ └── application.yml # Application Configuration
+├── pom.xml # Maven Configuration
+└── README.md # Project Documentation
+```
+
+## API Interfaces
+
+
+### Service Interfaces
+
+
+## Development Guide
+
+### Implement Business Logic
+
+1. Implement specific business logic in the generated `*DubboImpl.java` classes
+2. Inject necessary business service dependencies
+3. Handle exceptions and error scenarios
+
+### Custom Configuration
+
+1. **Timeout Configuration**: Adjust `dubbo.provider.timeout` in `application.yml`
+2. **Thread Pool Configuration**: Configure `dubbo.provider.threads` and other parameters
+3. **Serialization Configuration**: Choose appropriate serialization method
+
+### Monitoring and Operations
+
+1. **Health Checks**: Dubbo provides built-in health check endpoints
+2. **Metrics Monitoring**: Integrate with Prometheus or other monitoring systems
+3. **Log Management**: Configure appropriate log levels and output formats
+
+## Testing
+
+```bash
+# Run unit tests
+mvn test
+
+# Run integration tests
+mvn integration-test
+```
+
+## Deployment
+
+### Development Environment
+```bash
+mvn spring-boot:run
+```
+
+### Production Environment
+```bash
+# Build production package
+mvn clean package -Pprod
+
+# Deploy using Docker
+docker build -t openapi-dubbo-server-petstore:1.0.0 .
+docker run -p 8080:8080 -p 20880:20880 openapi-dubbo-server-petstore:1.0.0
+```
+
+## Generator Configuration Options
+
+This project supports the following OpenAPI Generator configuration options:
+
+### Basic Configuration
+- `title`: API service title name (Default: "OpenAPI Dubbo")
+- `basePackage`: Base package name (Default: "org.openapitools")
+- `configPackage`: Configuration class package name (Default: "org.openapitools.configuration")
+- `dubboVersion`: Dubbo version (Default: "3.2.0")
+
+### Generation Control
+- `interfaceOnly`: Generate interfaces only, no implementation classes (Default: false)
+- `serviceInterface`: Generate service interfaces (Default: true)
+- `serviceImplementation`: Generate service implementations (Default: true)
+- `async`: Use asynchronous methods (Default: false)
+- `useTags`: Use tags to create class names (Default: true)
+- `useGenericResponse`: Use generic response wrapper (Default: false)
+
+### Registry Configuration
+- `registry-address`: Registry address, supports full address format (Default: "zookeeper://127.0.0.1:2181")
+ - Zookeeper example: `zookeeper://127.0.0.1:2181`
+ - Nacos example: `nacos://127.0.0.1:8848`
+
+#### 📋 Automatic Dependency Adaptation by Version
+The generator automatically selects the correct dependencies based on Dubbo version:
+
+**Dubbo 3.2 and earlier versions**:
+- Zookeeper: `dubbo-dependencies-zookeeper` (Aggregation POM)
+- Nacos: `dubbo-registry-nacos` + `nacos-client:2.2.4`
+
+**Dubbo 3.3+ versions**:
+- Zookeeper: `dubbo-registry-zookeeper` + `dubbo-remoting-zookeeper-curator5`
+- Nacos: `dubbo-registry-nacos` + `nacos-client:2.5.0`
+
+### Date-Time Library Configuration
+- `dateLibrary`: Date-time library selection (Default: "java8")
+ - `java8`: Java 8 native JSR310 (Recommended, for JDK 1.8+)
+ - `java8-localdatetime`: Java 8 using LocalDateTime (For legacy applications only)
+ - `joda`: Joda time library (For legacy applications only)
+ - `legacy`: Traditional java.util.Date
+
+### Usage Examples
+
+#### 🔧 Dubbo 3.2 Version Example
+```bash
+# Using Zookeeper (3.2 version automatically uses dubbo-dependencies-zookeeper)
+java -jar openapi-generator-cli.jar generate \
+-i /Users/redoom/IdeaProjects/openapi.yaml \
+-g java-dubbo \
+-o /Users/redoom/IdeaProjects/openapi-test \
+--additional-properties=registry-address=zookeeper://127.0.0.1:2181 \
+--additional-properties=dubboVersion=3.2.0 \
+--additional-properties=dateLibrary=java8
+
+# Using Nacos (3.2 version uses nacos-client:2.2.4)
+java -jar openapi-generator-cli.jar generate \
+-i /Users/redoom/IdeaProjects/openapi.yaml \
+-g java-dubbo \
+-o /Users/redoom/IdeaProjects/openapi-test \
+--additional-properties=registry-address=nacos://127.0.0.1:8848 \
+--additional-properties=dubboVersion=3.2.0 \
+--additional-properties=dateLibrary=java8
+```
+
+#### 🚀 Dubbo 3.3+ Version Example
+```bash
+# Using Zookeeper (3.3+ version automatically uses new modular dependencies)
+java -jar openapi-generator-cli.jar generate \
+-i /Users/redoom/IdeaProjects/openapi.yaml \
+-g java-dubbo \
+-o /Users/redoom/IdeaProjects/openapi-test \
+--additional-properties=registry-address=zookeeper://127.0.0.1:2181 \
+--additional-properties=dubboVersion=3.3.0 \
+--additional-properties=dateLibrary=java8
+
+# Using Nacos (3.3+ version uses nacos-client:2.5.0)
+java -jar openapi-generator-cli.jar generate \
+-i /Users/redoom/IdeaProjects/openapi.yaml \
+-g java-dubbo \
+-o /Users/redoom/IdeaProjects/openapi-test \
+--additional-properties=registry-address=nacos://127.0.0.1:8848 \
+--additional-properties=dubboVersion=3.3.0 \
+--additional-properties=dateLibrary=java8
+```
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Registry Connection Failed**
+ - Check if the registry center is started
+ - Verify network connection and port configuration
+
+2. **Service Call Timeout**
+ - Adjust `dubbo.provider.timeout` settings
+ - Check network latency and service performance
+
+3. **Serialization Exception**
+ - Ensure all model classes implement `Serializable` interface
+ - Check Jackson configuration
+
+### Debug Logging
+
+Enable debug mode to see detailed logs:
+
+```yaml
+logging:
+ level:
+ org.apache.dubbo: DEBUG
+ : DEBUG
+```
+
+## License
+
+This project is licensed under the [Apache License 2.0](LICENSE).
+
+## Contributing
+
+Issues and Pull Requests are welcome!
+
+## Contact
+
+
+
+---
+
+> This project is automatically generated by OpenAPI Generator, based on Apache Dubbo microservice architecture.
diff --git a/samples/server/petstore/java-dubbo/pom.xml b/samples/server/petstore/java-dubbo/pom.xml
new file mode 100644
index 00000000000..c7046f070f5
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/pom.xml
@@ -0,0 +1,87 @@
+
+
+ 4.0.0
+
+ org.openapitools
+ openapi-dubbo-server-petstore
+ 1.0.0
+ jar
+
+ OpenAPI Petstore
+ This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.18
+
+
+
+
+ 17
+ UTF-8
+ UTF-8
+ 3.2.18
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-starter
+ ${dubbo.version}
+
+
+
+
+ org.apache.dubbo
+ dubbo
+ ${dubbo.version}
+
+
+
+
+
+ org.apache.dubbo
+ dubbo-dependencies-zookeeper
+ ${dubbo.version}
+ pom
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ ${java.version}
+ ${java.version}
+ ${project.build.sourceEncoding}
+
+
+
+
+
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/OpenAPIPetstoreApplication.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/OpenAPIPetstoreApplication.java
new file mode 100644
index 00000000000..239ebf52bf3
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/OpenAPIPetstoreApplication.java
@@ -0,0 +1,15 @@
+package org.openapitools.example;
+
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableDubbo(scanBasePackages = "org.openapitools.example")
+public class OpenAPIPetstoreApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(OpenAPIPetstoreApplication.class, args);
+ }
+
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/PetServiceController.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/PetServiceController.java
new file mode 100644
index 00000000000..df8b9ef220e
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/PetServiceController.java
@@ -0,0 +1,86 @@
+package org.openapitools.example.api.consumer;
+
+import org.openapitools.example.model.ModelApiResponse;
+import org.openapitools.example.model.Pet;
+import org.openapitools.example.model.*;
+import org.openapitools.example.api.interfaces.PetService;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+@RestController
+@RequestMapping("/pet")
+public class PetServiceController {
+
+ @DubboReference
+ private PetService petService;
+
+ @RequestMapping(method = RequestMethod.POST, value = "/")
+ public Pet addPet(
+ @RequestParam(name = "pet") Pet pet
+ ) {
+ return petService.addPet(pet);
+ }
+
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{petId}")
+ public void deletePet(
+ @RequestParam(name = "petId") Long petId,
+ @RequestParam(name = "apiKey") String apiKey
+ ) {
+ petService.deletePet(petId, apiKey);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/findByStatus")
+ public List findPetsByStatus(
+ @RequestParam(name = "status") List status
+ ) {
+ return petService.findPetsByStatus(status);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/findByTags")
+ public List findPetsByTags(
+ @RequestParam(name = "tags") List tags
+ ) {
+ return petService.findPetsByTags(tags);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/{petId}")
+ public Pet getPetById(
+ @RequestParam(name = "petId") Long petId
+ ) {
+ return petService.getPetById(petId);
+ }
+
+ @RequestMapping(method = RequestMethod.PUT, value = "/")
+ public Pet updatePet(
+ @RequestParam(name = "pet") Pet pet
+ ) {
+ return petService.updatePet(pet);
+ }
+
+ @RequestMapping(method = RequestMethod.POST, value = "/{petId}")
+ public void updatePetWithForm(
+ @RequestParam(name = "petId") Long petId,
+ @RequestParam(name = "name") String name,
+ @RequestParam(name = "status") String status
+ ) {
+ petService.updatePetWithForm(petId, name, status);
+ }
+
+ @RequestMapping(method = RequestMethod.POST, value = "/{petId}/uploadImage")
+ public ModelApiResponse uploadFile(
+ @RequestParam(name = "petId") Long petId,
+ @RequestParam(name = "additionalMetadata") String additionalMetadata,
+ @RequestParam(name = "_file") org.springframework.web.multipart.MultipartFile _file
+ ) {
+ return petService.uploadFile(petId, additionalMetadata, _file);
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/StoreServiceController.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/StoreServiceController.java
new file mode 100644
index 00000000000..07e054c2d96
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/StoreServiceController.java
@@ -0,0 +1,51 @@
+package org.openapitools.example.api.consumer;
+
+import org.openapitools.example.model.Order;
+import org.openapitools.example.model.*;
+import org.openapitools.example.api.interfaces.StoreService;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+@RestController
+@RequestMapping("/store")
+public class StoreServiceController {
+
+ @DubboReference
+ private StoreService storeService;
+
+ @RequestMapping(method = RequestMethod.DELETE, value = "/order/{orderId}")
+ public void deleteOrder(
+ @RequestParam(name = "orderId") String orderId
+ ) {
+ storeService.deleteOrder(orderId);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/inventory")
+ public Map getInventory(
+ ) {
+ return storeService.getInventory();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/order/{orderId}")
+ public Order getOrderById(
+ @RequestParam(name = "orderId") Long orderId
+ ) {
+ return storeService.getOrderById(orderId);
+ }
+
+ @RequestMapping(method = RequestMethod.POST, value = "/order")
+ public Order placeOrder(
+ @RequestParam(name = "order") Order order
+ ) {
+ return storeService.placeOrder(order);
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/UserServiceController.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/UserServiceController.java
new file mode 100644
index 00000000000..853037db62e
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/consumer/UserServiceController.java
@@ -0,0 +1,82 @@
+package org.openapitools.example.api.consumer;
+
+import java.time.OffsetDateTime;
+import org.openapitools.example.model.User;
+import org.openapitools.example.model.*;
+import org.openapitools.example.api.interfaces.UserService;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+@RestController
+@RequestMapping("/user")
+public class UserServiceController {
+
+ @DubboReference
+ private UserService userService;
+
+ @RequestMapping(method = RequestMethod.POST, value = "/")
+ public void createUser(
+ @RequestParam(name = "user") User user
+ ) {
+ userService.createUser(user);
+ }
+
+ @RequestMapping(method = RequestMethod.POST, value = "/createWithArray")
+ public void createUsersWithArrayInput(
+ @RequestParam(name = "user") List user
+ ) {
+ userService.createUsersWithArrayInput(user);
+ }
+
+ @RequestMapping(method = RequestMethod.POST, value = "/createWithList")
+ public void createUsersWithListInput(
+ @RequestParam(name = "user") List user
+ ) {
+ userService.createUsersWithListInput(user);
+ }
+
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{username}")
+ public void deleteUser(
+ @RequestParam(name = "username") String username
+ ) {
+ userService.deleteUser(username);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/{username}")
+ public User getUserByName(
+ @RequestParam(name = "username") String username
+ ) {
+ return userService.getUserByName(username);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/login")
+ public String loginUser(
+ @RequestParam(name = "username") String username,
+ @RequestParam(name = "password") String password
+ ) {
+ return userService.loginUser(username, password);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/logout")
+ public void logoutUser(
+ ) {
+ userService.logoutUser();
+ }
+
+ @RequestMapping(method = RequestMethod.PUT, value = "/{username}")
+ public void updateUser(
+ @RequestParam(name = "username") String username,
+ @RequestParam(name = "user") User user
+ ) {
+ userService.updateUser(username, user);
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/PetService.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/PetService.java
new file mode 100644
index 00000000000..7749895b2b8
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/PetService.java
@@ -0,0 +1,115 @@
+package org.openapitools.example.api.interfaces;
+
+import org.openapitools.example.model.ModelApiResponse;
+import org.openapitools.example.model.Pet;
+import org.openapitools.example.model.*;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+public interface PetService {
+
+ /**
+ * Add a new pet to the store
+ *
+ *
+ * @param pet Pet object that needs to be added to the store (required)
+ * @return Pet
+ */
+ Pet addPet(
+ Pet pet
+ );
+
+ /**
+ * Deletes a pet
+ *
+ *
+ * @param petId Pet id to delete (required)
+ * @param apiKey (optional)
+ * @return void
+ */
+ void deletePet(
+ Long petId,
+ String apiKey
+ );
+
+ /**
+ * Finds Pets by status
+ * Multiple status values can be provided with comma separated strings
+ *
+ * @param status Status values that need to be considered for filter (required)
+ * @return List
+ */
+ List findPetsByStatus(
+ List status
+ );
+
+ /**
+ * Finds Pets by tags
+ * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
+ *
+ * @param tags Tags to filter by (required)
+ * @return List
+ */
+ List findPetsByTags(
+ List tags
+ );
+
+ /**
+ * Find pet by ID
+ * Returns a single pet
+ *
+ * @param petId ID of pet to return (required)
+ * @return Pet
+ */
+ Pet getPetById(
+ Long petId
+ );
+
+ /**
+ * Update an existing pet
+ *
+ *
+ * @param pet Pet object that needs to be added to the store (required)
+ * @return Pet
+ */
+ Pet updatePet(
+ Pet pet
+ );
+
+ /**
+ * Updates a pet in the store with form data
+ *
+ *
+ * @param petId ID of pet that needs to be updated (required)
+ * @param name Updated name of the pet (optional)
+ * @param status Updated status of the pet (optional)
+ * @return void
+ */
+ void updatePetWithForm(
+ Long petId,
+ String name,
+ String status
+ );
+
+ /**
+ * uploads an image
+ *
+ *
+ * @param petId ID of pet to update (required)
+ * @param additionalMetadata Additional data to pass to server (optional)
+ * @param _file file to upload (optional)
+ * @return ModelApiResponse
+ */
+ ModelApiResponse uploadFile(
+ Long petId,
+ String additionalMetadata,
+ org.springframework.web.multipart.MultipartFile _file
+ );
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/StoreService.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/StoreService.java
new file mode 100644
index 00000000000..5286e4d5850
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/StoreService.java
@@ -0,0 +1,58 @@
+package org.openapitools.example.api.interfaces;
+
+import org.openapitools.example.model.Order;
+import org.openapitools.example.model.*;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+public interface StoreService {
+
+ /**
+ * Delete purchase order by ID
+ * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
+ *
+ * @param orderId ID of the order that needs to be deleted (required)
+ * @return void
+ */
+ void deleteOrder(
+ String orderId
+ );
+
+ /**
+ * Returns pet inventories by status
+ * Returns a map of status codes to quantities
+ *
+ * @return Map
+ */
+ Map getInventory(
+ );
+
+ /**
+ * Find purchase order by ID
+ * For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
+ *
+ * @param orderId ID of pet that needs to be fetched (required)
+ * @return Order
+ */
+ Order getOrderById(
+ Long orderId
+ );
+
+ /**
+ * Place an order for a pet
+ *
+ *
+ * @param order order placed for purchasing the pet (required)
+ * @return Order
+ */
+ Order placeOrder(
+ Order order
+ );
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/UserService.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/UserService.java
new file mode 100644
index 00000000000..1b123d3cf11
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/interfaces/UserService.java
@@ -0,0 +1,107 @@
+package org.openapitools.example.api.interfaces;
+
+import java.time.OffsetDateTime;
+import org.openapitools.example.model.User;
+import org.openapitools.example.model.*;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+public interface UserService {
+
+ /**
+ * Create user
+ * This can only be done by the logged in user.
+ *
+ * @param user Created user object (required)
+ * @return void
+ */
+ void createUser(
+ User user
+ );
+
+ /**
+ * Creates list of users with given input array
+ *
+ *
+ * @param user List of user object (required)
+ * @return void
+ */
+ void createUsersWithArrayInput(
+ List user
+ );
+
+ /**
+ * Creates list of users with given input array
+ *
+ *
+ * @param user List of user object (required)
+ * @return void
+ */
+ void createUsersWithListInput(
+ List user
+ );
+
+ /**
+ * Delete user
+ * This can only be done by the logged in user.
+ *
+ * @param username The name that needs to be deleted (required)
+ * @return void
+ */
+ void deleteUser(
+ String username
+ );
+
+ /**
+ * Get user by user name
+ *
+ *
+ * @param username The name that needs to be fetched. Use user1 for testing. (required)
+ * @return User
+ */
+ User getUserByName(
+ String username
+ );
+
+ /**
+ * Logs user into the system
+ *
+ *
+ * @param username The user name for login (required)
+ * @param password The password for login in clear text (required)
+ * @return String
+ */
+ String loginUser(
+ String username,
+ String password
+ );
+
+ /**
+ * Logs out current logged in user session
+ *
+ *
+ * @return void
+ */
+ void logoutUser(
+ );
+
+ /**
+ * Updated user
+ * This can only be done by the logged in user.
+ *
+ * @param username name that need to be deleted (required)
+ * @param user Updated user object (required)
+ * @return void
+ */
+ void updateUser(
+ String username,
+ User user
+ );
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/PetServiceImpl.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/PetServiceImpl.java
new file mode 100644
index 00000000000..b8935a3aca6
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/PetServiceImpl.java
@@ -0,0 +1,113 @@
+package org.openapitools.example.api.provider;
+
+import org.openapitools.example.model.ModelApiResponse;
+import org.openapitools.example.model.Pet;
+import org.openapitools.example.model.*;
+import org.openapitools.example.api.interfaces.PetService;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+@DubboService
+public class PetServiceImpl implements PetService {
+
+ private static final Logger logger = LoggerFactory.getLogger(PetServiceImpl.class);
+
+ @Override
+ public Pet addPet(
+ Pet pet
+ ) {
+ logger.info("Dubbo service method addPet called with parameters: pet={}", pet);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public void deletePet(
+ Long petId,
+ String apiKey
+ ) {
+ logger.info("Dubbo service method deletePet called with parameters: petId={}, apiKey={}", petId, apiKey);
+
+ // TODO: Implement your business logic here
+ }
+
+ @Override
+ public List findPetsByStatus(
+ List status
+ ) {
+ logger.info("Dubbo service method findPetsByStatus called with parameters: status={}", status);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public List findPetsByTags(
+ List tags
+ ) {
+ logger.info("Dubbo service method findPetsByTags called with parameters: tags={}", tags);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public Pet getPetById(
+ Long petId
+ ) {
+ logger.info("Dubbo service method getPetById called with parameters: petId={}", petId);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public Pet updatePet(
+ Pet pet
+ ) {
+ logger.info("Dubbo service method updatePet called with parameters: pet={}", pet);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public void updatePetWithForm(
+ Long petId,
+ String name,
+ String status
+ ) {
+ logger.info("Dubbo service method updatePetWithForm called with parameters: petId={}, name={}, status={}", petId, name, status);
+
+ // TODO: Implement your business logic here
+ }
+
+ @Override
+ public ModelApiResponse uploadFile(
+ Long petId,
+ String additionalMetadata,
+ org.springframework.web.multipart.MultipartFile _file
+ ) {
+ logger.info("Dubbo service method uploadFile called with parameters: petId={}, additionalMetadata={}, _file={}", petId, additionalMetadata, _file);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/StoreServiceImpl.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/StoreServiceImpl.java
new file mode 100644
index 00000000000..59e5f8f6871
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/StoreServiceImpl.java
@@ -0,0 +1,64 @@
+package org.openapitools.example.api.provider;
+
+import org.openapitools.example.model.Order;
+import org.openapitools.example.model.*;
+import org.openapitools.example.api.interfaces.StoreService;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+@DubboService
+public class StoreServiceImpl implements StoreService {
+
+ private static final Logger logger = LoggerFactory.getLogger(StoreServiceImpl.class);
+
+ @Override
+ public void deleteOrder(
+ String orderId
+ ) {
+ logger.info("Dubbo service method deleteOrder called with parameters: orderId={}", orderId);
+
+ // TODO: Implement your business logic here
+ }
+
+ @Override
+ public Map getInventory(
+ ) {
+ logger.info("Dubbo service method getInventory called with parameters: ");
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public Order getOrderById(
+ Long orderId
+ ) {
+ logger.info("Dubbo service method getOrderById called with parameters: orderId={}", orderId);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public Order placeOrder(
+ Order order
+ ) {
+ logger.info("Dubbo service method placeOrder called with parameters: order={}", order);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/UserServiceImpl.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/UserServiceImpl.java
new file mode 100644
index 00000000000..fcdb4a95693
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/api/provider/UserServiceImpl.java
@@ -0,0 +1,101 @@
+package org.openapitools.example.api.provider;
+
+import java.time.OffsetDateTime;
+import org.openapitools.example.model.User;
+import org.openapitools.example.model.*;
+import org.openapitools.example.api.interfaces.UserService;
+import java.util.List;
+import java.util.Map;
+import java.time.OffsetDateTime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.annotation.Generated;
+
+
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+@DubboService
+public class UserServiceImpl implements UserService {
+
+ private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
+
+ @Override
+ public void createUser(
+ User user
+ ) {
+ logger.info("Dubbo service method createUser called with parameters: user={}", user);
+
+ // TODO: Implement your business logic here
+ }
+
+ @Override
+ public void createUsersWithArrayInput(
+ List user
+ ) {
+ logger.info("Dubbo service method createUsersWithArrayInput called with parameters: user={}", user);
+
+ // TODO: Implement your business logic here
+ }
+
+ @Override
+ public void createUsersWithListInput(
+ List user
+ ) {
+ logger.info("Dubbo service method createUsersWithListInput called with parameters: user={}", user);
+
+ // TODO: Implement your business logic here
+ }
+
+ @Override
+ public void deleteUser(
+ String username
+ ) {
+ logger.info("Dubbo service method deleteUser called with parameters: username={}", username);
+
+ // TODO: Implement your business logic here
+ }
+
+ @Override
+ public User getUserByName(
+ String username
+ ) {
+ logger.info("Dubbo service method getUserByName called with parameters: username={}", username);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public String loginUser(
+ String username,
+ String password
+ ) {
+ logger.info("Dubbo service method loginUser called with parameters: username={}, password={}", username, password);
+
+ // TODO: Implement your business logic here
+ // Replace this with actual implementation
+ return null;
+ }
+
+ @Override
+ public void logoutUser(
+ ) {
+ logger.info("Dubbo service method logoutUser called with parameters: ");
+
+ // TODO: Implement your business logic here
+ }
+
+ @Override
+ public void updateUser(
+ String username,
+ User user
+ ) {
+ logger.info("Dubbo service method updateUser called with parameters: username={}, user={}", username, user);
+
+ // TODO: Implement your business logic here
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Category.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Category.java
new file mode 100644
index 00000000000..f4927f411ac
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Category.java
@@ -0,0 +1,87 @@
+package org.openapitools.example.model;
+
+import java.util.Objects;
+import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.Generated;
+import java.time.*;
+import java.math.*;
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+/**
+ * A category for a pet
+ */
+public class Category implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("id")
+ private Long id;
+
+ @JsonProperty("name")
+ private String name;
+
+ /**
+ *
+ * @return id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Category category = (Category) o;
+ return Objects.equals(this.id, category.id) &&
+ Objects.equals(this.name, category.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class Category {\n");
+
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/ModelApiResponse.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/ModelApiResponse.java
new file mode 100644
index 00000000000..08b263e1e1e
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/ModelApiResponse.java
@@ -0,0 +1,104 @@
+package org.openapitools.example.model;
+
+import java.util.Objects;
+import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.Generated;
+import java.time.*;
+import java.math.*;
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+/**
+ * Describes the result of uploading an image resource
+ */
+public class ModelApiResponse implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("code")
+ private Integer code;
+
+ @JsonProperty("type")
+ private String type;
+
+ @JsonProperty("message")
+ private String message;
+
+ /**
+ *
+ * @return code
+ */
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ /**
+ *
+ * @return type
+ */
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ *
+ * @return message
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ModelApiResponse _apiResponse = (ModelApiResponse) o;
+ return Objects.equals(this.code, _apiResponse.code) &&
+ Objects.equals(this.type, _apiResponse.type) &&
+ Objects.equals(this.message, _apiResponse.message);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(code, type, message);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class ModelApiResponse {\n");
+
+ sb.append(" code: ").append(toIndentedString(code)).append("\n");
+ sb.append(" type: ").append(toIndentedString(type)).append("\n");
+ sb.append(" message: ").append(toIndentedString(message)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Order.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Order.java
new file mode 100644
index 00000000000..cd8c7e6d863
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Order.java
@@ -0,0 +1,159 @@
+package org.openapitools.example.model;
+
+import java.time.OffsetDateTime;
+import java.util.Objects;
+import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.Generated;
+import java.time.*;
+import java.math.*;
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+/**
+ * An order for a pets from the pet store
+ */
+public class Order implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("id")
+ private Long id;
+
+ @JsonProperty("petId")
+ private Long petId;
+
+ @JsonProperty("quantity")
+ private Integer quantity;
+
+ @JsonProperty("shipDate")
+ private OffsetDateTime shipDate;
+
+ /**
+ * Order Status
+ */
+ @JsonProperty("status")
+ private String status;
+
+ @JsonProperty("complete")
+ private Boolean complete = false;
+
+ /**
+ *
+ * @return id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return petId
+ */
+ public Long getPetId() {
+ return petId;
+ }
+
+ public void setPetId(Long petId) {
+ this.petId = petId;
+ }
+
+ /**
+ *
+ * @return quantity
+ */
+ public Integer getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(Integer quantity) {
+ this.quantity = quantity;
+ }
+
+ /**
+ *
+ * @return shipDate
+ */
+ public OffsetDateTime getShipDate() {
+ return shipDate;
+ }
+
+ public void setShipDate(OffsetDateTime shipDate) {
+ this.shipDate = shipDate;
+ }
+
+ /**
+ * Order Status
+ * @return status
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ /**
+ *
+ * @return complete
+ */
+ public Boolean getComplete() {
+ return complete;
+ }
+
+ public void setComplete(Boolean complete) {
+ this.complete = complete;
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Order order = (Order) o;
+ return Objects.equals(this.id, order.id) &&
+ Objects.equals(this.petId, order.petId) &&
+ Objects.equals(this.quantity, order.quantity) &&
+ Objects.equals(this.shipDate, order.shipDate) &&
+ Objects.equals(this.status, order.status) &&
+ Objects.equals(this.complete, order.complete);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, petId, quantity, shipDate, status, complete);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class Order {\n");
+
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ sb.append(" petId: ").append(toIndentedString(petId)).append("\n");
+ sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n");
+ sb.append(" shipDate: ").append(toIndentedString(shipDate)).append("\n");
+ sb.append(" status: ").append(toIndentedString(status)).append("\n");
+ sb.append(" complete: ").append(toIndentedString(complete)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Pet.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Pet.java
new file mode 100644
index 00000000000..fde4e66f361
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Pet.java
@@ -0,0 +1,161 @@
+package org.openapitools.example.model;
+
+import org.openapitools.example.model.Category;
+import org.openapitools.example.model.Tag;
+import java.util.*;
+import java.util.Objects;
+import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.Generated;
+import java.time.*;
+import java.math.*;
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+/**
+ * A pet for sale in the pet store
+ */
+public class Pet implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("id")
+ private Long id;
+
+ @JsonProperty("category")
+ private Category category;
+
+ @JsonProperty("name")
+ private String name;
+
+ @JsonProperty("photoUrls")
+ private List photoUrls = new ArrayList<>();
+
+ @JsonProperty("tags")
+ private List tags = new ArrayList<>();
+
+ /**
+ * pet status in the store
+ */
+ @JsonProperty("status")
+ private String status;
+
+ /**
+ *
+ * @return id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return category
+ */
+ public Category getCategory() {
+ return category;
+ }
+
+ public void setCategory(Category category) {
+ this.category = category;
+ }
+
+ /**
+ *
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ *
+ * @return photoUrls
+ */
+ public List getPhotoUrls() {
+ return photoUrls;
+ }
+
+ public void setPhotoUrls(List photoUrls) {
+ this.photoUrls = photoUrls;
+ }
+
+ /**
+ *
+ * @return tags
+ */
+ public List getTags() {
+ return tags;
+ }
+
+ public void setTags(List tags) {
+ this.tags = tags;
+ }
+
+ /**
+ * pet status in the store
+ * @return status
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Pet pet = (Pet) o;
+ return Objects.equals(this.id, pet.id) &&
+ Objects.equals(this.category, pet.category) &&
+ Objects.equals(this.name, pet.name) &&
+ Objects.equals(this.photoUrls, pet.photoUrls) &&
+ Objects.equals(this.tags, pet.tags) &&
+ Objects.equals(this.status, pet.status);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, category, name, photoUrls, tags, status);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class Pet {\n");
+
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ sb.append(" category: ").append(toIndentedString(category)).append("\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" photoUrls: ").append(toIndentedString(photoUrls)).append("\n");
+ sb.append(" tags: ").append(toIndentedString(tags)).append("\n");
+ sb.append(" status: ").append(toIndentedString(status)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Tag.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Tag.java
new file mode 100644
index 00000000000..b8a7d9e4f34
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/Tag.java
@@ -0,0 +1,87 @@
+package org.openapitools.example.model;
+
+import java.util.Objects;
+import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.Generated;
+import java.time.*;
+import java.math.*;
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+/**
+ * A tag for a pet
+ */
+public class Tag implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("id")
+ private Long id;
+
+ @JsonProperty("name")
+ private String name;
+
+ /**
+ *
+ * @return id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Tag tag = (Tag) o;
+ return Objects.equals(this.id, tag.id) &&
+ Objects.equals(this.name, tag.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class Tag {\n");
+
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/User.java b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/User.java
new file mode 100644
index 00000000000..f6478107940
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/java/org/openapitools/example/model/User.java
@@ -0,0 +1,192 @@
+package org.openapitools.example.model;
+
+import java.util.Objects;
+import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.Generated;
+import java.time.*;
+import java.math.*;
+@Generated(value = "org.openapitools.codegen.languages.JavaDubboServerCodegen", comments = "Generator version: 7.16.0-SNAPSHOT")
+
+/**
+ * A User who is purchasing from the pet store
+ */
+public class User implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("id")
+ private Long id;
+
+ @JsonProperty("username")
+ private String username;
+
+ @JsonProperty("firstName")
+ private String firstName;
+
+ @JsonProperty("lastName")
+ private String lastName;
+
+ @JsonProperty("email")
+ private String email;
+
+ @JsonProperty("password")
+ private String password;
+
+ @JsonProperty("phone")
+ private String phone;
+
+ /**
+ * User Status
+ */
+ @JsonProperty("userStatus")
+ private Integer userStatus;
+
+ /**
+ *
+ * @return id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return username
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ /**
+ *
+ * @return firstName
+ */
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ /**
+ *
+ * @return lastName
+ */
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ /**
+ *
+ * @return email
+ */
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ /**
+ *
+ * @return password
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ /**
+ *
+ * @return phone
+ */
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ /**
+ * User Status
+ * @return userStatus
+ */
+ public Integer getUserStatus() {
+ return userStatus;
+ }
+
+ public void setUserStatus(Integer userStatus) {
+ this.userStatus = userStatus;
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ User user = (User) o;
+ return Objects.equals(this.id, user.id) &&
+ Objects.equals(this.username, user.username) &&
+ Objects.equals(this.firstName, user.firstName) &&
+ Objects.equals(this.lastName, user.lastName) &&
+ Objects.equals(this.email, user.email) &&
+ Objects.equals(this.password, user.password) &&
+ Objects.equals(this.phone, user.phone) &&
+ Objects.equals(this.userStatus, user.userStatus);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class User {\n");
+
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ sb.append(" username: ").append(toIndentedString(username)).append("\n");
+ sb.append(" firstName: ").append(toIndentedString(firstName)).append("\n");
+ sb.append(" lastName: ").append(toIndentedString(lastName)).append("\n");
+ sb.append(" email: ").append(toIndentedString(email)).append("\n");
+ sb.append(" password: ").append(toIndentedString(password)).append("\n");
+ sb.append(" phone: ").append(toIndentedString(phone)).append("\n");
+ sb.append(" userStatus: ").append(toIndentedString(userStatus)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/samples/server/petstore/java-dubbo/src/main/resources/application.yml b/samples/server/petstore/java-dubbo/src/main/resources/application.yml
new file mode 100644
index 00000000000..49798795a74
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/main/resources/application.yml
@@ -0,0 +1,20 @@
+spring:
+ application:
+ name: openapi-dubbo-server-petstore-provider
+
+dubbo:
+ application:
+ name: openapi-dubbo-server-petstore
+ logger: slf4j
+ registry:
+ address: zookeeper://127.0.0.1:2181
+ # 协议配置
+ protocol:
+ name: tri
+ port: -1 # auto-increment port
+
+logging:
+ level:
+ root: INFO
+ org.apache.dubbo: INFO
+ org.openapitools.example: DEBUG
diff --git a/samples/server/petstore/java-dubbo/src/test/java/org/openapitools/example/OpenAPIPetstoreApplicationTests.java b/samples/server/petstore/java-dubbo/src/test/java/org/openapitools/example/OpenAPIPetstoreApplicationTests.java
new file mode 100644
index 00000000000..6d1fc667b8c
--- /dev/null
+++ b/samples/server/petstore/java-dubbo/src/test/java/org/openapitools/example/OpenAPIPetstoreApplicationTests.java
@@ -0,0 +1,13 @@
+package org.openapitools.example;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class OpenAPIPetstoreApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}