Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swagger - how to use swagger-codegen and build a project on the long term

The Swagger project is wonderful to create easily client and server apps in every language, but I don't understand how to maintain or extend an existing project in a proper way.

I'm generating a Java server - language parameter is jaxrs-spec.

I have written my own Maven pom and using the swagger-codegen-maven-plugin and so now I'm able to generate model or api directly with maven.

I see that every time I rebuild my project the API will be completely rewritten by swagger-codegen plugin.

I need to implement my application logic, and at moment I didn't see any other way than customise the generated API sources. So, to avoid loosing my work at every build I could configure the .swagger-codegen-ignore (and I did), but I had only postponed the problem.

Because first time I have to update the swagger.json, the only option I have is to regenerate the entire API and overwrite my work. Ok, I could use git and try to restore the removed part, but is really an ugly solution.

So, the question is:

using swagger-codegen (or Swagger in general) is there a pattern, an how to, a documented way that allow me to add a behaviour and/or extend the generated APIs without overwrite my code?

like image 893
freedev Avatar asked Jan 27 '17 11:01

freedev


People also ask

What is the use of swagger codegen?

Swagger Codegen is an open source project which allows generation of API client libraries (SDK generation), server stubs, and documentation automatically from an OpenAPI Specification.

How do I generate swagger documentation for REST API automatically?

Use Swagger Inspector to quickly generate your OAS-based documentation for existing REST APIs by calling each end point and using the associated response to generate OAS-compliant documentation, or string together a series of calls to generate a full OAS document for multiple API endpoints.


1 Answers

It depends on the language / templates that you choose, since some of them are more flexible than others, but the same principle holds true: You shouldn't be adding any additional logic in the generated code. Unfortunately, by looking at the sample for jaxrs-spec, these templates don't look as good as the ones for say, jaxrs-resteasy.

At this point, you can either:

  1. Switch templates to a different jaxrs
  2. Write your own templates and use them instead
  3. Modify / update the swagger-codegen templates and commit them back.

I'll walk through an explanation of how this is done for the other templates. The way this is currently done is through factories, but it could just as easily be done with dependency injection. Codgen generates stub implementations that are the boilerplate to stand up the API, and delegates the actual logic to another class.

For jaxrs-resteasy, here's what codegen generates for a GET /{username} method (I removed the swagger annotations it also puts in):

@GET
@Path("/{username}")
@Produces({ "application/xml", "application/json" })
public Response getUserByName( @PathParam("username") String username,@Context SecurityContext securityContext)
throws NotFoundException {
    return delegate.getUserByName(username,securityContext);
}

The actual method just delegates to a factory, which it obtains like so:

private final UserApiService delegate = UserApiServiceFactory.getUserApi();

It can do this because it also generates a base class for the API to implement:

public abstract class UserApiService {
    // methods omitted...
    public abstract Response getUserByName(String username, SecurityContext securityContext) throws NotFoundException;
    // methods omitted...
}

Now, in non-generated code, the user adds an implementation of this base class:

public class UserApiServiceImpl extends UserApiService {
      // methods omitted...
      @Override
      public Response getUserByName(String username, SecurityContextsecurityContext) throws NotFoundException {
          // do some magic!
          return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
    }
    // methods omitted...
}

And then, the user adds the factory in the package that codegen expects, so the generated code can obtain the above implementation:

public class UserApiServiceFactory {
   private final static UserApiService service = new UserApiServiceImpl();

   public static UserApiService getUserApi() {
      return service;
   }
}

Now the code that was generated knows exactly which implementation of UserApiService to delegate to. At this point, the entire server boilerplate is separated from the application logic, allowing you to regenerate the API without overwriting your custom logic.

This answer assumes that the sample for jaxrs-spec is an accurate example of what swagger-codegen produces for that language parameter. Sometimes they get out of date.

like image 51
nickb Avatar answered Sep 19 '22 02:09

nickb