diff --git a/.github/workflows/samples-java-client-echo-api-jdk11.yaml b/.github/workflows/samples-java-client-echo-api-jdk11.yaml
index 12813b635003c28ab07f7d2fbfdbb84d207a7894..08322740ee2f48b8e14b31f81dea0a6a0ce26cef 100644
--- a/.github/workflows/samples-java-client-echo-api-jdk11.yaml
+++ b/.github/workflows/samples-java-client-echo-api-jdk11.yaml
@@ -19,6 +19,7 @@ jobs:
           - samples/client/echo_api/java/apache-httpclient
           - samples/client/echo_api/java/native
           - samples/client/echo_api/java/feign-gson
+          - samples/client/echo_api/java/resttemplate
     steps:
       - uses: actions/checkout@v3
       - uses: actions/setup-java@v3
diff --git a/bin/configs/java-resttemplate-echo-api.yaml b/bin/configs/java-resttemplate-echo-api.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..27700c642dfb534e2420abdcee74038b6c190f68
--- /dev/null
+++ b/bin/configs/java-resttemplate-echo-api.yaml
@@ -0,0 +1,8 @@
+generatorName: java
+outputDir: samples/client/echo_api/java/resttemplate
+library: resttemplate
+inputSpec: modules/openapi-generator/src/test/resources/3_0/echo_api.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+  artifactId: echo-api-resttemplate
+  hideGenerationTimestamp: "true"
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/ApiClient.mustache
index b5de6ce3a1981d62213d250e41f034f3b6b90d71..6b9ac75b9cdd10cad930a30b60d31cd87ce357e3 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/ApiClient.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/ApiClient.mustache
@@ -674,16 +674,18 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
         Map<String,Object> uriParams = new HashMap<>();
         uriParams.putAll(pathParams);
 
-        String finalUri = path;
+        String queryUri = null;
 
         if (queryParams != null && !queryParams.isEmpty()) {
             //Include queryParams in uriParams taking into account the paramName
-            String queryUri = generateQueryUri(queryParams, uriParams);
-            //Append to finalUri the templatized query string like "?param1={param1Value}&.......
-            finalUri += "?" + queryUri;
-        }
-        String expandedPath = this.expandPath(finalUri, uriParams);
-        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(expandedPath);
+            String query = generateQueryUri(queryParams, uriParams);
+            queryUri = expandPath("?" + query, uriParams).substring(1); //exclude the '?'
+            //queryUri is the templatized query string like "?param1={param1Value}&.......
+        }
+        String expandedPath = this.expandPath(path, uriParams);
+        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath)
+                .path(expandedPath)
+                .query(queryUri);
 
         URI uri;
         try {
diff --git a/samples/client/echo_api/java/resttemplate/.github/workflows/maven.yml b/samples/client/echo_api/java/resttemplate/.github/workflows/maven.yml
new file mode 100644
index 0000000000000000000000000000000000000000..aa75c116424ba875ecf6f7fded8bf69948d82c07
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/.github/workflows/maven.yml
@@ -0,0 +1,30 @@
+# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+#
+# This file is auto-generated by OpenAPI Generator (https://openapi-generator.tech)
+
+name: Java CI with Maven
+
+on:
+  push:
+    branches: [ main, master ]
+  pull_request:
+    branches: [ main, master ]
+
+jobs:
+  build:
+    name: Build Echo Server API
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        java: [ '8' ]
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up JDK
+      uses: actions/setup-java@v2
+      with:
+        java-version: ${{ matrix.java }}
+        distribution: 'temurin'
+        cache: maven
+    - name: Build with Maven
+      run: mvn -B package --no-transfer-progress --file pom.xml
diff --git a/samples/client/echo_api/java/resttemplate/.gitignore b/samples/client/echo_api/java/resttemplate/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a530464afa1b2835232cf27d5747f2e79c66d4a1
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/.gitignore
@@ -0,0 +1,21 @@
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# exclude jar for gradle wrapper
+!gradle/wrapper/*.jar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+# build files
+**/target
+target
+.gradle
+build
diff --git a/samples/client/echo_api/java/resttemplate/.openapi-generator-ignore b/samples/client/echo_api/java/resttemplate/.openapi-generator-ignore
new file mode 100644
index 0000000000000000000000000000000000000000..7484ee590a3894506cf063799b885428f95a71be
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# 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
diff --git a/samples/client/echo_api/java/resttemplate/.openapi-generator/FILES b/samples/client/echo_api/java/resttemplate/.openapi-generator/FILES
new file mode 100644
index 0000000000000000000000000000000000000000..9e58ba44aaa40fc2a92f999bb9eb205dbd19f8fa
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/.openapi-generator/FILES
@@ -0,0 +1,39 @@
+.github/workflows/maven.yml
+.gitignore
+.travis.yml
+README.md
+api/openapi.yaml
+build.gradle
+build.sbt
+docs/BodyApi.md
+docs/Category.md
+docs/PathApi.md
+docs/Pet.md
+docs/QueryApi.md
+docs/Tag.md
+docs/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.md
+git_push.sh
+gradle.properties
+gradle/wrapper/gradle-wrapper.jar
+gradle/wrapper/gradle-wrapper.properties
+gradlew
+gradlew.bat
+pom.xml
+settings.gradle
+src/main/AndroidManifest.xml
+src/main/java/org/openapitools/client/ApiClient.java
+src/main/java/org/openapitools/client/JavaTimeFormatter.java
+src/main/java/org/openapitools/client/RFC3339DateFormat.java
+src/main/java/org/openapitools/client/ServerConfiguration.java
+src/main/java/org/openapitools/client/ServerVariable.java
+src/main/java/org/openapitools/client/api/BodyApi.java
+src/main/java/org/openapitools/client/api/PathApi.java
+src/main/java/org/openapitools/client/api/QueryApi.java
+src/main/java/org/openapitools/client/auth/ApiKeyAuth.java
+src/main/java/org/openapitools/client/auth/Authentication.java
+src/main/java/org/openapitools/client/auth/HttpBasicAuth.java
+src/main/java/org/openapitools/client/auth/HttpBearerAuth.java
+src/main/java/org/openapitools/client/model/Category.java
+src/main/java/org/openapitools/client/model/Pet.java
+src/main/java/org/openapitools/client/model/Tag.java
+src/main/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.java
diff --git a/samples/client/echo_api/java/resttemplate/.openapi-generator/VERSION b/samples/client/echo_api/java/resttemplate/.openapi-generator/VERSION
new file mode 100644
index 0000000000000000000000000000000000000000..d6b4ec4aa7839721c7e141ff985b26c4de167f9b
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/.openapi-generator/VERSION
@@ -0,0 +1 @@
+6.3.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/client/echo_api/java/resttemplate/.travis.yml b/samples/client/echo_api/java/resttemplate/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1b6741c083c7908f5eeaccf5584d3f475052ca55
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/.travis.yml
@@ -0,0 +1,22 @@
+#
+# Generated by OpenAPI Generator: https://openapi-generator.tech
+#
+# Ref: https://docs.travis-ci.com/user/languages/java/
+#
+language: java
+jdk:
+  - openjdk12
+  - openjdk11
+  - openjdk10
+  - openjdk9
+  - openjdk8
+before_install:
+  # ensure gradlew has proper permission
+  - chmod a+x ./gradlew
+script:
+  # test using maven
+  #- mvn test
+  # test using gradle
+  - gradle test
+  # test using sbt
+  # - sbt test
diff --git a/samples/client/echo_api/java/resttemplate/README.md b/samples/client/echo_api/java/resttemplate/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..61d54d89be381db0476291f7ea3a7ce5fdcbe75c
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/README.md
@@ -0,0 +1,143 @@
+# echo-api-resttemplate
+
+Echo Server API
+
+- API version: 0.1.0
+
+Echo Server API
+
+
+*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*
+
+## Requirements
+
+Building the API client library requires:
+
+1. Java 1.8+
+2. Maven/Gradle
+
+## Installation
+
+To install the API client library to your local Maven repository, simply execute:
+
+```shell
+mvn clean install
+```
+
+To deploy it to a remote Maven repository instead, configure the settings of the repository and execute:
+
+```shell
+mvn clean deploy
+```
+
+Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information.
+
+### Maven users
+
+Add this dependency to your project's POM:
+
+```xml
+<dependency>
+  <groupId>org.openapitools</groupId>
+  <artifactId>echo-api-resttemplate</artifactId>
+  <version>0.1.0</version>
+  <scope>compile</scope>
+</dependency>
+```
+
+### Gradle users
+
+Add this dependency to your project's build file:
+
+```groovy
+  repositories {
+    mavenCentral()     // Needed if the 'echo-api-resttemplate' jar has been published to maven central.
+    mavenLocal()       // Needed if the 'echo-api-resttemplate' jar has been published to the local maven repo.
+  }
+
+  dependencies {
+     implementation "org.openapitools:echo-api-resttemplate:0.1.0"
+  }
+```
+
+### Others
+
+At first generate the JAR by executing:
+
+```shell
+mvn clean package
+```
+
+Then manually install the following JARs:
+
+- `target/echo-api-resttemplate-0.1.0.jar`
+- `target/lib/*.jar`
+
+## Getting Started
+
+Please follow the [installation](#installation) instruction and execute the following Java code:
+
+```java
+
+import org.openapitools.client.*;
+import org.openapitools.client.auth.*;
+import org.openapitools.client.model.*;
+import org.openapitools.client.api.BodyApi;
+
+public class BodyApiExample {
+
+    public static void main(String[] args) {
+        ApiClient defaultClient = Configuration.getDefaultApiClient();
+        defaultClient.setBasePath("http://localhost:3000");
+        
+        BodyApi apiInstance = new BodyApi(defaultClient);
+        Pet pet = new Pet(); // Pet | Pet object that needs to be added to the store
+        try {
+            Pet result = apiInstance.testEchoBodyPet(pet);
+            System.out.println(result);
+        } catch (ApiException e) {
+            System.err.println("Exception when calling BodyApi#testEchoBodyPet");
+            System.err.println("Status code: " + e.getCode());
+            System.err.println("Reason: " + e.getResponseBody());
+            System.err.println("Response headers: " + e.getResponseHeaders());
+            e.printStackTrace();
+        }
+    }
+}
+
+```
+
+## Documentation for API Endpoints
+
+All URIs are relative to *http://localhost:3000*
+
+Class | Method | HTTP request | Description
+------------ | ------------- | ------------- | -------------
+*BodyApi* | [**testEchoBodyPet**](docs/BodyApi.md#testEchoBodyPet) | **POST** /echo/body/Pet | Test body parameter(s)
+*PathApi* | [**testsPathStringPathStringIntegerPathInteger**](docs/PathApi.md#testsPathStringPathStringIntegerPathInteger) | **GET** /path/string/{path_string}/integer/{path_integer} | Test path parameter(s)
+*QueryApi* | [**testQueryIntegerBooleanString**](docs/QueryApi.md#testQueryIntegerBooleanString) | **GET** /query/integer/boolean/string | Test query parameter(s)
+*QueryApi* | [**testQueryStyleFormExplodeTrueArrayString**](docs/QueryApi.md#testQueryStyleFormExplodeTrueArrayString) | **GET** /query/style_form/explode_true/array_string | Test query parameter(s)
+*QueryApi* | [**testQueryStyleFormExplodeTrueObject**](docs/QueryApi.md#testQueryStyleFormExplodeTrueObject) | **GET** /query/style_form/explode_true/object | Test query parameter(s)
+
+
+## Documentation for Models
+
+ - [Category](docs/Category.md)
+ - [Pet](docs/Pet.md)
+ - [Tag](docs/Tag.md)
+ - [TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter](docs/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.md)
+
+
+## Documentation for Authorization
+
+All endpoints do not require authorization.
+Authentication schemes defined for the API:
+
+## Recommendation
+
+It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues.
+
+## Author
+
+team@openapitools.org
+
diff --git a/samples/client/echo_api/java/resttemplate/api/openapi.yaml b/samples/client/echo_api/java/resttemplate/api/openapi.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4dd00e163181d92a4bf01c8514fefd3b8897e136
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/api/openapi.yaml
@@ -0,0 +1,242 @@
+openapi: 3.0.3
+info:
+  contact:
+    email: team@openapitools.org
+  description: Echo Server API
+  license:
+    name: Apache 2.0
+    url: http://www.apache.org/licenses/LICENSE-2.0.html
+  title: Echo Server API
+  version: 0.1.0
+servers:
+- url: http://localhost:3000/
+paths:
+  /path/string/{path_string}/integer/{path_integer}:
+    get:
+      description: Test path parameter(s)
+      operationId: "tests/path/string/{path_string}/integer/{path_integer}"
+      parameters:
+      - explode: false
+        in: path
+        name: path_string
+        required: true
+        schema:
+          type: string
+        style: simple
+      - explode: false
+        in: path
+        name: path_integer
+        required: true
+        schema:
+          type: integer
+        style: simple
+      responses:
+        "200":
+          content:
+            text/plain:
+              schema:
+                type: string
+          description: Successful operation
+      summary: Test path parameter(s)
+      tags:
+      - path
+      x-accepts: text/plain
+  /query/integer/boolean/string:
+    get:
+      description: Test query parameter(s)
+      operationId: test/query/integer/boolean/string
+      parameters:
+      - explode: true
+        in: query
+        name: integer_query
+        required: false
+        schema:
+          type: integer
+        style: form
+      - explode: true
+        in: query
+        name: boolean_query
+        required: false
+        schema:
+          type: boolean
+        style: form
+      - explode: true
+        in: query
+        name: string_query
+        required: false
+        schema:
+          type: string
+        style: form
+      responses:
+        "200":
+          content:
+            text/plain:
+              schema:
+                type: string
+          description: Successful operation
+      summary: Test query parameter(s)
+      tags:
+      - query
+      x-accepts: text/plain
+  /query/style_form/explode_true/array_string:
+    get:
+      description: Test query parameter(s)
+      operationId: test/query/style_form/explode_true/array_string
+      parameters:
+      - explode: true
+        in: query
+        name: query_object
+        required: false
+        schema:
+          $ref: '#/components/schemas/test_query_style_form_explode_true_array_string_query_object_parameter'
+        style: form
+      responses:
+        "200":
+          content:
+            text/plain:
+              schema:
+                type: string
+          description: Successful operation
+      summary: Test query parameter(s)
+      tags:
+      - query
+      x-accepts: text/plain
+  /query/style_form/explode_true/object:
+    get:
+      description: Test query parameter(s)
+      operationId: test/query/style_form/explode_true/object
+      parameters:
+      - explode: true
+        in: query
+        name: query_object
+        required: false
+        schema:
+          $ref: '#/components/schemas/Pet'
+        style: form
+      responses:
+        "200":
+          content:
+            text/plain:
+              schema:
+                type: string
+          description: Successful operation
+      summary: Test query parameter(s)
+      tags:
+      - query
+      x-accepts: text/plain
+  /echo/body/Pet:
+    post:
+      description: Test body parameter(s)
+      operationId: test/echo/body/Pet
+      requestBody:
+        $ref: '#/components/requestBodies/Pet'
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pet'
+          description: Successful operation
+      summary: Test body parameter(s)
+      tags:
+      - body
+      x-content-type: application/json
+      x-accepts: application/json
+components:
+  requestBodies:
+    Pet:
+      content:
+        application/json:
+          schema:
+            $ref: '#/components/schemas/Pet'
+      description: Pet object that needs to be added to the store
+  schemas:
+    Category:
+      example:
+        name: Dogs
+        id: 1
+      properties:
+        id:
+          example: 1
+          format: int64
+          type: integer
+        name:
+          example: Dogs
+          type: string
+      type: object
+      xml:
+        name: category
+    Tag:
+      example:
+        name: name
+        id: 0
+      properties:
+        id:
+          format: int64
+          type: integer
+        name:
+          type: string
+      type: object
+      xml:
+        name: tag
+    Pet:
+      example:
+        photoUrls:
+        - photoUrls
+        - photoUrls
+        name: doggie
+        id: 10
+        category:
+          name: Dogs
+          id: 1
+        tags:
+        - name: name
+          id: 0
+        - name: name
+          id: 0
+        status: available
+      properties:
+        id:
+          example: 10
+          format: int64
+          type: integer
+        name:
+          example: doggie
+          type: string
+        category:
+          $ref: '#/components/schemas/Category'
+        photoUrls:
+          items:
+            type: string
+            xml:
+              name: photoUrl
+          type: array
+          xml:
+            wrapped: true
+        tags:
+          items:
+            $ref: '#/components/schemas/Tag'
+          type: array
+          xml:
+            wrapped: true
+        status:
+          description: pet status in the store
+          enum:
+          - available
+          - pending
+          - sold
+          type: string
+      required:
+      - name
+      - photoUrls
+      type: object
+      xml:
+        name: pet
+    test_query_style_form_explode_true_array_string_query_object_parameter:
+      properties:
+        values:
+          items:
+            type: string
+          type: array
+      type: object
+
diff --git a/samples/client/echo_api/java/resttemplate/build.gradle b/samples/client/echo_api/java/resttemplate/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..cbff32ba6a2c30fd41bb6ce0705f1a5a4cacfb11
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/build.gradle
@@ -0,0 +1,123 @@
+apply plugin: 'idea'
+apply plugin: 'eclipse'
+
+group = 'org.openapitools'
+version = '0.1.0'
+
+buildscript {
+    repositories {
+        mavenCentral()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:1.5.+'
+        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
+    }
+}
+
+repositories {
+    mavenCentral()
+}
+
+
+if(hasProperty('target') && target == 'android') {
+
+    apply plugin: 'com.android.library'
+    apply plugin: 'com.github.dcendents.android-maven'
+
+    android {
+        compileSdkVersion 23
+        buildToolsVersion '23.0.2'
+        defaultConfig {
+            minSdkVersion 14
+            targetSdkVersion 22
+        }
+        compileOptions {
+            sourceCompatibility JavaVersion.VERSION_1_8
+            targetCompatibility JavaVersion.VERSION_1_8
+        }
+
+        // Rename the aar correctly
+        libraryVariants.all { variant ->
+            variant.outputs.each { output ->
+                def outputFile = output.outputFile
+                if (outputFile != null && outputFile.name.endsWith('.aar')) {
+                    def fileName = "${project.name}-${variant.baseName}-${version}.aar"
+                    output.outputFile = new File(outputFile.parent, fileName)
+                }
+            }
+        }
+
+        dependencies {
+            provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version"
+        }
+    }
+
+    afterEvaluate {
+        android.libraryVariants.all { variant ->
+            def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
+            task.description = "Create jar artifact for ${variant.name}"
+            task.dependsOn variant.javaCompile
+            task.from variant.javaCompile.destinationDir
+            task.destinationDir = project.file("${project.buildDir}/outputs/jar")
+            task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
+            artifacts.add('archives', task);
+        }
+    }
+
+    task sourcesJar(type: Jar) {
+        from android.sourceSets.main.java.srcDirs
+        classifier = 'sources'
+    }
+
+    artifacts {
+        archives sourcesJar
+    }
+
+} else {
+
+    apply plugin: 'java'
+    apply plugin: 'maven-publish'
+
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+
+    publishing {
+        publications {
+            maven(MavenPublication) {
+               artifactId = 'echo-api-resttemplate'
+               from components.java
+            }
+        }
+    }
+
+    task execute(type:JavaExec) {
+       main = System.getProperty('mainClass')
+       classpath = sourceSets.main.runtimeClasspath
+    }
+}
+
+ext {
+    swagger_annotations_version = "1.6.9"
+    jackson_version = "2.14.1"
+    jackson_databind_version = "2.14.1"
+    jackson_databind_nullable_version = "0.2.4"
+    jakarta_annotation_version = "1.3.5"
+    spring_web_version = "5.3.24"
+    jodatime_version = "2.9.9"
+    junit_version = "4.13.2"
+}
+
+dependencies {
+    implementation "io.swagger:swagger-annotations:$swagger_annotations_version"
+    implementation "com.google.code.findbugs:jsr305:3.0.2"
+    implementation "org.springframework:spring-web:$spring_web_version"
+    implementation "org.springframework:spring-context:$spring_web_version"
+    implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version"
+    implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
+    implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version"
+    implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version"
+    implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version"
+    implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
+    implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version"
+    testImplementation "junit:junit:$junit_version"
+}
diff --git a/samples/client/echo_api/java/resttemplate/build.sbt b/samples/client/echo_api/java/resttemplate/build.sbt
new file mode 100644
index 0000000000000000000000000000000000000000..464090415c47109523e91779d4f40e19495c9cf1
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/build.sbt
@@ -0,0 +1 @@
+# TODO
diff --git a/samples/client/echo_api/java/resttemplate/docs/BodyApi.md b/samples/client/echo_api/java/resttemplate/docs/BodyApi.md
new file mode 100644
index 0000000000000000000000000000000000000000..298dede6e494a6d2de7c6810273c316471036163
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/docs/BodyApi.md
@@ -0,0 +1,75 @@
+# BodyApi
+
+All URIs are relative to *http://localhost:3000*
+
+| Method | HTTP request | Description |
+|------------- | ------------- | -------------|
+| [**testEchoBodyPet**](BodyApi.md#testEchoBodyPet) | **POST** /echo/body/Pet | Test body parameter(s) |
+
+
+
+## testEchoBodyPet
+
+> Pet testEchoBodyPet(pet)
+
+Test body parameter(s)
+
+Test body parameter(s)
+
+### Example
+
+```java
+// Import classes:
+import org.openapitools.client.ApiClient;
+import org.openapitools.client.ApiException;
+import org.openapitools.client.Configuration;
+import org.openapitools.client.models.*;
+import org.openapitools.client.api.BodyApi;
+
+public class Example {
+    public static void main(String[] args) {
+        ApiClient defaultClient = Configuration.getDefaultApiClient();
+        defaultClient.setBasePath("http://localhost:3000");
+
+        BodyApi apiInstance = new BodyApi(defaultClient);
+        Pet pet = new Pet(); // Pet | Pet object that needs to be added to the store
+        try {
+            Pet result = apiInstance.testEchoBodyPet(pet);
+            System.out.println(result);
+        } catch (ApiException e) {
+            System.err.println("Exception when calling BodyApi#testEchoBodyPet");
+            System.err.println("Status code: " + e.getCode());
+            System.err.println("Reason: " + e.getResponseBody());
+            System.err.println("Response headers: " + e.getResponseHeaders());
+            e.printStackTrace();
+        }
+    }
+}
+```
+
+### Parameters
+
+
+| Name | Type | Description  | Notes |
+|------------- | ------------- | ------------- | -------------|
+| **pet** | [**Pet**](Pet.md)| Pet object that needs to be added to the store | [optional] |
+
+### Return type
+
+[**Pet**](Pet.md)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+- **Content-Type**: application/json
+- **Accept**: application/json
+
+
+### HTTP response details
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+| **200** | Successful operation |  -  |
+
diff --git a/samples/client/echo_api/java/resttemplate/docs/Category.md b/samples/client/echo_api/java/resttemplate/docs/Category.md
new file mode 100644
index 0000000000000000000000000000000000000000..7289ebf585bbb60cf89928ab7b82407634f33f9b
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/docs/Category.md
@@ -0,0 +1,14 @@
+
+
+# Category
+
+
+## Properties
+
+| Name | Type | Description | Notes |
+|------------ | ------------- | ------------- | -------------|
+|**id** | **Long** |  |  [optional] |
+|**name** | **String** |  |  [optional] |
+
+
+
diff --git a/samples/client/echo_api/java/resttemplate/docs/PathApi.md b/samples/client/echo_api/java/resttemplate/docs/PathApi.md
new file mode 100644
index 0000000000000000000000000000000000000000..a4122aa3d47f562a19e4daf0173d469cbc7b53c1
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/docs/PathApi.md
@@ -0,0 +1,77 @@
+# PathApi
+
+All URIs are relative to *http://localhost:3000*
+
+| Method | HTTP request | Description |
+|------------- | ------------- | -------------|
+| [**testsPathStringPathStringIntegerPathInteger**](PathApi.md#testsPathStringPathStringIntegerPathInteger) | **GET** /path/string/{path_string}/integer/{path_integer} | Test path parameter(s) |
+
+
+
+## testsPathStringPathStringIntegerPathInteger
+
+> String testsPathStringPathStringIntegerPathInteger(pathString, pathInteger)
+
+Test path parameter(s)
+
+Test path parameter(s)
+
+### Example
+
+```java
+// Import classes:
+import org.openapitools.client.ApiClient;
+import org.openapitools.client.ApiException;
+import org.openapitools.client.Configuration;
+import org.openapitools.client.models.*;
+import org.openapitools.client.api.PathApi;
+
+public class Example {
+    public static void main(String[] args) {
+        ApiClient defaultClient = Configuration.getDefaultApiClient();
+        defaultClient.setBasePath("http://localhost:3000");
+
+        PathApi apiInstance = new PathApi(defaultClient);
+        String pathString = "pathString_example"; // String | 
+        Integer pathInteger = 56; // Integer | 
+        try {
+            String result = apiInstance.testsPathStringPathStringIntegerPathInteger(pathString, pathInteger);
+            System.out.println(result);
+        } catch (ApiException e) {
+            System.err.println("Exception when calling PathApi#testsPathStringPathStringIntegerPathInteger");
+            System.err.println("Status code: " + e.getCode());
+            System.err.println("Reason: " + e.getResponseBody());
+            System.err.println("Response headers: " + e.getResponseHeaders());
+            e.printStackTrace();
+        }
+    }
+}
+```
+
+### Parameters
+
+
+| Name | Type | Description  | Notes |
+|------------- | ------------- | ------------- | -------------|
+| **pathString** | **String**|  | |
+| **pathInteger** | **Integer**|  | |
+
+### Return type
+
+**String**
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+- **Content-Type**: Not defined
+- **Accept**: text/plain
+
+
+### HTTP response details
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+| **200** | Successful operation |  -  |
+
diff --git a/samples/client/echo_api/java/resttemplate/docs/Pet.md b/samples/client/echo_api/java/resttemplate/docs/Pet.md
new file mode 100644
index 0000000000000000000000000000000000000000..82aa8a25ed7cfefa64036345676a6d98c75795fa
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/docs/Pet.md
@@ -0,0 +1,28 @@
+
+
+# Pet
+
+
+## Properties
+
+| Name | Type | Description | Notes |
+|------------ | ------------- | ------------- | -------------|
+|**id** | **Long** |  |  [optional] |
+|**name** | **String** |  |  |
+|**category** | [**Category**](Category.md) |  |  [optional] |
+|**photoUrls** | **List&lt;String&gt;** |  |  |
+|**tags** | [**List&lt;Tag&gt;**](Tag.md) |  |  [optional] |
+|**status** | [**StatusEnum**](#StatusEnum) | pet status in the store |  [optional] |
+
+
+
+## Enum: StatusEnum
+
+| Name | Value |
+|---- | -----|
+| AVAILABLE | &quot;available&quot; |
+| PENDING | &quot;pending&quot; |
+| SOLD | &quot;sold&quot; |
+
+
+
diff --git a/samples/client/echo_api/java/resttemplate/docs/QueryApi.md b/samples/client/echo_api/java/resttemplate/docs/QueryApi.md
new file mode 100644
index 0000000000000000000000000000000000000000..45183a18b44b2f95217675fb244283751876102e
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/docs/QueryApi.md
@@ -0,0 +1,213 @@
+# QueryApi
+
+All URIs are relative to *http://localhost:3000*
+
+| Method | HTTP request | Description |
+|------------- | ------------- | -------------|
+| [**testQueryIntegerBooleanString**](QueryApi.md#testQueryIntegerBooleanString) | **GET** /query/integer/boolean/string | Test query parameter(s) |
+| [**testQueryStyleFormExplodeTrueArrayString**](QueryApi.md#testQueryStyleFormExplodeTrueArrayString) | **GET** /query/style_form/explode_true/array_string | Test query parameter(s) |
+| [**testQueryStyleFormExplodeTrueObject**](QueryApi.md#testQueryStyleFormExplodeTrueObject) | **GET** /query/style_form/explode_true/object | Test query parameter(s) |
+
+
+
+## testQueryIntegerBooleanString
+
+> String testQueryIntegerBooleanString(integerQuery, booleanQuery, stringQuery)
+
+Test query parameter(s)
+
+Test query parameter(s)
+
+### Example
+
+```java
+// Import classes:
+import org.openapitools.client.ApiClient;
+import org.openapitools.client.ApiException;
+import org.openapitools.client.Configuration;
+import org.openapitools.client.models.*;
+import org.openapitools.client.api.QueryApi;
+
+public class Example {
+    public static void main(String[] args) {
+        ApiClient defaultClient = Configuration.getDefaultApiClient();
+        defaultClient.setBasePath("http://localhost:3000");
+
+        QueryApi apiInstance = new QueryApi(defaultClient);
+        Integer integerQuery = 56; // Integer | 
+        Boolean booleanQuery = true; // Boolean | 
+        String stringQuery = "stringQuery_example"; // String | 
+        try {
+            String result = apiInstance.testQueryIntegerBooleanString(integerQuery, booleanQuery, stringQuery);
+            System.out.println(result);
+        } catch (ApiException e) {
+            System.err.println("Exception when calling QueryApi#testQueryIntegerBooleanString");
+            System.err.println("Status code: " + e.getCode());
+            System.err.println("Reason: " + e.getResponseBody());
+            System.err.println("Response headers: " + e.getResponseHeaders());
+            e.printStackTrace();
+        }
+    }
+}
+```
+
+### Parameters
+
+
+| Name | Type | Description  | Notes |
+|------------- | ------------- | ------------- | -------------|
+| **integerQuery** | **Integer**|  | [optional] |
+| **booleanQuery** | **Boolean**|  | [optional] |
+| **stringQuery** | **String**|  | [optional] |
+
+### Return type
+
+**String**
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+- **Content-Type**: Not defined
+- **Accept**: text/plain
+
+
+### HTTP response details
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+| **200** | Successful operation |  -  |
+
+
+## testQueryStyleFormExplodeTrueArrayString
+
+> String testQueryStyleFormExplodeTrueArrayString(queryObject)
+
+Test query parameter(s)
+
+Test query parameter(s)
+
+### Example
+
+```java
+// Import classes:
+import org.openapitools.client.ApiClient;
+import org.openapitools.client.ApiException;
+import org.openapitools.client.Configuration;
+import org.openapitools.client.models.*;
+import org.openapitools.client.api.QueryApi;
+
+public class Example {
+    public static void main(String[] args) {
+        ApiClient defaultClient = Configuration.getDefaultApiClient();
+        defaultClient.setBasePath("http://localhost:3000");
+
+        QueryApi apiInstance = new QueryApi(defaultClient);
+        TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter queryObject = new HashMap(); // TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter | 
+        try {
+            String result = apiInstance.testQueryStyleFormExplodeTrueArrayString(queryObject);
+            System.out.println(result);
+        } catch (ApiException e) {
+            System.err.println("Exception when calling QueryApi#testQueryStyleFormExplodeTrueArrayString");
+            System.err.println("Status code: " + e.getCode());
+            System.err.println("Reason: " + e.getResponseBody());
+            System.err.println("Response headers: " + e.getResponseHeaders());
+            e.printStackTrace();
+        }
+    }
+}
+```
+
+### Parameters
+
+
+| Name | Type | Description  | Notes |
+|------------- | ------------- | ------------- | -------------|
+| **queryObject** | [**TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter**](.md)|  | [optional] |
+
+### Return type
+
+**String**
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+- **Content-Type**: Not defined
+- **Accept**: text/plain
+
+
+### HTTP response details
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+| **200** | Successful operation |  -  |
+
+
+## testQueryStyleFormExplodeTrueObject
+
+> String testQueryStyleFormExplodeTrueObject(queryObject)
+
+Test query parameter(s)
+
+Test query parameter(s)
+
+### Example
+
+```java
+// Import classes:
+import org.openapitools.client.ApiClient;
+import org.openapitools.client.ApiException;
+import org.openapitools.client.Configuration;
+import org.openapitools.client.models.*;
+import org.openapitools.client.api.QueryApi;
+
+public class Example {
+    public static void main(String[] args) {
+        ApiClient defaultClient = Configuration.getDefaultApiClient();
+        defaultClient.setBasePath("http://localhost:3000");
+
+        QueryApi apiInstance = new QueryApi(defaultClient);
+        Pet queryObject = new HashMap(); // Pet | 
+        try {
+            String result = apiInstance.testQueryStyleFormExplodeTrueObject(queryObject);
+            System.out.println(result);
+        } catch (ApiException e) {
+            System.err.println("Exception when calling QueryApi#testQueryStyleFormExplodeTrueObject");
+            System.err.println("Status code: " + e.getCode());
+            System.err.println("Reason: " + e.getResponseBody());
+            System.err.println("Response headers: " + e.getResponseHeaders());
+            e.printStackTrace();
+        }
+    }
+}
+```
+
+### Parameters
+
+
+| Name | Type | Description  | Notes |
+|------------- | ------------- | ------------- | -------------|
+| **queryObject** | [**Pet**](.md)|  | [optional] |
+
+### Return type
+
+**String**
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+- **Content-Type**: Not defined
+- **Accept**: text/plain
+
+
+### HTTP response details
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+| **200** | Successful operation |  -  |
+
diff --git a/samples/client/echo_api/java/resttemplate/docs/Tag.md b/samples/client/echo_api/java/resttemplate/docs/Tag.md
new file mode 100644
index 0000000000000000000000000000000000000000..5088b2dd1c314d59ed7157a5a22dab84b2a1722b
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/docs/Tag.md
@@ -0,0 +1,14 @@
+
+
+# Tag
+
+
+## Properties
+
+| Name | Type | Description | Notes |
+|------------ | ------------- | ------------- | -------------|
+|**id** | **Long** |  |  [optional] |
+|**name** | **String** |  |  [optional] |
+
+
+
diff --git a/samples/client/echo_api/java/resttemplate/docs/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.md b/samples/client/echo_api/java/resttemplate/docs/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.md
new file mode 100644
index 0000000000000000000000000000000000000000..9235e80fb8236088c47c8016267bc33a3fb6e452
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/docs/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.md
@@ -0,0 +1,13 @@
+
+
+# TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter
+
+
+## Properties
+
+| Name | Type | Description | Notes |
+|------------ | ------------- | ------------- | -------------|
+|**values** | **List&lt;String&gt;** |  |  [optional] |
+
+
+
diff --git a/samples/client/echo_api/java/resttemplate/git_push.sh b/samples/client/echo_api/java/resttemplate/git_push.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f53a75d4fabe760cce49eddfd62fcc702938ea90
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/git_push.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
+#
+# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
+
+git_user_id=$1
+git_repo_id=$2
+release_note=$3
+git_host=$4
+
+if [ "$git_host" = "" ]; then
+    git_host="github.com"
+    echo "[INFO] No command line input provided. Set \$git_host to $git_host"
+fi
+
+if [ "$git_user_id" = "" ]; then
+    git_user_id="GIT_USER_ID"
+    echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
+fi
+
+if [ "$git_repo_id" = "" ]; then
+    git_repo_id="GIT_REPO_ID"
+    echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
+fi
+
+if [ "$release_note" = "" ]; then
+    release_note="Minor update"
+    echo "[INFO] No command line input provided. Set \$release_note to $release_note"
+fi
+
+# Initialize the local directory as a Git repository
+git init
+
+# Adds the files in the local repository and stages them for commit.
+git add .
+
+# Commits the tracked changes and prepares them to be pushed to a remote repository.
+git commit -m "$release_note"
+
+# Sets the new remote
+git_remote=$(git remote)
+if [ "$git_remote" = "" ]; then # git remote not defined
+
+    if [ "$GIT_TOKEN" = "" ]; then
+        echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
+        git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
+    else
+        git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
+    fi
+
+fi
+
+git pull origin master
+
+# Pushes (Forces) the changes in the local repository up to the remote repository
+echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
+git push origin master 2>&1 | grep -v 'To https'
diff --git a/samples/client/echo_api/java/resttemplate/gradle.properties b/samples/client/echo_api/java/resttemplate/gradle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..a3408578278a3127ad96adfb5d99b6df0bbd07bb
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/gradle.properties
@@ -0,0 +1,6 @@
+# This file is automatically generated by OpenAPI Generator (https://github.com/openAPITools/openapi-generator).
+# To include other gradle properties as part of the code generation process, please use the `gradleProperties` option.
+#
+# Gradle properties reference: https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
+# For example, uncomment below to build for Android
+#target = android
diff --git a/samples/client/echo_api/java/resttemplate/gradle/wrapper/gradle-wrapper.jar b/samples/client/echo_api/java/resttemplate/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..7454180f2ae8848c63b8b4dea2cb829da983f2fa
Binary files /dev/null and b/samples/client/echo_api/java/resttemplate/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/samples/client/echo_api/java/resttemplate/gradle/wrapper/gradle-wrapper.properties b/samples/client/echo_api/java/resttemplate/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..ffed3a254e91df704a9acc0f2745c0e340d9b582
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/samples/client/echo_api/java/resttemplate/gradlew b/samples/client/echo_api/java/resttemplate/gradlew
new file mode 100644
index 0000000000000000000000000000000000000000..005bcde04284b46eb4e3d5ff31181bbac2ec9f16
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# 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 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.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/samples/client/echo_api/java/resttemplate/gradlew.bat b/samples/client/echo_api/java/resttemplate/gradlew.bat
new file mode 100644
index 0000000000000000000000000000000000000000..6a68175eb70fc4290bae78dcf4d745a2b52a6a27
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/samples/client/echo_api/java/resttemplate/pom.xml b/samples/client/echo_api/java/resttemplate/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..41f36b874553a3f3dcfc1fab61873f8f70f266a2
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/pom.xml
@@ -0,0 +1,278 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.openapitools</groupId>
+    <artifactId>echo-api-resttemplate</artifactId>
+    <packaging>jar</packaging>
+    <name>echo-api-resttemplate</name>
+    <version>0.1.0</version>
+    <url>https://github.com/openapitools/openapi-generator</url>
+    <description>OpenAPI Java</description>
+    <scm>
+        <connection>scm:git:git@github.com:openapitools/openapi-generator.git</connection>
+        <developerConnection>scm:git:git@github.com:openapitools/openapi-generator.git</developerConnection>
+        <url>https://github.com/openapitools/openapi-generator</url>
+    </scm>
+
+    <licenses>
+        <license>
+            <name>Unlicense</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <developers>
+        <developer>
+            <name>OpenAPI-Generator Contributors</name>
+            <email>team@openapitools.org</email>
+            <organization>OpenAPITools.org</organization>
+            <organizationUrl>http://openapitools.org</organizationUrl>
+        </developer>
+    </developers>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <version>3.0.0-M1</version>
+                <executions>
+                    <execution>
+                        <id>enforce-maven</id>
+                        <goals>
+                            <goal>enforce</goal>
+                        </goals>
+                        <configuration>
+                            <rules>
+                                <requireMavenVersion>
+                                    <version>2.2.0</version>
+                                </requireMavenVersion>
+                            </rules>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.12</version>
+                <configuration>
+                    <systemProperties>
+                        <property>
+                            <name>loggerPath</name>
+                            <value>conf/log4j.properties</value>
+                        </property>
+                    </systemProperties>
+                    <argLine>-Xms512m -Xmx1500m</argLine>
+                    <parallel>methods</parallel>
+                    <forkMode>pertest</forkMode>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- attach test jar -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>jar</goal>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>1.10</version>
+                <executions>
+                    <execution>
+                        <id>add_sources</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>src/main/java</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>add_test_sources</id>
+                        <phase>generate-test-sources</phase>
+                        <goals>
+                            <goal>add-test-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>src/test/java</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.6.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>3.3.2</version>
+                <configuration>
+                    <doclint>none</doclint>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>attach-javadocs</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>2.2.1</version>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar-no-fork</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>sign-artifacts</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <version>1.5</version>
+                        <executions>
+                            <execution>
+                                <id>sign-artifacts</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+    <dependencies>
+
+        <!-- @Nullable annotation -->
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>3.0.2</version>
+        </dependency>
+
+        <!-- HTTP client: Spring RestTemplate -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>${spring-web-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>${spring-web-version}</version>
+        </dependency>
+
+        <!-- JSON processing: jackson -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>${jackson-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>${jackson-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>${jackson-databind-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+            <version>${jackson-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openapitools</groupId>
+            <artifactId>jackson-databind-nullable</artifactId>
+            <version>${jackson-databind-nullable-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+            <version>${jackson-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.annotation</groupId>
+            <artifactId>jakarta.annotation-api</artifactId>
+            <version>${jakarta-annotation-version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit-version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <swagger-annotations-version>1.6.9</swagger-annotations-version>
+        <spring-web-version>5.3.24</spring-web-version>
+        <jackson-version>2.14.1</jackson-version>
+        <jackson-databind-version>2.14.1</jackson-databind-version>
+        <jackson-databind-nullable-version>0.2.4</jackson-databind-nullable-version>
+        <jakarta-annotation-version>1.3.5</jakarta-annotation-version>
+        <maven-plugin-version>1.0.0</maven-plugin-version>
+        <junit-version>4.13.2</junit-version>
+    </properties>
+</project>
diff --git a/samples/client/echo_api/java/resttemplate/settings.gradle b/samples/client/echo_api/java/resttemplate/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..5b9c824d855eed033b93286c2f15504ba551e81f
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = "echo-api-resttemplate"
\ No newline at end of file
diff --git a/samples/client/echo_api/java/resttemplate/src/main/AndroidManifest.xml b/samples/client/echo_api/java/resttemplate/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..54fbcb3da1e8284ef277fb6ac33d694007906a74
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+<manifest package="org.openapitools.client" xmlns:android="http://schemas.android.com/apk/res/android">
+    <application />
+</manifest>
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ApiClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..827d707c74a54b380144d420e60a4bf8ebf2ffcb
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ApiClient.java
@@ -0,0 +1,729 @@
+package org.openapitools.client;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.InvalidMediaTypeException;
+import org.springframework.http.MediaType;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.RequestEntity.BodyBuilder;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.BufferingClientHttpRequestFactory;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+import org.openapitools.jackson.nullable.JsonNullableModule;
+
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TimeZone;
+import java.time.OffsetDateTime;
+
+import org.openapitools.client.auth.Authentication;
+
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+@Component("org.openapitools.client.ApiClient")
+public class ApiClient extends JavaTimeFormatter {
+    public enum CollectionFormat {
+        CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null);
+
+        private final String separator;
+
+        private CollectionFormat(String separator) {
+            this.separator = separator;
+        }
+
+        private String collectionToString(Collection<?> collection) {
+            return StringUtils.collectionToDelimitedString(collection, separator);
+        }
+    }
+
+    private boolean debugging = false;
+
+    private HttpHeaders defaultHeaders = new HttpHeaders();
+    private MultiValueMap<String, String> defaultCookies = new LinkedMultiValueMap<String, String>();
+
+    private String basePath = "http://localhost:3000";
+
+    private RestTemplate restTemplate;
+
+    private Map<String, Authentication> authentications;
+
+    private DateFormat dateFormat;
+
+    public ApiClient() {
+        this.restTemplate = buildRestTemplate();
+        init();
+    }
+
+    @Autowired
+    public ApiClient(RestTemplate restTemplate) {
+        this.restTemplate = restTemplate;
+        init();
+    }
+
+    protected void init() {
+        // Use RFC3339 format for date and datetime.
+        // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
+        this.dateFormat = new RFC3339DateFormat();
+
+        // Use UTC as the default time zone.
+        this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+        // Set default User-Agent.
+        setUserAgent("Java-SDK");
+
+        // Setup authentications (key: authentication name, value: authentication).
+        authentications = new HashMap<String, Authentication>();
+        // Prevent the authentications from being modified.
+        authentications = Collections.unmodifiableMap(authentications);
+    }
+
+    /**
+     * Get the current base path
+     *
+     * @return String the base path
+     */
+    public String getBasePath() {
+        return basePath;
+    }
+
+    /**
+     * Set the base path, which should include the host
+     *
+     * @param basePath the base path
+     * @return ApiClient this client
+     */
+    public ApiClient setBasePath(String basePath) {
+        this.basePath = basePath;
+        return this;
+    }
+
+    /**
+     * Get authentications (key: authentication name, value: authentication).
+     *
+     * @return Map the currently configured authentication types
+     */
+    public Map<String, Authentication> getAuthentications() {
+        return authentications;
+    }
+
+    /**
+     * Get authentication for the given name.
+     *
+     * @param authName The authentication name
+     * @return The authentication, null if not found
+     */
+    public Authentication getAuthentication(String authName) {
+        return authentications.get(authName);
+    }
+
+
+
+
+
+    /**
+     * Set the User-Agent header's value (by adding to the default header map).
+     *
+     * @param userAgent the user agent string
+     * @return ApiClient this client
+     */
+    public ApiClient setUserAgent(String userAgent) {
+        addDefaultHeader("User-Agent", userAgent);
+        return this;
+    }
+
+    /**
+     * Add a default header.
+     *
+     * @param name  The header's name
+     * @param value The header's value
+     * @return ApiClient this client
+     */
+    public ApiClient addDefaultHeader(String name, String value) {
+        if (defaultHeaders.containsKey(name)) {
+            defaultHeaders.remove(name);
+        }
+        defaultHeaders.add(name, value);
+        return this;
+    }
+
+    /**
+     * Add a default cookie.
+     *
+     * @param name  The cookie's name
+     * @param value The cookie's value
+     * @return ApiClient this client
+     */
+    public ApiClient addDefaultCookie(String name, String value) {
+        if (defaultCookies.containsKey(name)) {
+            defaultCookies.remove(name);
+        }
+        defaultCookies.add(name, value);
+        return this;
+    }
+
+    public void setDebugging(boolean debugging) {
+        List<ClientHttpRequestInterceptor> currentInterceptors = this.restTemplate.getInterceptors();
+        if (debugging) {
+            if (currentInterceptors == null) {
+                currentInterceptors = new ArrayList<ClientHttpRequestInterceptor>();
+            }
+            ClientHttpRequestInterceptor interceptor = new ApiClientHttpRequestInterceptor();
+            currentInterceptors.add(interceptor);
+            this.restTemplate.setInterceptors(currentInterceptors);
+        } else {
+            if (currentInterceptors != null && !currentInterceptors.isEmpty()) {
+                Iterator<ClientHttpRequestInterceptor> iter = currentInterceptors.iterator();
+                while (iter.hasNext()) {
+                    ClientHttpRequestInterceptor interceptor = iter.next();
+                    if (interceptor instanceof ApiClientHttpRequestInterceptor) {
+                        iter.remove();
+                    }
+                }
+                this.restTemplate.setInterceptors(currentInterceptors);
+            }
+        }
+        this.debugging = debugging;
+    }
+
+    /**
+     * Check that whether debugging is enabled for this API client.
+     * @return boolean true if this client is enabled for debugging, false otherwise
+     */
+    public boolean isDebugging() {
+        return debugging;
+    }
+
+    /**
+     * Get the date format used to parse/format date parameters.
+     * @return DateFormat format
+     */
+    public DateFormat getDateFormat() {
+        return dateFormat;
+    }
+
+    /**
+     * Set the date format used to parse/format date parameters.
+     * @param dateFormat Date format
+     * @return API client
+     */
+    public ApiClient setDateFormat(DateFormat dateFormat) {
+        this.dateFormat = dateFormat;
+        return this;
+    }
+
+    /**
+     * Parse the given string into Date object.
+     *
+     * @param str the string to parse
+     * @return the Date parsed from the string
+     */
+    public Date parseDate(String str) {
+        try {
+            return dateFormat.parse(str);
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Format the given Date object into string.
+     *
+     * @param date the date to format
+     * @return the formatted date as string
+     */
+    public String formatDate(Date date) {
+        return dateFormat.format(date);
+    }
+
+    /**
+     * Format the given parameter object into string.
+     *
+     * @param param the object to convert
+     * @return String the parameter represented as a String
+     */
+    public String parameterToString(Object param) {
+        if (param == null) {
+            return "";
+        } else if (param instanceof Date) {
+            return formatDate( (Date) param);
+        } else if (param instanceof OffsetDateTime) {
+            return formatOffsetDateTime((OffsetDateTime) param);
+        } else if (param instanceof Collection) {
+            StringBuilder b = new StringBuilder();
+            for (Object o : (Collection<?>) param) {
+                if (b.length() > 0) {
+                    b.append(",");
+                }
+                b.append(String.valueOf(o));
+            }
+            return b.toString();
+        } else {
+            return String.valueOf(param);
+        }
+    }
+
+    /**
+    * Formats the specified collection path parameter to a string value.
+    *
+    * @param collectionFormat The collection format of the parameter.
+    * @param values The values of the parameter.
+    * @return String representation of the parameter
+    */
+    public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection<?> values) {
+        // create the value based on the collection format
+        if (CollectionFormat.MULTI.equals(collectionFormat)) {
+            // not valid for path params
+            return parameterToString(values);
+        }
+
+        // collectionFormat is assumed to be "csv" by default
+        if (collectionFormat == null) {
+            collectionFormat = CollectionFormat.CSV;
+        }
+
+        return collectionFormat.collectionToString(values);
+    }
+
+    /**
+     * Converts a parameter to a {@link MultiValueMap} for use in REST requests
+     *
+     * @param collectionFormat The format to convert to
+     * @param name The name of the parameter
+     * @param value The parameter's value
+     * @return a Map containing the String value(s) of the input parameter
+     */
+    public MultiValueMap<String, String> parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) {
+        final MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
+
+        if (name == null || name.isEmpty() || value == null) {
+            return params;
+        }
+
+        if (collectionFormat == null) {
+            collectionFormat = CollectionFormat.CSV;
+        }
+
+        if (value instanceof Map) {
+            @SuppressWarnings("unchecked")
+            final Map<String, Object> valuesMap = (Map<String, Object>) value;
+            for (final Entry<String, Object> entry : valuesMap.entrySet()) {
+                params.add(entry.getKey(), parameterToString(entry.getValue()));
+            }
+            return params;
+        }
+
+        Collection<?> valueCollection = null;
+        if (value instanceof Collection) {
+            valueCollection = (Collection<?>) value;
+        } else {
+            params.add(name, parameterToString(value));
+            return params;
+        }
+
+        if (valueCollection.isEmpty()) {
+            return params;
+        }
+
+        if (collectionFormat.equals(CollectionFormat.MULTI)) {
+            for (Object item : valueCollection) {
+                params.add(name, parameterToString(item));
+            }
+            return params;
+        }
+
+        List<String> values = new ArrayList<String>();
+        for (Object o : valueCollection) {
+            values.add(parameterToString(o));
+        }
+        params.add(name, collectionFormat.collectionToString(values));
+
+        return params;
+    }
+
+   /**
+    * Check if the given {@code String} is a JSON MIME.
+    *
+    * @param mediaType the input MediaType
+    * @return boolean true if the MediaType represents JSON, false otherwise
+    */
+    public boolean isJsonMime(String mediaType) {
+        // "* / *" is default to JSON
+        if ("*/*".equals(mediaType)) {
+            return true;
+        }
+
+        try {
+            return isJsonMime(MediaType.parseMediaType(mediaType));
+        } catch (InvalidMediaTypeException e) {
+        }
+        return false;
+    }
+
+    /**
+     * Check if the given MIME is a JSON MIME.
+     * JSON MIME examples:
+     *     application/json
+     *     application/json; charset=UTF8
+     *     APPLICATION/JSON
+     *
+     * @param mediaType the input MediaType
+     * @return boolean true if the MediaType represents JSON, false otherwise
+     */
+    public boolean isJsonMime(MediaType mediaType) {
+        return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$"));
+    }
+
+   /**
+    * Check if the given {@code String} is a Problem JSON MIME (RFC-7807).
+    *
+    * @param mediaType the input MediaType
+    * @return boolean true if the MediaType represents Problem JSON, false otherwise
+    */
+    public boolean isProblemJsonMime(String mediaType) {
+        return "application/problem+json".equalsIgnoreCase(mediaType);
+    }
+
+    /**
+     * Select the Accept header's value from the given accepts array:
+     *     if JSON exists in the given array, use it;
+     *     otherwise use all of them (joining into a string)
+     *
+     * @param accepts The accepts array to select from
+     * @return List The list of MediaTypes to use for the Accept header
+     */
+    public List<MediaType> selectHeaderAccept(String[] accepts) {
+        if (accepts.length == 0) {
+            return null;
+        }
+        for (String accept : accepts) {
+            MediaType mediaType = MediaType.parseMediaType(accept);
+            if (isJsonMime(mediaType) && !isProblemJsonMime(accept)) {
+                return Collections.singletonList(mediaType);
+            }
+        }
+        return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts));
+    }
+
+    /**
+     * Select the Content-Type header's value from the given array:
+     *     if JSON exists in the given array, use it;
+     *     otherwise use the first one of the array.
+     *
+     * @param contentTypes The Content-Type array to select from
+     * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used.
+     */
+    public MediaType selectHeaderContentType(String[] contentTypes) {
+        if (contentTypes.length == 0) {
+            return MediaType.APPLICATION_JSON;
+        }
+        for (String contentType : contentTypes) {
+            MediaType mediaType = MediaType.parseMediaType(contentType);
+            if (isJsonMime(mediaType)) {
+                return mediaType;
+            }
+        }
+        return MediaType.parseMediaType(contentTypes[0]);
+    }
+
+    /**
+     * Select the body to use for the request
+     *
+     * @param obj the body object
+     * @param formParams the form parameters
+     * @param contentType the content type of the request
+     * @return Object the selected body
+     */
+    protected Object selectBody(Object obj, MultiValueMap<String, Object> formParams, MediaType contentType) {
+        boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType);
+        return isForm ? formParams : obj;
+    }
+
+    /**
+     * Expand path template with variables
+     *
+     * @param pathTemplate path template with placeholders
+     * @param variables variables to replace
+     * @return path with placeholders replaced by variables
+     */
+    public String expandPath(String pathTemplate, Map<String, Object> variables) {
+        return restTemplate.getUriTemplateHandler().expand(pathTemplate, variables).toString();
+    }
+
+    /**
+     * Include queryParams in uriParams taking into account the paramName
+     *
+     * @param queryParams The query parameters
+     * @param uriParams The path parameters
+     * return templatized query string
+     */
+    public String generateQueryUri(MultiValueMap<String, String> queryParams, Map<String, Object> uriParams) {
+        StringBuilder queryBuilder = new StringBuilder();
+        queryParams.forEach((name, values) -> {
+            try {
+                final String encodedName = URLEncoder.encode(name.toString(), "UTF-8");
+                if (CollectionUtils.isEmpty(values)) {
+                    if (queryBuilder.length() != 0) {
+                        queryBuilder.append('&');
+                    }
+                    queryBuilder.append(encodedName);
+                } else {
+                    int valueItemCounter = 0;
+                    for (Object value : values) {
+                        if (queryBuilder.length() != 0) {
+                            queryBuilder.append('&');
+                        }
+                        queryBuilder.append(encodedName);
+                        if (value != null) {
+                            String templatizedKey = encodedName + valueItemCounter++;
+                            uriParams.put(templatizedKey, value.toString());
+                            queryBuilder.append('=').append("{").append(templatizedKey).append("}");
+                        }
+                    }
+                }
+            } catch (UnsupportedEncodingException e) {
+
+            }
+        });
+        return queryBuilder.toString();
+
+    }
+
+    /**
+     * Invoke API by sending HTTP request with the given options.
+     *
+     * @param <T> the return type to use
+     * @param path The sub-path of the HTTP URL
+     * @param method The request method
+     * @param pathParams The path parameters
+     * @param queryParams The query parameters
+     * @param body The request body object
+     * @param headerParams The header parameters
+     * @param cookieParams The cookie parameters
+     * @param formParams The form parameters
+     * @param accept The request's Accept header
+     * @param contentType The request's Content-Type header
+     * @param authNames The authentications to apply
+     * @param returnType The return type into which to deserialize the response
+     * @return ResponseEntity&lt;T&gt; The response of the chosen type
+     */
+    public <T> ResponseEntity<T> invokeAPI(String path, HttpMethod method, Map<String, Object> pathParams, MultiValueMap<String, String> queryParams, Object body, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams, MultiValueMap<String, Object> formParams, List<MediaType> accept, MediaType contentType, String[] authNames, ParameterizedTypeReference<T> returnType) throws RestClientException {
+        updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);
+
+        Map<String,Object> uriParams = new HashMap<>();
+        uriParams.putAll(pathParams);
+
+        String queryUri = null;
+
+        if (queryParams != null && !queryParams.isEmpty()) {
+            //Include queryParams in uriParams taking into account the paramName
+            String query = generateQueryUri(queryParams, uriParams);
+            queryUri = expandPath("?" + query, uriParams).substring(1); //exclude the '?'
+            //queryUri is the templatized query string like "?param1={param1Value}&.......
+        }
+        String expandedPath = this.expandPath(path, uriParams);
+        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath)
+                .path(expandedPath)
+                .query(queryUri);
+
+        URI uri;
+        try {
+            uri = new URI(builder.build().toUriString());
+        } catch (URISyntaxException ex)  {
+            throw new RestClientException("Could not build URL: " + builder.toUriString(), ex);
+        }
+
+        final BodyBuilder requestBuilder = RequestEntity.method(method, uri);
+        if (accept != null) {
+            requestBuilder.accept(accept.toArray(new MediaType[accept.size()]));
+        }
+        if (contentType != null) {
+            requestBuilder.contentType(contentType);
+        }
+
+        addHeadersToRequest(headerParams, requestBuilder);
+        addHeadersToRequest(defaultHeaders, requestBuilder);
+        addCookiesToRequest(cookieParams, requestBuilder);
+        addCookiesToRequest(defaultCookies, requestBuilder);
+
+        RequestEntity<Object> requestEntity = requestBuilder.body(selectBody(body, formParams, contentType));
+
+        ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
+
+        if (responseEntity.getStatusCode().is2xxSuccessful()) {
+            return responseEntity;
+        } else {
+            // The error handler built into the RestTemplate should handle 400 and 500 series errors.
+            throw new RestClientException("API returned " + responseEntity.getStatusCode() + " and it wasn't handled by the RestTemplate error handler");
+        }
+    }
+
+    /**
+     * Add headers to the request that is being built
+     * @param headers The headers to add
+     * @param requestBuilder The current request
+     */
+    protected void addHeadersToRequest(HttpHeaders headers, BodyBuilder requestBuilder) {
+        for (Entry<String, List<String>> entry : headers.entrySet()) {
+            List<String> values = entry.getValue();
+            for (String value : values) {
+                if (value != null) {
+                    requestBuilder.header(entry.getKey(), value);
+                }
+            }
+        }
+    }
+
+    /**
+     * Add cookies to the request that is being built
+     *
+     * @param cookies        The cookies to add
+     * @param requestBuilder The current request
+     */
+    protected void addCookiesToRequest(MultiValueMap<String, String> cookies, BodyBuilder requestBuilder) {
+        if (!cookies.isEmpty()) {
+            requestBuilder.header("Cookie", buildCookieHeader(cookies));
+        }
+    }
+
+    /**
+     * Build cookie header. Keeps a single value per cookie (as per <a href="https://tools.ietf.org/html/rfc6265#section-5.3">
+     * RFC6265 section 5.3</a>).
+     *
+     * @param cookies map all cookies
+     * @return header string for cookies.
+     */
+    private String buildCookieHeader(MultiValueMap<String, String> cookies) {
+        final StringBuilder cookieValue = new StringBuilder();
+        String delimiter = "";
+        for (final Map.Entry<String, List<String>> entry : cookies.entrySet()) {
+            final String value = entry.getValue().get(entry.getValue().size() - 1);
+            cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), value));
+            delimiter = "; ";
+        }
+        return cookieValue.toString();
+    }
+
+    /**
+     * Build the RestTemplate used to make HTTP requests.
+     * @return RestTemplate
+     */
+    protected RestTemplate buildRestTemplate() {
+        RestTemplate restTemplate = new RestTemplate();
+        // This allows us to read the response more than once - Necessary for debugging.
+        restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory()));
+
+        // disable default URL encoding
+        DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory();
+        uriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
+        restTemplate.setUriTemplateHandler(uriBuilderFactory);
+        return restTemplate;
+    }
+
+    /**
+     * Update query and header parameters based on authentication settings.
+     *
+     * @param authNames The authentications to apply
+     * @param queryParams The query parameters
+     * @param headerParams The header parameters
+     */
+    protected void updateParamsForAuth(String[] authNames, MultiValueMap<String, String> queryParams, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams) {
+        for (String authName : authNames) {
+            Authentication auth = authentications.get(authName);
+            if (auth == null) {
+                throw new RestClientException("Authentication undefined: " + authName);
+            }
+            auth.applyToParams(queryParams, headerParams, cookieParams);
+        }
+    }
+
+    private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
+        private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class);
+
+        @Override
+        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
+            logRequest(request, body);
+            ClientHttpResponse response = execution.execute(request, body);
+            logResponse(response);
+            return response;
+        }
+
+        private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException {
+            log.info("URI: " + request.getURI());
+            log.info("HTTP Method: " + request.getMethod());
+            log.info("HTTP Headers: " + headersToString(request.getHeaders()));
+            log.info("Request Body: " + new String(body, StandardCharsets.UTF_8));
+        }
+
+        private void logResponse(ClientHttpResponse response) throws IOException {
+            log.info("HTTP Status Code: " + response.getRawStatusCode());
+            log.info("Status Text: " + response.getStatusText());
+            log.info("HTTP Headers: " + headersToString(response.getHeaders()));
+            log.info("Response Body: " + bodyToString(response.getBody()));
+        }
+
+        private String headersToString(HttpHeaders headers) {
+            if(headers == null || headers.isEmpty()) {
+                return "";
+            }
+            StringBuilder builder = new StringBuilder();
+            for (Entry<String, List<String>> entry : headers.entrySet()) {
+                builder.append(entry.getKey()).append("=[");
+                for (String value : entry.getValue()) {
+                    builder.append(value).append(",");
+                }
+                builder.setLength(builder.length() - 1); // Get rid of trailing comma
+                builder.append("],");
+            }
+            builder.setLength(builder.length() - 1); // Get rid of trailing comma
+            return builder.toString();
+        }
+
+        private String bodyToString(InputStream body) throws IOException {
+            StringBuilder builder = new StringBuilder();
+            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8));
+            String line = bufferedReader.readLine();
+            while (line != null) {
+                builder.append(line).append(System.lineSeparator());
+                line = bufferedReader.readLine();
+            }
+            bufferedReader.close();
+            return builder.toString();
+        }
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/JavaTimeFormatter.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/JavaTimeFormatter.java
new file mode 100644
index 0000000000000000000000000000000000000000..b51199a21b0600d681448a1d3a06e25811ed06d2
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/JavaTimeFormatter.java
@@ -0,0 +1,64 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package org.openapitools.client;
+
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+/**
+ * Class that add parsing/formatting support for Java 8+ {@code OffsetDateTime} class.
+ * It's generated for java clients when {@code AbstractJavaCodegen#dateLibrary} specified as {@code java8}.
+ */
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+public class JavaTimeFormatter {
+
+    private DateTimeFormatter offsetDateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+
+    /**
+     * Get the date format used to parse/format {@code OffsetDateTime} parameters.
+     * @return DateTimeFormatter
+     */
+    public DateTimeFormatter getOffsetDateTimeFormatter() {
+        return offsetDateTimeFormatter;
+    }
+
+    /**
+     * Set the date format used to parse/format {@code OffsetDateTime} parameters.
+     * @param offsetDateTimeFormatter {@code DateTimeFormatter}
+     */
+    public void setOffsetDateTimeFormatter(DateTimeFormatter offsetDateTimeFormatter) {
+        this.offsetDateTimeFormatter = offsetDateTimeFormatter;
+    }
+
+    /**
+     * Parse the given string into {@code OffsetDateTime} object.
+     * @param str String
+     * @return {@code OffsetDateTime}
+     */
+    public OffsetDateTime parseOffsetDateTime(String str) {
+        try {
+            return OffsetDateTime.parse(str, offsetDateTimeFormatter);
+        } catch (DateTimeParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    /**
+     * Format the given {@code OffsetDateTime} object into string.
+     * @param offsetDateTime {@code OffsetDateTime}
+     * @return {@code OffsetDateTime} in string format
+     */
+    public String formatOffsetDateTime(OffsetDateTime offsetDateTime) {
+        return offsetDateTimeFormatter.format(offsetDateTime);
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/RFC3339DateFormat.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/RFC3339DateFormat.java
new file mode 100644
index 0000000000000000000000000000000000000000..22bbe68c49f4ebc262ee1b44233061a696fa3468
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/RFC3339DateFormat.java
@@ -0,0 +1,57 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package org.openapitools.client;
+
+import com.fasterxml.jackson.databind.util.StdDateFormat;
+
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.text.DecimalFormat;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+public class RFC3339DateFormat extends DateFormat {
+  private static final long serialVersionUID = 1L;
+  private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC");
+
+  private final StdDateFormat fmt = new StdDateFormat()
+          .withTimeZone(TIMEZONE_Z)
+          .withColonInTimeZone(true);
+
+  public RFC3339DateFormat() {
+    this.calendar = new GregorianCalendar();
+    this.numberFormat = new DecimalFormat();
+  }
+
+  @Override
+  public Date parse(String source) {
+    return parse(source, new ParsePosition(0));
+  }
+
+  @Override
+  public Date parse(String source, ParsePosition pos) {
+    return fmt.parse(source, pos);
+  }
+
+  @Override
+  public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
+    return fmt.format(date, toAppendTo, fieldPosition);
+  }
+
+  @Override
+  public Object clone() {
+    return super.clone();
+  }
+}
\ No newline at end of file
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ServerConfiguration.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ServerConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..59edc528a446ae73525d93958da24bc939bcef1e
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ServerConfiguration.java
@@ -0,0 +1,58 @@
+package org.openapitools.client;
+
+import java.util.Map;
+
+/**
+ * Representing a Server configuration.
+ */
+public class ServerConfiguration {
+    public String URL;
+    public String description;
+    public Map<String, ServerVariable> variables;
+
+    /**
+     * @param URL A URL to the target host.
+     * @param description A description of the host designated by the URL.
+     * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template.
+     */
+    public ServerConfiguration(String URL, String description, Map<String, ServerVariable> variables) {
+        this.URL = URL;
+        this.description = description;
+        this.variables = variables;
+    }
+
+    /**
+     * Format URL template using given variables.
+     *
+     * @param variables A map between a variable name and its value.
+     * @return Formatted URL.
+     */
+    public String URL(Map<String, String> variables) {
+        String url = this.URL;
+
+        // go through variables and replace placeholders
+        for (Map.Entry<String, ServerVariable> variable: this.variables.entrySet()) {
+            String name = variable.getKey();
+            ServerVariable serverVariable = variable.getValue();
+            String value = serverVariable.defaultValue;
+
+            if (variables != null && variables.containsKey(name)) {
+                value = variables.get(name);
+                if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) {
+                    throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + ".");
+                }
+            }
+            url = url.replace("{" + name + "}", value);
+        }
+        return url;
+    }
+
+    /**
+     * Format URL template using default server variables.
+     *
+     * @return Formatted URL.
+     */
+    public String URL() {
+        return URL(null);
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ServerVariable.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ServerVariable.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2f13e2166621ccecd578c6c2436b8a165e204b4
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ServerVariable.java
@@ -0,0 +1,23 @@
+package org.openapitools.client;
+
+import java.util.HashSet;
+
+/**
+ * Representing a Server Variable for server URL template substitution.
+ */
+public class ServerVariable {
+    public String description;
+    public String defaultValue;
+    public HashSet<String> enumValues = null;
+
+    /**
+     * @param description A description for the server variable.
+     * @param defaultValue The default value to use for substitution.
+     * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set.
+     */
+    public ServerVariable(String description, String defaultValue, HashSet<String> enumValues) {
+        this.description = description;
+        this.defaultValue = defaultValue;
+        this.enumValues = enumValues;
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/BodyApi.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/BodyApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..7de6f92f34ddc7e29ce371b7a976386fab1df2b6
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/BodyApi.java
@@ -0,0 +1,93 @@
+package org.openapitools.client.api;
+
+import org.openapitools.client.ApiClient;
+
+import org.openapitools.client.model.Pet;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+@Component("org.openapitools.client.api.BodyApi")
+public class BodyApi {
+    private ApiClient apiClient;
+
+    public BodyApi() {
+        this(new ApiClient());
+    }
+
+    @Autowired
+    public BodyApi(ApiClient apiClient) {
+        this.apiClient = apiClient;
+    }
+
+    public ApiClient getApiClient() {
+        return apiClient;
+    }
+
+    public void setApiClient(ApiClient apiClient) {
+        this.apiClient = apiClient;
+    }
+
+    /**
+     * Test body parameter(s)
+     * Test body parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param pet Pet object that needs to be added to the store (optional)
+     * @return Pet
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public Pet testEchoBodyPet(Pet pet) throws RestClientException {
+        return testEchoBodyPetWithHttpInfo(pet).getBody();
+    }
+
+    /**
+     * Test body parameter(s)
+     * Test body parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param pet Pet object that needs to be added to the store (optional)
+     * @return ResponseEntity&lt;Pet&gt;
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public ResponseEntity<Pet> testEchoBodyPetWithHttpInfo(Pet pet) throws RestClientException {
+        Object localVarPostBody = pet;
+        
+
+        final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
+        final HttpHeaders localVarHeaderParams = new HttpHeaders();
+        final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
+        final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
+
+        final String[] localVarAccepts = { 
+            "application/json"
+         };
+        final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
+        final String[] localVarContentTypes = { 
+            "application/json"
+         };
+        final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
+
+        String[] localVarAuthNames = new String[] {  };
+
+        ParameterizedTypeReference<Pet> localReturnType = new ParameterizedTypeReference<Pet>() {};
+        return apiClient.invokeAPI("/echo/body/Pet", HttpMethod.POST, Collections.<String, Object>emptyMap(), localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType);
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/PathApi.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/PathApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c498d4e28de58787562db88c7e5052cef250b15
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/PathApi.java
@@ -0,0 +1,106 @@
+package org.openapitools.client.api;
+
+import org.openapitools.client.ApiClient;
+
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+@Component("org.openapitools.client.api.PathApi")
+public class PathApi {
+    private ApiClient apiClient;
+
+    public PathApi() {
+        this(new ApiClient());
+    }
+
+    @Autowired
+    public PathApi(ApiClient apiClient) {
+        this.apiClient = apiClient;
+    }
+
+    public ApiClient getApiClient() {
+        return apiClient;
+    }
+
+    public void setApiClient(ApiClient apiClient) {
+        this.apiClient = apiClient;
+    }
+
+    /**
+     * Test path parameter(s)
+     * Test path parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param pathString  (required)
+     * @param pathInteger  (required)
+     * @return String
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public String testsPathStringPathStringIntegerPathInteger(String pathString, Integer pathInteger) throws RestClientException {
+        return testsPathStringPathStringIntegerPathIntegerWithHttpInfo(pathString, pathInteger).getBody();
+    }
+
+    /**
+     * Test path parameter(s)
+     * Test path parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param pathString  (required)
+     * @param pathInteger  (required)
+     * @return ResponseEntity&lt;String&gt;
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public ResponseEntity<String> testsPathStringPathStringIntegerPathIntegerWithHttpInfo(String pathString, Integer pathInteger) throws RestClientException {
+        Object localVarPostBody = null;
+        
+        // verify the required parameter 'pathString' is set
+        if (pathString == null) {
+            throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'pathString' when calling testsPathStringPathStringIntegerPathInteger");
+        }
+        
+        // verify the required parameter 'pathInteger' is set
+        if (pathInteger == null) {
+            throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'pathInteger' when calling testsPathStringPathStringIntegerPathInteger");
+        }
+        
+        // create path and map variables
+        final Map<String, Object> uriVariables = new HashMap<String, Object>();
+        uriVariables.put("path_string", pathString);
+        uriVariables.put("path_integer", pathInteger);
+
+        final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
+        final HttpHeaders localVarHeaderParams = new HttpHeaders();
+        final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
+        final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
+
+        final String[] localVarAccepts = { 
+            "text/plain"
+         };
+        final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
+        final String[] localVarContentTypes = {  };
+        final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
+
+        String[] localVarAuthNames = new String[] {  };
+
+        ParameterizedTypeReference<String> localReturnType = new ParameterizedTypeReference<String>() {};
+        return apiClient.invokeAPI("/path/string/{path_string}/integer/{path_integer}", HttpMethod.GET, uriVariables, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType);
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/QueryApi.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/QueryApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d20b51c88601f6f50c1bae4382a994cbcbec689
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/QueryApi.java
@@ -0,0 +1,186 @@
+package org.openapitools.client.api;
+
+import org.openapitools.client.ApiClient;
+
+import org.openapitools.client.model.Pet;
+import org.openapitools.client.model.TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+@Component("org.openapitools.client.api.QueryApi")
+public class QueryApi {
+    private ApiClient apiClient;
+
+    public QueryApi() {
+        this(new ApiClient());
+    }
+
+    @Autowired
+    public QueryApi(ApiClient apiClient) {
+        this.apiClient = apiClient;
+    }
+
+    public ApiClient getApiClient() {
+        return apiClient;
+    }
+
+    public void setApiClient(ApiClient apiClient) {
+        this.apiClient = apiClient;
+    }
+
+    /**
+     * Test query parameter(s)
+     * Test query parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param integerQuery  (optional)
+     * @param booleanQuery  (optional)
+     * @param stringQuery  (optional)
+     * @return String
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public String testQueryIntegerBooleanString(Integer integerQuery, Boolean booleanQuery, String stringQuery) throws RestClientException {
+        return testQueryIntegerBooleanStringWithHttpInfo(integerQuery, booleanQuery, stringQuery).getBody();
+    }
+
+    /**
+     * Test query parameter(s)
+     * Test query parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param integerQuery  (optional)
+     * @param booleanQuery  (optional)
+     * @param stringQuery  (optional)
+     * @return ResponseEntity&lt;String&gt;
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public ResponseEntity<String> testQueryIntegerBooleanStringWithHttpInfo(Integer integerQuery, Boolean booleanQuery, String stringQuery) throws RestClientException {
+        Object localVarPostBody = null;
+        
+
+        final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
+        final HttpHeaders localVarHeaderParams = new HttpHeaders();
+        final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
+        final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
+
+        localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(null, "integer_query", integerQuery));
+        localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(null, "boolean_query", booleanQuery));
+        localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(null, "string_query", stringQuery));
+
+        final String[] localVarAccepts = { 
+            "text/plain"
+         };
+        final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
+        final String[] localVarContentTypes = {  };
+        final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
+
+        String[] localVarAuthNames = new String[] {  };
+
+        ParameterizedTypeReference<String> localReturnType = new ParameterizedTypeReference<String>() {};
+        return apiClient.invokeAPI("/query/integer/boolean/string", HttpMethod.GET, Collections.<String, Object>emptyMap(), localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType);
+    }
+    /**
+     * Test query parameter(s)
+     * Test query parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param queryObject  (optional)
+     * @return String
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public String testQueryStyleFormExplodeTrueArrayString(TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter queryObject) throws RestClientException {
+        return testQueryStyleFormExplodeTrueArrayStringWithHttpInfo(queryObject).getBody();
+    }
+
+    /**
+     * Test query parameter(s)
+     * Test query parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param queryObject  (optional)
+     * @return ResponseEntity&lt;String&gt;
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public ResponseEntity<String> testQueryStyleFormExplodeTrueArrayStringWithHttpInfo(TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter queryObject) throws RestClientException {
+        Object localVarPostBody = null;
+        
+
+        final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
+        final HttpHeaders localVarHeaderParams = new HttpHeaders();
+        final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
+        final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
+
+        localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(null, "query_object", queryObject));
+
+        final String[] localVarAccepts = { 
+            "text/plain"
+         };
+        final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
+        final String[] localVarContentTypes = {  };
+        final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
+
+        String[] localVarAuthNames = new String[] {  };
+
+        ParameterizedTypeReference<String> localReturnType = new ParameterizedTypeReference<String>() {};
+        return apiClient.invokeAPI("/query/style_form/explode_true/array_string", HttpMethod.GET, Collections.<String, Object>emptyMap(), localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType);
+    }
+    /**
+     * Test query parameter(s)
+     * Test query parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param queryObject  (optional)
+     * @return String
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public String testQueryStyleFormExplodeTrueObject(Pet queryObject) throws RestClientException {
+        return testQueryStyleFormExplodeTrueObjectWithHttpInfo(queryObject).getBody();
+    }
+
+    /**
+     * Test query parameter(s)
+     * Test query parameter(s)
+     * <p><b>200</b> - Successful operation
+     * @param queryObject  (optional)
+     * @return ResponseEntity&lt;String&gt;
+     * @throws RestClientException if an error occurs while attempting to invoke the API
+     */
+    public ResponseEntity<String> testQueryStyleFormExplodeTrueObjectWithHttpInfo(Pet queryObject) throws RestClientException {
+        Object localVarPostBody = null;
+        
+
+        final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
+        final HttpHeaders localVarHeaderParams = new HttpHeaders();
+        final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
+        final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
+
+        localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(null, "query_object", queryObject));
+
+        final String[] localVarAccepts = { 
+            "text/plain"
+         };
+        final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
+        final String[] localVarContentTypes = {  };
+        final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
+
+        String[] localVarAuthNames = new String[] {  };
+
+        ParameterizedTypeReference<String> localReturnType = new ParameterizedTypeReference<String>() {};
+        return apiClient.invokeAPI("/query/style_form/explode_true/object", HttpMethod.GET, Collections.<String, Object>emptyMap(), localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType);
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/ApiKeyAuth.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/ApiKeyAuth.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e9f3733160e9f72574aadd92fe80c1ce5906231
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/ApiKeyAuth.java
@@ -0,0 +1,62 @@
+package org.openapitools.client.auth;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.util.MultiValueMap;
+
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+public class ApiKeyAuth implements Authentication {
+    private final String location;
+    private final String paramName;
+
+    private String apiKey;
+    private String apiKeyPrefix;
+
+    public ApiKeyAuth(String location, String paramName) {
+        this.location = location;
+        this.paramName = paramName;
+    }
+
+    public String getLocation() {
+        return location;
+    }
+
+    public String getParamName() {
+        return paramName;
+    }
+
+    public String getApiKey() {
+        return apiKey;
+    }
+
+    public void setApiKey(String apiKey) {
+        this.apiKey = apiKey;
+    }
+
+    public String getApiKeyPrefix() {
+        return apiKeyPrefix;
+    }
+
+    public void setApiKeyPrefix(String apiKeyPrefix) {
+        this.apiKeyPrefix = apiKeyPrefix;
+    }
+
+    @Override
+    public void applyToParams(MultiValueMap<String, String> queryParams, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams) {
+        if (apiKey == null) {
+            return;
+        }
+        String value;
+        if (apiKeyPrefix != null) {
+            value = apiKeyPrefix + " " + apiKey;
+        } else {
+            value = apiKey;
+        }
+        if (location.equals("query")) {
+            queryParams.add(paramName, value);
+        } else if (location.equals("header")) {
+            headerParams.add(paramName, value);
+        } else if (location.equals("cookie")) {
+            cookieParams.add(paramName, value);
+        }
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/Authentication.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/Authentication.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f9a14ebd7c316292ef457edee6ee994e05a21af
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/Authentication.java
@@ -0,0 +1,14 @@
+package org.openapitools.client.auth;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.util.MultiValueMap;
+
+public interface Authentication {
+    /**
+     * Apply authentication settings to header and / or query parameters.
+     * @param queryParams The query parameters for the request
+     * @param headerParams The header parameters for the request
+     * @param cookieParams The cookie parameters for the request
+     */
+    public void applyToParams(MultiValueMap<String, String> queryParams, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams);
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/HttpBasicAuth.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/HttpBasicAuth.java
new file mode 100644
index 0000000000000000000000000000000000000000..bbbbba67a472e02f3ed5b56ee372a1d91aad046d
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/HttpBasicAuth.java
@@ -0,0 +1,39 @@
+package org.openapitools.client.auth;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.MultiValueMap;
+
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+public class HttpBasicAuth implements Authentication {
+    private String username;
+    private String password;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    @Override
+    public void applyToParams(MultiValueMap<String, String> queryParams, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams) {
+        if (username == null && password == null) {
+            return;
+        }
+        String str = (username == null ? "" : username) + ":" + (password == null ? "" : password);
+        headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8)));
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/HttpBearerAuth.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/HttpBearerAuth.java
new file mode 100644
index 0000000000000000000000000000000000000000..299c05b12e049ba6ac77a476f9a769ea03f9e03e
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/auth/HttpBearerAuth.java
@@ -0,0 +1,38 @@
+package org.openapitools.client.auth;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.MultiValueMap;
+
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+public class HttpBearerAuth implements Authentication {
+    private final String scheme;
+    private String bearerToken;
+
+    public HttpBearerAuth(String scheme) {
+        this.scheme = scheme;
+    }
+
+    public String getBearerToken() {
+        return bearerToken;
+    }
+
+    public void setBearerToken(String bearerToken) {
+        this.bearerToken = bearerToken;
+    }
+
+    @Override
+    public void applyToParams(MultiValueMap<String, String> queryParams, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams) {
+        if (bearerToken == null) {
+            return;
+        }
+        headerParams.add(HttpHeaders.AUTHORIZATION, (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken);
+    }
+
+    private static String upperCaseBearer(String scheme) {
+        return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme;
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Category.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Category.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2a52c12a29d603ea7679022113e69bd4c955f60
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Category.java
@@ -0,0 +1,136 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.model;
+
+import java.util.Objects;
+import java.util.Arrays;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+/**
+ * Category
+ */
+@JsonPropertyOrder({
+  Category.JSON_PROPERTY_ID,
+  Category.JSON_PROPERTY_NAME
+})
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+public class Category {
+  public static final String JSON_PROPERTY_ID = "id";
+  private Long id;
+
+  public static final String JSON_PROPERTY_NAME = "name";
+  private String name;
+
+  public Category() {
+  }
+
+  public Category id(Long id) {
+    
+    this.id = id;
+    return this;
+  }
+
+   /**
+   * Get id
+   * @return id
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_ID)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public Long getId() {
+    return id;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_ID)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+
+  public Category name(String name) {
+    
+    this.name = name;
+    return this;
+  }
+
+   /**
+   * Get name
+   * @return name
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_NAME)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public String getName() {
+    return name;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_NAME)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  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/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Pet.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Pet.java
new file mode 100644
index 0000000000000000000000000000000000000000..3484a3d0c6eee266e4d93b761f0695ac4e748585
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Pet.java
@@ -0,0 +1,318 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.model;
+
+import java.util.Objects;
+import java.util.Arrays;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
+import java.util.ArrayList;
+import java.util.List;
+import org.openapitools.client.model.Category;
+import org.openapitools.client.model.Tag;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+/**
+ * Pet
+ */
+@JsonPropertyOrder({
+  Pet.JSON_PROPERTY_ID,
+  Pet.JSON_PROPERTY_NAME,
+  Pet.JSON_PROPERTY_CATEGORY,
+  Pet.JSON_PROPERTY_PHOTO_URLS,
+  Pet.JSON_PROPERTY_TAGS,
+  Pet.JSON_PROPERTY_STATUS
+})
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+public class Pet {
+  public static final String JSON_PROPERTY_ID = "id";
+  private Long id;
+
+  public static final String JSON_PROPERTY_NAME = "name";
+  private String name;
+
+  public static final String JSON_PROPERTY_CATEGORY = "category";
+  private Category category;
+
+  public static final String JSON_PROPERTY_PHOTO_URLS = "photoUrls";
+  private List<String> photoUrls = new ArrayList<>();
+
+  public static final String JSON_PROPERTY_TAGS = "tags";
+  private List<Tag> tags = null;
+
+  /**
+   * pet status in the store
+   */
+  public enum StatusEnum {
+    AVAILABLE("available"),
+    
+    PENDING("pending"),
+    
+    SOLD("sold");
+
+    private String value;
+
+    StatusEnum(String value) {
+      this.value = value;
+    }
+
+    @JsonValue
+    public String getValue() {
+      return value;
+    }
+
+    @Override
+    public String toString() {
+      return String.valueOf(value);
+    }
+
+    @JsonCreator
+    public static StatusEnum fromValue(String value) {
+      for (StatusEnum b : StatusEnum.values()) {
+        if (b.value.equals(value)) {
+          return b;
+        }
+      }
+      throw new IllegalArgumentException("Unexpected value '" + value + "'");
+    }
+  }
+
+  public static final String JSON_PROPERTY_STATUS = "status";
+  private StatusEnum status;
+
+  public Pet() {
+  }
+
+  public Pet id(Long id) {
+    
+    this.id = id;
+    return this;
+  }
+
+   /**
+   * Get id
+   * @return id
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_ID)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public Long getId() {
+    return id;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_ID)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+
+  public Pet name(String name) {
+    
+    this.name = name;
+    return this;
+  }
+
+   /**
+   * Get name
+   * @return name
+  **/
+  @javax.annotation.Nonnull
+  @JsonProperty(JSON_PROPERTY_NAME)
+  @JsonInclude(value = JsonInclude.Include.ALWAYS)
+
+  public String getName() {
+    return name;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_NAME)
+  @JsonInclude(value = JsonInclude.Include.ALWAYS)
+  public void setName(String name) {
+    this.name = name;
+  }
+
+
+  public Pet category(Category category) {
+    
+    this.category = category;
+    return this;
+  }
+
+   /**
+   * Get category
+   * @return category
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_CATEGORY)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public Category getCategory() {
+    return category;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_CATEGORY)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  public void setCategory(Category category) {
+    this.category = category;
+  }
+
+
+  public Pet photoUrls(List<String> photoUrls) {
+    
+    this.photoUrls = photoUrls;
+    return this;
+  }
+
+  public Pet addPhotoUrlsItem(String photoUrlsItem) {
+    this.photoUrls.add(photoUrlsItem);
+    return this;
+  }
+
+   /**
+   * Get photoUrls
+   * @return photoUrls
+  **/
+  @javax.annotation.Nonnull
+  @JsonProperty(JSON_PROPERTY_PHOTO_URLS)
+  @JsonInclude(value = JsonInclude.Include.ALWAYS)
+
+  public List<String> getPhotoUrls() {
+    return photoUrls;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_PHOTO_URLS)
+  @JsonInclude(value = JsonInclude.Include.ALWAYS)
+  public void setPhotoUrls(List<String> photoUrls) {
+    this.photoUrls = photoUrls;
+  }
+
+
+  public Pet tags(List<Tag> tags) {
+    
+    this.tags = tags;
+    return this;
+  }
+
+  public Pet addTagsItem(Tag tagsItem) {
+    if (this.tags == null) {
+      this.tags = new ArrayList<>();
+    }
+    this.tags.add(tagsItem);
+    return this;
+  }
+
+   /**
+   * Get tags
+   * @return tags
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_TAGS)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public List<Tag> getTags() {
+    return tags;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_TAGS)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  public void setTags(List<Tag> tags) {
+    this.tags = tags;
+  }
+
+
+  public Pet status(StatusEnum status) {
+    
+    this.status = status;
+    return this;
+  }
+
+   /**
+   * pet status in the store
+   * @return status
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_STATUS)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public StatusEnum getStatus() {
+    return status;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_STATUS)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  public void setStatus(StatusEnum 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.name, pet.name) &&
+        Objects.equals(this.category, pet.category) &&
+        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, name, category, 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("    name: ").append(toIndentedString(name)).append("\n");
+    sb.append("    category: ").append(toIndentedString(category)).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/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Tag.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Tag.java
new file mode 100644
index 0000000000000000000000000000000000000000..2da4a88b526664863b6366a99900d80949e6f078
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/Tag.java
@@ -0,0 +1,136 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.model;
+
+import java.util.Objects;
+import java.util.Arrays;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+/**
+ * Tag
+ */
+@JsonPropertyOrder({
+  Tag.JSON_PROPERTY_ID,
+  Tag.JSON_PROPERTY_NAME
+})
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+public class Tag {
+  public static final String JSON_PROPERTY_ID = "id";
+  private Long id;
+
+  public static final String JSON_PROPERTY_NAME = "name";
+  private String name;
+
+  public Tag() {
+  }
+
+  public Tag id(Long id) {
+    
+    this.id = id;
+    return this;
+  }
+
+   /**
+   * Get id
+   * @return id
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_ID)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public Long getId() {
+    return id;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_ID)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+
+  public Tag name(String name) {
+    
+    this.name = name;
+    return this;
+  }
+
+   /**
+   * Get name
+   * @return name
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_NAME)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public String getName() {
+    return name;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_NAME)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  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/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.java b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.java
new file mode 100644
index 0000000000000000000000000000000000000000..4fc23acdc7e147414427f1075b3538e56a249de4
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.java
@@ -0,0 +1,115 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.model;
+
+import java.util.Objects;
+import java.util.Arrays;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
+import java.util.ArrayList;
+import java.util.List;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+/**
+ * TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter
+ */
+@JsonPropertyOrder({
+  TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.JSON_PROPERTY_VALUES
+})
+@JsonTypeName("test_query_style_form_explode_true_array_string_query_object_parameter")
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
+public class TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter {
+  public static final String JSON_PROPERTY_VALUES = "values";
+  private List<String> values = null;
+
+  public TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter() {
+  }
+
+  public TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter values(List<String> values) {
+    
+    this.values = values;
+    return this;
+  }
+
+  public TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter addValuesItem(String valuesItem) {
+    if (this.values == null) {
+      this.values = new ArrayList<>();
+    }
+    this.values.add(valuesItem);
+    return this;
+  }
+
+   /**
+   * Get values
+   * @return values
+  **/
+  @javax.annotation.Nullable
+  @JsonProperty(JSON_PROPERTY_VALUES)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+
+  public List<String> getValues() {
+    return values;
+  }
+
+
+  @JsonProperty(JSON_PROPERTY_VALUES)
+  @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+  public void setValues(List<String> values) {
+    this.values = values;
+  }
+
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter testQueryStyleFormExplodeTrueArrayStringQueryObjectParameter = (TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter) o;
+    return Objects.equals(this.values, testQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.values);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(values);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter {\n");
+    sb.append("    values: ").append(toIndentedString(values)).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/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/CustomTest.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/CustomTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c7de58a5faa4808b7e21fe5e68744adfcfb44d4
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/CustomTest.java
@@ -0,0 +1,60 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.oprg
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client;
+
+import org.springframework.web.client.RestClientException;
+import org.junit.Assert;
+import org.openapitools.client.api.QueryApi;
+import org.openapitools.client.model.Category;
+import org.openapitools.client.model.Pet;
+import org.openapitools.client.model.TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter;
+import org.junit.Test;
+import org.junit.Ignore;
+
+import java.util.*;
+
+
+/**
+ * API tests for QueryApi
+ */
+public class CustomTest {
+
+    private final QueryApi api = new QueryApi();
+
+
+    /**
+     * Test query parameter(s)
+     * <p>
+     * Test query parameter(s)
+     *
+     * @throws RestClientException if the Api call fails
+     */
+    @Test
+    public void testQueryStyleFormExplodeTrueObjectTest() throws RestClientException{
+
+    }
+
+    /**
+     * Test query parameter(s)
+     * <p>
+     * Test query parameter(s)
+     *
+     * @throws RestClientException if the Api call fails
+     */
+    @Test
+    public void testQueryStyleFormExplodeTrueArrayString() throws RestClientException {
+
+    }
+
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/EchoServerResponseParser.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/EchoServerResponseParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..b68af6d4a74c1503eb8db9c0c05adbcdd25941f7
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/EchoServerResponseParser.java
@@ -0,0 +1,51 @@
+/*
+ * 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 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.client;
+
+public class EchoServerResponseParser {
+    public String method; // e.g. GET
+    public String path; // e.g. /query/style_form/explode_true/object?id=12345
+    public String protocol; // e.g. HTTP/1.1
+    public java.util.HashMap<String, String> headers = new java.util.HashMap<>();
+
+    public EchoServerResponseParser(String response) {
+        if (response == null) {
+            throw new RuntimeException("Echo server response cannot be null");
+        }
+
+        String[] lines = response.split("\n");
+        boolean firstLine = true;
+
+        for (String line : lines) {
+            if (firstLine) {
+                String[] items = line.split(" ");
+                this.method = items[0];
+                this.path = items[1];
+                this.protocol = items[2];
+                firstLine = false;
+                continue;
+            }
+
+            // store the header key-value pair in headers
+            String[] keyValue = line.split(": ");
+            if (keyValue.length == 2) { // skip blank line, non key-value pair
+                this.headers.put(keyValue[0], keyValue[1]);
+            }
+        }
+
+    }
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/BodyApiTest.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/BodyApiTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..cedf0ac16e8cc97faeec6e2793aa9daa6be5f27f
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/BodyApiTest.java
@@ -0,0 +1,52 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.api;
+
+import org.openapitools.client.model.Pet;
+import org.junit.Test;
+import org.junit.Ignore;
+
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * API tests for BodyApi
+ */
+@Ignore
+public class BodyApiTest {
+
+    private final BodyApi api = new BodyApi();
+
+    
+    /**
+     * Test body parameter(s)
+     *
+     * Test body parameter(s)
+     *
+     * @throws ApiException
+     *          if the Api call fails
+     */
+    @Test
+    public void testEchoBodyPetTest() {
+        Pet pet = null;
+        Pet response = api.testEchoBodyPet(pet);
+
+        // TODO: test validations
+    }
+    
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/PathApiTest.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/PathApiTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..01ab30331d6286b5cb24b5a521182dd28a808ed9
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/PathApiTest.java
@@ -0,0 +1,52 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.api;
+
+import org.junit.Test;
+import org.junit.Ignore;
+
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * API tests for PathApi
+ */
+@Ignore
+public class PathApiTest {
+
+    private final PathApi api = new PathApi();
+
+    
+    /**
+     * Test path parameter(s)
+     *
+     * Test path parameter(s)
+     *
+     * @throws ApiException
+     *          if the Api call fails
+     */
+    @Test
+    public void testsPathStringPathStringIntegerPathIntegerTest() {
+        String pathString = null;
+        Integer pathInteger = null;
+        String response = api.testsPathStringPathStringIntegerPathInteger(pathString, pathInteger);
+
+        // TODO: test validations
+    }
+    
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/QueryApiTest.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/QueryApiTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..03961136f9c00036d4e33b9846f7263745e961ee
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/api/QueryApiTest.java
@@ -0,0 +1,87 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.api;
+
+import org.openapitools.client.model.Pet;
+import org.openapitools.client.model.TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter;
+import org.junit.Test;
+import org.junit.Ignore;
+
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * API tests for QueryApi
+ */
+@Ignore
+public class QueryApiTest {
+
+    private final QueryApi api = new QueryApi();
+
+    
+    /**
+     * Test query parameter(s)
+     *
+     * Test query parameter(s)
+     *
+     * @throws ApiException
+     *          if the Api call fails
+     */
+    @Test
+    public void testQueryIntegerBooleanStringTest() {
+        Integer integerQuery = null;
+        Boolean booleanQuery = null;
+        String stringQuery = null;
+        String response = api.testQueryIntegerBooleanString(integerQuery, booleanQuery, stringQuery);
+
+        // TODO: test validations
+    }
+    
+    /**
+     * Test query parameter(s)
+     *
+     * Test query parameter(s)
+     *
+     * @throws ApiException
+     *          if the Api call fails
+     */
+    @Test
+    public void testQueryStyleFormExplodeTrueArrayStringTest() {
+        TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter queryObject = null;
+        String response = api.testQueryStyleFormExplodeTrueArrayString(queryObject);
+
+        // TODO: test validations
+    }
+    
+    /**
+     * Test query parameter(s)
+     *
+     * Test query parameter(s)
+     *
+     * @throws ApiException
+     *          if the Api call fails
+     */
+    @Test
+    public void testQueryStyleFormExplodeTrueObjectTest() {
+        Pet queryObject = null;
+        String response = api.testQueryStyleFormExplodeTrueObject(queryObject);
+
+        // TODO: test validations
+    }
+    
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/CategoryTest.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/CategoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..51804e0c14cf9c2791b1fd6feca267f6dff8c35c
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/CategoryTest.java
@@ -0,0 +1,56 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/**
+ * Model tests for Category
+ */
+public class CategoryTest {
+    private final Category model = new Category();
+
+    /**
+     * Model tests for Category
+     */
+    @Test
+    public void testCategory() {
+        // TODO: test Category
+    }
+
+    /**
+     * Test the property 'id'
+     */
+    @Test
+    public void idTest() {
+        // TODO: test id
+    }
+
+    /**
+     * Test the property 'name'
+     */
+    @Test
+    public void nameTest() {
+        // TODO: test name
+    }
+
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/PetTest.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/PetTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2002d08bf8a796516ff622d1b5c15042d8c71a34
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/PetTest.java
@@ -0,0 +1,92 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
+import java.util.ArrayList;
+import java.util.List;
+import org.openapitools.client.model.Category;
+import org.openapitools.client.model.Tag;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/**
+ * Model tests for Pet
+ */
+public class PetTest {
+    private final Pet model = new Pet();
+
+    /**
+     * Model tests for Pet
+     */
+    @Test
+    public void testPet() {
+        // TODO: test Pet
+    }
+
+    /**
+     * Test the property 'id'
+     */
+    @Test
+    public void idTest() {
+        // TODO: test id
+    }
+
+    /**
+     * Test the property 'name'
+     */
+    @Test
+    public void nameTest() {
+        // TODO: test name
+    }
+
+    /**
+     * Test the property 'category'
+     */
+    @Test
+    public void categoryTest() {
+        // TODO: test category
+    }
+
+    /**
+     * Test the property 'photoUrls'
+     */
+    @Test
+    public void photoUrlsTest() {
+        // TODO: test photoUrls
+    }
+
+    /**
+     * Test the property 'tags'
+     */
+    @Test
+    public void tagsTest() {
+        // TODO: test tags
+    }
+
+    /**
+     * Test the property 'status'
+     */
+    @Test
+    public void statusTest() {
+        // TODO: test status
+    }
+
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/TagTest.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/TagTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1d4b9de0d53d9f6aa4c777887471ce7407f6934
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/TagTest.java
@@ -0,0 +1,56 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/**
+ * Model tests for Tag
+ */
+public class TagTest {
+    private final Tag model = new Tag();
+
+    /**
+     * Model tests for Tag
+     */
+    @Test
+    public void testTag() {
+        // TODO: test Tag
+    }
+
+    /**
+     * Test the property 'id'
+     */
+    @Test
+    public void idTest() {
+        // TODO: test id
+    }
+
+    /**
+     * Test the property 'name'
+     */
+    @Test
+    public void nameTest() {
+        // TODO: test name
+    }
+
+}
diff --git a/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameterTest.java b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameterTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..82e7035a25a2d8110986a093e0a5dc84490b9690
--- /dev/null
+++ b/samples/client/echo_api/java/resttemplate/src/test/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameterTest.java
@@ -0,0 +1,50 @@
+/*
+ * Echo Server API
+ * Echo Server API
+ *
+ * The version of the OpenAPI document: 0.1.0
+ * Contact: team@openapitools.org
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package org.openapitools.client.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/**
+ * Model tests for TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter
+ */
+public class TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameterTest {
+    private final TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter model = new TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter();
+
+    /**
+     * Model tests for TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter
+     */
+    @Test
+    public void testTestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter() {
+        // TODO: test TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter
+    }
+
+    /**
+     * Test the property 'values'
+     */
+    @Test
+    public void valuesTest() {
+        // TODO: test values
+    }
+
+}
diff --git a/samples/client/petstore/java/resttemplate-swagger1/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/resttemplate-swagger1/src/main/java/org/openapitools/client/ApiClient.java
index dc250a75c79f2797dc7d7abbd0d02cc854d160f3..561e27b4db026b84817c4c35f5677ae6246527d0 100644
--- a/samples/client/petstore/java/resttemplate-swagger1/src/main/java/org/openapitools/client/ApiClient.java
+++ b/samples/client/petstore/java/resttemplate-swagger1/src/main/java/org/openapitools/client/ApiClient.java
@@ -597,16 +597,18 @@ public class ApiClient extends JavaTimeFormatter {
         Map<String,Object> uriParams = new HashMap<>();
         uriParams.putAll(pathParams);
 
-        String finalUri = path;
+        String queryUri = null;
 
         if (queryParams != null && !queryParams.isEmpty()) {
             //Include queryParams in uriParams taking into account the paramName
-            String queryUri = generateQueryUri(queryParams, uriParams);
-            //Append to finalUri the templatized query string like "?param1={param1Value}&.......
-            finalUri += "?" + queryUri;
-        }
-        String expandedPath = this.expandPath(finalUri, uriParams);
-        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(expandedPath);
+            String query = generateQueryUri(queryParams, uriParams);
+            queryUri = expandPath("?" + query, uriParams).substring(1); //exclude the '?'
+            //queryUri is the templatized query string like "?param1={param1Value}&.......
+        }
+        String expandedPath = this.expandPath(path, uriParams);
+        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath)
+                .path(expandedPath)
+                .query(queryUri);
 
         URI uri;
         try {
diff --git a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/ApiClient.java
index 8340b6cfa8ef2c60f2d348325bbe5785d7a12098..d96ed08a5cc87bd9564ab5fe1df2459b73875919 100644
--- a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/ApiClient.java
+++ b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/ApiClient.java
@@ -634,16 +634,18 @@ public class ApiClient extends JavaTimeFormatter {
         Map<String,Object> uriParams = new HashMap<>();
         uriParams.putAll(pathParams);
 
-        String finalUri = path;
+        String queryUri = null;
 
         if (queryParams != null && !queryParams.isEmpty()) {
             //Include queryParams in uriParams taking into account the paramName
-            String queryUri = generateQueryUri(queryParams, uriParams);
-            //Append to finalUri the templatized query string like "?param1={param1Value}&.......
-            finalUri += "?" + queryUri;
-        }
-        String expandedPath = this.expandPath(finalUri, uriParams);
-        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(expandedPath);
+            String query = generateQueryUri(queryParams, uriParams);
+            queryUri = expandPath("?" + query, uriParams).substring(1); //exclude the '?'
+            //queryUri is the templatized query string like "?param1={param1Value}&.......
+        }
+        String expandedPath = this.expandPath(path, uriParams);
+        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath)
+                .path(expandedPath)
+                .query(queryUri);
 
         URI uri;
         try {
diff --git a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/ApiClient.java
index b1d9b1cf1d262537066dfbc1484a4fbf53df2928..e75299e540be045396c1a766fef62f4604be9fe7 100644
--- a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/ApiClient.java
+++ b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/ApiClient.java
@@ -629,16 +629,18 @@ public class ApiClient extends JavaTimeFormatter {
         Map<String,Object> uriParams = new HashMap<>();
         uriParams.putAll(pathParams);
 
-        String finalUri = path;
+        String queryUri = null;
 
         if (queryParams != null && !queryParams.isEmpty()) {
             //Include queryParams in uriParams taking into account the paramName
-            String queryUri = generateQueryUri(queryParams, uriParams);
-            //Append to finalUri the templatized query string like "?param1={param1Value}&.......
-            finalUri += "?" + queryUri;
-        }
-        String expandedPath = this.expandPath(finalUri, uriParams);
-        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(expandedPath);
+            String query = generateQueryUri(queryParams, uriParams);
+            queryUri = expandPath("?" + query, uriParams).substring(1); //exclude the '?'
+            //queryUri is the templatized query string like "?param1={param1Value}&.......
+        }
+        String expandedPath = this.expandPath(path, uriParams);
+        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath)
+                .path(expandedPath)
+                .query(queryUri);
 
         URI uri;
         try {