From Swagger 2.0 to OpenAPI

The road of the API is paved with breaking library changes

I still recently read articles like this one where it is shown that people seems to use more the older Swagger 2.0 than the more recent OpenApi 3.x specification.

What is Swagger

For the ones that happen to not know what Swagger/OpenAPI is, I will quickly mention that it is a tool that enables API developers to provide, while implementing the core logic, an up-to-date documentation as well as client libraries, for a number of programming languages.

There exist a number of tool that - starting from the living development - are able to generate this client side code.

In what is regarded as "API economy", I take as a given that this provide an huge value, and is unlocking quite a number of possibility.

An example ? Implement the backend, and generate the Android client code for a potential app.

Cut the Buzzwords

Low/No code? I have no idea what that means, and I freak out when I hear those names.

I code for a living, and expect to keep finding code to be written, the fact that you can automate the plumbing code is a net win for me, and it should be for humanity.

Code isn't going to disappear anytime soon, just that we need to focus on the part that has value added to it: none really benefits from writing over and over integrations: automatize any repetition, focus on the business logic.

This way, OpenAPI is a spec and a set of tools to go on with nerd life and focus on solving problems that deserve your attention, not the toil.

A bit of history

Now that we are onboard with the entire Swagger thingie and why it is important, I get back to the point: sometimes around 2017, this tool too good to be true, forked to give life to OpenAPI.

As it is usual with code that was born to succeed, bad things can always happen, but, differently from what I first tought, that is not what happened with Swagger: the tool was so successful that it was raised up and donated to create an open spec: OpenAPI.

Therefore, an actual fork was done; but differently from what everyone would expect, it's totally fine to use either the old one and the new one.

In the article: We need to talk... it's very well explained that there is basically no point in holding back to the old one.

What happens in Java land

Now, for what happens specifically in the Java world, if you stick to some framework like Spring, or Quarkus or... some other, you will probably be good to go to just update the versions and carry on with your life.

The point is, if you don't totally buy into any framework, you're probably bound to suffer infinite pains to get what you want.

This was especially the case for me when I wanted to start using the latest OpenAPI on a project that was just fine with JaxRS.

Most of the pain due to the fact that changes in the Java implementation, for whatever reason, have been reckless and wild: things just change name both in the spec and in the implementation detail.

Down to the nitty-gritty details for Java code

First point, the following annotation in Swagger 2.x:

@io.swagger.annotations.Api

has been replaced in OpenAPI 3.x by:

@io.swagger.v3.oas.annotations.tags.Tag

Quite unintuitive, isn't it?

The easy part was to replace those dependencies:

    <dependency>
      <groupId>io.swagger</groupId>
      <artifactId>swagger-jaxrs</artifactId>
      <version>1.6.7</version>
    </dependency>
    <dependency>
      <groupId>io.swagger</groupId>
      <artifactId>swagger-annotations</artifactId>
      <version>1.6.7</version>
    </dependency>

whith:

<dependency>
    <groupId>io.swagger.core.v3</groupId>
    <artifactId>swagger-annotations</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>io.swagger.core.v3</groupId>
    <artifactId>swagger-jaxrs2</artifactId>
    <artifactId>swagger-annotations</artifactId>
    <version>2.2.2</version>
</dependency>

And then of course if you were using the following in your JAXRS project:

io.swagger.jaxrs.listing.ApiListingResource
io.swagger.jaxrs.listing.SwaggerSerializers

The not-so-similar names to use are now the following:

io.swagger.v3.jaxrs2.integration.resources.OpenApiResource
io.swagger.v3.jaxrs2.integration.resources.AcceptHeaderOpenApiResource

But, for those in the same self-sabotaging category as myself that initialize the entire stack above without the help of a framework, I will show how I get the entire thing off the ground:

import java.util.HashSet;
import java.util.Set;

import javax.servlet.ServletConfig;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;


public class MyJaxrsApplication extends Application {

	private Set<Object> singletons = new HashSet<Object>();

	@Override
	public Set<Object> getSingletons() {
		return singletons;
	}

	public MyJaxrsApplication(@Context ServletConfig servletConfig) {
		super();

		singletons.add(new MyFirstRestController());
		singletons.add(new MySecondRestController());	
	
		setupSwagger();
	}
	
	
    private void setupSwagger() {
    	singletons.add(new io.swagger.v3.jaxrs2.integration.resources.OpenApiResource());
    	singletons.add(new io.swagger.v3.jaxrs2.integration.resources.AcceptHeaderOpenApiResource());
    }
}

This way it works. If you want any further explanation on how to get this to work, do not hesitate to reach out



[programming] [java] [api] [backend]