Goal of this project is to provide tooling for Maven projects (and maybe Gradle) to generate code from swagger-definitions (yaml or json) during build. This is not a onetime-generator. Code will be generated at every build to make sure your implementation matches your api.

It also provides different templates for code-generation.

Installation

Installation with maven is easy. Just add the following snippet into your pom.xml:

Example 1. plugin configuration in pom.xml
<plugin>
    <groupId>org.zalando.maven.plugins</groupId>
    <artifactId>swagger-codegen-maven-plugin</artifactId>
    <version>${plugin.version}</version>
    <configuration>
        <apiFile>${project.basedir}/src/main/resources/api.yaml</apiFile>
        <language>springinterfaces</language>
        <apiPackage>com.yourcompany.api</apiPackage>
        <modelPackage>com.yourcompany.model</modelPackage>
    </configuration>
    <!-- put template-dependency here, directly into plugin -->
    <dependencies>
        <dependency>
            <groupId>org.zalando.stups</groupId>
            <artifactId>swagger-codegen-template-spring-interfaces</artifactId>
            <version>${template.version}</version>
        </dependency>
    </dependencies>
</plugin>

Templates

Table 1. Overview of existing templates
templatename

springinterfaces

springinterfacesNoSwaggerAnnotations

springinterfacesResponseEntity

springinterfacesResponseEntityNoSwaggerAnnotations

jaxrsinterfaces

The following examples are generated from the official pet-store-example by swagger.

springinterfaces

When using springinterfaces as template then the generated code looks like this:

Example 2. generated code
package de.zalando.swagger.api;

import de.zalando.swagger.model.*;

import io.swagger.annotations.*;

import java.util.Map;
import de.zalando.swagger.model.Order;

import java.util.List;

import java.io.InputStream;

import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;

//
// GENERATED CLASS, DO NOT EDIT
//

@Api(value = "/store")
public interface StoreApi {

  @RequestMapping(value="/store/inventory",method=RequestMethod.GET , produces={ "application/json", "application/xml" })
  @ApiOperation(value = "Returns pet inventories by status", notes = "Returns a map of status codes to quantities", response = Map.class, responseContainer = "map")
  @ApiResponses(value = {
    @ApiResponse(code = 200, message = "successful operation")
  })
  Integer getInventory();

  @RequestMapping(value="/store/order",method=RequestMethod.POST , produces={ "application/json", "application/xml" })
  @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class)
  @ApiResponses(value = {
    @ApiResponse(code = 200, message = "successful operation"),
    @ApiResponse(code = 400, message = "Invalid Order")
  })
  Order placeOrder(@ApiParam(value = "order placed for purchasing the pet"  ) @RequestBody Order body);

  @RequestMapping(value="/store/order/{orderId}",method=RequestMethod.GET , produces={ "application/json", "application/xml" })
  @ApiOperation(value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class)
  @ApiResponses(value = {
    @ApiResponse(code = 404, message = "Order not found"),
    @ApiResponse(code = 200, message = "successful operation"),
    @ApiResponse(code = 400, message = "Invalid ID supplied")
  })
  Order getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") String orderId);

  @RequestMapping(value="/store/order/{orderId}",method=RequestMethod.DELETE , produces={ "application/json", "application/xml" })
  @ApiOperation(value = "Delete purchase order by ID", notes = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors")
  @ApiResponses(value = {
    @ApiResponse(code = 404, message = "Order not found"),
    @ApiResponse(code = 400, message = "Invalid ID supplied")
  })
  void deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathVariable("orderId") String orderId);

}

springinterfacesNoSwaggerAnnotations

You can guess by the templates name what the code will look like, right?

Example 3. generated code, no swagger-annotations
package de.zalando.swagger.api;

import de.zalando.swagger.model.*;

import java.util.Map;
import de.zalando.swagger.model.Order;

import java.util.List;

import java.io.InputStream;

import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;

//
// GENERATED CLASS, DO NOT EDIT
//

public interface StoreApi {

  @RequestMapping(value="/store/inventory",method=RequestMethod.GET , produces={ "application/json", "application/xml" })
  Integer getInventory();

  @RequestMapping(value="/store/order",method=RequestMethod.POST , produces={ "application/json", "application/xml" })
  Order placeOrder( @RequestBody Order body);

  @RequestMapping(value="/store/order/{orderId}",method=RequestMethod.GET , produces={ "application/json", "application/xml" })
  Order getOrderById( @PathVariable("orderId") String orderId);

  @RequestMapping(value="/store/order/{orderId}",method=RequestMethod.DELETE , produces={ "application/json", "application/xml" })
  void deleteOrder( @PathVariable("orderId") String orderId);

}

springinterfacesResponseEntity

If you like to use Springs ResponseEntity as return-value.

Example 4. generated code, with ResponseEntity and Swagger-Annotations
package de.zalando.swagger.api;

import de.zalando.swagger.model.*;

import io.swagger.annotations.*;

import java.util.Map;
import de.zalando.swagger.model.Order;

import java.util.List;

import java.io.InputStream;

import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;

//
// GENERATED CLASS, DO NOT EDIT
//

@Api(value = "/store")
public interface StoreApi {

  @RequestMapping(value="/store/inventory",method=RequestMethod.GET , produces={ "application/json", "application/xml" })
  @ApiOperation(value = "Returns pet inventories by status", notes = "Returns a map of status codes to quantities", response = Map.class, responseContainer = "map")
  @ApiResponses(value = {
    @ApiResponse(code = 200, message = "successful operation")
  })
  ResponseEntity<Integer> getInventory();

  @RequestMapping(value="/store/order",method=RequestMethod.POST , produces={ "application/json", "application/xml" })
  @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class)
  @ApiResponses(value = {
    @ApiResponse(code = 200, message = "successful operation"),
    @ApiResponse(code = 400, message = "Invalid Order")
  })
  ResponseEntity<Order> placeOrder(@ApiParam(value = "order placed for purchasing the pet"  ) @RequestBody Order body);

  @RequestMapping(value="/store/order/{orderId}",method=RequestMethod.GET , produces={ "application/json", "application/xml" })
  @ApiOperation(value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class)
  @ApiResponses(value = {
    @ApiResponse(code = 404, message = "Order not found"),
    @ApiResponse(code = 200, message = "successful operation"),
    @ApiResponse(code = 400, message = "Invalid ID supplied")
  })
  ResponseEntity<Order> getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") String orderId);

  @RequestMapping(value="/store/order/{orderId}",method=RequestMethod.DELETE , produces={ "application/json", "application/xml" })
  @ApiOperation(value = "Delete purchase order by ID", notes = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors")
  @ApiResponses(value = {
    @ApiResponse(code = 404, message = "Order not found"),
    @ApiResponse(code = 400, message = "Invalid ID supplied")
  })
  void deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathVariable("orderId") String orderId);

}

springinterfacesResponseEntityNoSwaggerAnnotations

You can guess again …​

Example 5. generated code, with ResponseEntity without Swagger-Annotations
package de.zalando.swagger.api;

import de.zalando.swagger.model.*;

import java.util.Map;
import de.zalando.swagger.model.Order;

import java.util.List;

import java.io.InputStream;

import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;

//
// GENERATED CLASS, DO NOT EDIT
//

public interface StoreApi {

  @RequestMapping(value="/store/inventory",method=RequestMethod.GET , produces={ "application/json", "application/xml" })
  ResponseEntity<Integer> getInventory();

  @RequestMapping(value="/store/order",method=RequestMethod.POST , produces={ "application/json", "application/xml" })
  ResponseEntity<Order> placeOrder( @RequestBody Order body);

  @RequestMapping(value="/store/order/{orderId}",method=RequestMethod.GET , produces={ "application/json", "application/xml" })
  ResponseEntity<Order> getOrderById( @PathVariable("orderId") String orderId);

  @RequestMapping(value="/store/order/{orderId}",method=RequestMethod.DELETE , produces={ "application/json", "application/xml" })
  void deleteOrder( @PathVariable("orderId") String orderId);

}

jaxrsinterfaces

There exist also an template for JAX-RS.

Example 6. generated code for JAX-RS
package de.zalando.swagger.api;

import de.zalando.swagger.model.*;

import io.swagger.annotations.*;

import java.util.Map;
import de.zalando.swagger.model.Order;

import java.util.List;
import de.zalando.swagger.api.NotFoundException;

import java.io.InputStream;

import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;

import javax.ws.rs.core.Response;
import javax.ws.rs.*;

@Path("/store")
@Api(value = "/store", description = "the store API")
public interface StoreApi {

  @GET
  @Path("/inventory")

  @Produces({ "application/json", "application/xml" })
  // Integer
  @ApiOperation(value = "Returns pet inventories by status", notes = "Returns a map of status codes to quantities", response = Integer.class, responseContainer = "map")
  @ApiResponses(value = {
    @ApiResponse(code = 200, message = "successful operation") })

  public Response getInventory()
      throws NotFoundException;


  @POST
  @Path("/order")

  @Produces({ "application/json", "application/xml" })
  // Order
  @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class)
  @ApiResponses(value = {
    @ApiResponse(code = 200, message = "successful operation"),

    @ApiResponse(code = 400, message = "Invalid Order") })

  public Response placeOrder(@ApiParam(value = "order placed for purchasing the pet"  ) Order body)
      throws NotFoundException;


  @GET
  @Path("/order/{orderId}")

  @Produces({ "application/json", "application/xml" })
  // Order
  @ApiOperation(value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class)
  @ApiResponses(value = {
    @ApiResponse(code = 404, message = "Order not found"),

    @ApiResponse(code = 200, message = "successful operation"),

    @ApiResponse(code = 400, message = "Invalid ID supplied") })

  public Response getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathParam("orderId") String orderId)
      throws NotFoundException;


  @DELETE
  @Path("/order/{orderId}")

  @Produces({ "application/json", "application/xml" })
  // Void
  @ApiOperation(value = "Delete purchase order by ID", notes = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", response = Void.class)
  @ApiResponses(value = {
    @ApiResponse(code = 404, message = "Order not found"),

    @ApiResponse(code = 400, message = "Invalid ID supplied") })

  public Response deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathParam("orderId") String orderId)
      throws NotFoundException;


}

Further Configuration Options

There are some more configuration-options for the maven-plugin.

Example 7. plugin configuration in pom.xml
<plugin>
    ... skipped ...
    <configuration>
        <apiFile>${project.basedir}/src/main/resources/api.yaml</apiFile>
        <language>springinterfaces</language>
        <apiPackage>com.yourcompany.api</apiPackage>
        <modelPackage>com.yourcompany.model</modelPackage>
        <!-- skip generation for api -->
        <skipApigeneration>true</skipApigeneration>
        <!-- model-definitions to exclude from generation -->
        <excludedModels>
            <excludedModel>Application</excludedModel>
            <excludedModel>ApplicationDetails</excludedModel>
        </excludedModels>
        <!-- skip generation of model-definitions completely -->
        <skipModelgeneration>true</skipModelgeneration>
        <yamlToJson>true</yamlToJson>
        <yamlToJsonOutputDirectory>${project.build.directory}/classes</yamlToJsonOutputDirectory>
        <enableBuilderSupport>true</enableBuilderSupport>
        <enable303>true</enable303>
    </configuration>
    <!-- put template-dependency here, directly into plugin -->
    ... skipped ...
</plugin>
Table 2. Overview of configuration options
option description

yamlToJson

transform the yaml into json

yamlToJsonOutputDirectory

location for generated json-file

enableBuilderSupport

creates simple builder for model-definitions

enable303

add JSR-303 annotations if possible to model-definitions

excludedModels

Models to exclude from generation

skipModelgeneration

completely skips generation of model-definitions

skipApigeneration

maybe you only want to generate the model, because api is shared by another module