├── .circleci
└── config.yml
├── README.md
├── pom.xml
├── renovate.json
└── src
├── main
├── java
│ └── pl
│ │ └── piomin
│ │ └── services
│ │ └── versioning
│ │ ├── VersioningApplication.java
│ │ ├── controller
│ │ ├── PersonController.java
│ │ └── PersonControllerWithHeaders.java
│ │ ├── mapper
│ │ └── PersonMapper.java
│ │ ├── model
│ │ ├── Gender.java
│ │ ├── Person.java
│ │ ├── PersonCurrent.java
│ │ └── PersonOld.java
│ │ └── repository
│ │ └── PersonRepository.java
└── resources
│ └── application.yml
└── test
└── java
└── pl
└── piomin
└── services
└── versioning
├── PersonControllerTests.java
└── PersonControllerWithHeadersTests.java
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | jobs:
4 | build:
5 | docker:
6 | - image: 'cimg/openjdk:21.0.6'
7 | steps:
8 | - checkout
9 | - run:
10 | name: Analyze on SonarCloud
11 | command: mvn verify sonar:sonar
12 |
13 | executors:
14 | jdk:
15 | docker:
16 | - image: 'cimg/openjdk:21.0.6'
17 |
18 | orbs:
19 | maven: circleci/maven@2.0.0
20 |
21 | workflows:
22 | maven_test:
23 | jobs:
24 | - maven/test:
25 | executor: jdk
26 | - build:
27 | context: SonarCloud
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Versioning REST API with Spring Boot and Swagger [](https://twitter.com/piotr_minkowski)
2 |
3 | [](https://circleci.com/gh/piomin/sample-api-versioning)
4 |
5 | [](https://sonarcloud.io/dashboard?id=piomin_sample-api-versioning)
6 | [](https://sonarcloud.io/dashboard?id=piomin_sample-api-versioning)
7 | [](https://sonarcloud.io/dashboard?id=piomin_sample-api-versioning)
8 | [](https://sonarcloud.io/dashboard?id=piomin_sample-api-versioning)
9 |
10 | Detailed description can be found here: [Versioning REST API with Spring Boot and Swagger](https://piotrminkowski.com/2018/02/19/versioning-rest-api-with-spring-boot-and-swagger/)
11 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | pl.piomin.services
5 | sample-api-versioning
6 | 1.0-SNAPSHOT
7 |
8 |
9 | 21
10 | piomin_sample-api-versioning
11 | piomin
12 | https://sonarcloud.io
13 |
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 3.5.0
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-web
25 |
26 |
27 | org.springdoc
28 | springdoc-openapi-starter-webmvc-ui
29 | 2.8.8
30 |
31 |
32 | com.fasterxml.jackson.datatype
33 | jackson-datatype-jsr310
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-test
38 |
39 |
40 | org.instancio
41 | instancio-junit
42 | 5.4.1
43 |
44 |
45 |
46 |
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-maven-plugin
51 |
52 |
53 |
54 | build-info
55 |
56 |
57 |
58 |
59 |
60 | org.jacoco
61 | jacoco-maven-plugin
62 | 0.8.13
63 |
64 |
65 |
66 | prepare-agent
67 |
68 |
69 |
70 | report
71 | test
72 |
73 | report
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:base",":dependencyDashboard"
5 | ],
6 | "packageRules": [
7 | {
8 | "matchUpdateTypes": ["minor", "patch", "pin", "digest"],
9 | "automerge": true
10 | }
11 | ],
12 | "prCreation": "not-pending"
13 | }
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/VersioningApplication.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning;
2 |
3 | import org.springdoc.core.models.GroupedOpenApi;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.context.annotation.Bean;
7 | import pl.piomin.services.versioning.model.Gender;
8 | import pl.piomin.services.versioning.model.PersonOld;
9 | import pl.piomin.services.versioning.repository.PersonRepository;
10 |
11 | import java.time.LocalDate;
12 |
13 | @SpringBootApplication
14 | public class VersioningApplication {
15 |
16 | public static void main(String[] args) {
17 | SpringApplication.run(VersioningApplication.class, args);
18 | }
19 |
20 | @Bean
21 | PersonRepository repository() {
22 | PersonRepository repository = new PersonRepository();
23 | repository.add(new PersonOld(1L, "John Smith", Gender.MALE, LocalDate.parse("1977-01-20")));
24 | repository.add(new PersonOld(2L, "Lawrence Crawford", Gender.MALE, LocalDate.parse("1987-01-20")));
25 | repository.add(new PersonOld(3L, "Adam Blair", Gender.MALE, LocalDate.parse("1982-01-20")));
26 | repository.add(new PersonOld(4L, "Laura Saint", Gender.FEMALE, LocalDate.parse("1965-01-20")));
27 | return repository;
28 | }
29 |
30 | @Bean
31 | public GroupedOpenApi personApiViaHeaders() {
32 | return GroupedOpenApi.builder()
33 | .group("person-via-headers")
34 | .pathsToMatch("/persons-via-headers/**")
35 | .build();
36 | }
37 |
38 | @Bean
39 | public GroupedOpenApi personApi10() {
40 | return GroupedOpenApi.builder()
41 | .group("person-api-1.0")
42 | .pathsToMatch("/person/v1.0/**")
43 | .build();
44 | }
45 |
46 | @Bean
47 | public GroupedOpenApi personApi11() {
48 | return GroupedOpenApi.builder()
49 | .group("person-api-1.1")
50 | .pathsToMatch("/person/v1.1/**")
51 | .build();
52 | }
53 |
54 | @Bean
55 | public GroupedOpenApi personApi12() {
56 | return GroupedOpenApi.builder()
57 | .group("person-api-1.2")
58 | .pathsToMatch("/person/v1.2/**")
59 | .build();
60 | }
61 |
62 | // @Bean
63 | // public Docket swaggerPersonApi10() {
64 | // return new Docket(DocumentationType.SWAGGER_2)
65 | // .groupName("person-api-1.0")
66 | // .select()
67 | // .apis(RequestHandlerSelectors.basePackage("pl.piomin.services.versioning.controller"))
68 | // .paths(regex("/person/v1.0.*"))
69 | // .build()
70 | // .apiInfo(new ApiInfoBuilder().version("1.0").title("Person API").description("Documentation Person API v1.0").build());
71 | // }
72 | //
73 | // @Bean
74 | // public Docket swaggerPersonApi11() {
75 | // return new Docket(DocumentationType.SWAGGER_2)
76 | // .groupName("person-api-1.1")
77 | // .select()
78 | // .apis(RequestHandlerSelectors.basePackage("pl.piomin.services.versioning.controller"))
79 | // .paths(regex("/person/v1.1.*"))
80 | // .build()
81 | // .apiInfo(new ApiInfoBuilder().version("1.1").title("Person API").description("Documentation Person API v1.1").build());
82 | // }
83 | //
84 | // @Bean
85 | // public Docket swaggerPersonApi12() {
86 | // return new Docket(DocumentationType.SWAGGER_2)
87 | // .groupName("person-api-1.2")
88 | // .select()
89 | // .apis(RequestHandlerSelectors.basePackage("pl.piomin.services.versioning.controller"))
90 | // .paths(regex("/person/v1.2.*"))
91 | // .build()
92 | // .apiInfo(new ApiInfoBuilder().version("1.2").title("Person API").description("Documentation Person API v1.2").build());
93 | // }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/controller/PersonController.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning.controller;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.web.bind.annotation.DeleteMapping;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 | import org.springframework.web.bind.annotation.PutMapping;
9 | import org.springframework.web.bind.annotation.RequestBody;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import pl.piomin.services.versioning.mapper.PersonMapper;
14 | import pl.piomin.services.versioning.model.PersonCurrent;
15 | import pl.piomin.services.versioning.model.PersonOld;
16 | import pl.piomin.services.versioning.repository.PersonRepository;
17 |
18 | @RestController
19 | @RequestMapping("/person")
20 | public class PersonController {
21 |
22 | @Autowired
23 | PersonMapper mapper;
24 | @Autowired
25 | PersonRepository repository;
26 |
27 | @PostMapping({"/v1.0", "/v1.1"})
28 | public PersonOld add(@RequestBody PersonOld person) {
29 | return (PersonOld) repository.add(person);
30 | }
31 |
32 | @PostMapping("/v1.2")
33 | public PersonCurrent add(@RequestBody PersonCurrent person) {
34 | // return mapper.map((PersonOld) repository.add(person));
35 | return (PersonCurrent) repository.add(person);
36 | }
37 |
38 | @PutMapping("/v1.0")
39 | @Deprecated
40 | public PersonOld update(@RequestBody PersonOld person) {
41 | return (PersonOld) repository.update(person);
42 | }
43 |
44 | @PutMapping("/v1.1/{id}")
45 | public PersonOld update(@PathVariable("id") Long id, @RequestBody PersonOld person) {
46 | return (PersonOld) repository.update(person);
47 | }
48 |
49 | @PutMapping("/v1.2/{id}")
50 | public PersonCurrent update(@PathVariable("id") Long id, @RequestBody PersonCurrent person) {
51 | return mapper.map((PersonOld) repository.update(person));
52 | }
53 |
54 | @GetMapping({"/v1.0/{id}", "/v1.1/{id}"})
55 | public PersonOld findByIdOld(@PathVariable("id") Long id) {
56 | return (PersonOld) repository.findById(id);
57 | }
58 |
59 | @GetMapping("/v1.2/{id}")
60 | public PersonCurrent findById(@PathVariable("id") Long id) {
61 | return mapper.map((PersonOld) repository.findById(id));
62 | }
63 |
64 | @DeleteMapping({"/v1.0/{id}", "/v1.1/{id}", "/v1.2/{id}"})
65 | public void delete(@PathVariable("id") Long id) {
66 | repository.delete(id);
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/controller/PersonControllerWithHeaders.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning.controller;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.web.bind.annotation.*;
5 | import pl.piomin.services.versioning.mapper.PersonMapper;
6 | import pl.piomin.services.versioning.model.PersonCurrent;
7 | import pl.piomin.services.versioning.model.PersonOld;
8 | import pl.piomin.services.versioning.repository.PersonRepository;
9 |
10 | @RestController
11 | @RequestMapping("/persons-via-headers")
12 | public class PersonControllerWithHeaders {
13 |
14 | @Autowired
15 | PersonMapper mapper;
16 | @Autowired
17 | PersonRepository repository;
18 |
19 | @PostMapping(headers = "X-VERSION=v1.0")
20 | public PersonOld add(@RequestBody PersonOld person) {
21 | return (PersonOld) repository.add(person);
22 | }
23 |
24 | @PostMapping(headers = "X-VERSION=v1.2")
25 | public PersonCurrent add(@RequestBody PersonCurrent person) {
26 | return (PersonCurrent) repository.add(person);
27 | }
28 |
29 | @PutMapping(headers = "X-VERSION=v1.0")
30 | @Deprecated
31 | public PersonOld update(@RequestBody PersonOld person) {
32 | return (PersonOld) repository.update(person);
33 | }
34 |
35 | @PutMapping(value = "/{id}", headers = "X-VERSION=v1.1")
36 | public PersonOld update(@PathVariable("id") Long id, @RequestBody PersonOld person) {
37 | return (PersonOld) repository.update(person);
38 | }
39 |
40 | @PutMapping(value = "/{id}", headers = "X-VERSION=v1.2")
41 | public PersonCurrent update(@PathVariable("id") Long id, @RequestBody PersonCurrent person) {
42 | return mapper.map((PersonOld) repository.update(person));
43 | }
44 |
45 | @GetMapping(value = "/{id}", headers = "X-VERSION=v1.0")
46 | public PersonOld findByIdOld(@PathVariable("id") Long id) {
47 | return (PersonOld) repository.findById(id);
48 | }
49 |
50 | @GetMapping(value = "/{id}", headers = "X-VERSION=v1.2")
51 | public PersonCurrent findById(@PathVariable("id") Long id) {
52 | return mapper.map((PersonOld) repository.findById(id));
53 | }
54 |
55 | @DeleteMapping("/{id}")
56 | public void delete(@PathVariable("id") Long id) {
57 | repository.delete(id);
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/mapper/PersonMapper.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning.mapper;
2 |
3 | import java.time.LocalDate;
4 | import java.time.Period;
5 |
6 | import org.springframework.stereotype.Component;
7 |
8 | import pl.piomin.services.versioning.model.PersonCurrent;
9 | import pl.piomin.services.versioning.model.PersonOld;
10 |
11 | @Component
12 | public class PersonMapper {
13 |
14 | public PersonCurrent map(PersonOld person) {
15 | int age = Period.between(person.getBirthDate(), LocalDate.now()).getYears();
16 | return new PersonCurrent(person.getId(), person.getName(), person.getGender(), age);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/model/Gender.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning.model;
2 |
3 | public enum Gender {
4 |
5 | MALE, FEMALE;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/model/Person.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning.model;
2 |
3 | public abstract class Person {
4 |
5 | private Long id;
6 | private String name;
7 | private Gender gender;
8 |
9 | public Person() {
10 |
11 | }
12 |
13 | public Person(Long id, String name, Gender gender) {
14 | this.id = id;
15 | this.name = name;
16 | this.gender = gender;
17 | }
18 |
19 | public Long getId() {
20 | return id;
21 | }
22 |
23 | public void setId(Long id) {
24 | this.id = id;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | public void setName(String name) {
32 | this.name = name;
33 | }
34 |
35 | public Gender getGender() {
36 | return gender;
37 | }
38 |
39 | public void setGender(Gender gender) {
40 | this.gender = gender;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/model/PersonCurrent.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning.model;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 |
5 | @Schema(name = "Person")
6 | public class PersonCurrent extends Person {
7 |
8 | private int age;
9 |
10 | public PersonCurrent() {
11 |
12 | }
13 |
14 | public PersonCurrent(Long id, String name, Gender gender, int age) {
15 | super(id, name, gender);
16 | this.age = age;
17 | }
18 |
19 | public int getAge() {
20 | return age;
21 | }
22 |
23 | public void setAge(int age) {
24 | this.age = age;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/model/PersonOld.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonFormat;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 |
6 | import java.time.LocalDate;
7 |
8 | @Schema(name = "Person")
9 | public class PersonOld extends Person {
10 |
11 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
12 | private LocalDate birthDate;
13 |
14 | public PersonOld() {
15 |
16 | }
17 |
18 | public PersonOld(Long id, String name, Gender gender, LocalDate birthDate) {
19 | super(id, name, gender);
20 | this.birthDate = birthDate;
21 | }
22 |
23 | public LocalDate getBirthDate() {
24 | return birthDate;
25 | }
26 |
27 | public void setBirthDate(LocalDate birthDate) {
28 | this.birthDate = birthDate;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/pl/piomin/services/versioning/repository/PersonRepository.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning.repository;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Optional;
6 |
7 | import pl.piomin.services.versioning.model.Person;
8 |
9 | public class PersonRepository {
10 |
11 | private List persons = new ArrayList<>();
12 |
13 | public Person add(Person person) {
14 | person.setId((long) (persons.size()+1));
15 | persons.add(person);
16 | return person;
17 | }
18 |
19 | public Person update(Person person) {
20 | persons.set(person.getId().intValue() - 1, person);
21 | return person;
22 | }
23 |
24 | public Person update(Long id, Person person) {
25 | persons.set(id.intValue() - 1, person);
26 | return person;
27 | }
28 |
29 | public Person findById(Long id) {
30 | Optional person = persons.stream().filter(a -> a.getId().equals(id)).findFirst();
31 | if (person.isPresent())
32 | return person.get();
33 | else
34 | return null;
35 | }
36 |
37 | public void delete(Long id) {
38 | persons.remove(id.intValue());
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8090
--------------------------------------------------------------------------------
/src/test/java/pl/piomin/services/versioning/PersonControllerTests.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning;
2 |
3 | import org.instancio.Instancio;
4 | import org.junit.jupiter.api.MethodOrderer;
5 | import org.junit.jupiter.api.Order;
6 | import org.junit.jupiter.api.Test;
7 | import org.junit.jupiter.api.TestMethodOrder;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.boot.test.context.SpringBootTest;
10 | import org.springframework.boot.test.web.client.TestRestTemplate;
11 | import pl.piomin.services.versioning.model.PersonCurrent;
12 | import pl.piomin.services.versioning.model.PersonOld;
13 |
14 | import static org.junit.jupiter.api.Assertions.*;
15 |
16 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
17 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
18 | public class PersonControllerTests {
19 |
20 | @Autowired
21 | TestRestTemplate restTemplate;
22 |
23 | @Test
24 | @Order(1)
25 | void addV0() {
26 | PersonOld p = restTemplate.postForObject("/person/v1.1", Instancio.create(PersonOld.class), PersonOld.class);
27 | assertNotNull(p);
28 | assertNotNull(p.getId());
29 | }
30 |
31 | @Test
32 | @Order(2)
33 | void addV2() {
34 | PersonCurrent p = restTemplate.postForObject("/person/v1.2", Instancio.create(PersonCurrent.class), PersonCurrent.class);
35 | assertNotNull(p);
36 | assertNotNull(p.getId());
37 | assertTrue(p.getAge() > 0);
38 | }
39 |
40 | @Test
41 | @Order(3)
42 | void findByIdV0() {
43 | PersonOld p = restTemplate.getForObject("/person/v1.0/{id}", PersonOld.class, 1);
44 | assertNotNull(p);
45 | assertNotNull(p.getId());
46 | }
47 |
48 | @Test
49 | @Order(3)
50 | void findByIdV2() {
51 | PersonCurrent p = restTemplate.getForObject("/person/v1.2/{id}", PersonCurrent.class, 2);
52 | assertNotNull(p);
53 | assertNotNull(p.getId());
54 | assertTrue(p.getAge() > 0);
55 | }
56 |
57 | @Test
58 | @Order(3)
59 | void findByIdV2ToV1Compability() {
60 | PersonCurrent p = restTemplate.getForObject("/person/v1.2/{id}", PersonCurrent.class, 1);
61 | assertNotNull(p);
62 | assertNotNull(p.getId());
63 | assertTrue(p.getAge() > 0);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/test/java/pl/piomin/services/versioning/PersonControllerWithHeadersTests.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.versioning;
2 |
3 | import org.instancio.Instancio;
4 | import org.junit.jupiter.api.MethodOrderer;
5 | import org.junit.jupiter.api.Order;
6 | import org.junit.jupiter.api.Test;
7 | import org.junit.jupiter.api.TestMethodOrder;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.boot.test.context.SpringBootTest;
10 | import org.springframework.boot.test.web.client.TestRestTemplate;
11 | import org.springframework.http.HttpEntity;
12 | import org.springframework.http.HttpHeaders;
13 | import org.springframework.http.HttpMethod;
14 | import org.springframework.http.ResponseEntity;
15 | import pl.piomin.services.versioning.model.PersonCurrent;
16 | import pl.piomin.services.versioning.model.PersonOld;
17 |
18 | import static org.junit.jupiter.api.Assertions.assertNotNull;
19 | import static org.junit.jupiter.api.Assertions.assertTrue;
20 |
21 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
22 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
23 | public class PersonControllerWithHeadersTests {
24 |
25 | @Autowired
26 | TestRestTemplate restTemplate;
27 |
28 | @Test
29 | @Order(1)
30 | void addV0() {
31 | HttpHeaders headers = new HttpHeaders();
32 | headers.add("X-VERSION", "v1.0");
33 | HttpEntity httpEntity = new HttpEntity<>(Instancio.create(PersonOld.class), headers);
34 | ResponseEntity p = restTemplate.exchange("/persons-via-headers", HttpMethod.POST, httpEntity, PersonOld.class);
35 | assertTrue(p.getStatusCode().is2xxSuccessful());
36 | assertNotNull(p.getBody());
37 | assertNotNull(p.getBody().getId());
38 | }
39 |
40 | @Test
41 | @Order(2)
42 | void addV2() {
43 | HttpHeaders headers = new HttpHeaders();
44 | headers.add("X-VERSION", "v1.2");
45 | HttpEntity httpEntity = new HttpEntity<>(Instancio.create(PersonCurrent.class), headers);
46 | ResponseEntity p = restTemplate.exchange("/persons-via-headers", HttpMethod.POST, httpEntity, PersonCurrent.class);
47 | assertTrue(p.getStatusCode().is2xxSuccessful());
48 | assertNotNull(p.getBody());
49 | assertNotNull(p.getBody().getId());
50 | assertTrue(p.getBody().getAge() > 0);
51 | }
52 |
53 | @Test
54 | @Order(3)
55 | void findByIdV0() {
56 | HttpHeaders headers = new HttpHeaders();
57 | headers.add("X-VERSION", "v1.0");
58 | HttpEntity httpEntity = new HttpEntity<>(headers);
59 | ResponseEntity p = restTemplate.exchange("/persons-via-headers/{id}", HttpMethod.GET, httpEntity, PersonOld.class, 1);
60 | assertTrue(p.getStatusCode().is2xxSuccessful());
61 | assertNotNull(p.getBody());
62 | assertNotNull(p.getBody().getId());
63 | }
64 |
65 | @Test
66 | @Order(3)
67 | void findByIdV2() {
68 | HttpHeaders headers = new HttpHeaders();
69 | headers.add("X-VERSION", "v1.2");
70 | HttpEntity httpEntity = new HttpEntity<>(headers);
71 | ResponseEntity p = restTemplate.exchange("/persons-via-headers/{id}", HttpMethod.GET, httpEntity, PersonCurrent.class, 2);
72 | assertTrue(p.getStatusCode().is2xxSuccessful());
73 | assertNotNull(p.getBody());
74 | assertNotNull(p.getBody().getId());
75 | assertTrue(p.getBody().getAge() > 0);
76 | }
77 |
78 | @Test
79 | @Order(3)
80 | void findByIdV2ToV1Compability() {
81 | HttpHeaders headers = new HttpHeaders();
82 | headers.add("X-VERSION", "v1.2");
83 | HttpEntity httpEntity = new HttpEntity<>(headers);
84 | ResponseEntity p = restTemplate.exchange("/persons-via-headers/{id}", HttpMethod.GET, httpEntity, PersonCurrent.class, 1);
85 | assertTrue(p.getStatusCode().is2xxSuccessful());
86 | assertNotNull(p.getBody());
87 | assertNotNull(p.getBody().getId());
88 | assertTrue(p.getBody().getAge() > 0);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------