Introduction

If there is a server, then it has an api and you need to write a client to it.

Of course, it is better if the client is written automatically: then it is relevant and contains fewer errors.

It is now customary to write clients for the HTTP protocol from OpenAPI specifications. Fortunately, they are also generated automatically by the server in most cases. And when for some reason the generator is not used, it contains errors and is outdated: do not do this.

Swagger-codegen vs openapi-generator

There are 2 main swagger generators-codegen (the original one) and openapi-generator (its fork).

If we compare:

And see how many have been downloaded:

It’s clearly visible that openapi-generator is more popular and is being developed more actively.

How do I generate a client library?

docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
    -i /local/specs/simple.json \
    -g kotlin \
    --additional-properties enumPropertyNaming=UPPERCASE \
    --additional-properties library=jvm-spring-webclient \
    --additional-properties useSpringBoot3=true \
    --additional-properties serializationLibrary=jackson \
    -o /local/clients/simple

We want a client for spring 3 on Kotlin.

What’s wrong with the Java client?

  • we lose information about null
  • we need coroutines

Are you satisfied with what is generated?

No:

  • coroutines are not used, which means that the code for switching to coroutines will be in the main application - the biggest disadvantage
  • client interfaces from Spring 3 are not used: readability is worse
  • a bunch of some left-hand code in the infrastructure package – it is better to use an external dependency (if desired, it can easily be replaced with its own in the build files of the main application)
  • for some reason, ktlint was not put into the docker image and they issue a warning about it (because of this, unformatted code)
  • a strange approach to types: why do they write kotlin.String for kotlin, but do not write java.lang.String for java?

Maybe it’s better in another project?

No, it’s about the same there.

What should I do?

We’re finishing it.

New parameters:

  • --library=jvm-spring-http-interface --additional-properties useCoroutines=true – enables generation of interfaces with coroutines
  • --global-property apiTests=false,modelTests=false – do not generate tests (garbage, because we are not going to run them)
  • --additional-properties omitInfrastructureClasses=true – do not generate the infrastructure code (connect the dependency to the main project)
  • I thought that it doesn’t make much sense to connect the dependency to the client, it’s better to the main project, so that you don’t have to deal with its exclusion later
  • added ktlint to the docker image
  • removed the generation of standard class names with the prefix kotlin.*

Building an image:

cd openapi-generator
docker build . -f .hub.cli.dockerfile -t stepin/openapi-generator-cli

Launching an image:

docker run --rm -v ${PWD}:/local stepin/openapi-generator-cli generate \
    -i /local/specs/simple.json \
    -g kotlin \
    --library=jvm-spring-http-interface \
    --additional-properties groupId=name.stepin \
    --additional-properties artifactId=simple-client \
    --additional-properties artifactVersion=0.2.0 \
    --additional-properties packageName=name.stepin.client.simple \
    --additional-properties useSpringBoot3=true \
    --additional-properties useCoroutines=true \
    --additional-properties serializationLibrary=jackson \
    --additional-properties omitInfrastructureClasses=true \
    --additional-properties enumPropertyNaming=UPPERCASE \
    --global-property apiTests=false,modelTests=false \
    -o /local/clients/simple

So far, it has a beta status: everything seems to work for me, but there will certainly be some marginal cases. Plus, the library for connecting http interface clients to the project is understandable and written in a draft, but has not yet been published.