{"id":138867,"date":"2025-11-17T18:22:00","date_gmt":"2025-11-17T16:22:00","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=138867"},"modified":"2025-11-17T17:10:27","modified_gmt":"2025-11-17T15:10:27","slug":"http-client-from-openapi-spec-and-spring-boot-example","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html","title":{"rendered":"HTTP Client From OpenAPI Spec And Spring Boot Example"},"content":{"rendered":"<h2 class=\"wp-block-heading\">1. Introduction<\/h2>\n<p>OpenAPI ( formerly Swagger) provides a standard way to describe Rest APIs and <a href=\"https:\/\/openapi-generator.tech\/\" target=\"_blank\" rel=\"noreferrer noopener\">OpenAPI Generator tool<\/a> to generate http client from openapi spec. The generator tool takes an OpenAPI specification, then uses the selected generator (e.g., <code>java<\/code>), library (e.g., <code>webclient<\/code>), and config options to fill <a href=\"https:\/\/mustache.github.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Mustache template<\/a> files with API metadata and models, producing fully generated source code tailored to that setup. In this example, I will demonstrate how to generate HTTP Client source code from an OpenAPI Spec <a href=\"https:\/\/www.ibm.com\/think\/topics\/yaml\" target=\"_blank\" rel=\"noreferrer noopener\">YAML<\/a> file in a Gradle project.<\/p>\n<h2 class=\"wp-block-heading\">2. Setup<\/h2>\n<h3 class=\"wp-block-heading\">2.1 An OpenAPI Spec YAML File<\/h3>\n<p>In this step, I will create a &#8220;<code>demoApi.yaml<\/code>&#8221; file that describes a <code>User<\/code> API for <code>POST<\/code>, <code>GET<\/code> APIs.<\/p>\n<p><span style=\"text-decoration: underline\"><em>demoApi.yaml<\/em><\/span><\/p>\n<pre class=\"brush:plain;highlight:[15,16,33,54,79]\">openapi: 3.0.0\ninfo:\n  title: Sample User API\n  description: This is a sample API for managing users.\n  version: 1.0.0\nservers:\n  - url: https:\/\/api.example.com\/v1\n    description: Production server\n  - url: https:\/\/staging.example.com\/v1\n    description: Staging server\ntags:\n  - name: users\n    description: Operations related to users\npaths:\n  \/users:\n    get:\n      tags:\n        - users\n      summary: Get all users\n      operationId: getUsers\n      description: Retrieves a list of all registered users.\n      responses:\n        '200':\n          description: A list of users\n          content:\n            application\/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#\/components\/schemas\/User'\n        '500':\n          description: Internal server error\n    post:\n      tags:\n        - users\n      summary: Create a new user\n      operationId: createUser\n      description: Creates a new user with the provided details.\n      requestBody:\n        required: true\n        content:\n          application\/json:\n            schema:\n              $ref: '#\/components\/schemas\/User'\n      responses:\n        '201':\n          description: User created successfully\n          content:\n            application\/json:\n              schema:\n                $ref: '#\/components\/schemas\/User'\n        '400':\n          description: Invalid input\n  \/users\/{userId}:\n    get:\n      tags:\n        - users\n      summary: Get user by ID\n      operationId: getUserById\n      description: Retrieves a single user by their ID.\n      parameters:\n        - in: path\n          name: userId\n          schema:\n            type: string\n          required: true\n          description: The ID of the user to retrieve.\n      responses:\n        '200':\n          description: User found\n          content:\n            application\/json:\n              schema:\n                $ref: '#\/components\/schemas\/User'\n        '404':\n          description: User not found\ncomponents:\n  schemas:\n    User:\n      type: object\n      properties:\n        id:\n          type: string\n          format: uuid\n          description: Unique identifier for the user.\n        name:\n          type: string\n          description: Name of the user.\n        email:\n          type: string\n          format: email\n          description: Email address of the user.\n      required:\n        - id\n        - name\n        - email\n   <\/pre>\n<ul class=\"wp-block-list\">\n<li>Line 15,16: GET <strong>\/users<\/strong> to fetch all users.<\/li>\n<li>Line 33: POST <strong>\/users<\/strong> to create a new user<\/li>\n<li>Line 54, 55: GET \/<strong>users\/{id}<\/strong> to retrieve a user by ID<\/li>\n<li>Line 79: a <code>User<\/code> schema.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">2.2 Build.gradle<\/h3>\n<p>In this step, I will edit the &#8220;<code>build.gradle<\/code>&#8221; file to generate HTTP <code>WebClient<\/code> via the &#8220;<code>org.openapi.generator<\/code>&#8221; plugin..<\/p>\n<p><span style=\"text-decoration: underline\"><em>build.gradle<\/em><\/span><\/p>\n<pre class=\"brush:plain; highlight:[5,22,24,25,26,27,28,29,30,31,32,33,34,35,36,57,64]\">plugins {\n\tid 'java'\n\tid 'org.springframework.boot' version '3.5.7'\n\tid 'io.spring.dependency-management' version '1.1.7'\n\tid 'org.openapi.generator' version '7.5.0'\n}\n\ngroup = 'org.jcg.zheng.demo'\nversion = '0.0.1-SNAPSHOT'\ndescription = 'Demo project for Spring Boot'\n\njava {\n\ttoolchain {\n\t\tlanguageVersion = JavaLanguageVersion.of(21)\n\t}\n}\n\nrepositories {\n\tmavenCentral()\n}\n\ndef openApiOutputDir = \"$buildDir\/generated\"\n\ntask openApiGenerateJavaWebClient( type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {\n    inputSpec = file(\"$projectDir\/src\/main\/resources\/demoApi.yaml\").path\n    outputDir = \"${openApiOutputDir}\/java\/webclient\"\n    apiPackage = \"org.jcg.zheng.demo.javawebclient.api\"\n    modelPackage = \"org.jcg.zheng.demo.javawebclient.model\"\n \tgeneratorName = \"java\" \/\/general-purpose java client library \n    library = \"webclient\" \/\/other options: webclient, resttemplate, feign, jersey2\n    enablePostProcessFile = true\n    configOptions = [\n                      useJakartaEe: \"true\",\n                      dateLibrary: \"java8\",\n                      reactive: \"false\",\n                      hideGenerationTimestamp: \"true\"\n                    ]\n}\n\ndependencies {\n\timplementation 'org.springframework.boot:spring-boot-starter-web'\n\timplementation 'org.springframework.boot:spring-boot-starter-validation'\n\t\n\t\/\/here are dependencies for webclient\n\timplementation 'org.springframework.boot:spring-boot-starter-webflux'\n\timplementation 'org.openapitools:jackson-databind-nullable:0.2.6'\n\t\n\ttestImplementation 'org.springframework.boot:spring-boot-starter-test'\n\ttestRuntimeOnly 'org.junit.platform:junit-platform-launcher'\n}\n\ntasks.named('test') {\n\tuseJUnitPlatform()\n}\n\ntasks.named('compileJava') {    \n    dependsOn(tasks.openApiGenerateJavaWebClient)\n    source(\"$buildDir\/generated\/src\/main\/java\")\n}\n\nsourceSets{\n    main {        \n        java {            \n            srcDir(\"${openApiOutputDir}\/java\/webclient\/src\/main\/java\")\n        }\n    }\n\n}\n\n<\/pre>\n<ul class=\"wp-block-list\">\n<li>Line 5: imports the &#8220;<code>org.openapi.generator<\/code>&#8221; plugin.<\/li>\n<li>Line 22: defines the <code>openApiOutputDir<\/code> to <code>\"$buildDir\/generated\"<\/code>.<\/li>\n<li>Line 24: defines the <code>openApiGenerateJavaWebClient<\/code> task to generate <code>webclient<\/code><\/li>\n<li>Line 25: sets the <code>inputSpec<\/code> file path.<\/li>\n<li>Line 26: sets up the <code>outputDir<\/code>.<\/li>\n<li>Line 27: sets the <code>apiPackage<\/code> name. <strong>Note<\/strong>: the best practice is to name it as the project&#8217;s base package.<\/li>\n<li>Line 28: sets the <code>modelPackage<\/code> name.<\/li>\n<li>Line 29: sets the <code>generatorName=java <\/code> for general-purpose java client.<\/li>\n<li>Line 30: sets the library to <code>webclient<\/code> for generating Spring WebFlux <code>WebClient<\/code>.<\/li>\n<li>Line 32: sets additional configuration options.<\/li>\n<li>Line 57: invokes the <code>openApiGeneratorJavaWebClient<\/code> before the <code>compileJava<\/code> task.<\/li>\n<li>Line 64: adds the generated source directory to the <code>sourceSets<\/code>.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">2.3 HttpclientWebclientApplication<\/h3>\n<p>No change to the generated <code>HttpclientWebclientApplication.java<\/code> class.<\/p>\n<p><span style=\"text-decoration: underline\"><em>HttpclientWebclientApplication.java<\/em><\/span><\/p>\n<pre class=\"brush:java\">package org.jcg.zheng.demo.httpclient_webclient;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class HttpclientWebclientApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(HttpclientWebclientApplication.class, args);\n\t}\n}\n<\/pre>\n<h2 class=\"wp-block-heading\">3. Generate HTTP Client from Openapi Spec.<\/h2>\n<p>In this step, I will execute the <code>gradlew build<\/code> command to generate the HTTP <code>WebClient<\/code>.<\/p>\n<p><span style=\"text-decoration: underline\"><em>gradlew build output<\/em><\/span><\/p>\n<pre class=\"brush:plain; highlight:[9]\">C:\\MaryZheng\\workspace\\httpclient-webclient&gt;gradlew build\n\n&gt; Task :openApiGenerateJavaWebClient\n################################################################################\n# Thanks for using OpenAPI Generator.                                          #\n# Please consider donation to help us maintain this project \u2261\u0192\u00d6\u00c5                 #\n# https:\/\/opencollective.com\/openapi_generator\/donate                          #\n################################################################################\nSuccessfully generated code to C:\\MaryZheng\\workspace\\httpclient-webclient\\build\/generated\/java\/webclient\n\n&gt; Task :compileJava\nNote: C:\\MaryZheng\\workspace\\httpclient-webclient\\build\\generated\\java\\webclient\\src\\main\\java\\org\\jcg\\zheng\\demo\\javawebclient\\ApiClient.java uses or overrides a deprecated API.\nNote: Recompile with -Xlint:deprecation for details.\nJava HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended\n\n[Incubating] Problems report is available at: file:\/\/\/C:\/MaryZheng\/workspace\/httpclient-webclient\/build\/reports\/problems\/problems-report.html\n\nBUILD SUCCESSFUL in 9s\n8 actionable tasks: 8 executed\nC:\\MaryZheng\\workspace\\httpclient-webclient&gt;<\/pre>\n<ul class=\"wp-block-list\">\n<li>Line 9: the source code is generated successfully.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">4. View Generated Files<\/h2>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/11\/projectPackages.jpg\"><img decoding=\"async\" width=\"402\" height=\"677\" src=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/11\/projectPackages.jpg\" alt=\"http client from openapi spec\" class=\"wp-image-138944\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/11\/projectPackages.jpg 402w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/11\/projectPackages-178x300.jpg 178w\" sizes=\"(max-width: 402px) 100vw, 402px\" \/><\/a><figcaption class=\"wp-element-caption\">Figure 1 Project Setting<\/figcaption><\/figure>\n<\/div>\n<p>Figure 1 shows four packages generated from the <code>gradlew build<\/code> command. <\/p>\n<p>We will review the following classes:<\/p>\n<ul class=\"wp-block-list\">\n<li><code>ApiClient.java<\/code>: this is the core helper class that wraps <code>org.springframework.web.reactive.function.client.WebClient<\/code> and manages HTTP communication, including creates and configures the Spring <code>WebClient<\/code> instance, handles JSON encoding\/decoding, converts Java objects to query\/form params, authentication, and error handling. All generated API classes(<code>UsersApi<\/code>, etc.) depend on it.<\/li>\n<li><code>UsersApi.java<\/code>: this is generated API client class that represents all HTTP operations(GET, POST, PUT, DELETE, etc.) based on the openApi Specification&#8217;s endpoints \u2014 e.g. <code>\/users<\/code>, <code>\/users\/{id}<\/code>.<\/li>\n<li><code>User.java<\/code>: this is <code>Plain Old Java Object(POJO)<\/code> generated from the OpenAPI schema definition for the <code>User<\/code> model.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">4.1 Generated ApiClient<\/h3>\n<p>In this step, I will view the generated <code>ApiClient.java<\/code> class.<\/p>\n<p><span style=\"text-decoration: underline\"><em>ApiClient.java<\/em><\/span><\/p>\n<pre class=\"brush:java\">package org.jcg.zheng.demo.javawebclient;\n\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;\nimport org.openapitools.jackson.nullable.JsonNullableModule;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.InvalidMediaTypeException;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.RequestEntity;\nimport org.springframework.http.RequestEntity.BodyBuilder;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.client.BufferingClientHttpRequestFactory;\nimport org.springframework.http.client.ClientHttpRequestExecution;\nimport org.springframework.http.client.ClientHttpRequestInterceptor;\nimport org.springframework.http.client.ClientHttpResponse;\nimport org.springframework.http.codec.json.Jackson2JsonDecoder;\nimport org.springframework.http.codec.json.Jackson2JsonEncoder;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\nimport org.springframework.util.StringUtils;\nimport org.springframework.http.client.reactive.ClientHttpRequest;\nimport org.springframework.web.client.RestClientException;\nimport org.springframework.web.util.UriComponentsBuilder;\nimport org.springframework.web.reactive.function.client.WebClient;\nimport org.springframework.web.reactive.function.client.WebClient.ResponseSpec;\nimport org.springframework.web.reactive.function.client.ClientResponse;\nimport org.springframework.web.reactive.function.BodyInserter;\nimport org.springframework.web.reactive.function.BodyInserters;\nimport org.springframework.web.reactive.function.client.ExchangeStrategies;\nimport reactor.core.publisher.Mono;\nimport reactor.core.publisher.Flux;\nimport java.util.Optional;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.UnsupportedEncodingException;\nimport java.net.URLEncoder;\nimport java.nio.charset.StandardCharsets;\nimport java.text.DateFormat;\nimport java.text.ParseException;\nimport java.util.Arrays;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.TimeZone;\n\nimport jakarta.annotation.Nullable;\n\nimport java.time.OffsetDateTime;\n\nimport org.jcg.zheng.demo.javawebclient.auth.Authentication;\nimport org.jcg.zheng.demo.javawebclient.auth.HttpBasicAuth;\nimport org.jcg.zheng.demo.javawebclient.auth.HttpBearerAuth;\nimport org.jcg.zheng.demo.javawebclient.auth.ApiKeyAuth;\n\n@jakarta.annotation.Generated(value = \"org.openapitools.codegen.languages.JavaClientCodegen\", comments = \"Generator version: 7.5.0\")\npublic class ApiClient extends JavaTimeFormatter {\n    public enum CollectionFormat {\n        CSV(\",\"), TSV(\"\\t\"), SSV(\" \"), PIPES(\"|\"), MULTI(null);\n\n        private final String separator;\n        private CollectionFormat(String separator) {\n            this.separator = separator;\n        }\n\n        private String collectionToString(Collection&lt;?&gt; collection) {\n            return StringUtils.collectionToDelimitedString(collection, separator);\n        }\n    }\n\n    private static final String URI_TEMPLATE_ATTRIBUTE = WebClient.class.getName() + \".uriTemplate\";\n\n    private HttpHeaders defaultHeaders = new HttpHeaders();\n    private MultiValueMap&lt;String, String&gt; defaultCookies = new LinkedMultiValueMap&lt;String, String&gt;();\n\n    private String basePath = \"https:\/\/api.example.com\/v1\";\n\n    private final WebClient webClient;\n    private final DateFormat dateFormat;\n    private final ObjectMapper objectMapper;\n\n    private Map&lt;String, Authentication&gt; authentications;\n\n\n    public ApiClient() {\n        this.dateFormat = createDefaultDateFormat();\n        this.objectMapper = createDefaultObjectMapper(this.dateFormat);\n        this.webClient = buildWebClient(this.objectMapper);\n        this.init();\n    }\n\n    public ApiClient(WebClient webClient) {\n        this(Optional.ofNullable(webClient).orElseGet(() -&gt; buildWebClient()), createDefaultDateFormat());\n    }\n\n    public ApiClient(ObjectMapper mapper, DateFormat format) {\n        this(buildWebClient(mapper.copy()), format);\n    }\n\n    public ApiClient(WebClient webClient, ObjectMapper mapper, DateFormat format) {\n        this(Optional.ofNullable(webClient).orElseGet(() -&gt; buildWebClient(mapper.copy())), format);\n    }\n\n    private ApiClient(WebClient webClient, DateFormat format) {\n        this.webClient = webClient;\n        this.dateFormat = format;\n        this.objectMapper = createDefaultObjectMapper(format);\n        this.init();\n    }\n\n    public static DateFormat createDefaultDateFormat() {\n        DateFormat dateFormat = new RFC3339DateFormat();\n        dateFormat.setTimeZone(TimeZone.getTimeZone(\"UTC\"));\n        return dateFormat;\n    }\n\n    public static ObjectMapper createDefaultObjectMapper(@Nullable DateFormat dateFormat) {\n        if (null == dateFormat) {\n            dateFormat = createDefaultDateFormat();\n        }\n        ObjectMapper mapper = new ObjectMapper();\n        mapper.setDateFormat(dateFormat);\n        mapper.registerModule(new JavaTimeModule());\n        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);\n        JsonNullableModule jnm = new JsonNullableModule();\n        mapper.registerModule(jnm);\n        return mapper;\n    }\n\n    protected void init() {\n        \/\/ Setup authentications (key: authentication name, value: authentication).\n        authentications = new HashMap&lt;String, Authentication&gt;();\n        \/\/ Prevent the authentications from being modified.\n        authentications = Collections.unmodifiableMap(authentications);\n    }\n\n    \/**\n    * Build the WebClientBuilder used to make WebClient.\n    * @param mapper ObjectMapper used for serialize\/deserialize\n    * @return WebClient\n    *\/\n    public static WebClient.Builder buildWebClientBuilder(ObjectMapper mapper) {\n        ExchangeStrategies strategies = ExchangeStrategies\n            .builder()\n            .codecs(clientDefaultCodecsConfigurer -&gt; {\n                clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(mapper, MediaType.APPLICATION_JSON));\n                clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper, MediaType.APPLICATION_JSON));\n            }).build();\n        WebClient.Builder webClientBuilder = WebClient.builder().exchangeStrategies(strategies);\n        return webClientBuilder;\n    }\n\n    \/**\n     * Build the WebClientBuilder used to make WebClient.\n     * @return WebClient\n     *\/\n    public static WebClient.Builder buildWebClientBuilder() {\n        return buildWebClientBuilder(createDefaultObjectMapper(null));\n    }\n\n    \/**\n     * Build the WebClient used to make HTTP requests.\n     * @param mapper ObjectMapper used for serialize\/deserialize\n     * @return WebClient\n     *\/\n    public static WebClient buildWebClient(ObjectMapper mapper) {\n        return buildWebClientBuilder(mapper).build();\n    }\n\n    \/**\n     * Build the WebClient used to make HTTP requests.\n     * @return WebClient\n     *\/\n    public static WebClient buildWebClient() {\n        return buildWebClientBuilder(createDefaultObjectMapper(null)).build();\n    }\n\n    \/**\n     * Get the current base path\n     * @return String the base path\n     *\/\n    public String getBasePath() {\n        return basePath;\n    }\n\n    \/**\n     * Set the base path, which should include the host\n     * @param basePath the base path\n     * @return ApiClient this client\n     *\/\n    public ApiClient setBasePath(String basePath) {\n        this.basePath = basePath;\n        return this;\n    }\n\n    \/**\n     * Get authentications (key: authentication name, value: authentication).\n     * @return Map the currently configured authentication types\n     *\/\n    public Map&lt;String, Authentication&gt; getAuthentications() {\n        return authentications;\n    }\n\n    \/**\n     * Get authentication for the given name.\n     *\n     * @param authName The authentication name\n     * @return The authentication, null if not found\n     *\/\n    public Authentication getAuthentication(String authName) {\n        return authentications.get(authName);\n    }\n\n    \/**\n     * Helper method to set access token for the first Bearer authentication.\n     * @param bearerToken Bearer token\n     *\/\n    public void setBearerToken(String bearerToken) {\n        for (Authentication auth : authentications.values()) {\n            if (auth instanceof HttpBearerAuth) {\n                ((HttpBearerAuth) auth).setBearerToken(bearerToken);\n                return;\n            }\n        }\n        throw new RuntimeException(\"No Bearer authentication configured!\");\n    }\n\n    \/**\n     * Helper method to set username for the first HTTP basic authentication.\n     * @param username the username\n     *\/\n    public void setUsername(String username) {\n        for (Authentication auth : authentications.values()) {\n            if (auth instanceof HttpBasicAuth) {\n                ((HttpBasicAuth) auth).setUsername(username);\n                return;\n            }\n        }\n        throw new RuntimeException(\"No HTTP basic authentication configured!\");\n    }\n\n    \/**\n     * Helper method to set password for the first HTTP basic authentication.\n     * @param password the password\n     *\/\n    public void setPassword(String password) {\n        for (Authentication auth : authentications.values()) {\n            if (auth instanceof HttpBasicAuth) {\n                ((HttpBasicAuth) auth).setPassword(password);\n                return;\n            }\n        }\n        throw new RuntimeException(\"No HTTP basic authentication configured!\");\n    }\n\n    \/**\n     * Helper method to set API key value for the first API key authentication.\n     * @param apiKey the API key\n     *\/\n    public void setApiKey(String apiKey) {\n        for (Authentication auth : authentications.values()) {\n            if (auth instanceof ApiKeyAuth) {\n                ((ApiKeyAuth) auth).setApiKey(apiKey);\n                return;\n            }\n        }\n        throw new RuntimeException(\"No API key authentication configured!\");\n    }\n\n    \/**\n     * Helper method to set API key prefix for the first API key authentication.\n     * @param apiKeyPrefix the API key prefix\n     *\/\n    public void setApiKeyPrefix(String apiKeyPrefix) {\n        for (Authentication auth : authentications.values()) {\n            if (auth instanceof ApiKeyAuth) {\n                ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);\n                return;\n            }\n        }\n        throw new RuntimeException(\"No API key authentication configured!\");\n    }\n\n    \/**\n     * Set the User-Agent header's value (by adding to the default header map).\n     * @param userAgent the user agent string\n     * @return ApiClient this client\n     *\/\n    public ApiClient setUserAgent(String userAgent) {\n        addDefaultHeader(\"User-Agent\", userAgent);\n        return this;\n    }\n\n    \/**\n     * Add a default header.\n     *\n     * @param name The header's name\n     * @param value The header's value\n     * @return ApiClient this client\n     *\/\n    public ApiClient addDefaultHeader(String name, String value) {\n        if (defaultHeaders.containsKey(name)) {\n            defaultHeaders.remove(name);\n        }\n        defaultHeaders.add(name, value);\n        return this;\n    }\n\n    \/**\n     * Add a default cookie.\n     *\n     * @param name The cookie's name\n     * @param value The cookie's value\n     * @return ApiClient this client\n     *\/\n    public ApiClient addDefaultCookie(String name, String value) {\n        if (defaultCookies.containsKey(name)) {\n            defaultCookies.remove(name);\n        }\n        defaultCookies.add(name, value);\n        return this;\n    }\n\n    \/**\n     * Get the date format used to parse\/format date parameters.\n     * @return DateFormat format\n     *\/\n    public DateFormat getDateFormat() {\n        return dateFormat;\n    }\n\n    \/**\n     * Parse the given string into Date object.\n     *\/\n    public Date parseDate(String str) {\n        try {\n            return dateFormat.parse(str);\n        } catch (ParseException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    \/**\n     * Format the given Date object into string.\n     *\/\n    public String formatDate(Date date) {\n        return dateFormat.format(date);\n    }\n\n    \/**\n     * Get the ObjectMapper used to make HTTP requests.\n     * @return ObjectMapper objectMapper\n     *\/\n    public ObjectMapper getObjectMapper() {\n        return objectMapper;\n    }\n\n    \/**\n     * Get the WebClient used to make HTTP requests.\n     * @return WebClient webClient\n     *\/\n    public WebClient getWebClient() {\n        return webClient;\n    }\n\n    \/**\n     * Format the given parameter object into string.\n     * @param param the object to convert\n     * @return String the parameter represented as a String\n     *\/\n    public String parameterToString(Object param) {\n        if (param == null) {\n            return \"\";\n        } else if (param instanceof Date) {\n            return formatDate( (Date) param);\n        } else if (param instanceof OffsetDateTime) {\n            return formatOffsetDateTime((OffsetDateTime) param);\n        } else if (param instanceof Collection) {\n            StringBuilder b = new StringBuilder();\n            for(Object o : (Collection&lt;?&gt;) param) {\n                if(b.length() &gt; 0) {\n                    b.append(\",\");\n                }\n                b.append(String.valueOf(o));\n            }\n            return b.toString();\n        } else {\n            return String.valueOf(param);\n        }\n    }\n\n    \/**\n     * Converts a parameter to a {@link MultiValueMap} for use in REST requests\n     * @param collectionFormat The format to convert to\n     * @param name The name of the parameter\n     * @param value The parameter's value\n     * @return a Map containing the String value(s) of the input parameter\n     *\/\n    public MultiValueMap&lt;String, String&gt; parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) {\n        final MultiValueMap&lt;String, String&gt; params = new LinkedMultiValueMap&lt;String, String&gt;();\n\n        if (name == null || name.isEmpty() || value == null) {\n            return params;\n        }\n\n        if(collectionFormat == null) {\n            collectionFormat = CollectionFormat.CSV;\n        }\n\n        if (value instanceof Map) {\n            @SuppressWarnings(\"unchecked\")\n            final Map&lt;String, Object&gt; valuesMap = (Map&lt;String, Object&gt;) value;\n            for (final Entry&lt;String, Object&gt; entry : valuesMap.entrySet()) {\n                params.add(entry.getKey(), parameterToString(entry.getValue()));\n            }\n            return params;\n        }\n\n        Collection&lt;?&gt; valueCollection = null;\n        if (value instanceof Collection) {\n            valueCollection = (Collection&lt;?&gt;) value;\n        } else {\n            params.add(name, parameterToString(value));\n            return params;\n        }\n\n        if (valueCollection.isEmpty()){\n            return params;\n        }\n\n        if (collectionFormat.equals(CollectionFormat.MULTI)) {\n            for (Object item : valueCollection) {\n                params.add(name, parameterToString(item));\n            }\n            return params;\n        }\n\n        List&lt;String&gt; values = new ArrayList&lt;String&gt;();\n        for(Object o : valueCollection) {\n            values.add(parameterToString(o));\n        }\n        params.add(name, collectionFormat.collectionToString(values));\n\n        return params;\n    }\n\n    \/**\n    * Check if the given {@code String} is a JSON MIME.\n    * @param mediaType the input MediaType\n    * @return boolean true if the MediaType represents JSON, false otherwise\n    *\/\n    public boolean isJsonMime(String mediaType) {\n        \/\/ \"* \/ *\" is default to JSON\n        if (\"*\/*\".equals(mediaType)) {\n            return true;\n        }\n\n        try {\n            return isJsonMime(MediaType.parseMediaType(mediaType));\n        } catch (InvalidMediaTypeException e) {\n        }\n        return false;\n    }\n\n    \/**\n     * Check if the given MIME is a JSON MIME.\n     * JSON MIME examples:\n     *     application\/json\n     *     application\/json; charset=UTF8\n     *     APPLICATION\/JSON\n     * @param mediaType the input MediaType\n     * @return boolean true if the MediaType represents JSON, false otherwise\n     *\/\n    public boolean isJsonMime(MediaType mediaType) {\n        return mediaType != null &amp;&amp; (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches(\"^.*(\\\\+json|ndjson)[;]?\\\\s*$\"));\n    }\n\n    \/**\n    * Check if the given {@code String} is a Problem JSON MIME (RFC-7807).\n    * @param mediaType the input MediaType\n    * @return boolean true if the MediaType represents Problem JSON, false otherwise\n    *\/\n    public boolean isProblemJsonMime(String mediaType) {\n        return \"application\/problem+json\".equalsIgnoreCase(mediaType);\n    }\n\n    \/**\n     * Select the Accept header's value from the given accepts array:\n     *     if JSON exists in the given array, use it;\n     *     otherwise use all of them (joining into a string)\n     *\n     * @param accepts The accepts array to select from\n     * @return List The list of MediaTypes to use for the Accept header\n     *\/\n    public List&lt;MediaType&gt; selectHeaderAccept(String[] accepts) {\n        if (accepts.length == 0) {\n            return null;\n        }\n        for (String accept : accepts) {\n            MediaType mediaType = MediaType.parseMediaType(accept);\n            if (isJsonMime(mediaType) &amp;&amp; !isProblemJsonMime(accept)) {\n                return Collections.singletonList(mediaType);\n            }\n        }\n        return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts));\n    }\n\n    \/**\n     * Select the Content-Type header's value from the given array:\n     *     if JSON exists in the given array, use it;\n     *     otherwise use the first one of the array.\n     *\n     * @param contentTypes The Content-Type array to select from\n     * @return MediaType The Content-Type header to use. If the given array is empty, null will be returned.\n     *\/\n    public MediaType selectHeaderContentType(String[] contentTypes) {\n        if (contentTypes.length == 0) {\n            return null;\n        }\n        for (String contentType : contentTypes) {\n            MediaType mediaType = MediaType.parseMediaType(contentType);\n            if (isJsonMime(mediaType)) {\n                return mediaType;\n            }\n        }\n        return MediaType.parseMediaType(contentTypes[0]);\n    }\n\n    \/**\n     * Select the body to use for the request\n     * @param obj the body object\n     * @param formParams the form parameters\n     * @param contentType the content type of the request\n     * @return Object the selected body\n     *\/\n    protected BodyInserter&lt;?, ? super ClientHttpRequest&gt; selectBody(Object obj, MultiValueMap&lt;String, Object&gt; formParams, MediaType contentType) {\n        if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {\n            MultiValueMap&lt;String, String&gt; map = new LinkedMultiValueMap&lt;&gt;();\n\n            formParams\n                    .toSingleValueMap()\n                    .entrySet()\n                    .forEach(es -&gt; map.add(es.getKey(), String.valueOf(es.getValue())));\n\n            return BodyInserters.fromFormData(map);\n        } else if(MediaType.MULTIPART_FORM_DATA.equals(contentType)) {\n            return BodyInserters.fromMultipartData(formParams);\n        } else {\n            return obj != null ? BodyInserters.fromValue(obj) : null;\n        }\n    }\n\n    \/**\n     * Invoke API by sending HTTP request with the given options.\n     *\n     * @param &lt;T&gt; the return type to use\n     * @param path The sub-path of the HTTP URL\n     * @param method The request method\n     * @param pathParams The path parameters\n     * @param queryParams The query parameters\n     * @param body The request body object\n     * @param headerParams The header parameters\n     * @param formParams The form parameters\n     * @param accept The request's Accept header\n     * @param contentType The request's Content-Type header\n     * @param authNames The authentications to apply\n     * @param returnType The return type into which to deserialize the response\n     * @return The response body in chosen type\n     *\/\n    public &lt;T&gt; ResponseSpec invokeAPI(String path, HttpMethod method, Map&lt;String, Object&gt; pathParams, MultiValueMap&lt;String, String&gt; queryParams, Object body, HttpHeaders headerParams, MultiValueMap&lt;String, String&gt; cookieParams, MultiValueMap&lt;String, Object&gt; formParams, List&lt;MediaType&gt; accept, MediaType contentType, String[] authNames, ParameterizedTypeReference&lt;T&gt; returnType) throws RestClientException {\n        final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames);\n        return requestBuilder.retrieve();\n    }\n\n    \/**\n     * Include queryParams in uriParams taking into account the paramName\n     * @param queryParams The query parameters\n     * @param uriParams The path parameters\n     * return templatized query string\n     *\/\n    private String generateQueryUri(MultiValueMap&lt;String, String&gt; queryParams, Map&lt;String, Object&gt; uriParams) {\n        StringBuilder queryBuilder = new StringBuilder();\n        queryParams.forEach((name, values) -&gt; {\n            if (CollectionUtils.isEmpty(values)) {\n                if (queryBuilder.length() != 0) {\n                    queryBuilder.append('&amp;');\n                }\n                queryBuilder.append(name);\n            } else {\n                int valueItemCounter = 0;\n                for (Object value : values) {\n                    if (queryBuilder.length() != 0) {\n                        queryBuilder.append('&amp;');\n                    }\n                    queryBuilder.append(name);\n                    if (value != null) {\n                        String templatizedKey = name + valueItemCounter++;\n                        uriParams.put(templatizedKey, value.toString());\n                        queryBuilder.append('=').append(\"{\").append(templatizedKey).append(\"}\");\n                    }\n                }\n            }\n        });\n        return queryBuilder.toString();\n    }\n\n    private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, Map&lt;String, Object&gt; pathParams,\n        MultiValueMap&lt;String, String&gt; queryParams, Object body, HttpHeaders headerParams,\n        MultiValueMap&lt;String, String&gt; cookieParams, MultiValueMap&lt;String, Object&gt; formParams, List&lt;MediaType&gt; accept,\n        MediaType contentType, String[] authNames) {\n        updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);\n\n        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path);\n\n        String finalUri = builder.build(false).toUriString();\n        Map&lt;String, Object&gt; uriParams = new HashMap&lt;&gt;();\n        uriParams.putAll(pathParams);\n\n        if (queryParams != null &amp;&amp; !queryParams.isEmpty()) {\n            \/\/Include queryParams in uriParams taking into account the paramName\n            String queryUri = generateQueryUri(queryParams, uriParams);\n            \/\/Append to finalUri the templatized query string like \"?param1={param1Value}&amp;.......\n            finalUri += \"?\" + queryUri;\n        }\n\n        final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(finalUri, uriParams);\n\n        if (accept != null) {\n            requestBuilder.accept(accept.toArray(new MediaType[accept.size()]));\n        }\n        if(contentType != null) {\n            requestBuilder.contentType(contentType);\n        }\n\n        addHeadersToRequest(headerParams, requestBuilder);\n        addHeadersToRequest(defaultHeaders, requestBuilder);\n        addCookiesToRequest(cookieParams, requestBuilder);\n        addCookiesToRequest(defaultCookies, requestBuilder);\n\n        requestBuilder.attribute(URI_TEMPLATE_ATTRIBUTE, path);\n\n        requestBuilder.body(selectBody(body, formParams, contentType));\n        return requestBuilder;\n    }\n\n    \/**\n     * Add headers to the request that is being built\n     * @param headers The headers to add\n     * @param requestBuilder The current request\n     *\/\n    protected void addHeadersToRequest(HttpHeaders headers, WebClient.RequestBodySpec requestBuilder) {\n        for (Entry&lt;String, List&lt;String&gt;&gt; entry : headers.entrySet()) {\n            List&lt;String&gt; values = entry.getValue();\n            for(String value : values) {\n                if (value != null) {\n                    requestBuilder.header(entry.getKey(), value);\n                }\n            }\n        }\n    }\n\n    \/**\n     * Add cookies to the request that is being built\n     * @param cookies The cookies to add\n     * @param requestBuilder The current request\n     *\/\n    protected void addCookiesToRequest(MultiValueMap&lt;String, String&gt; cookies, WebClient.RequestBodySpec requestBuilder) {\n        for (Entry&lt;String, List&lt;String&gt;&gt; entry : cookies.entrySet()) {\n            List&lt;String&gt; values = entry.getValue();\n            for(String value : values) {\n                if (value != null) {\n                    requestBuilder.cookie(entry.getKey(), value);\n                }\n            }\n        }\n    }\n\n    \/**\n     * Update query and header parameters based on authentication settings.\n     *\n     * @param authNames The authentications to apply\n     * @param queryParams The query parameters\n     * @param headerParams The header parameters\n     * @param cookieParams the cookie parameters\n     *\/\n    protected void updateParamsForAuth(String[] authNames, MultiValueMap&lt;String, String&gt; queryParams, HttpHeaders headerParams, MultiValueMap&lt;String, String&gt; cookieParams) {\n        for (String authName : authNames) {\n            Authentication auth = authentications.get(authName);\n            if (auth == null) {\n                throw new RestClientException(\"Authentication undefined: \" + authName);\n            }\n            auth.applyToParams(queryParams, headerParams, cookieParams);\n        }\n    }\n\n    \/**\n    * Formats the specified collection path parameter to a string value.\n    *\n    * @param collectionFormat The collection format of the parameter.\n    * @param values The values of the parameter.\n    * @return String representation of the parameter\n    *\/\n    public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection&lt;?&gt; values) {\n        \/\/ create the value based on the collection format\n        if (CollectionFormat.MULTI.equals(collectionFormat)) {\n            \/\/ not valid for path params\n            return parameterToString(values);\n        }\n\n         \/\/ collectionFormat is assumed to be \"csv\" by default\n        if(collectionFormat == null) {\n            collectionFormat = CollectionFormat.CSV;\n        }\n\n        return collectionFormat.collectionToString(values);\n    }\n}\n\n<\/pre>\n<ul class=\"wp-block-list\">\n<li>The generated <code>ApiClient<\/code> class has 731 lines.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">4.2 Generated UserApi<\/h3>\n<p>In this step, I will view the generated <code>UserApi.java<\/code> class.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p><span style=\"text-decoration: underline\"><em>UserApi.java<\/em><\/span><\/p>\n<pre class=\"brush:java\">package org.jcg.zheng.demo.javawebclient.api;\n\nimport org.jcg.zheng.demo.javawebclient.ApiClient;\n\nimport org.jcg.zheng.demo.javawebclient.model.User;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.web.reactive.function.client.WebClient.ResponseSpec;\nimport org.springframework.web.reactive.function.client.WebClientResponseException;\nimport org.springframework.core.io.FileSystemResource;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport reactor.core.publisher.Mono;\nimport reactor.core.publisher.Flux;\n\n@jakarta.annotation.Generated(value = \"org.openapitools.codegen.languages.JavaClientCodegen\", comments = \"Generator version: 7.5.0\")\npublic class UsersApi {\n    private ApiClient apiClient;\n\n    public UsersApi() {\n        this(new ApiClient());\n    }\n\n    @Autowired\n    public UsersApi(ApiClient apiClient) {\n        this.apiClient = apiClient;\n    }\n\n    public ApiClient getApiClient() {\n        return apiClient;\n    }\n\n    public void setApiClient(ApiClient apiClient) {\n        this.apiClient = apiClient;\n    }\n\n    \/**\n     * Create a new user\n     * Creates a new user with the provided details.\n     * &lt;p&gt;&lt;b&gt;201&lt;\/b&gt; - User created successfully\n     * &lt;p&gt;&lt;b&gt;400&lt;\/b&gt; - Invalid input\n     * @param user The user parameter\n     * @return User\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    private ResponseSpec createUserRequestCreation(User user) throws WebClientResponseException {\n        Object postBody = user;\n        \/\/ verify the required parameter 'user' is set\n        if (user == null) {\n            throw new WebClientResponseException(\"Missing the required parameter 'user' when calling createUser\", HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase(), null, null, null);\n        }\n        \/\/ create path and map variables\n        final Map&lt;String, Object&gt; pathParams = new HashMap&lt;String, Object&gt;();\n\n        final MultiValueMap&lt;String, String&gt; queryParams = new LinkedMultiValueMap&lt;String, String&gt;();\n        final HttpHeaders headerParams = new HttpHeaders();\n        final MultiValueMap&lt;String, String&gt; cookieParams = new LinkedMultiValueMap&lt;String, String&gt;();\n        final MultiValueMap&lt;String, Object&gt; formParams = new LinkedMultiValueMap&lt;String, Object&gt;();\n\n        final String[] localVarAccepts = { \n            \"application\/json\"\n        };\n        final List&lt;MediaType&gt; localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);\n        final String[] localVarContentTypes = { \n            \"application\/json\"\n        };\n        final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);\n\n        String[] localVarAuthNames = new String[] {  };\n\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return apiClient.invokeAPI(\"\/users\", HttpMethod.POST, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType);\n    }\n\n    \/**\n     * Create a new user\n     * Creates a new user with the provided details.\n     * &lt;p&gt;&lt;b&gt;201&lt;\/b&gt; - User created successfully\n     * &lt;p&gt;&lt;b&gt;400&lt;\/b&gt; - Invalid input\n     * @param user The user parameter\n     * @return User\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public Mono&lt;User&gt; createUser(User user) throws WebClientResponseException {\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return createUserRequestCreation(user).bodyToMono(localVarReturnType);\n    }\n\n    \/**\n     * Create a new user\n     * Creates a new user with the provided details.\n     * &lt;p&gt;&lt;b&gt;201&lt;\/b&gt; - User created successfully\n     * &lt;p&gt;&lt;b&gt;400&lt;\/b&gt; - Invalid input\n     * @param user The user parameter\n     * @return ResponseEntity&lt;User&gt;\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public Mono&lt;ResponseEntity&lt;User&gt;&gt; createUserWithHttpInfo(User user) throws WebClientResponseException {\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return createUserRequestCreation(user).toEntity(localVarReturnType);\n    }\n\n    \/**\n     * Create a new user\n     * Creates a new user with the provided details.\n     * &lt;p&gt;&lt;b&gt;201&lt;\/b&gt; - User created successfully\n     * &lt;p&gt;&lt;b&gt;400&lt;\/b&gt; - Invalid input\n     * @param user The user parameter\n     * @return ResponseSpec\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public ResponseSpec createUserWithResponseSpec(User user) throws WebClientResponseException {\n        return createUserRequestCreation(user);\n    }\n    \/**\n     * Get user by ID\n     * Retrieves a single user by their ID.\n     * &lt;p&gt;&lt;b&gt;200&lt;\/b&gt; - User found\n     * &lt;p&gt;&lt;b&gt;404&lt;\/b&gt; - User not found\n     * @param userId The ID of the user to retrieve.\n     * @return User\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    private ResponseSpec getUserByIdRequestCreation(String userId) throws WebClientResponseException {\n        Object postBody = null;\n        \/\/ verify the required parameter 'userId' is set\n        if (userId == null) {\n            throw new WebClientResponseException(\"Missing the required parameter 'userId' when calling getUserById\", HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase(), null, null, null);\n        }\n        \/\/ create path and map variables\n        final Map&lt;String, Object&gt; pathParams = new HashMap&lt;String, Object&gt;();\n\n        pathParams.put(\"userId\", userId);\n\n        final MultiValueMap&lt;String, String&gt; queryParams = new LinkedMultiValueMap&lt;String, String&gt;();\n        final HttpHeaders headerParams = new HttpHeaders();\n        final MultiValueMap&lt;String, String&gt; cookieParams = new LinkedMultiValueMap&lt;String, String&gt;();\n        final MultiValueMap&lt;String, Object&gt; formParams = new LinkedMultiValueMap&lt;String, Object&gt;();\n\n        final String[] localVarAccepts = { \n            \"application\/json\"\n        };\n        final List&lt;MediaType&gt; localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);\n        final String[] localVarContentTypes = { };\n        final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);\n\n        String[] localVarAuthNames = new String[] {  };\n\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return apiClient.invokeAPI(\"\/users\/{userId}\", HttpMethod.GET, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType);\n    }\n\n    \/**\n     * Get user by ID\n     * Retrieves a single user by their ID.\n     * &lt;p&gt;&lt;b&gt;200&lt;\/b&gt; - User found\n     * &lt;p&gt;&lt;b&gt;404&lt;\/b&gt; - User not found\n     * @param userId The ID of the user to retrieve.\n     * @return User\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public Mono&lt;User&gt; getUserById(String userId) throws WebClientResponseException {\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return getUserByIdRequestCreation(userId).bodyToMono(localVarReturnType);\n    }\n\n    \/**\n     * Get user by ID\n     * Retrieves a single user by their ID.\n     * &lt;p&gt;&lt;b&gt;200&lt;\/b&gt; - User found\n     * &lt;p&gt;&lt;b&gt;404&lt;\/b&gt; - User not found\n     * @param userId The ID of the user to retrieve.\n     * @return ResponseEntity&lt;User&gt;\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public Mono&lt;ResponseEntity&lt;User&gt;&gt; getUserByIdWithHttpInfo(String userId) throws WebClientResponseException {\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return getUserByIdRequestCreation(userId).toEntity(localVarReturnType);\n    }\n\n    \/**\n     * Get user by ID\n     * Retrieves a single user by their ID.\n     * &lt;p&gt;&lt;b&gt;200&lt;\/b&gt; - User found\n     * &lt;p&gt;&lt;b&gt;404&lt;\/b&gt; - User not found\n     * @param userId The ID of the user to retrieve.\n     * @return ResponseSpec\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public ResponseSpec getUserByIdWithResponseSpec(String userId) throws WebClientResponseException {\n        return getUserByIdRequestCreation(userId);\n    }\n    \/**\n     * Get all users\n     * Retrieves a list of all registered users.\n     * &lt;p&gt;&lt;b&gt;200&lt;\/b&gt; - A list of users\n     * &lt;p&gt;&lt;b&gt;500&lt;\/b&gt; - Internal server error\n     * @return List&lt;User&gt;\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    private ResponseSpec getUsersRequestCreation() throws WebClientResponseException {\n        Object postBody = null;\n        \/\/ create path and map variables\n        final Map&lt;String, Object&gt; pathParams = new HashMap&lt;String, Object&gt;();\n\n        final MultiValueMap&lt;String, String&gt; queryParams = new LinkedMultiValueMap&lt;String, String&gt;();\n        final HttpHeaders headerParams = new HttpHeaders();\n        final MultiValueMap&lt;String, String&gt; cookieParams = new LinkedMultiValueMap&lt;String, String&gt;();\n        final MultiValueMap&lt;String, Object&gt; formParams = new LinkedMultiValueMap&lt;String, Object&gt;();\n\n        final String[] localVarAccepts = { \n            \"application\/json\"\n        };\n        final List&lt;MediaType&gt; localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);\n        final String[] localVarContentTypes = { };\n        final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);\n\n        String[] localVarAuthNames = new String[] {  };\n\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return apiClient.invokeAPI(\"\/users\", HttpMethod.GET, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType);\n    }\n\n    \/**\n     * Get all users\n     * Retrieves a list of all registered users.\n     * &lt;p&gt;&lt;b&gt;200&lt;\/b&gt; - A list of users\n     * &lt;p&gt;&lt;b&gt;500&lt;\/b&gt; - Internal server error\n     * @return List&lt;User&gt;\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public Flux&lt;User&gt; getUsers() throws WebClientResponseException {\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return getUsersRequestCreation().bodyToFlux(localVarReturnType);\n    }\n\n    \/**\n     * Get all users\n     * Retrieves a list of all registered users.\n     * &lt;p&gt;&lt;b&gt;200&lt;\/b&gt; - A list of users\n     * &lt;p&gt;&lt;b&gt;500&lt;\/b&gt; - Internal server error\n     * @return ResponseEntity&lt;List&lt;User&gt;&gt;\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public Mono&lt;ResponseEntity&lt;List&lt;User&gt;&gt;&gt; getUsersWithHttpInfo() throws WebClientResponseException {\n        ParameterizedTypeReference&lt;User&gt; localVarReturnType = new ParameterizedTypeReference&lt;User&gt;() {};\n        return getUsersRequestCreation().toEntityList(localVarReturnType);\n    }\n\n    \/**\n     * Get all users\n     * Retrieves a list of all registered users.\n     * &lt;p&gt;&lt;b&gt;200&lt;\/b&gt; - A list of users\n     * &lt;p&gt;&lt;b&gt;500&lt;\/b&gt; - Internal server error\n     * @return ResponseSpec\n     * @throws WebClientResponseException if an error occurs while attempting to invoke the API\n     *\/\n    public ResponseSpec getUsersWithResponseSpec() throws WebClientResponseException {\n        return getUsersRequestCreation();\n    }\n}\n<\/pre>\n<ul class=\"wp-block-list\">\n<li>The generated <code>UserApi<\/code> has 273 lines.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">4.3 Generated User<\/h3>\n<p>In this step, I will view the generated <code>User.java<\/code> class.<\/p>\n<p><span style=\"text-decoration: underline\"><em>User.java<\/em><\/span><\/p>\n<pre class=\"brush:java\">\/*\n * Sample User API\n * This is a sample API for managing users.\n *\n * The version of the OpenAPI document: 1.0.0\n * \n *\n * NOTE: This class is auto generated by OpenAPI Generator (https:\/\/openapi-generator.tech).\n * https:\/\/openapi-generator.tech\n * Do not edit the class manually.\n *\/\n\n\npackage org.jcg.zheng.demo.javawebclient.model;\n\nimport java.util.Objects;\nimport java.util.Arrays;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonTypeName;\nimport com.fasterxml.jackson.annotation.JsonValue;\nimport java.util.UUID;\nimport com.fasterxml.jackson.annotation.JsonPropertyOrder;\nimport com.fasterxml.jackson.annotation.JsonTypeName;\n\n\/**\n * User\n *\/\n@JsonPropertyOrder({\n  User.JSON_PROPERTY_ID,\n  User.JSON_PROPERTY_NAME,\n  User.JSON_PROPERTY_EMAIL\n})\n@jakarta.annotation.Generated(value = \"org.openapitools.codegen.languages.JavaClientCodegen\", comments = \"Generator version: 7.5.0\")\npublic class User {\n  public static final String JSON_PROPERTY_ID = \"id\";\n  private UUID id;\n\n  public static final String JSON_PROPERTY_NAME = \"name\";\n  private String name;\n\n  public static final String JSON_PROPERTY_EMAIL = \"email\";\n  private String email;\n\n  public User() {\n  }\n\n  public User id(UUID id) {\n    \n    this.id = id;\n    return this;\n  }\n\n   \/**\n   * Unique identifier for the user.\n   * @return id\n  **\/\n  @jakarta.annotation.Nonnull\n  @JsonProperty(JSON_PROPERTY_ID)\n  @JsonInclude(value = JsonInclude.Include.ALWAYS)\n\n  public UUID getId() {\n    return id;\n  }\n\n\n  @JsonProperty(JSON_PROPERTY_ID)\n  @JsonInclude(value = JsonInclude.Include.ALWAYS)\n  public void setId(UUID id) {\n    this.id = id;\n  }\n\n\n  public User name(String name) {\n    \n    this.name = name;\n    return this;\n  }\n\n   \/**\n   * Name of the user.\n   * @return name\n  **\/\n  @jakarta.annotation.Nonnull\n  @JsonProperty(JSON_PROPERTY_NAME)\n  @JsonInclude(value = JsonInclude.Include.ALWAYS)\n\n  public String getName() {\n    return name;\n  }\n\n\n  @JsonProperty(JSON_PROPERTY_NAME)\n  @JsonInclude(value = JsonInclude.Include.ALWAYS)\n  public void setName(String name) {\n    this.name = name;\n  }\n\n\n  public User email(String email) {\n    \n    this.email = email;\n    return this;\n  }\n\n   \/**\n   * Email address of the user.\n   * @return email\n  **\/\n  @jakarta.annotation.Nonnull\n  @JsonProperty(JSON_PROPERTY_EMAIL)\n  @JsonInclude(value = JsonInclude.Include.ALWAYS)\n\n  public String getEmail() {\n    return email;\n  }\n\n\n  @JsonProperty(JSON_PROPERTY_EMAIL)\n  @JsonInclude(value = JsonInclude.Include.ALWAYS)\n  public void setEmail(String email) {\n    this.email = email;\n  }\n\n  @Override\n  public boolean equals(Object o) {\n    if (this == o) {\n      return true;\n    }\n    if (o == null || getClass() != o.getClass()) {\n      return false;\n    }\n    User user = (User) o;\n    return Objects.equals(this.id, user.id) &amp;&amp;\n        Objects.equals(this.name, user.name) &amp;&amp;\n        Objects.equals(this.email, user.email);\n  }\n\n  @Override\n  public int hashCode() {\n    return Objects.hash(id, name, email);\n  }\n\n  @Override\n  public String toString() {\n    StringBuilder sb = new StringBuilder();\n    sb.append(\"class User {\\n\");\n    sb.append(\"    id: \").append(toIndentedString(id)).append(\"\\n\");\n    sb.append(\"    name: \").append(toIndentedString(name)).append(\"\\n\");\n    sb.append(\"    email: \").append(toIndentedString(email)).append(\"\\n\");\n    sb.append(\"}\");\n    return sb.toString();\n  }\n\n  \/**\n   * Convert the given object to string with each line indented by 4 spaces\n   * (except the first line).\n   *\/\n  private String toIndentedString(Object o) {\n    if (o == null) {\n      return \"null\";\n    }\n    return o.toString().replace(\"\\n\", \"\\n    \");\n  }\n\n}\n\n<\/pre>\n<ul class=\"wp-block-list\">\n<li>The generated <code>User<\/code> class is lengthy comparing to a class with <a href=\"https:\/\/projectlombok.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Lombok<\/a> annotations.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">5. Invoke Generated Class<\/h2>\n<h3 class=\"wp-block-heading\">5.1 Invoke Generated Class<\/h3>\n<p>In this step, I will create a <code>JavaWebClientService.java<\/code> to invoke the generated <code>UserApi<\/code>.<\/p>\n<p><span style=\"text-decoration: underline\"><em>JavaWebClientService.java<\/em><\/span><\/p>\n<pre class=\"brush:java;highlight:[18,19]\">package org.jcg.zheng.demo.httpclient_webclient;\n\nimport org.jcg.zheng.demo.javawebclient.ApiClient;\nimport org.jcg.zheng.demo.javawebclient.api.UsersApi;\nimport org.jcg.zheng.demo.javawebclient.model.User;\nimport org.springframework.stereotype.Service;\n\nimport reactor.core.publisher.Flux;\nimport reactor.core.publisher.Mono;\n\n@Service\npublic class JavaWebClientService {\n\n\tprivate final UsersApi usersApi;\n\n\tpublic JavaWebClientService() {\n\t\tsuper();\n\t\tthis.usersApi = new UsersApi(new ApiClient());\n\t\tthis.usersApi.getApiClient().setBasePath(\"http:\/\/localhost:8080\");\n\t}\n\n\tpublic Mono&lt;User&gt; createUser(User user) {\n\t\treturn usersApi.createUser(user);\n\t}\n\n\tpublic Mono&lt;User&gt; getUser(String userId) {\n\t\treturn usersApi.getUserById(userId);\n\t}\n\n\tpublic Flux&lt;User&gt; getUsers() {\n\t\treturn usersApi.getUsers();\n\t}\n\n}\n<\/pre>\n<ul class=\"wp-block-list\">\n<li>Line 18: initiates new <code>UsersApi<\/code> and integrated with the <code>JavaWebClientService<\/code> bean.<\/li>\n<li>Line 19: sets the <code>basePath<\/code> for the <code>apiClient<\/code>.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">5.2 Demonstrate<\/h3>\n<p>In this step, I will start the Spring Boot application and capture the server log.<\/p>\n<p><span style=\"text-decoration: underline\"><em>Spring Boot Server Log<\/em><\/span><\/p>\n<pre>\n  .   ____          _            __ _ _\n \/\\\\ \/ ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\\n( ( )\\___ | '_ | '_| | '_ \\\/ _` | \\ \\ \\ \\\n \\\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )\n  '  |____| .__|_| |_|_| |_\\__, | \/ \/ \/ \/\n =========|_|==============|___\/=\/_\/_\/_\/\n\n :: Spring Boot ::                (v3.5.7)\n\n2025-11-09T09:42:44.729-06:00  INFO 8360 --- [httpclient-webclient] [           main] o.j.z.d.h.HttpclientWebclientApplication : Starting HttpclientWebclientApplication using Java 21.0.8 with PID 8360 (C:\\MaryZheng\\workspace\\httpclient-webclient\\bin\\main started by zzhen in C:\\MaryZheng\\workspace\\httpclient-webclient)\n2025-11-09T09:42:44.732-06:00  INFO 8360 --- [httpclient-webclient] [           main] o.j.z.d.h.HttpclientWebclientApplication : No active profile set, falling back to 1 default profile: \"default\"\n2025-11-09T09:42:45.851-06:00  INFO 8360 --- [httpclient-webclient] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)\n2025-11-09T09:42:45.864-06:00  INFO 8360 --- [httpclient-webclient] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]\n2025-11-09T09:42:45.864-06:00  INFO 8360 --- [httpclient-webclient] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat\/10.1.48]\n2025-11-09T09:42:45.912-06:00  INFO 8360 --- [httpclient-webclient] [           main] o.a.c.c.C.[Tomcat].[localhost].[\/]       : Initializing Spring embedded WebApplicationContext\n2025-11-09T09:42:45.914-06:00  INFO 8360 --- [httpclient-webclient] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1131 ms\n2025-11-09T09:42:46.548-06:00  INFO 8360 --- [httpclient-webclient] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '\/'\n2025-11-09T09:42:46.557-06:00  INFO 8360 --- [httpclient-webclient] [           main] o.j.z.d.h.HttpclientWebclientApplication : Started HttpclientWebclientApplication in 2.344 seconds (process running for 2.808)\n<\/pre>\n<ul class=\"wp-block-list\">\n<li>Line 18: the Spring Boot application is started successfully.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">6. Advantages &amp; Drawbacks of OpenAPI<\/h2>\n<p>Using OpenAPI for client generation offers the following advantages:<\/p>\n<ol class=\"wp-block-list\">\n<li><strong>Automation and Consistency<\/strong> \u2013 Clients are generated from a single source of truth, reducing human error.<\/li>\n<li><strong>Faster Development<\/strong> \u2013 No need to manually write HTTP clients or data transfer objects.<\/li>\n<li><strong>Language Flexibility<\/strong> \u2013 OpenAPI Generator supports over 50 programming languages.<\/li>\n<li><strong>Strong Typing<\/strong> \u2013 Generated models enforce schema validation and make code more robust.<\/li>\n<li><strong>Up-to-Date Integration<\/strong> \u2013 When the API changes, simply regenerate the client for immediate updates.<\/li>\n<\/ol>\n<p>However, the static Mustache template triggers the following drawbacks:<\/p>\n<ol class=\"wp-block-list\">\n<li><strong>Complex Configuration<\/strong> \u2013 The generator can be tricky to configure for large or legacy APIs.<\/li>\n<li><strong>Code Overhead<\/strong> \u2013 Generated code may include unnecessary or verbose classes.<\/li>\n<li><strong>Customization Difficulty<\/strong> \u2013 Modifying generated code directly is discouraged; templates or post-processing scripts may be needed.<\/li>\n<li><strong>Regeneration Risks<\/strong> \u2013 Regenerating code can overwrite manual changes if not properly separated.<\/li>\n<\/ol>\n<h2 class=\"wp-block-heading\">7. Conclusion<\/h2>\n<p>Generating HTTP clients from an OpenAPI specification provides a reliable, consistent, and maintainable approach to API integration in Spring Boot applications. It reduces manual effort, eliminates boilerplate code, and helps maintain contract alignment between services. For the &#8220;<code>java<\/code>&#8221; generator, beside the &#8220;<code>webclient<\/code>&#8221; library used in this example, here are a few other common libraries supported by OpenAPI generator.<\/p>\n<figure class=\"wp-block-table\">\n<table class=\"has-fixed-layout\">\n<tbody>\n<tr>\n<td><strong>Library for Generator=&#8221;java&#8221;<\/strong><\/td>\n<td><strong>Description<\/strong><\/td>\n<td><strong>Mustache Template Link<\/strong><\/td>\n<td><strong>Method to Get Client<\/strong><\/td>\n<\/tr>\n<tr>\n<td>webclient<\/td>\n<td>Spring WebFlux HttpClient<\/td>\n<td><a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/tree\/master\/modules\/openapi-generator\/src\/main\/resources\/Java\/libraries\/webclient\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/OpenAPITools\/openapi-generator\/tree\/master\/modules\/openapi-generator\/src\/main\/resources\/Java\/libraries\/webclient<\/a><\/td>\n<td>new UserApi(new ApiClient)<\/td>\n<\/tr>\n<tr>\n<td>feign<\/td>\n<td>Feign Client<\/td>\n<td><a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/tree\/master\/modules\/openapi-generator\/src\/main\/resources\/Java\/libraries\/feign\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/OpenAPITools\/openapi-generator\/tree\/master\/modules\/openapi-generator\/src\/main\/resources\/Java\/libraries\/feign<\/a><\/td>\n<td>Feign.builder().target(UserApi.class, basePath)<\/td>\n<\/tr>\n<tr>\n<td>resttemplate<\/td>\n<td>RestTemplate Client<\/td>\n<td><a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/tree\/master\/modules\/openapi-generator\/src\/main\/resources\/Java\/libraries\/feign\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/OpenAPITools\/openapi-generator\/tree\/master\/modules\/openapi-generator\/src\/main\/resources\/Java\/libraries\/feign<\/a><\/td>\n<td>new UserApi(new ApiClient)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2 class=\"wp-block-heading\">8. Download<\/h2>\n<p>This was an example of a Gradle project that generated the HTTP <code>Webclient<\/code> in a Spring Boot project<\/p>\n<div class=\"download\"><strong>Download<\/strong><br \/>\nYou can download the full source code of this example here: <a href=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/11\/httpclient-webclient.zip\"><strong>Generating HTTP Client from OpenAPI Spec Example<\/strong><\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction OpenAPI ( formerly Swagger) provides a standard way to describe Rest APIs and OpenAPI Generator tool to generate http client from openapi spec. The generator tool takes an OpenAPI specification, then uses the selected generator (e.g., java), library (e.g., webclient), and config options to fill Mustache template files with API metadata and models, &hellip;<\/p>\n","protected":false},"author":128892,"featured_media":121875,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[2966,2034],"class_list":["post-138867","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-http-clients","tag-openapi"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HTTP Client From OpenAPI Spec And Spring Boot Example - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn more about http client from openapi spec? Then check out our detailed examples!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HTTP Client From OpenAPI Spec And Spring Boot Example - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn more about http client from openapi spec? Then check out our detailed examples!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-17T16:22:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Mary Zheng\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mary Zheng\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html\"},\"author\":{\"name\":\"Mary Zheng\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/33e795ab61de7fab61ed89b4de1668f5\"},\"headline\":\"HTTP Client From OpenAPI Spec And Spring Boot Example\",\"datePublished\":\"2025-11-17T16:22:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html\"},\"wordCount\":807,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/spring-boot-logo.jpg\",\"keywords\":[\"HTTP Clients\",\"OpenAPI\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html\",\"name\":\"HTTP Client From OpenAPI Spec And Spring Boot Example - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/spring-boot-logo.jpg\",\"datePublished\":\"2025-11-17T16:22:00+00:00\",\"description\":\"Interested to learn more about http client from openapi spec? Then check out our detailed examples!\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/spring-boot-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/spring-boot-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/http-client-from-openapi-spec-and-spring-boot-example.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"HTTP Client From OpenAPI Spec And Spring Boot Example\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/33e795ab61de7fab61ed89b4de1668f5\",\"name\":\"Mary Zheng\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/cropped-Mary-Zheng-96x96.jpg\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/cropped-Mary-Zheng-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/cropped-Mary-Zheng-96x96.jpg\",\"caption\":\"Mary Zheng\"},\"description\":\"Mary graduated from the Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She worked as a lead Software Engineer where she led and worked with others to design, implement, and monitor the software solution.\",\"sameAs\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/mary-zheng\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HTTP Client From OpenAPI Spec And Spring Boot Example - Java Code Geeks","description":"Interested to learn more about http client from openapi spec? Then check out our detailed examples!","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html","og_locale":"en_US","og_type":"article","og_title":"HTTP Client From OpenAPI Spec And Spring Boot Example - Java Code Geeks","og_description":"Interested to learn more about http client from openapi spec? Then check out our detailed examples!","og_url":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2025-11-17T16:22:00+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","type":"image\/jpeg"}],"author":"Mary Zheng","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Mary Zheng","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html"},"author":{"name":"Mary Zheng","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/33e795ab61de7fab61ed89b4de1668f5"},"headline":"HTTP Client From OpenAPI Spec And Spring Boot Example","datePublished":"2025-11-17T16:22:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html"},"wordCount":807,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","keywords":["HTTP Clients","OpenAPI"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html","url":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html","name":"HTTP Client From OpenAPI Spec And Spring Boot Example - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","datePublished":"2025-11-17T16:22:00+00:00","description":"Interested to learn more about http client from openapi spec? Then check out our detailed examples!","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/http-client-from-openapi-spec-and-spring-boot-example.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"HTTP Client From OpenAPI Spec And Spring Boot Example"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/33e795ab61de7fab61ed89b4de1668f5","name":"Mary Zheng","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/cropped-Mary-Zheng-96x96.jpg","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/cropped-Mary-Zheng-96x96.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/cropped-Mary-Zheng-96x96.jpg","caption":"Mary Zheng"},"description":"Mary graduated from the Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She worked as a lead Software Engineer where she led and worked with others to design, implement, and monitor the software solution.","sameAs":["https:\/\/www.javacodegeeks.com\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/mary-zheng"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/138867","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/128892"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=138867"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/138867\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/121875"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=138867"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=138867"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=138867"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}