6.18 API Versioning

Since 1.1.x, Micronaut supports API versioning via a dedicated @Version annotation.

The following example demonstrates how to version an API:

Versioning an API

  1. import io.micronaut.core.version.annotation.Version;
  2. import io.micronaut.http.annotation.Controller;
  3. import io.micronaut.http.annotation.Get;
  4. @Controller("/versioned")
  5. class VersionedController {
  6. @Version("1") (1)
  7. @Get("/hello")
  8. String helloV1() {
  9. return "helloV1";
  10. }
  11. @Version("2") (2)
  12. @Get("/hello")
  13. String helloV2() {
  14. return "helloV2";
  15. }

Versioning an API

  1. import io.micronaut.core.version.annotation.Version
  2. import io.micronaut.http.annotation.Controller
  3. import io.micronaut.http.annotation.Get
  4. @Controller("/versioned")
  5. class VersionedController {
  6. @Version("1") (1)
  7. @Get("/hello")
  8. String helloV1() {
  9. "helloV1"
  10. }
  11. @Version("2") (2)
  12. @Get("/hello")
  13. String helloV2() {
  14. "helloV2"
  15. }

Versioning an API

  1. import io.micronaut.core.version.annotation.Version
  2. import io.micronaut.http.annotation.Controller
  3. import io.micronaut.http.annotation.Get
  4. @Controller("/versioned")
  5. internal class VersionedController {
  6. @Version("1") (1)
  7. @Get("/hello")
  8. fun helloV1(): String {
  9. return "helloV1"
  10. }
  11. @Version("2") (2)
  12. @Get("/hello")
  13. fun helloV2(): String {
  14. return "helloV2"
  15. }
1The helloV1 method is declared as version 1
2The helloV2 method is declared as version 2

You should then enabling versioning by setting micronaut.router.versioning.enabled to true in application.yml:

Enabling Versioning

  1. micronaut:
  2. router:
  3. versioning:
  4. enabled: true

By default Micronaut has 2 out-of-the-box strategies for resolving the version that are based on an HTTP header named X-API-VERSION or a request parameter named api-version, however this is configurable. A full configuration example can be seen below:

Configuring Versioning

  1. micronaut:
  2. router:
  3. versioning:
  4. enabled: true (1)
  5. parameter:
  6. enabled: false (2)
  7. names: 'v,api-version' (3)
  8. header:
  9. enabled: true (4)
  10. names: (5)
  11. - 'X-API-VERSION'
  12. - 'Accept-Version'
1Enables versioning
2Enables or disables parameter based versioning
3Specify the parameter names as a comma separated list
4Enables or disables header based versioning
5Specify the header names as a YAML list

If this is not enough you can also implement the RequestVersionResolver interface which receives the HttpRequest and can implement any strategy you choose.

Default Version

It is possible to supply a default version through configuration.

Configuring Default Version

  1. micronaut:
  2. router:
  3. versioning:
  4. enabled: true
  5. default-version: 3 (1)
1Sets the default version

A route will not be matched if the following conditions are met:

  • The default version is configured

  • No version is found in the request

  • The route defines a version

  • The route version does not match the default version

If the incoming request specifies a version then the default version has no effect.

Versioning Client Requests

Micronaut’s Declarative HTTP client also supports automatic versioning of outgoing requests via the @Version annotation.

By default if you annotate a client interface with @Version the value supplied to the annotation will be included using the X-API-VERSION header.

For example:

  1. import io.micronaut.core.version.annotation.Version;
  2. import io.micronaut.http.annotation.Get;
  3. import io.micronaut.http.client.annotation.Client;
  4. import io.reactivex.Single;
  5. @Client("/hello")
  6. @Version("1") (1)
  7. public interface HelloClient {
  8. @Get("/greeting/{name}")
  9. String sayHello(String name);
  10. @Version("2")
  11. @Get("/greeting/{name}")
  12. Single<String> sayHelloTwo(String name); (2)
  13. }
  1. import io.micronaut.core.version.annotation.Version
  2. import io.micronaut.http.annotation.Get
  3. import io.micronaut.http.client.annotation.Client
  4. import io.reactivex.Single
  5. @Client("/hello")
  6. @Version("1") (1)
  7. interface HelloClient {
  8. @Get("/greeting/{name}")
  9. String sayHello(String name)
  10. @Version("2")
  11. @Get("/greeting/{name}")
  12. Single<String> sayHelloTwo(String name) (2)
  13. }
  1. import io.micronaut.core.version.annotation.Version
  2. import io.micronaut.http.annotation.Get
  3. import io.micronaut.http.client.annotation.Client
  4. import io.reactivex.Single
  5. @Client("/hello")
  6. @Version("1") (1)
  7. interface HelloClient {
  8. @Get("/greeting/{name}")
  9. fun sayHello(name : String) : String
  10. @Version("2")
  11. @Get("/greeting/{name}")
  12. fun sayHelloTwo(name : String) : Single<String> (2)
  13. }
1The @Version can be used as the type level to specify the version to use for all methods
2When defined at the method level it is used only for that method

The default behaviour for how the version is sent for each call can be configured with DefaultClientVersioningConfiguration:

🔗

Table 1. Configuration Properties for DefaultClientVersioningConfiguration
PropertyTypeDescription

micronaut.http.client.versioning.default.headers

java.util.List

The list of request header names.

micronaut.http.client.versioning.default.parameters

java.util.List

The list of request query parameter names.

For example to use Accept-Version as the header name:

Configuring Client Versioning

  1. micronaut:
  2. http:
  3. client:
  4. versioning:
  5. default:
  6. headers:
  7. - 'Accept-Version'
  8. - 'X-API-VERSION'

The default key is used to refer to the default configuration. You can specify client specific configuration by using the value passed to @Client (typically the service ID). For example:

Configuring Versioning

  1. micronaut:
  2. http:
  3. client:
  4. versioning:
  5. greeting-service:
  6. headers:
  7. - 'Accept-Version'
  8. - 'X-API-VERSION'

The above uses a key called greeting-service which can be used to configure a client annotated with @Client('greeting-service').