diff --git a/pom.xml b/pom.xml
index 3c77d52fe837068427f592049d402ad0f22a3477..d35db9f34122b7aa268511d3a9f36983dbd927de 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,11 +19,16 @@
 
     <properties>
         <spring-data-jdbc.version>1.2.1.RELEASE</spring-data-jdbc.version>
-        <springfox-swagger.version>2.9.2</springfox-swagger.version>
+        <springfox-swagger.version>3.0.0</springfox-swagger.version>
         <jacoco.version>0.8.5</jacoco.version>
-
         <docker.jib-maven-plugin.version>1.3.0</docker.jib-maven-plugin.version>
         <docker.image.prefix>springcommunity</docker.image.prefix>
+        <jsr305.version>3.0.2</jsr305.version>
+        <jackson-databind-nullable.version>0.2.1</jackson-databind-nullable.version>
+        <mapstruct.version>1.4.1.Final</mapstruct.version>
+        <jaxb-api.version>2.3.0</jaxb-api.version>
+        <openapi-generator-maven-plugin.version>5.2.1</openapi-generator-maven-plugin.version>
+        <build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version>
     </properties>
 
     <dependencies>
@@ -123,16 +128,26 @@
             <artifactId>json-path</artifactId>
             <scope>test</scope>
         </dependency>
-
         <dependency>
             <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger2</artifactId>
+            <artifactId>springfox-boot-starter</artifactId>
             <version>${springfox-swagger.version}</version>
         </dependency>
+
         <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger-ui</artifactId>
-            <version>${springfox-swagger.version}</version>
+            <groupId>org.openapitools</groupId>
+            <artifactId>jackson-databind-nullable</artifactId>
+            <version>${jackson-databind-nullable.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct</artifactId>
+            <version>${mapstruct.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct-processor</artifactId>
+            <version>${mapstruct.version}</version>
         </dependency>
 
         <dependency>
@@ -144,7 +159,7 @@
         <dependency>
             <groupId>javax.xml.bind</groupId>
             <artifactId>jaxb-api</artifactId>
-            <version>2.3.0</version>
+            <version>${jaxb-api.version}</version>
         </dependency>
     </dependencies>
 
@@ -234,7 +249,90 @@
                     </to>
                 </configuration>
             </plugin>
+
+
+            <plugin>
+                <groupId>org.openapitools</groupId>
+                <artifactId>openapi-generator-maven-plugin</artifactId>
+                <!-- RELEASE_VERSION -->
+                <version>${openapi-generator-maven-plugin.version}</version>
+                <!-- /RELEASE_VERSION -->
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                        <configuration>
+                            <inputSpec>${project.basedir}/src/main/resources/api-docs.yml</inputSpec>
+                            <modelPackage>org.springframework.samples.petclinic.dto</modelPackage>
+                            <generatorName>spring</generatorName>
+                            <library>spring-boot</library>
+
+                            <!-- Only enabling model generation -->
+                            <modelNameSuffix>Dto</modelNameSuffix>
+                            <generateApiTests>false</generateApiTests>
+                            <generateModelDocumentation>false</generateModelDocumentation>
+                            <generateModelTests>false</generateModelTests>
+                            <generateApis>false</generateApis>
+                            <generateApiDocumentation>false</generateApiDocumentation>
+                            <generateModels>true</generateModels>
+                            <generateSupportingFiles>false</generateSupportingFiles>
+                            <!-- Activating JAVA8 features -->
+                            <configOptions>
+                                <performBeanValidation>true</performBeanValidation>
+                                <dateLibrary>legacy</dateLibrary>
+                                <java8>true</java8>
+                                <openApiNullable>false</openApiNullable>
+                                <serializationLibrary>jackson</serializationLibrary>
+                            </configOptions>
+                            <!-- override the default library to jersey2 -->
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>${build-helper-maven-plugin.version}</version>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>target/generated-sources/openapi/src/main/java</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.mapstruct</groupId>
+                            <artifactId>mapstruct-processor</artifactId>
+                            <version>${mapstruct.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                    <compilerArgs>
+                        <compilerArg>
+                            -Amapstruct.suppressGeneratorTimestamp=true
+                        </compilerArg>
+                        <compilerArg>
+                            -Amapstruct.suppressGeneratorVersionInfoComment=true
+                        </compilerArg>
+                        <compilerArg>
+                            -Amapstruct.defaultComponentModel=spring
+                        </compilerArg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
-
 </project>
diff --git a/readme.md b/readme.md
index 6f2490f9d537805f56e8d0fe28f3aa37300f31a8..8ee0d540164df29c89a40e256109aa246cfc865d 100644
--- a/readme.md
+++ b/readme.md
@@ -33,8 +33,12 @@ There are actuator health check and info routes as well:
 * [http://localhost:9966/petclinic/actuator/health](http://localhost:9966/petclinic/actuator/health)
 * [http://localhost:9966/petclinic/actuator/info](http://localhost:9966/petclinic/actuator/info)
 
-## Swagger REST API documentation presented here (after application start):
-[http://localhost:9966/petclinic/swagger-ui.html](http://localhost:9966/petclinic/swagger-ui.html)
+## OpenAPI REST API documentation presented here (after application start):
+
+You can reach the swagger UI with this URL
+[http://localhost:9966/petclinic/](http://localhost:9966/petclinic/swagger-ui.html).
+
+You then can get the Open API description reaching this URL [localhost:9966/petclinic/v3/api-docs](localhost:9966/petclinic/v3/api-docs).
 
 ## Screenshot of the Angular client
 
diff --git a/src/main/java/org/springframework/samples/petclinic/mapper/OwnerMapper.java b/src/main/java/org/springframework/samples/petclinic/mapper/OwnerMapper.java
new file mode 100755
index 0000000000000000000000000000000000000000..193e2f2c96c40dba93b93d668a3ddef90458d4bc
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/mapper/OwnerMapper.java
@@ -0,0 +1,22 @@
+package org.springframework.samples.petclinic.mapper;
+
+import org.mapstruct.Mapper;
+import org.springframework.samples.petclinic.dto.OwnerDto;
+import org.springframework.samples.petclinic.model.Owner;
+
+import java.util.Collection;
+
+/**
+ * Maps Owner & OwnerDto using Mapstruct
+ */
+@Mapper(uses = PetMapper.class)
+public interface OwnerMapper {
+
+    OwnerDto toOwnerDto(Owner owner);
+
+    Owner toOwner(OwnerDto ownerDto);
+
+    Collection<OwnerDto> toOwnerDtoCollection(Collection<Owner> ownerCollection);
+
+    Collection<Owner> toOwners(Collection<OwnerDto> ownerDtos);
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/mapper/PetMapper.java b/src/main/java/org/springframework/samples/petclinic/mapper/PetMapper.java
new file mode 100755
index 0000000000000000000000000000000000000000..a455d33fd15aa670c16d339a2fc30faa19ddcda3
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/mapper/PetMapper.java
@@ -0,0 +1,29 @@
+package org.springframework.samples.petclinic.mapper;
+
+import org.mapstruct.Mapper;
+import org.springframework.samples.petclinic.dto.PetDto;
+import org.springframework.samples.petclinic.dto.PetTypeDto;
+import org.springframework.samples.petclinic.model.Pet;
+import org.springframework.samples.petclinic.model.PetType;
+
+import java.util.Collection;
+
+/**
+ * Map Pet & PetDto using mapstruct
+ */
+@Mapper
+public interface PetMapper {
+    PetDto toPetDto(Pet pet);
+
+    Collection<PetDto> toPetsDto(Collection<Pet> pets);
+
+    Collection<Pet> toPets(Collection<PetDto> pets);
+
+    Pet toPet(PetDto petDto);
+
+    PetTypeDto toPetTypeDto(PetType petType);
+
+    PetType toPetType(PetTypeDto petTypeDto);
+
+    Collection<PetTypeDto> toPetTypeDtos(Collection<PetType> petTypes);
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/mapper/PetTypeMapper.java b/src/main/java/org/springframework/samples/petclinic/mapper/PetTypeMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8e096f45c9eb4838ede013caa9821cf045eb4ea
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/mapper/PetTypeMapper.java
@@ -0,0 +1,20 @@
+package org.springframework.samples.petclinic.mapper;
+
+import org.mapstruct.Mapper;
+import org.springframework.samples.petclinic.dto.PetTypeDto;
+import org.springframework.samples.petclinic.model.PetType;
+
+import java.util.Collection;
+
+/**
+ * Map PetType & PetTypeDto using mapstruct
+ */
+@Mapper
+public interface PetTypeMapper {
+
+    PetType toPetType(PetTypeDto petTypeDto);
+
+    PetTypeDto toPetTypeDto(PetType petType);
+
+    Collection<PetTypeDto> toPetTypeDtos(Collection<PetType> petTypes);
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/mapper/SpecialtyMapper.java b/src/main/java/org/springframework/samples/petclinic/mapper/SpecialtyMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e0a2c853f24dc244dc46ddadad021ac327962ea
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/mapper/SpecialtyMapper.java
@@ -0,0 +1,22 @@
+package org.springframework.samples.petclinic.mapper;
+
+import org.mapstruct.Mapper;
+import org.springframework.samples.petclinic.dto.SpecialtyDto;
+import org.springframework.samples.petclinic.model.Specialty;
+
+import java.util.Collection;
+
+/**
+ * Map Specialty & SpecialtyDto using mapstruct
+ */
+@Mapper
+public interface SpecialtyMapper {
+    Specialty toSpecialty(SpecialtyDto specialtyDto);
+
+    SpecialtyDto toSpecialtyDto(Specialty specialty);
+
+    Collection<SpecialtyDto> toSpecialtyDtos(Collection<Specialty> specialties);
+
+    Collection<Specialty> toSpecialtys(Collection<SpecialtyDto> specialties);
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/mapper/UserMapper.java b/src/main/java/org/springframework/samples/petclinic/mapper/UserMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..a79985e0d136a839c9cfbf381b24c15bff7588fe
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/mapper/UserMapper.java
@@ -0,0 +1,28 @@
+package org.springframework.samples.petclinic.mapper;
+
+import org.mapstruct.Mapper;
+import org.springframework.samples.petclinic.dto.RoleDto;
+import org.springframework.samples.petclinic.dto.UserDto;
+import org.springframework.samples.petclinic.model.Role;
+import org.springframework.samples.petclinic.model.User;
+
+import java.util.Collection;
+
+/**
+ * Map User/Role & UserDto/RoleDto using mapstruct
+ */
+@Mapper
+public interface UserMapper {
+    Role toRole(RoleDto roleDto);
+
+    RoleDto toRoleDto(Role role);
+
+    Collection<RoleDto> toRoleDtos(Collection<Role> roles);
+
+    User toUser(UserDto userDto);
+
+    UserDto toUserDto(User user);
+
+    Collection<Role> toRoles(Collection<RoleDto> roleDtos);
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/mapper/VetMapper.java b/src/main/java/org/springframework/samples/petclinic/mapper/VetMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..79fb0262bb5c9b64bbea8358b080ea6aa4e31853
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/mapper/VetMapper.java
@@ -0,0 +1,19 @@
+package org.springframework.samples.petclinic.mapper;
+
+import org.mapstruct.Mapper;
+import org.springframework.samples.petclinic.dto.VetDto;
+import org.springframework.samples.petclinic.model.Vet;
+
+import java.util.Collection;
+
+/**
+ * Map Vet & VetoDto using mapstruct
+ */
+@Mapper(uses = SpecialtyMapper.class)
+public interface VetMapper {
+    Vet toVet(VetDto vetDto);
+
+    VetDto toVetDto(Vet vet);
+
+    Collection<VetDto> toVetDtos(Collection<Vet> vets);
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/mapper/VisitMapper.java b/src/main/java/org/springframework/samples/petclinic/mapper/VisitMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..36fe15768dc7c93144f1c6e36219f395f325523e
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/mapper/VisitMapper.java
@@ -0,0 +1,20 @@
+package org.springframework.samples.petclinic.mapper;
+
+import org.mapstruct.Mapper;
+import org.springframework.samples.petclinic.dto.VisitDto;
+import org.springframework.samples.petclinic.model.Visit;
+
+import java.util.Collection;
+
+/**
+ * Map Visit & VisitDto using mapstruct
+ */
+@Mapper(uses = PetMapper.class)
+public interface VisitMapper {
+    Visit toVisit(VisitDto visitDto);
+
+    VisitDto toVisitDto(Visit visit);
+
+    Collection<VisitDto> toVisitsDto(Collection<Visit> visits);
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Owner.java b/src/main/java/org/springframework/samples/petclinic/model/Owner.java
index e957e86aefd0762a13e521317892856d87c9aecd..8591cbfdc27107277b1066ee412ee84c98f959d8 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Owner.java
+++ b/src/main/java/org/springframework/samples/petclinic/model/Owner.java
@@ -15,30 +15,15 @@
  */
 package org.springframework.samples.petclinic.model;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import javax.validation.constraints.Digits;
-import javax.validation.constraints.NotEmpty;
-
 import org.springframework.beans.support.MutableSortDefinition;
 import org.springframework.beans.support.PropertyComparator;
 import org.springframework.core.style.ToStringCreator;
-import org.springframework.samples.petclinic.rest.JacksonCustomOwnerDeserializer;
-import org.springframework.samples.petclinic.rest.JacksonCustomOwnerSerializer;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import javax.persistence.*;
+import javax.validation.constraints.Digits;
+import javax.validation.constraints.NotEmpty;
+import java.util.*;
+
 
 /**
  * Simple JavaBean domain object representing an owner.
@@ -50,8 +35,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
  */
 @Entity
 @Table(name = "owners")
-@JsonSerialize(using = JacksonCustomOwnerSerializer.class)
-@JsonDeserialize(using = JacksonCustomOwnerDeserializer.class)
 public class Owner extends Person {
     @Column(name = "address")
     @NotEmpty
@@ -93,7 +76,7 @@ public class Owner extends Person {
     public void setTelephone(String telephone) {
         this.telephone = telephone;
     }
-    @JsonIgnore
+
     protected Set<Pet> getPetsInternal() {
         if (this.pets == null) {
             this.pets = new HashSet<>();
@@ -111,6 +94,10 @@ public class Owner extends Person {
         return Collections.unmodifiableList(sortedPets);
     }
 
+    public void setPets(List<Pet> pets) {
+        this.pets = new HashSet<>(pets);
+    }
+
     public void addPet(Pet pet) {
         getPetsInternal().add(pet);
         pet.setOwner(this);
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Pet.java b/src/main/java/org/springframework/samples/petclinic/model/Pet.java
index 329f71872dd4f9a51188e45c79bedc35157d2fd0..bee28ffbdc7222ddd41924afef6a86c5dc3581a5 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Pet.java
+++ b/src/main/java/org/springframework/samples/petclinic/model/Pet.java
@@ -15,33 +15,13 @@
  */
 package org.springframework.samples.petclinic.model;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-
 import org.springframework.beans.support.MutableSortDefinition;
 import org.springframework.beans.support.PropertyComparator;
 import org.springframework.format.annotation.DateTimeFormat;
-import org.springframework.samples.petclinic.rest.JacksonCustomPetDeserializer;
-import org.springframework.samples.petclinic.rest.JacksonCustomPetSerializer;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import javax.persistence.*;
+import java.util.*;
+
 
 /**
  * Simple business object representing a pet.
@@ -52,8 +32,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
  */
 @Entity
 @Table(name = "pets")
-@JsonSerialize(using = JacksonCustomPetSerializer.class)
-@JsonDeserialize(using = JacksonCustomPetDeserializer.class)
 public class Pet extends NamedEntity {
 
     @Column(name = "birth_date")
@@ -72,15 +50,14 @@ public class Pet extends NamedEntity {
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "pet", fetch = FetchType.EAGER)
     private Set<Visit> visits;
 
+    public Date getBirthDate() {
+        return this.birthDate;
+    }
 
     public void setBirthDate(Date birthDate) {
         this.birthDate = birthDate;
     }
 
-    public Date getBirthDate() {
-        return this.birthDate;
-    }
-
     public PetType getType() {
         return this.type;
     }
@@ -96,7 +73,7 @@ public class Pet extends NamedEntity {
     public void setOwner(Owner owner) {
         this.owner = owner;
     }
-    @JsonIgnore
+
     protected Set<Visit> getVisitsInternal() {
         if (this.visits == null) {
             this.visits = new HashSet<>();
@@ -114,6 +91,10 @@ public class Pet extends NamedEntity {
         return Collections.unmodifiableList(sortedVisits);
     }
 
+    public void setVisits(List<Visit> visits) {
+        this.visits = new HashSet<>(visits);
+    }
+
     public void addVisit(Visit visit) {
         getVisitsInternal().add(visit);
         visit.setPet(this);
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Vet.java b/src/main/java/org/springframework/samples/petclinic/model/Vet.java
index e7c2aa781b36f3281d7d334f857454161de28289..acda93e939a3eaf70b8230aaad8d72bdcb2d92ef 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Vet.java
+++ b/src/main/java/org/springframework/samples/petclinic/model/Vet.java
@@ -15,24 +15,13 @@
  */
 package org.springframework.samples.petclinic.model;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.Table;
-import javax.xml.bind.annotation.XmlElement;
-
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import org.springframework.beans.support.MutableSortDefinition;
 import org.springframework.beans.support.PropertyComparator;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
+import javax.persistence.*;
+import javax.xml.bind.annotation.XmlElement;
+import java.util.*;
 
 /**
  * Simple JavaBean domain object representing a veterinarian.
@@ -50,7 +39,7 @@ public class Vet extends Person {
     @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"),
         inverseJoinColumns = @JoinColumn(name = "specialty_id"))
     private Set<Specialty> specialties;
-    
+
     @JsonIgnore
     protected Set<Specialty> getSpecialtiesInternal() {
         if (this.specialties == null) {
@@ -69,6 +58,11 @@ public class Vet extends Person {
         PropertyComparator.sort(sortedSpecs, new MutableSortDefinition("name", true, true));
         return Collections.unmodifiableList(sortedSpecs);
     }
+
+    public void setSpecialties(List<Specialty> specialties) {
+        this.specialties = new HashSet<>(specialties);
+    }
+
     @JsonIgnore
     public int getNrOfSpecialties() {
         return getSpecialtiesInternal().size();
@@ -77,7 +71,7 @@ public class Vet extends Person {
     public void addSpecialty(Specialty specialty) {
         getSpecialtiesInternal().add(specialty);
     }
-    
+
     public void clearSpecialties() {
         getSpecialtiesInternal().clear();
     }
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Visit.java b/src/main/java/org/springframework/samples/petclinic/model/Visit.java
index 05a39cdc1681d13479461e6c1c28640ed6d94164..e030aae1d22e7e3dc7d9a3b0d9493a3fe9e89a5e 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Visit.java
+++ b/src/main/java/org/springframework/samples/petclinic/model/Visit.java
@@ -15,24 +15,12 @@
  */
 package org.springframework.samples.petclinic.model;
 
-import java.util.Date;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-
-import javax.validation.constraints.NotEmpty;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import org.springframework.format.annotation.DateTimeFormat;
-import org.springframework.samples.petclinic.rest.JacksonCustomVisitDeserializer;
-import org.springframework.samples.petclinic.rest.JacksonCustomVisitSerializer;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import javax.persistence.*;
+import javax.validation.constraints.NotEmpty;
+import java.util.Date;
 
 /**
  * Simple JavaBean domain object representing a visit.
@@ -41,8 +29,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
  */
 @Entity
 @Table(name = "visits")
-@JsonSerialize(using = JacksonCustomVisitSerializer.class)
-@JsonDeserialize(using = JacksonCustomVisitDeserializer.class)
 public class Visit extends BaseEntity {
 
     /**
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java
index f4fc842f9710e146907dbfda34442b817e5c4143..0b3bc28a5d44ea5a8e1dde8cd65e5c2f536cfb57 100644
--- a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java
@@ -15,14 +15,6 @@
  */
 package org.springframework.samples.petclinic.repository.jdbc;
 
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.sql.DataSource;
-import javax.transaction.Transactional;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Profile;
 import org.springframework.dao.DataAccessException;
@@ -40,6 +32,13 @@ import org.springframework.samples.petclinic.repository.OwnerRepository;
 import org.springframework.samples.petclinic.util.EntityUtils;
 import org.springframework.stereotype.Repository;
 
+import javax.sql.DataSource;
+import javax.transaction.Transactional;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * A simple JDBC-based implementation of the {@link OwnerRepository} interface.
  *
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/springdatajpa/SpringDataPetTypeRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/springdatajpa/SpringDataPetTypeRepositoryImpl.java
index a02f9a447b496b3eef478e481515c573069cf191..70c619dbdd872fa1088b427c5a362d2f7d6fdaa1 100644
--- a/src/main/java/org/springframework/samples/petclinic/repository/springdatajpa/SpringDataPetTypeRepositoryImpl.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/springdatajpa/SpringDataPetTypeRepositoryImpl.java
@@ -16,17 +16,15 @@
 
 package org.springframework.samples.petclinic.repository.springdatajpa;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-
 import org.springframework.context.annotation.Profile;
 import org.springframework.samples.petclinic.model.Pet;
 import org.springframework.samples.petclinic.model.PetType;
 import org.springframework.samples.petclinic.model.Visit;
 
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.util.List;
+
 /**
  * @author Vitaliy Fedoriv
  *
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomOwnerDeserializer.java b/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomOwnerDeserializer.java
deleted file mode 100644
index d629b8b501135cc7aa7b92a7eebfe5f0949090a5..0000000000000000000000000000000000000000
--- a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomOwnerDeserializer.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.samples.petclinic.rest;
-
-import java.io.IOException;
-
-import org.springframework.samples.petclinic.model.Owner;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-/**
- * @author Vitaliy Fedoriv
- *
- */
-
-public class JacksonCustomOwnerDeserializer extends StdDeserializer<Owner> {
-
-	public JacksonCustomOwnerDeserializer(){
-		this(null);
-	}
-
-	public JacksonCustomOwnerDeserializer(Class<Owner> t) {
-		super(t);
-	}
-
-	@Override
-	public Owner deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
-		JsonNode node = parser.getCodec().readTree(parser);
-		Owner owner = new Owner();
-		String firstName = node.get("firstName").asText(null);
-		String lastName = node.get("lastName").asText(null);
-		String address = node.get("address").asText(null);
-		String city = node.get("city").asText(null);
-		String telephone = node.get("telephone").asText(null);
-		if (node.hasNonNull("id")) {
-			owner.setId(node.get("id").asInt());
-		}
-        owner.setFirstName(firstName);
-        owner.setLastName(lastName);
-        owner.setAddress(address);
-        owner.setCity(city);
-        owner.setTelephone(telephone);
-		return owner;
-	}
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomOwnerSerializer.java b/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomOwnerSerializer.java
deleted file mode 100644
index 594d82a06a9227ca8b2a87ed2deb932902320e1d..0000000000000000000000000000000000000000
--- a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomOwnerSerializer.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.samples.petclinic.rest;
-
-import java.io.IOException;
-import java.text.Format;
-import java.text.SimpleDateFormat;
-
-import org.springframework.samples.petclinic.model.Owner;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.PetType;
-import org.springframework.samples.petclinic.model.Visit;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
-/**
- * @author Vitaliy Fedoriv
- *
- */
-
-public class JacksonCustomOwnerSerializer extends StdSerializer<Owner> {
-
-	public JacksonCustomOwnerSerializer() {
-		this(null);
-	}
-
-	public JacksonCustomOwnerSerializer(Class<Owner> t) {
-		super(t);
-	}
-
-	@Override
-	public void serialize(Owner owner, JsonGenerator jgen, SerializerProvider provider) throws IOException {
-		Format formatter = new SimpleDateFormat("yyyy/MM/dd");
-		jgen.writeStartObject();
-		if (owner.getId() == null) {
-			jgen.writeNullField("id");
-		} else {
-			jgen.writeNumberField("id", owner.getId());
-		}
-
-		jgen.writeStringField("firstName", owner.getFirstName());
-		jgen.writeStringField("lastName", owner.getLastName());
-		jgen.writeStringField("address", owner.getAddress());
-		jgen.writeStringField("city", owner.getCity());
-		jgen.writeStringField("telephone", owner.getTelephone());
-		// write pets array
-		jgen.writeArrayFieldStart("pets");
-		for (Pet pet : owner.getPets()) {
-			jgen.writeStartObject(); // pet
-			if (pet.getId() == null) {
-				jgen.writeNullField("id");
-			} else {
-				jgen.writeNumberField("id", pet.getId());
-			}
-			jgen.writeStringField("name", pet.getName());
-			jgen.writeStringField("birthDate", formatter.format(pet.getBirthDate()));
-
-			PetType petType = pet.getType();
-			jgen.writeObjectFieldStart("type");
-			jgen.writeNumberField("id", petType.getId());
-			jgen.writeStringField("name", petType.getName());
-			jgen.writeEndObject(); // type
-
-            if (pet.getOwner().getId() == null) {
-                jgen.writeNullField("owner");
-            } else {
-                jgen.writeNumberField("owner", pet.getOwner().getId());
-            }
-			// write visits array
-			jgen.writeArrayFieldStart("visits");
-			for (Visit visit : pet.getVisits()) {
-				jgen.writeStartObject(); // visit
-				if (visit.getId() == null) {
-					jgen.writeNullField("id");
-				} else {
-					jgen.writeNumberField("id", visit.getId());
-				}
-				jgen.writeStringField("date", formatter.format(visit.getDate()));
-				jgen.writeStringField("description", visit.getDescription());
-				jgen.writeNumberField("pet", visit.getPet().getId());
-				jgen.writeEndObject(); // visit
-			}
-			jgen.writeEndArray(); // visits
-			jgen.writeEndObject(); // pet
-		}
-		jgen.writeEndArray(); // pets
-		jgen.writeEndObject(); // owner
-	}
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomPetDeserializer.java b/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomPetDeserializer.java
deleted file mode 100644
index d879e88ee2439c2dd0145a13ce96bec2ab6d5ef8..0000000000000000000000000000000000000000
--- a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomPetDeserializer.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.samples.petclinic.rest;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.springframework.samples.petclinic.model.Owner;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.PetType;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-/**
- * @author Vitaliy Fedoriv
- *
- */
-
-public class JacksonCustomPetDeserializer extends StdDeserializer<Pet> {
-
-	public JacksonCustomPetDeserializer() {
-		this(null);
-	}
-
-	public JacksonCustomPetDeserializer(Class<Pet> t) {
-		super(t);
-	}
-
-	@Override
-	public Pet deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
-		SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
-		Pet pet = new Pet();
-		Owner owner = new Owner();
-		PetType petType = new PetType();
-		ObjectMapper mapper = new ObjectMapper();
-		Date birthDate = null;
-		JsonNode node = parser.getCodec().readTree(parser);
-		JsonNode owner_node = node.get("owner");
-		JsonNode type_node = node.get("type");
-		owner = mapper.treeToValue(owner_node, Owner.class);
-		petType = mapper.treeToValue(type_node, PetType.class);
-		int petId = node.get("id").asInt();
-		String name = node.get("name").asText(null);
-		String birthDateStr = node.get("birthDate").asText(null);
-		try {
-			birthDate = formatter.parse(birthDateStr);
-		} catch (ParseException e) {
-			e.printStackTrace();
-			throw new IOException(e);
-		}
-
-		if (!(petId == 0)) {
-			pet.setId(petId);
-		}
-		pet.setName(name);
-		pet.setBirthDate(birthDate);
-		pet.setOwner(owner);
-		pet.setType(petType);
-		return pet;
-	}
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomPetSerializer.java b/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomPetSerializer.java
deleted file mode 100644
index 9abb4b86522fdf6d24691a8a3ae62c2a32c113a3..0000000000000000000000000000000000000000
--- a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomPetSerializer.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.samples.petclinic.rest;
-
-import java.io.IOException;
-import java.text.Format;
-import java.text.SimpleDateFormat;
-
-import org.springframework.samples.petclinic.model.Owner;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.PetType;
-import org.springframework.samples.petclinic.model.Visit;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
-/**
- * @author Vitaliy Fedoriv
- *
- */
-
-public class JacksonCustomPetSerializer extends StdSerializer<Pet> {
-
-	public JacksonCustomPetSerializer() {
-		this(null);
-	}
-
-	protected JacksonCustomPetSerializer(Class<Pet> t) {
-		super(t);
-	}
-
-	@Override
-	public void serialize(Pet pet, JsonGenerator jgen, SerializerProvider provider) throws IOException {
-		Format formatter = new SimpleDateFormat("yyyy/MM/dd");
-		jgen.writeStartObject(); // pet
-		if (pet.getId() == null) {
-			jgen.writeNullField("id");
-		} else {
-			jgen.writeNumberField("id", pet.getId());
-		}
-		jgen.writeStringField("name", pet.getName());
-		jgen.writeStringField("birthDate", formatter.format(pet.getBirthDate()));
-
-		PetType petType = pet.getType();
-		jgen.writeObjectFieldStart("type");
-		jgen.writeNumberField("id", petType.getId());
-		jgen.writeStringField("name", petType.getName());
-		jgen.writeEndObject(); // type
-
-		Owner owner = pet.getOwner();
-		jgen.writeObjectFieldStart("owner");
-		jgen.writeNumberField("id", owner.getId());
-		jgen.writeStringField("firstName", owner.getFirstName());
-		jgen.writeStringField("lastName", owner.getLastName());
-		jgen.writeStringField("address", owner.getAddress());
-		jgen.writeStringField("city", owner.getCity());
-		jgen.writeStringField("telephone", owner.getTelephone());
-		jgen.writeEndObject(); // owner
-		// write visits array
-		jgen.writeArrayFieldStart("visits");
-		for (Visit visit : pet.getVisits()) {
-			jgen.writeStartObject(); // visit
-			jgen.writeNumberField("id", visit.getId());
-			jgen.writeStringField("date", formatter.format(visit.getDate()));
-			jgen.writeStringField("description", visit.getDescription());
-			jgen.writeNumberField("pet", visit.getPet().getId());
-			jgen.writeEndObject(); // visit
-		}
-		jgen.writeEndArray(); // visits
-		jgen.writeEndObject(); // pet
-	}
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomVisitDeserializer.java b/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomVisitDeserializer.java
deleted file mode 100644
index f71626e21006e5e8c62dd4ecd398d46a7bd27b93..0000000000000000000000000000000000000000
--- a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomVisitDeserializer.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.samples.petclinic.rest;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.Visit;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-/**
- * @author Vitaliy Fedoriv
- *
- */
-
-public class JacksonCustomVisitDeserializer extends StdDeserializer<Visit> {
-
-	public JacksonCustomVisitDeserializer() {
-		this(null);
-	}
-
-	public JacksonCustomVisitDeserializer(Class<Visit> t) {
-		super(t);
-	}
-
-	@Override
-	public Visit deserialize(JsonParser parser, DeserializationContext context)	throws IOException, JsonProcessingException {
-		SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
-		Visit visit = new Visit();
-		Pet pet = new Pet();
-		ObjectMapper mapper = new ObjectMapper();
-		Date visitDate = null;
-		JsonNode node = parser.getCodec().readTree(parser);
-		JsonNode pet_node = node.get("pet");
-		pet = mapper.treeToValue(pet_node, Pet.class);
-		int visitId = node.get("id").asInt();
-		String visitDateStr = node.get("date").asText(null);
-		String description = node.get("description").asText(null);
-		try {
-			visitDate = formatter.parse(visitDateStr);
-		} catch (ParseException e) {
-			e.printStackTrace();
-			throw new IOException(e);
-		}
-
-		if (!(visitId == 0)) {
-			visit.setId(visitId);
-		}
-		visit.setDate(visitDate);
-		visit.setDescription(description);
-		visit.setPet(pet);
-		return visit;
-	}
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomVisitSerializer.java b/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomVisitSerializer.java
deleted file mode 100644
index 84d7a8c798261b3fe4d088003d3d6459ba36a1a7..0000000000000000000000000000000000000000
--- a/src/main/java/org/springframework/samples/petclinic/rest/JacksonCustomVisitSerializer.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.samples.petclinic.rest;
-
-import java.io.IOException;
-import java.text.Format;
-import java.text.SimpleDateFormat;
-
-import org.springframework.samples.petclinic.model.Owner;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.PetType;
-import org.springframework.samples.petclinic.model.Visit;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
-/**
- * @author Vitaliy Fedoriv
- *
- */
-
-public class JacksonCustomVisitSerializer extends StdSerializer<Visit> {
-
-	public JacksonCustomVisitSerializer() {
-		this(null);
-	}
-
-	protected JacksonCustomVisitSerializer(Class<Visit> t) {
-		super(t);
-	}
-
-	@Override
-	public void serialize(Visit visit, JsonGenerator jgen, SerializerProvider provider) throws IOException {
-		if ((visit == null) || (visit.getPet() == null)) {
-			throw new IOException("Cannot serialize Visit object - visit or visit.pet is null");
-		}
-		Format formatter = new SimpleDateFormat("yyyy/MM/dd");
-		jgen.writeStartObject(); // visit
-		if (visit.getId() == null) {
-			jgen.writeNullField("id");
-		} else {
-			jgen.writeNumberField("id", visit.getId());
-		}
-		jgen.writeStringField("date", formatter.format(visit.getDate()));
-		jgen.writeStringField("description", visit.getDescription());
-
-		Pet pet = visit.getPet();
-		jgen.writeObjectFieldStart("pet");
-		if (pet.getId() == null) {
-			jgen.writeNullField("id");
-		} else {
-			jgen.writeNumberField("id", pet.getId());
-		}
-		jgen.writeStringField("name", pet.getName());
-		jgen.writeStringField("birthDate", formatter.format(pet.getBirthDate()));
-
-		PetType petType = pet.getType();
-		jgen.writeObjectFieldStart("type");
-		if (petType.getId() == null) {
-			jgen.writeNullField("id");
-		} else {
-			jgen.writeNumberField("id", petType.getId());
-		}
-		jgen.writeStringField("name", petType.getName());
-		jgen.writeEndObject(); // type
-
-		Owner owner = pet.getOwner();
-		jgen.writeObjectFieldStart("owner");
-		if (owner.getId() == null) {
-			jgen.writeNullField("id");
-		} else {
-			jgen.writeNumberField("id", owner.getId());
-		}
-		jgen.writeStringField("firstName", owner.getFirstName());
-		jgen.writeStringField("lastName", owner.getLastName());
-		jgen.writeStringField("address", owner.getAddress());
-		jgen.writeStringField("city", owner.getCity());
-		jgen.writeStringField("telephone", owner.getTelephone());
-		jgen.writeEndObject(); // owner
-		jgen.writeEndObject(); // pet
-		jgen.writeEndObject(); // visit
-	}
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/OwnerRestController.java b/src/main/java/org/springframework/samples/petclinic/rest/OwnerRestController.java
index 341adc0120cb96d68042d2cd3ef325face928553..d56042b243b49adeaea1554bf7359164b03d0a7f 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/OwnerRestController.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/OwnerRestController.java
@@ -16,28 +16,22 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import java.util.Collection;
-
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.samples.petclinic.dto.OwnerDto;
+import org.springframework.samples.petclinic.mapper.OwnerMapper;
 import org.springframework.samples.petclinic.model.Owner;
 import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import javax.transaction.Transactional;
+import javax.validation.Valid;
+import java.util.Collection;
+
 /**
  * @author Vitaliy Fedoriv
  */
@@ -47,82 +41,89 @@ import org.springframework.web.util.UriComponentsBuilder;
 @RequestMapping("/api/owners")
 public class OwnerRestController {
 
-    @Autowired
-    private ClinicService clinicService;
+    private final ClinicService clinicService;
+    private final OwnerMapper ownerMapper;
+
+    public OwnerRestController(ClinicService clinicService, OwnerMapper ownerMapper) {
+        this.clinicService = clinicService;
+        this.ownerMapper = ownerMapper;
+    }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "/*/lastname/{lastName}", method = RequestMethod.GET, produces = "application/json")
-    public ResponseEntity<Collection<Owner>> getOwnersList(@PathVariable("lastName") String ownerLastName) {
+    public ResponseEntity<Collection<OwnerDto>> getOwnersList(@PathVariable("lastName") String ownerLastName) {
         if (ownerLastName == null) {
             ownerLastName = "";
         }
         Collection<Owner> owners = this.clinicService.findOwnerByLastName(ownerLastName);
         if (owners.isEmpty()) {
-            return new ResponseEntity<Collection<Owner>>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
-        return new ResponseEntity<Collection<Owner>>(owners, HttpStatus.OK);
+        return new ResponseEntity<>(ownerMapper.toOwnerDtoCollection(owners), HttpStatus.OK);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
-    public ResponseEntity<Collection<Owner>> getOwners() {
+    public ResponseEntity<Collection<OwnerDto>> getOwners() {
         Collection<Owner> owners = this.clinicService.findAllOwners();
         if (owners.isEmpty()) {
-            return new ResponseEntity<Collection<Owner>>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
-        return new ResponseEntity<Collection<Owner>>(owners, HttpStatus.OK);
+        return new ResponseEntity<>(ownerMapper.toOwnerDtoCollection(owners), HttpStatus.OK);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "/{ownerId}", method = RequestMethod.GET, produces = "application/json")
-    public ResponseEntity<Owner> getOwner(@PathVariable("ownerId") int ownerId) {
+    public ResponseEntity<OwnerDto> getOwner(@PathVariable("ownerId") int ownerId) {
         Owner owner = null;
         owner = this.clinicService.findOwnerById(ownerId);
         if (owner == null) {
-            return new ResponseEntity<Owner>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
-        return new ResponseEntity<Owner>(owner, HttpStatus.OK);
+        return new ResponseEntity<>(ownerMapper.toOwnerDto(owner), HttpStatus.OK);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
-    public ResponseEntity<Owner> addOwner(@RequestBody @Valid Owner owner, BindingResult bindingResult,
-                                          UriComponentsBuilder ucBuilder) {
+    public ResponseEntity<OwnerDto> addOwner(@RequestBody @Valid OwnerDto ownerDto, BindingResult bindingResult,
+                                             UriComponentsBuilder ucBuilder) {
         HttpHeaders headers = new HttpHeaders();
-        if (bindingResult.hasErrors() || owner.getId() != null) {
-            BindingErrorsResponse errors = new BindingErrorsResponse(owner.getId());
+        if (bindingResult.hasErrors() || ownerDto.getId() != null) {
+            BindingErrorsResponse errors = new BindingErrorsResponse(ownerDto.getId());
             errors.addAllErrors(bindingResult);
             headers.add("errors", errors.toJSON());
-            return new ResponseEntity<Owner>(headers, HttpStatus.BAD_REQUEST);
+            return new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST);
         }
+        Owner owner = ownerMapper.toOwner(ownerDto);
         this.clinicService.saveOwner(owner);
+        ownerDto.setId(owner.getId());
         headers.setLocation(ucBuilder.path("/api/owners/{id}").buildAndExpand(owner.getId()).toUri());
-        return new ResponseEntity<Owner>(owner, headers, HttpStatus.CREATED);
+        return new ResponseEntity<>(ownerDto, headers, HttpStatus.CREATED);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "/{ownerId}", method = RequestMethod.PUT, produces = "application/json")
-    public ResponseEntity<Owner> updateOwner(@PathVariable("ownerId") int ownerId, @RequestBody @Valid Owner owner,
-                                             BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
-        boolean bodyIdMatchesPathId = owner.getId() == null || ownerId == owner.getId();
+    public ResponseEntity<OwnerDto> updateOwner(@PathVariable("ownerId") int ownerId, @RequestBody @Valid OwnerDto ownerDto,
+                                                BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
+        boolean bodyIdMatchesPathId = ownerDto.getId() == null || ownerId == ownerDto.getId();
         if (bindingResult.hasErrors() || !bodyIdMatchesPathId) {
-            BindingErrorsResponse errors = new BindingErrorsResponse(ownerId, owner.getId());
+            BindingErrorsResponse errors = new BindingErrorsResponse(ownerId, ownerDto.getId());
             errors.addAllErrors(bindingResult);
             HttpHeaders headers = new HttpHeaders();
             headers.add("errors", errors.toJSON());
-            return new ResponseEntity<Owner>(headers, HttpStatus.BAD_REQUEST);
+            return new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST);
         }
         Owner currentOwner = this.clinicService.findOwnerById(ownerId);
         if (currentOwner == null) {
-            return new ResponseEntity<Owner>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
-        currentOwner.setAddress(owner.getAddress());
-        currentOwner.setCity(owner.getCity());
-        currentOwner.setFirstName(owner.getFirstName());
-        currentOwner.setLastName(owner.getLastName());
-        currentOwner.setTelephone(owner.getTelephone());
+        currentOwner.setAddress(ownerDto.getAddress());
+        currentOwner.setCity(ownerDto.getCity());
+        currentOwner.setFirstName(ownerDto.getFirstName());
+        currentOwner.setLastName(ownerDto.getLastName());
+        currentOwner.setTelephone(ownerDto.getTelephone());
         this.clinicService.saveOwner(currentOwner);
-        return new ResponseEntity<Owner>(currentOwner, HttpStatus.NO_CONTENT);
+        return new ResponseEntity<>(ownerMapper.toOwnerDto(currentOwner), HttpStatus.NO_CONTENT);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
@@ -134,7 +135,7 @@ public class OwnerRestController {
             return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
         }
         this.clinicService.deleteOwner(owner);
-        return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
+        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/PetRestController.java b/src/main/java/org/springframework/samples/petclinic/rest/PetRestController.java
index fa077e91367a16bee024e4b1edefcc0d2ccf05be..f2ec45fd62dfbaeecca813da0a8281c6afe42eac 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/PetRestController.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/PetRestController.java
@@ -16,29 +16,23 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import java.util.Collection;
-
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.samples.petclinic.dto.PetDto;
+import org.springframework.samples.petclinic.dto.PetTypeDto;
+import org.springframework.samples.petclinic.mapper.PetMapper;
 import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.PetType;
 import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import javax.transaction.Transactional;
+import javax.validation.Valid;
+import java.util.Collection;
+
 /**
  * @author Vitaliy Fedoriv
  */
@@ -48,70 +42,77 @@ import org.springframework.web.util.UriComponentsBuilder;
 @RequestMapping("api/pets")
 public class PetRestController {
 
-    @Autowired
-    private ClinicService clinicService;
+    private final ClinicService clinicService;
+
+    private final PetMapper petMapper;
+
+    public PetRestController(ClinicService clinicService, PetMapper petMapper) {
+        this.clinicService = clinicService;
+        this.petMapper = petMapper;
+    }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "/{petId}", method = RequestMethod.GET, produces = "application/json")
-    public ResponseEntity<Pet> getPet(@PathVariable("petId") int petId) {
-        Pet pet = this.clinicService.findPetById(petId);
+    public ResponseEntity<PetDto> getPet(@PathVariable("petId") int petId) {
+        PetDto pet = petMapper.toPetDto(this.clinicService.findPetById(petId));
         if (pet == null) {
-            return new ResponseEntity<Pet>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<PetDto>(HttpStatus.NOT_FOUND);
         }
-        return new ResponseEntity<Pet>(pet, HttpStatus.OK);
+        return new ResponseEntity<PetDto>(pet, HttpStatus.OK);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
-    public ResponseEntity<Collection<Pet>> getPets() {
-        Collection<Pet> pets = this.clinicService.findAllPets();
+    public ResponseEntity<Collection<PetDto>> getPets() {
+        Collection<PetDto> pets = petMapper.toPetsDto(this.clinicService.findAllPets());
         if (pets.isEmpty()) {
-            return new ResponseEntity<Collection<Pet>>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<Collection<PetDto>>(HttpStatus.NOT_FOUND);
         }
-        return new ResponseEntity<Collection<Pet>>(pets, HttpStatus.OK);
+        return new ResponseEntity<Collection<PetDto>>(pets, HttpStatus.OK);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "/pettypes", method = RequestMethod.GET, produces = "application/json")
-    public ResponseEntity<Collection<PetType>> getPetTypes() {
-        return new ResponseEntity<Collection<PetType>>(this.clinicService.findPetTypes(), HttpStatus.OK);
+    public ResponseEntity<Collection<PetTypeDto>> getPetTypes() {
+        return new ResponseEntity<Collection<PetTypeDto>>(petMapper.toPetTypeDtos(this.clinicService.findPetTypes()), HttpStatus.OK);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
-    public ResponseEntity<Pet> addPet(@RequestBody @Valid Pet pet, BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
+    public ResponseEntity<PetDto> addPet(@RequestBody @Valid PetDto petDto, BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
         BindingErrorsResponse errors = new BindingErrorsResponse();
         HttpHeaders headers = new HttpHeaders();
-        if (bindingResult.hasErrors() || (pet == null)) {
+        if (bindingResult.hasErrors() || (petDto == null)) {
             errors.addAllErrors(bindingResult);
             headers.add("errors", errors.toJSON());
-            return new ResponseEntity<Pet>(headers, HttpStatus.BAD_REQUEST);
+            return new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST);
         }
+        Pet pet = petMapper.toPet(petDto);
         this.clinicService.savePet(pet);
+        petDto.setId(pet.getId());
         headers.setLocation(ucBuilder.path("/api/pets/{id}").buildAndExpand(pet.getId()).toUri());
-        return new ResponseEntity<Pet>(pet, headers, HttpStatus.CREATED);
+        return new ResponseEntity<>(petDto, headers, HttpStatus.CREATED);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
     @RequestMapping(value = "/{petId}", method = RequestMethod.PUT, produces = "application/json")
-    public ResponseEntity<Pet> updatePet(@PathVariable("petId") int petId, @RequestBody @Valid Pet pet, BindingResult bindingResult) {
+    public ResponseEntity<PetDto> updatePet(@PathVariable("petId") int petId, @RequestBody @Valid PetDto pet, BindingResult bindingResult) {
         BindingErrorsResponse errors = new BindingErrorsResponse();
         HttpHeaders headers = new HttpHeaders();
         if (bindingResult.hasErrors() || (pet == null)) {
             errors.addAllErrors(bindingResult);
             headers.add("errors", errors.toJSON());
-            return new ResponseEntity<Pet>(headers, HttpStatus.BAD_REQUEST);
+            return new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST);
         }
         Pet currentPet = this.clinicService.findPetById(petId);
         if (currentPet == null) {
-            return new ResponseEntity<Pet>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
         currentPet.setBirthDate(pet.getBirthDate());
         currentPet.setName(pet.getName());
-        currentPet.setType(pet.getType());
-        currentPet.setOwner(pet.getOwner());
+        currentPet.setType(petMapper.toPetType(pet.getType()));
         this.clinicService.savePet(currentPet);
-        return new ResponseEntity<Pet>(currentPet, HttpStatus.NO_CONTENT);
+        return new ResponseEntity<>(petMapper.toPetDto(currentPet), HttpStatus.NO_CONTENT);
     }
 
     @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/PetTypeRestController.java b/src/main/java/org/springframework/samples/petclinic/rest/PetTypeRestController.java
index ff6728769973dfffbb81a960b4cc1d9fc19d604f..89a5438e81d90ea4c25589c3a8c0f5928e948cd5 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/PetTypeRestController.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/PetTypeRestController.java
@@ -16,102 +16,103 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.samples.petclinic.dto.PetTypeDto;
+import org.springframework.samples.petclinic.mapper.PetTypeMapper;
 import org.springframework.samples.petclinic.model.PetType;
 import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import javax.transaction.Transactional;
+import javax.validation.Valid;
+import java.util.ArrayList;
+import java.util.Collection;
+
 @RestController
 @CrossOrigin(exposedHeaders = "errors, content-type")
 @RequestMapping("api/pettypes")
 public class PetTypeRestController {
 
-	@Autowired
-	private ClinicService clinicService;
+    private final ClinicService clinicService;
+    private final PetTypeMapper petTypeMapper;
+
+
+    public PetTypeRestController(ClinicService clinicService, PetTypeMapper petTypeMapper) {
+        this.clinicService = clinicService;
+        this.petTypeMapper = petTypeMapper;
+    }
 
-    @PreAuthorize( "hasAnyRole(@roles.OWNER_ADMIN, @roles.VET_ADMIN)" )
-	@RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
-	public ResponseEntity<Collection<PetType>> getAllPetTypes(){
-		Collection<PetType> petTypes = new ArrayList<PetType>();
-		petTypes.addAll(this.clinicService.findAllPetTypes());
-		if (petTypes.isEmpty()){
-			return new ResponseEntity<Collection<PetType>>(HttpStatus.NOT_FOUND);
-		}
-		return new ResponseEntity<Collection<PetType>>(petTypes, HttpStatus.OK);
-	}
+    @PreAuthorize("hasAnyRole(@roles.OWNER_ADMIN, @roles.VET_ADMIN)")
+    @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
+    public ResponseEntity<Collection<PetTypeDto>> getAllPetTypes() {
+        Collection<PetType> petTypes = new ArrayList<PetType>();
+        petTypes.addAll(this.clinicService.findAllPetTypes());
+        if (petTypes.isEmpty()) {
+            return new ResponseEntity<Collection<PetTypeDto>>(HttpStatus.NOT_FOUND);
+        }
+        return new ResponseEntity<Collection<PetTypeDto>>(petTypeMapper.toPetTypeDtos(petTypes), HttpStatus.OK);
+    }
 
-    @PreAuthorize( "hasAnyRole(@roles.OWNER_ADMIN, @roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{petTypeId}", method = RequestMethod.GET, produces = "application/json")
-	public ResponseEntity<PetType> getPetType(@PathVariable("petTypeId") int petTypeId){
-		PetType petType = this.clinicService.findPetTypeById(petTypeId);
-		if(petType == null){
-			return new ResponseEntity<PetType>(HttpStatus.NOT_FOUND);
-		}
-		return new ResponseEntity<PetType>(petType, HttpStatus.OK);
-	}
+    @PreAuthorize("hasAnyRole(@roles.OWNER_ADMIN, @roles.VET_ADMIN)")
+    @RequestMapping(value = "/{petTypeId}", method = RequestMethod.GET, produces = "application/json")
+    public ResponseEntity<PetTypeDto> getPetType(@PathVariable("petTypeId") int petTypeId) {
+        PetType petType = this.clinicService.findPetTypeById(petTypeId);
+        if (petType == null) {
+            return new ResponseEntity<PetTypeDto>(HttpStatus.NOT_FOUND);
+        }
+        return new ResponseEntity<PetTypeDto>(petTypeMapper.toPetTypeDto(petType), HttpStatus.OK);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
-	public ResponseEntity<PetType> addPetType(@RequestBody @Valid PetType petType, BindingResult bindingResult, UriComponentsBuilder ucBuilder){
-		BindingErrorsResponse errors = new BindingErrorsResponse();
-		HttpHeaders headers = new HttpHeaders();
-		if(bindingResult.hasErrors() || (petType == null)){
-			errors.addAllErrors(bindingResult);
-			headers.add("errors", errors.toJSON());
-			return new ResponseEntity<PetType>(headers, HttpStatus.BAD_REQUEST);
-		}
-		this.clinicService.savePetType(petType);
-		headers.setLocation(ucBuilder.path("/api/pettypes/{id}").buildAndExpand(petType.getId()).toUri());
-		return new ResponseEntity<PetType>(petType, headers, HttpStatus.CREATED);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
+    public ResponseEntity<PetTypeDto> addPetType(@RequestBody @Valid PetTypeDto petType, BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
+        BindingErrorsResponse errors = new BindingErrorsResponse();
+        HttpHeaders headers = new HttpHeaders();
+        if (bindingResult.hasErrors() || (petType == null)) {
+            errors.addAllErrors(bindingResult);
+            headers.add("errors", errors.toJSON());
+            return new ResponseEntity<PetTypeDto>(headers, HttpStatus.BAD_REQUEST);
+        }
+        final PetType type = petTypeMapper.toPetType(petType);
+        this.clinicService.savePetType(type);
+        headers.setLocation(ucBuilder.path("/api/pettypes/{id}").buildAndExpand(petType.getId()).toUri());
+        return new ResponseEntity<PetTypeDto>(petTypeMapper.toPetTypeDto(type), headers, HttpStatus.CREATED);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{petTypeId}", method = RequestMethod.PUT, produces = "application/json")
-	public ResponseEntity<PetType> updatePetType(@PathVariable("petTypeId") int petTypeId, @RequestBody @Valid PetType petType, BindingResult bindingResult){
-		BindingErrorsResponse errors = new BindingErrorsResponse();
-		HttpHeaders headers = new HttpHeaders();
-		if(bindingResult.hasErrors() || (petType == null)){
-			errors.addAllErrors(bindingResult);
-			headers.add("errors", errors.toJSON());
-			return new ResponseEntity<PetType>(headers, HttpStatus.BAD_REQUEST);
-		}
-		PetType currentPetType = this.clinicService.findPetTypeById(petTypeId);
-		if(currentPetType == null){
-			return new ResponseEntity<PetType>(HttpStatus.NOT_FOUND);
-		}
-		currentPetType.setName(petType.getName());
-		this.clinicService.savePetType(currentPetType);
-		return new ResponseEntity<PetType>(currentPetType, HttpStatus.NO_CONTENT);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "/{petTypeId}", method = RequestMethod.PUT, produces = "application/json")
+    public ResponseEntity<PetTypeDto> updatePetType(@PathVariable("petTypeId") int petTypeId, @RequestBody @Valid PetTypeDto petType, BindingResult bindingResult) {
+        BindingErrorsResponse errors = new BindingErrorsResponse();
+        HttpHeaders headers = new HttpHeaders();
+        if (bindingResult.hasErrors() || (petType == null)) {
+            errors.addAllErrors(bindingResult);
+            headers.add("errors", errors.toJSON());
+            return new ResponseEntity<PetTypeDto>(headers, HttpStatus.BAD_REQUEST);
+        }
+        PetType currentPetType = this.clinicService.findPetTypeById(petTypeId);
+        if (currentPetType == null) {
+            return new ResponseEntity<PetTypeDto>(HttpStatus.NOT_FOUND);
+        }
+        currentPetType.setName(petType.getName());
+        this.clinicService.savePetType(currentPetType);
+        return new ResponseEntity<PetTypeDto>(petTypeMapper.toPetTypeDto(currentPetType), HttpStatus.NO_CONTENT);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{petTypeId}", method = RequestMethod.DELETE, produces = "application/json")
-	@Transactional
-	public ResponseEntity<Void> deletePetType(@PathVariable("petTypeId") int petTypeId){
-		PetType petType = this.clinicService.findPetTypeById(petTypeId);
-		if(petType == null){
-			return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
-		}
-		this.clinicService.deletePetType(petType);
-		return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "/{petTypeId}", method = RequestMethod.DELETE, produces = "application/json")
+    @Transactional
+    public ResponseEntity<Void> deletePetType(@PathVariable("petTypeId") int petTypeId) {
+        PetType petType = this.clinicService.findPetTypeById(petTypeId);
+        if (petType == null) {
+            return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
+        }
+        this.clinicService.deletePetType(petType);
+        return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
+    }
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/SpecialtyRestController.java b/src/main/java/org/springframework/samples/petclinic/rest/SpecialtyRestController.java
index 6680e72952f846e05c01d26f9dcea4fb3c152543..5d89e1eb323b760ce612242c68f1b18cc9981fa3 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/SpecialtyRestController.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/SpecialtyRestController.java
@@ -16,32 +16,25 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.samples.petclinic.dto.SpecialtyDto;
+import org.springframework.samples.petclinic.mapper.SpecialtyMapper;
 import org.springframework.samples.petclinic.model.Specialty;
 import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import javax.transaction.Transactional;
+import javax.validation.Valid;
+import java.util.ArrayList;
+import java.util.Collection;
+
 /**
  * @author Vitaliy Fedoriv
- *
  */
 
 @RestController
@@ -49,74 +42,81 @@ import org.springframework.web.util.UriComponentsBuilder;
 @RequestMapping("api/specialties")
 public class SpecialtyRestController {
 
-	@Autowired
-	private ClinicService clinicService;
+    private final ClinicService clinicService;
+
+    private final SpecialtyMapper specialtyMapper;
+
+    public SpecialtyRestController(ClinicService clinicService, SpecialtyMapper specialtyMapper) {
+        this.clinicService = clinicService;
+        this.specialtyMapper = specialtyMapper;
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
-	public ResponseEntity<Collection<Specialty>> getAllSpecialtys(){
-		Collection<Specialty> specialties = new ArrayList<Specialty>();
-		specialties.addAll(this.clinicService.findAllSpecialties());
-		if (specialties.isEmpty()){
-			return new ResponseEntity<Collection<Specialty>>(HttpStatus.NOT_FOUND);
-		}
-		return new ResponseEntity<Collection<Specialty>>(specialties, HttpStatus.OK);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
+    public ResponseEntity<Collection<SpecialtyDto>> getAllSpecialtys() {
+        Collection<SpecialtyDto> specialties = new ArrayList<SpecialtyDto>();
+        specialties.addAll(specialtyMapper.toSpecialtyDtos(this.clinicService.findAllSpecialties()));
+        if (specialties.isEmpty()) {
+            return new ResponseEntity<Collection<SpecialtyDto>>(HttpStatus.NOT_FOUND);
+        }
+        return new ResponseEntity<Collection<SpecialtyDto>>(specialties, HttpStatus.OK);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{specialtyId}", method = RequestMethod.GET, produces = "application/json")
-	public ResponseEntity<Specialty> getSpecialty(@PathVariable("specialtyId") int specialtyId){
-		Specialty specialty = this.clinicService.findSpecialtyById(specialtyId);
-		if(specialty == null){
-			return new ResponseEntity<Specialty>(HttpStatus.NOT_FOUND);
-		}
-		return new ResponseEntity<Specialty>(specialty, HttpStatus.OK);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "/{specialtyId}", method = RequestMethod.GET, produces = "application/json")
+    public ResponseEntity<SpecialtyDto> getSpecialty(@PathVariable("specialtyId") int specialtyId) {
+        Specialty specialty = this.clinicService.findSpecialtyById(specialtyId);
+        if (specialty == null) {
+            return new ResponseEntity<SpecialtyDto>(HttpStatus.NOT_FOUND);
+        }
+        return new ResponseEntity<SpecialtyDto>(specialtyMapper.toSpecialtyDto(specialty), HttpStatus.OK);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
-	public ResponseEntity<Specialty> addSpecialty(@RequestBody @Valid Specialty specialty, BindingResult bindingResult, UriComponentsBuilder ucBuilder){
-		BindingErrorsResponse errors = new BindingErrorsResponse();
-		HttpHeaders headers = new HttpHeaders();
-		if(bindingResult.hasErrors() || (specialty == null)){
-			errors.addAllErrors(bindingResult);
-			headers.add("errors", errors.toJSON());
-			return new ResponseEntity<Specialty>(headers, HttpStatus.BAD_REQUEST);
-		}
-		this.clinicService.saveSpecialty(specialty);
-		headers.setLocation(ucBuilder.path("/api/specialtys/{id}").buildAndExpand(specialty.getId()).toUri());
-		return new ResponseEntity<Specialty>(specialty, headers, HttpStatus.CREATED);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
+    public ResponseEntity<SpecialtyDto> addSpecialty(@RequestBody @Valid SpecialtyDto specialtyDto, BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
+        BindingErrorsResponse errors = new BindingErrorsResponse();
+        HttpHeaders headers = new HttpHeaders();
+        if (bindingResult.hasErrors() || (specialtyDto == null)) {
+            errors.addAllErrors(bindingResult);
+            headers.add("errors", errors.toJSON());
+            return new ResponseEntity<SpecialtyDto>(headers, HttpStatus.BAD_REQUEST);
+        }
+        Specialty specialty = specialtyMapper.toSpecialty(specialtyDto);
+        this.clinicService.saveSpecialty(specialty);
+        headers.setLocation(ucBuilder.path("/api/specialtys/{id}").buildAndExpand(specialty.getId()).toUri());
+        return new ResponseEntity<SpecialtyDto>(specialtyMapper.toSpecialtyDto(specialty), headers, HttpStatus.CREATED);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{specialtyId}", method = RequestMethod.PUT, produces = "application/json")
-	public ResponseEntity<Specialty> updateSpecialty(@PathVariable("specialtyId") int specialtyId, @RequestBody @Valid Specialty specialty, BindingResult bindingResult){
-		BindingErrorsResponse errors = new BindingErrorsResponse();
-		HttpHeaders headers = new HttpHeaders();
-		if(bindingResult.hasErrors() || (specialty == null)){
-			errors.addAllErrors(bindingResult);
-			headers.add("errors", errors.toJSON());
-			return new ResponseEntity<Specialty>(headers, HttpStatus.BAD_REQUEST);
-		}
-		Specialty currentSpecialty = this.clinicService.findSpecialtyById(specialtyId);
-		if(currentSpecialty == null){
-			return new ResponseEntity<Specialty>(HttpStatus.NOT_FOUND);
-		}
-		currentSpecialty.setName(specialty.getName());
-		this.clinicService.saveSpecialty(currentSpecialty);
-		return new ResponseEntity<Specialty>(currentSpecialty, HttpStatus.NO_CONTENT);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "/{specialtyId}", method = RequestMethod.PUT, produces = "application/json")
+    public ResponseEntity<SpecialtyDto> updateSpecialty(@PathVariable("specialtyId") int specialtyId, @RequestBody @Valid SpecialtyDto specialtyDto, BindingResult bindingResult) {
+        BindingErrorsResponse errors = new BindingErrorsResponse();
+        HttpHeaders headers = new HttpHeaders();
+        if (bindingResult.hasErrors() || (specialtyDto == null)) {
+            errors.addAllErrors(bindingResult);
+            headers.add("errors", errors.toJSON());
+            return new ResponseEntity<SpecialtyDto>(headers, HttpStatus.BAD_REQUEST);
+        }
+        Specialty currentSpecialty = this.clinicService.findSpecialtyById(specialtyId);
+        if (currentSpecialty == null) {
+            return new ResponseEntity<SpecialtyDto>(HttpStatus.NOT_FOUND);
+        }
+        currentSpecialty.setName(specialtyDto.getName());
+        this.clinicService.saveSpecialty(currentSpecialty);
+        return new ResponseEntity<SpecialtyDto>(specialtyMapper.toSpecialtyDto(currentSpecialty), HttpStatus.NO_CONTENT);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{specialtyId}", method = RequestMethod.DELETE, produces = "application/json")
-	@Transactional
-	public ResponseEntity<Void> deleteSpecialty(@PathVariable("specialtyId") int specialtyId){
-		Specialty specialty = this.clinicService.findSpecialtyById(specialtyId);
-		if(specialty == null){
-			return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
-		}
-		this.clinicService.deleteSpecialty(specialty);
-		return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "/{specialtyId}", method = RequestMethod.DELETE, produces = "application/json")
+    @Transactional
+    public ResponseEntity<Void> deleteSpecialty(@PathVariable("specialtyId") int specialtyId) {
+        Specialty specialty = this.clinicService.findSpecialtyById(specialtyId);
+        if (specialty == null) {
+            return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
+        }
+        this.clinicService.deleteSpecialty(specialty);
+        return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
+    }
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/UserRestController.java b/src/main/java/org/springframework/samples/petclinic/rest/UserRestController.java
index 47ad14b73ab32fd9469f79d59073421a1717934a..915edd60ca2c429083e12523bf0b9e1d6f031094 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/UserRestController.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/UserRestController.java
@@ -16,43 +16,45 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.samples.petclinic.dto.UserDto;
+import org.springframework.samples.petclinic.mapper.UserMapper;
 import org.springframework.samples.petclinic.model.User;
 import org.springframework.samples.petclinic.service.UserService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
 
 @RestController
 @CrossOrigin(exposedHeaders = "errors, content-type")
 @RequestMapping("api/users")
 public class UserRestController {
 
-    @Autowired
-    private UserService userService;
+    private final UserService userService;
+    private final UserMapper userMapper;
+
+    public UserRestController(UserService userService, UserMapper userMapper) {
+        this.userService = userService;
+        this.userMapper = userMapper;
+    }
+
 
     @PreAuthorize( "hasRole(@roles.ADMIN)" )
     @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
-    public ResponseEntity<User> addOwner(@RequestBody @Valid User user,  BindingResult bindingResult) throws Exception {
+    public ResponseEntity<UserDto> addOwner(@RequestBody @Valid UserDto userDto, BindingResult bindingResult) throws Exception {
         BindingErrorsResponse errors = new BindingErrorsResponse();
         HttpHeaders headers = new HttpHeaders();
-        if (bindingResult.hasErrors() || (user == null)) {
+        if (bindingResult.hasErrors() || (userDto == null)) {
             errors.addAllErrors(bindingResult);
             headers.add("errors", errors.toJSON());
-            return new ResponseEntity<User>(user, headers, HttpStatus.BAD_REQUEST);
+            return new ResponseEntity<UserDto>(userDto, headers, HttpStatus.BAD_REQUEST);
         }
-
+        User user = userMapper.toUser(userDto);
         this.userService.saveUser(user);
-        return new ResponseEntity<User>(user, headers, HttpStatus.CREATED);
+        return new ResponseEntity<UserDto>(userMapper.toUserDto(user), headers, HttpStatus.CREATED);
     }
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/VetRestController.java b/src/main/java/org/springframework/samples/petclinic/rest/VetRestController.java
index 7570173a9118b01e5faa93690fffc9599762bf19..6469062b5552a515d29d56ee5b09091103cec847 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/VetRestController.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/VetRestController.java
@@ -15,33 +15,27 @@
  */
 package org.springframework.samples.petclinic.rest;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.samples.petclinic.dto.VetDto;
+import org.springframework.samples.petclinic.mapper.SpecialtyMapper;
+import org.springframework.samples.petclinic.mapper.VetMapper;
 import org.springframework.samples.petclinic.model.Specialty;
 import org.springframework.samples.petclinic.model.Vet;
 import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import javax.transaction.Transactional;
+import javax.validation.Valid;
+import java.util.ArrayList;
+import java.util.Collection;
+
 /**
  * @author Vitaliy Fedoriv
- *
  */
 
 @RestController
@@ -49,81 +43,88 @@ import org.springframework.web.util.UriComponentsBuilder;
 @RequestMapping("api/vets")
 public class VetRestController {
 
-	@Autowired
-	private ClinicService clinicService;
+    private final ClinicService clinicService;
+    private final VetMapper vetMapper;
+    private final SpecialtyMapper specialtyMapper;
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
-	public ResponseEntity<Collection<Vet>> getAllVets(){
-		Collection<Vet> vets = new ArrayList<Vet>();
-		vets.addAll(this.clinicService.findAllVets());
-		if (vets.isEmpty()){
-			return new ResponseEntity<Collection<Vet>>(HttpStatus.NOT_FOUND);
-		}
-		return new ResponseEntity<Collection<Vet>>(vets, HttpStatus.OK);
-	}
+    public VetRestController(ClinicService clinicService, VetMapper vetMapper, SpecialtyMapper specialtyMapper) {
+        this.clinicService = clinicService;
+        this.vetMapper = vetMapper;
+        this.specialtyMapper = specialtyMapper;
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{vetId}", method = RequestMethod.GET, produces = "application/json")
-	public ResponseEntity<Vet> getVet(@PathVariable("vetId") int vetId){
-		Vet vet = this.clinicService.findVetById(vetId);
-		if(vet == null){
-			return new ResponseEntity<Vet>(HttpStatus.NOT_FOUND);
-		}
-		return new ResponseEntity<Vet>(vet, HttpStatus.OK);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
+    public ResponseEntity<Collection<VetDto>> getAllVets() {
+        Collection<VetDto> vets = new ArrayList<VetDto>();
+        vets.addAll(vetMapper.toVetDtos(this.clinicService.findAllVets()));
+        if (vets.isEmpty()) {
+            return new ResponseEntity<Collection<VetDto>>(HttpStatus.NOT_FOUND);
+        }
+        return new ResponseEntity<Collection<VetDto>>(vets, HttpStatus.OK);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
-	public ResponseEntity<Vet> addVet(@RequestBody @Valid Vet vet, BindingResult bindingResult, UriComponentsBuilder ucBuilder){
-		BindingErrorsResponse errors = new BindingErrorsResponse();
-		HttpHeaders headers = new HttpHeaders();
-		if(bindingResult.hasErrors() || (vet == null)){
-			errors.addAllErrors(bindingResult);
-			headers.add("errors", errors.toJSON());
-			return new ResponseEntity<Vet>(headers, HttpStatus.BAD_REQUEST);
-		}
-		this.clinicService.saveVet(vet);
-		headers.setLocation(ucBuilder.path("/api/vets/{id}").buildAndExpand(vet.getId()).toUri());
-		return new ResponseEntity<Vet>(vet, headers, HttpStatus.CREATED);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "/{vetId}", method = RequestMethod.GET, produces = "application/json")
+    public ResponseEntity<VetDto> getVet(@PathVariable("vetId") int vetId) {
+        Vet vet = this.clinicService.findVetById(vetId);
+        if (vet == null) {
+            return new ResponseEntity<VetDto>(HttpStatus.NOT_FOUND);
+        }
+        return new ResponseEntity<VetDto>(vetMapper.toVetDto(vet), HttpStatus.OK);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{vetId}", method = RequestMethod.PUT, produces = "application/json")
-	public ResponseEntity<Vet> updateVet(@PathVariable("vetId") int vetId, @RequestBody @Valid Vet vet, BindingResult bindingResult){
-		BindingErrorsResponse errors = new BindingErrorsResponse();
-		HttpHeaders headers = new HttpHeaders();
-		if(bindingResult.hasErrors() || (vet == null)){
-			errors.addAllErrors(bindingResult);
-			headers.add("errors", errors.toJSON());
-			return new ResponseEntity<Vet>(headers, HttpStatus.BAD_REQUEST);
-		}
-		Vet currentVet = this.clinicService.findVetById(vetId);
-		if(currentVet == null){
-			return new ResponseEntity<Vet>(HttpStatus.NOT_FOUND);
-		}
-		currentVet.setFirstName(vet.getFirstName());
-		currentVet.setLastName(vet.getLastName());
-		currentVet.clearSpecialties();
-		for(Specialty spec : vet.getSpecialties()) {
-			currentVet.addSpecialty(spec);
-		}
-		this.clinicService.saveVet(currentVet);
-		return new ResponseEntity<Vet>(currentVet, HttpStatus.NO_CONTENT);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
+    public ResponseEntity<VetDto> addVet(@RequestBody @Valid VetDto vetDto, BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
+        BindingErrorsResponse errors = new BindingErrorsResponse();
+        HttpHeaders headers = new HttpHeaders();
+        if (bindingResult.hasErrors() || (vetDto == null)) {
+            errors.addAllErrors(bindingResult);
+            headers.add("errors", errors.toJSON());
+            return new ResponseEntity<VetDto>(headers, HttpStatus.BAD_REQUEST);
+        }
+        Vet vet = vetMapper.toVet(vetDto);
+        this.clinicService.saveVet(vet);
+        headers.setLocation(ucBuilder.path("/api/vets/{id}").buildAndExpand(vet.getId()).toUri());
+        return new ResponseEntity<VetDto>(vetMapper.toVetDto(vet), headers, HttpStatus.CREATED);
+    }
 
-    @PreAuthorize( "hasRole(@roles.VET_ADMIN)" )
-	@RequestMapping(value = "/{vetId}", method = RequestMethod.DELETE, produces = "application/json")
-	@Transactional
-	public ResponseEntity<Void> deleteVet(@PathVariable("vetId") int vetId){
-		Vet vet = this.clinicService.findVetById(vetId);
-		if(vet == null){
-			return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
-		}
-		this.clinicService.deleteVet(vet);
-		return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
-	}
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "/{vetId}", method = RequestMethod.PUT, produces = "application/json")
+    public ResponseEntity<VetDto> updateVet(@PathVariable("vetId") int vetId, @RequestBody @Valid VetDto vetDto, BindingResult bindingResult) {
+        BindingErrorsResponse errors = new BindingErrorsResponse();
+        HttpHeaders headers = new HttpHeaders();
+        if (bindingResult.hasErrors() || (vetDto == null)) {
+            errors.addAllErrors(bindingResult);
+            headers.add("errors", errors.toJSON());
+            return new ResponseEntity<VetDto>(headers, HttpStatus.BAD_REQUEST);
+        }
+        Vet currentVet = this.clinicService.findVetById(vetId);
+        if (currentVet == null) {
+            return new ResponseEntity<VetDto>(HttpStatus.NOT_FOUND);
+        }
+        currentVet.setFirstName(vetDto.getFirstName());
+        currentVet.setLastName(vetDto.getLastName());
+        currentVet.clearSpecialties();
+        for (Specialty spec : specialtyMapper.toSpecialtys(vetDto.getSpecialties())) {
+            currentVet.addSpecialty(spec);
+        }
+        this.clinicService.saveVet(currentVet);
+        return new ResponseEntity<VetDto>(vetMapper.toVetDto(currentVet), HttpStatus.NO_CONTENT);
+    }
 
+    @PreAuthorize("hasRole(@roles.VET_ADMIN)")
+    @RequestMapping(value = "/{vetId}", method = RequestMethod.DELETE, produces = "application/json")
+    @Transactional
+    public ResponseEntity<Void> deleteVet(@PathVariable("vetId") int vetId) {
+        Vet vet = this.clinicService.findVetById(vetId);
+        if (vet == null) {
+            return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
+        }
+        this.clinicService.deleteVet(vet);
+        return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
+    }
 
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/rest/VisitRestController.java b/src/main/java/org/springframework/samples/petclinic/rest/VisitRestController.java
index 92fe1531a39b34b292a81b9d5a0b11cbd921efc2..ee92cf38fa98366ce519813067f4f636c6c68f2a 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/VisitRestController.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/VisitRestController.java
@@ -16,32 +16,25 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.samples.petclinic.dto.VisitDto;
+import org.springframework.samples.petclinic.mapper.VisitMapper;
 import org.springframework.samples.petclinic.model.Visit;
 import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import javax.transaction.Transactional;
+import javax.validation.Valid;
+import java.util.ArrayList;
+import java.util.Collection;
+
 /**
  * @author Vitaliy Fedoriv
- *
  */
 
 @RestController
@@ -49,76 +42,85 @@ import org.springframework.web.util.UriComponentsBuilder;
 @RequestMapping("api/visits")
 public class VisitRestController {
 
-	@Autowired
-	private ClinicService clinicService;
-
-    @PreAuthorize( "hasRole(@roles.OWNER_ADMIN)" )
-	@RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
-	public ResponseEntity<Collection<Visit>> getAllVisits(){
-		Collection<Visit> visits = new ArrayList<Visit>();
-		visits.addAll(this.clinicService.findAllVisits());
-		if (visits.isEmpty()){
-			return new ResponseEntity<Collection<Visit>>(HttpStatus.NOT_FOUND);
-		}
-		return new ResponseEntity<Collection<Visit>>(visits, HttpStatus.OK);
-	}
-
-    @PreAuthorize( "hasRole(@roles.OWNER_ADMIN)" )
-	@RequestMapping(value = "/{visitId}", method = RequestMethod.GET, produces = "application/json")
-	public ResponseEntity<Visit> getVisit(@PathVariable("visitId") int visitId){
-		Visit visit = this.clinicService.findVisitById(visitId);
-		if(visit == null){
-			return new ResponseEntity<Visit>(HttpStatus.NOT_FOUND);
-		}
-		return new ResponseEntity<Visit>(visit, HttpStatus.OK);
-	}
-
-    @PreAuthorize( "hasRole(@roles.OWNER_ADMIN)" )
-	@RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
-	public ResponseEntity<Visit> addVisit(@RequestBody @Valid Visit visit, BindingResult bindingResult, UriComponentsBuilder ucBuilder){
-		BindingErrorsResponse errors = new BindingErrorsResponse();
-		HttpHeaders headers = new HttpHeaders();
-		if(bindingResult.hasErrors() || (visit == null) || (visit.getPet() == null)){
-			errors.addAllErrors(bindingResult);
-			headers.add("errors", errors.toJSON());
-			return new ResponseEntity<Visit>(headers, HttpStatus.BAD_REQUEST);
-		}
-		this.clinicService.saveVisit(visit);
-		headers.setLocation(ucBuilder.path("/api/visits/{id}").buildAndExpand(visit.getId()).toUri());
-		return new ResponseEntity<Visit>(visit, headers, HttpStatus.CREATED);
-	}
-
-    @PreAuthorize( "hasRole(@roles.OWNER_ADMIN)" )
-	@RequestMapping(value = "/{visitId}", method = RequestMethod.PUT, produces = "application/json")
-	public ResponseEntity<Visit> updateVisit(@PathVariable("visitId") int visitId, @RequestBody @Valid Visit visit, BindingResult bindingResult){
-		BindingErrorsResponse errors = new BindingErrorsResponse();
-		HttpHeaders headers = new HttpHeaders();
-		if(bindingResult.hasErrors() || (visit == null) || (visit.getPet() == null)){
-			errors.addAllErrors(bindingResult);
-			headers.add("errors", errors.toJSON());
-			return new ResponseEntity<Visit>(headers, HttpStatus.BAD_REQUEST);
-		}
-		Visit currentVisit = this.clinicService.findVisitById(visitId);
-		if(currentVisit == null){
-			return new ResponseEntity<Visit>(HttpStatus.NOT_FOUND);
-		}
-		currentVisit.setDate(visit.getDate());
-		currentVisit.setDescription(visit.getDescription());
-		currentVisit.setPet(visit.getPet());
-		this.clinicService.saveVisit(currentVisit);
-		return new ResponseEntity<Visit>(currentVisit, HttpStatus.NO_CONTENT);
-	}
-
-    @PreAuthorize( "hasRole(@roles.OWNER_ADMIN)" )
-	@RequestMapping(value = "/{visitId}", method = RequestMethod.DELETE, produces = "application/json")
-	@Transactional
-	public ResponseEntity<Void> deleteVisit(@PathVariable("visitId") int visitId){
-		Visit visit = this.clinicService.findVisitById(visitId);
-		if(visit == null){
-			return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
-		}
-		this.clinicService.deleteVisit(visit);
-		return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
-	}
+    private final ClinicService clinicService;
+
+    private final VisitMapper visitMapper;
+
+    public VisitRestController(ClinicService clinicService, VisitMapper visitMapper) {
+        this.clinicService = clinicService;
+        this.visitMapper = visitMapper;
+    }
+
+
+    @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
+    @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
+    public ResponseEntity<Collection<VisitDto>> getAllVisitDtos() {
+        Collection<Visit> visits = new ArrayList<>();
+
+        visits.addAll(this.clinicService.findAllVisits());
+        if (visits.isEmpty()) {
+            return new ResponseEntity<Collection<VisitDto>>(HttpStatus.NOT_FOUND);
+        }
+        return new ResponseEntity<Collection<VisitDto>>(visitMapper.toVisitsDto(visits), HttpStatus.OK);
+    }
+
+    @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
+    @RequestMapping(value = "/{visitId}", method = RequestMethod.GET, produces = "application/json")
+    public ResponseEntity<VisitDto> getVisitDto(@PathVariable("visitId") int visitId) {
+        Visit visit = this.clinicService.findVisitById(visitId);
+        if (visit == null) {
+            return new ResponseEntity<VisitDto>(HttpStatus.NOT_FOUND);
+        }
+        return new ResponseEntity<VisitDto>(visitMapper.toVisitDto(visit), HttpStatus.OK);
+    }
+
+    @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
+    @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
+    public ResponseEntity<VisitDto> addVisit(@RequestBody @Valid VisitDto visitDto, BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
+        BindingErrorsResponse errors = new BindingErrorsResponse();
+        HttpHeaders headers = new HttpHeaders();
+        if (bindingResult.hasErrors() || (visitDto == null)) {
+            errors.addAllErrors(bindingResult);
+            headers.add("errors", errors.toJSON());
+            return new ResponseEntity<VisitDto>(headers, HttpStatus.BAD_REQUEST);
+        }
+        Visit visit = visitMapper.toVisit(visitDto);
+        this.clinicService.saveVisit(visit);
+        visitDto = visitMapper.toVisitDto(visit);
+        headers.setLocation(ucBuilder.path("/api/visits/{id}").buildAndExpand(visit.getId()).toUri());
+        return new ResponseEntity<>(visitDto, headers, HttpStatus.CREATED);
+    }
+
+    @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
+    @RequestMapping(value = "/{visitId}", method = RequestMethod.PUT, produces = "application/json")
+    public ResponseEntity<VisitDto> updateVisit(@PathVariable("visitId") int visitId, @RequestBody @Valid VisitDto visitDto, BindingResult bindingResult) {
+        BindingErrorsResponse errors = new BindingErrorsResponse();
+        HttpHeaders headers = new HttpHeaders();
+        if (bindingResult.hasErrors() || (visitDto == null)) {
+            errors.addAllErrors(bindingResult);
+            headers.add("errors", errors.toJSON());
+            return new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST);
+        }
+        Visit currentVisit = this.clinicService.findVisitById(visitId);
+        if (currentVisit == null) {
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+        }
+        currentVisit.setDate(visitDto.getDate());
+        currentVisit.setDescription(visitDto.getDescription());
+        this.clinicService.saveVisit(currentVisit);
+        return new ResponseEntity<>(visitMapper.toVisitDto(currentVisit), HttpStatus.NO_CONTENT);
+    }
+
+    @PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
+    @RequestMapping(value = "/{visitId}", method = RequestMethod.DELETE, produces = "application/json")
+    @Transactional
+    public ResponseEntity<Void> deleteVisit(@PathVariable("visitId") int visitId) {
+        Visit visit = this.clinicService.findVisitById(visitId);
+        if (visit == null) {
+            return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
+        }
+        this.clinicService.deleteVisit(visit);
+        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+    }
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/util/ApplicationSwaggerConfig.java b/src/main/java/org/springframework/samples/petclinic/util/ApplicationSwaggerConfig.java
old mode 100644
new mode 100755
diff --git a/src/main/resources/api-docs.yml b/src/main/resources/api-docs.yml
new file mode 100755
index 0000000000000000000000000000000000000000..86063c6beaa536dbcc51ea0aacf089bbad9f42a1
--- /dev/null
+++ b/src/main/resources/api-docs.yml
@@ -0,0 +1,913 @@
+openapi: 3.0.1
+info:
+  title: Spring PetClinic
+  description: Spring PetClinic Sample Application.
+  license:
+    name: Apache 2.0
+    url: http://www.apache.org/licenses/LICENSE-2.0
+  version: '1.0'
+servers:
+  - url: http://localhost:8080/api
+tags:
+  - name: failing
+    description: Endpoint which always returns an error.
+  - name: owner
+    description: Endpoints related to pet owners.
+  - name: pet
+    description: Endpoints related to pets.
+  - name: vet
+    description: Endpoints related to vets.
+  - name: visit
+    description: Endpoints related to vet visits.
+paths:
+  /oops:
+    get:
+      tags:
+        - failing
+      operationId: failingRequest
+      summary: Always fails
+      description: Produces sample error response.
+      parameters:
+        - name: If-None-Match
+          in: header
+          description: A list of ETags of the responses the client has cached.
+          schema:
+            type: string
+      responses:
+        200:
+          description: Never returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            text/plain:
+              schema:
+                type: string
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+  /owner:
+    post:
+      tags:
+        - owner
+      operationId: addOwner
+      summary: Adds a pet owner
+      description: Records the details of a new pet owner.
+      requestBody:
+        description: The pet owner
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/OwnerFields'
+        required: true
+      responses:
+        201:
+          description: The pet owner was sucessfully added.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Owner'
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+    get:
+      tags:
+        - owner
+      operationId: listOwners
+      summary: Lists pet owners
+      description: Returns an array of pet owners.
+      parameters:
+        - name: lastName
+          in: query
+          description: Last name.
+          required: false
+          schema:
+            type: string
+            example: Davis
+        - name: If-None-Match
+          in: header
+          description: A list of ETags of the responses the client has cached.
+          schema:
+            type: string
+      responses:
+        200:
+          description: Owner details found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/Owner'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+  /owner/{ownerId}:
+    get:
+      tags:
+        - owner
+      operationId: getOwner
+      summary: Get a pet owner by ID
+      description: Returns the pet owner or a 404 error.
+      parameters:
+        - name: ownerId
+          in: path
+          description: The ID of the pet owner.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+        - name: If-None-Match
+          in: header
+          description: A list of ETags of the responses the client has cached.
+          schema:
+            type: string
+      responses:
+        200:
+          description: Owner details found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Owner'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Owner not found.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+    put:
+      tags:
+        - owner
+      operationId: updateOwner
+      summary: Update a pet owner's details
+      description: Updates the pet owner record with the specified details.
+      parameters:
+        - name: ownerId
+          in: path
+          description: The ID of the pet owner.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+      requestBody:
+        description: The pet owner details to use for the update.
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/OwnerFields'
+        required: true
+      responses:
+        200:
+          description: Update successful.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Owner'
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Owner not found.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+  /owner/{ownerId}/pet:
+    post:
+      tags:
+        - pet
+      operationId: addPet
+      summary: Adds a pet
+      description: Records the details of a new pet.
+      parameters:
+        - name: ownerId
+          in: path
+          description: The ID of the pet owner.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+      requestBody:
+        description: The details of the new pet.
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/PetFields'
+        required: true
+      responses:
+        201:
+          description: The pet was sucessfully added.
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Owner not found.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+  /owner/{ownerId}/pet/{petId}:
+    get:
+      tags:
+        - pet
+      operationId: getPet
+      summary: Get a pet by ID
+      description: Returns the pet or a 404 error.
+      parameters:
+        - name: ownerId
+          in: path
+          description: The ID of the pet owner.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+        - name: petId
+          in: path
+          description: The ID of the pet.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+        - name: If-None-Match
+          in: header
+          description: A list of ETags of the responses the client has cached.
+          schema:
+            type: string
+      responses:
+        200:
+          description: Pet details found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pet'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Owner not found.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+    put:
+      tags:
+        - pet
+      operationId: updatePet
+      summary: Update a pet's details
+      description: Updates the pet record with the specified details.
+      parameters:
+        - name: ownerId
+          in: path
+          description: The ID of the pet owner.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+        - name: petId
+          in: path
+          description: The ID of the pet.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+      requestBody:
+        description: The pet details to use for the update.
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/PetFields'
+        required: true
+      responses:
+        204:
+          description: Update successful.
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Pet not found for this owner.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+  /owner/{ownerId}/pet/{petId}/visit:
+    post:
+      tags:
+        - visit
+      operationId: addVisit
+      summary: Adds a vet visit
+      description: Records the details of a new vet visit.
+      parameters:
+        - name: ownerId
+          in: path
+          description: The ID of the pet owner.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+        - name: petId
+          in: path
+          description: The ID of the pet.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+      requestBody:
+        description: The details of the new vet visit.
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/VisitFields'
+        required: true
+      responses:
+        201:
+          description: The vet visit was sucessfully added.
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Pet not found for this owner.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+  /pet-type:
+    get:
+      tags:
+        - pet
+      operationId: listPetTypes
+      summary: Lists pet types
+      description: Returns an array of pet types.
+      parameters:
+        - name: If-None-Match
+          in: header
+          description: A list of ETags of the responses the client has cached.
+          schema:
+            type: string
+      responses:
+        200:
+          description: Pet types found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/PetType'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+  /vet:
+    get:
+      tags:
+        - vet
+      operationId: listVets
+      summary: Lists vets
+      description: Returns an array of vets.
+      parameters:
+        - name: If-None-Match
+          in: header
+          description: A list of ETags of the responses the client has cached.
+          schema:
+            type: string
+      responses:
+        200:
+          description: Vets found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/Vet'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+components:
+  schemas:
+    RestError:
+      title: REST Error
+      description: The schema for all error responses.
+      type: object
+      properties:
+        status:
+          title: Status
+          description: The HTTP status code.
+          type: integer
+          format: int32
+          example: 400
+          readOnly: true
+        error:
+          title: Error
+          description: The short error message.
+          type: string
+          example: Bad Request
+          readOnly: true
+        path:
+          title: Path
+          description: The path of the URL for this request.
+          type: string
+          format: uri
+          example: '/api/owner'
+          readOnly: true
+        timestamp:
+          title: Timestamp
+          description: The time the error occured.
+          type: string
+          format: date-time
+          example: '2019-08-21T21:41:46.158+0000'
+          readOnly: true
+        message:
+          title: Message
+          description: The long error message.
+          type: string
+          example: 'Request failed schema validation'
+          readOnly: true
+        schemaValidationErrors:
+          title: Schema validation errors
+          description: Validation errors against the OpenAPI schema.
+          type: array
+          items:
+            $ref: '#/components/schemas/ValidationMessage'
+        trace:
+          title: Trace
+          description: The stacktrace for this error.
+          type: string
+          example: 'com.atlassian.oai.validator.springmvc.InvalidRequestException: ...'
+          readOnly: true
+      required:
+        - status
+        - error
+        - path
+        - timestamp
+        - message
+        - schemaValidationErrors
+    ValidationMessage:
+      title: Validation message
+      description: Messages describing a validation error.
+      type: object
+      properties:
+        message:
+          title: Message
+          description: The valiation message.
+          type: string
+          example: "[Path '/lastName'] Instance type (null) does not match any allowed primitive type (allowed: [\"string\"])"
+          readOnly: true
+      required:
+        - message
+      additionalProperties: true
+    Specialty:
+      title: Specialty
+      description: Fields of specialty of vets.
+      type: object
+      properties:
+        id:
+          title: ID
+          description: The ID of the specialty.
+          type: integer
+          format: int32
+          minimum: 0
+          example: 1
+          readOnly: true
+        name:
+          title: Name
+          description: The name of the specialty.
+          type: string
+          maxLength: 80
+          minLength: 1
+          example: radiology
+      required:
+        - id
+        - name
+    OwnerFields:
+      title: Owner fields
+      description: Editable fields of a pet owner.
+      type: object
+      properties:
+        firstName:
+          title: First name
+          description: The first name of the pet owner.
+          type: string
+          minLength: 1
+          maxLength: 30
+          pattern: '^[a-zA-Z]*$'
+          example: George
+        lastName:
+          title: Last name
+          description: The last name of the pet owner.
+          type: string
+          minLength: 1
+          maxLength: 30
+          pattern: '^[a-zA-Z]*$'
+          example: Franklin
+        address:
+          title: Address
+          description: The postal address of the pet owner.
+          type: string
+          minLength: 1
+          maxLength: 255
+          example: '110 W. Liberty St.'
+        city:
+          title: City
+          description: The city of the pet owner.
+          type: string
+          minLength: 1
+          maxLength: 80
+          example: Madison
+        telephone:
+          title: Telephone number
+          description: The telephone number of the pet owner.
+          type: string
+          minLength: 1
+          maxLength: 20
+          pattern: '^[0-9]*$'
+          example: '6085551023'
+      required:
+        - firstName
+        - lastName
+        - address
+        - city
+        - telephone
+    Owner:
+      title: Owner
+      description: A pet owner.
+      allOf:
+        - $ref: '#/components/schemas/OwnerFields'
+        - type: object
+          properties:
+            id:
+              title: ID
+              description: The ID of the pet owner.
+              type: integer
+              format: int32
+              minimum: 0
+              example: 1
+              readOnly: true
+            pets:
+              title: Pets
+              description: The pets owned by this individual including any booked vet visits.
+              type: array
+              items:
+                $ref: '#/components/schemas/Pet'
+              readOnly: true
+          required:
+            - pets
+    PetFields:
+      title: Pet fields
+      description: Editable fields of a pet.
+      type: object
+      properties:
+        name:
+          title: Name
+          description: The name of the pet.
+          type: string
+          maxLength: 30
+          example: Leo
+        birthDate:
+          title: Birth date
+          description: The date of birth of the pet.
+          type: string
+          format: date
+          example: '2010-09-07'
+        typeId:
+          title: Type
+          description: The type of the pet.
+          type: integer
+          format: int32
+          example: 1
+      required:
+        - name
+    Pet:
+      title: Pet
+      description: A pet.
+      allOf:
+        - $ref: '#/components/schemas/PetFields'
+        - type: object
+          properties:
+            id:
+              title: ID
+              description: The ID of the pet.
+              type: integer
+              format: int32
+              minimum: 0
+              example: 1
+              readOnly: true
+            type:
+              $ref: '#/components/schemas/PetType'
+            visits:
+              title: Visits
+              description: Vet visit bookings for this pet.
+              type: array
+              items:
+                $ref: '#/components/schemas/Visit'
+              readOnly: true
+          required:
+            - id
+            - type
+            - visits
+    Vet:
+      title: Vet
+      description: A veterinarian.
+      type: object
+      properties:
+        id:
+          title: ID
+          description: The ID of the vet.
+          type: integer
+          format: int32
+          minimum: 0
+          example: 1
+          readOnly: true
+        firstName:
+          title: First name
+          description: The first name of the vet.
+          type: string
+          minLength: 1
+          maxLength: 30
+          pattern: '^[a-zA-Z]*$'
+          example: 'James'
+        lastName:
+          title: Last name
+          description: The last name of the vet.
+          type: string
+          minLength: 1
+          maxLength: 30
+          pattern: '^[a-zA-Z]*$'
+          example: 'Carter'
+        specialties:
+          title: Specialties
+          description: The specialties of the vet.
+          type: array
+          items:
+            $ref: '#/components/schemas/Specialty'
+      required:
+        - id
+        - firstName
+        - lastName
+        - specialties
+    VisitFields:
+      title: Visit fields
+      description: Editable fields of a vet visit.
+      type: object
+      properties:
+        date:
+          title: Date
+          description: The date of the visit.
+          type: string
+          format: date
+          example: '2013-01-01'
+        description:
+          title: Description
+          description: The description for the visit.
+          type: string
+          minLength: 1
+          maxLength: 255
+          example: 'rabies shot'
+      required:
+        - description
+    Visit:
+      title: Visit
+      description: A booking for a vet visit.
+      allOf:
+        - $ref: '#/components/schemas/VisitFields'
+        - type: object
+          properties:
+            id:
+              title: ID
+              description: The ID of the visit.
+              type: integer
+              format: int32
+              minimum: 0
+              example: 1
+              readOnly: true
+          required:
+            - id
+    PetType:
+      title: Pet type
+      description: A pet type.
+      type: object
+      properties:
+        id:
+          title: ID
+          description: The ID of the pet type.
+          type: integer
+          format: int32
+          minimum: 0
+          example: 1
+          readOnly: true
+        name:
+          title: Name
+          description: The name of the pet type.
+          type: string
+          maxLength: 80
+          minLength: 1
+          example: cat
+      required:
+        - id
+    User:
+      title: User
+      description: An user.
+      type: object
+      properties:
+        username:
+          title: username
+          description: The username
+          type: string
+          maxLength: 80
+          minLength: 1
+          example: john.doe
+        password:
+          title: Password
+          description: The password
+          type: string
+          maxLength: 80
+          minLength: 1
+          example: 1234
+        enabled:
+          title: enabled
+          description: Indicates if the user is enabled
+          type: boolean
+          example: true
+        roles:
+          title: Roles
+          description: The roles of an user
+          type: array
+          items:
+            $ref: '#/components/schemas/Role'
+      required:
+        - username
+    Role:
+      title: Role
+      description: A role.
+      type: object
+      properties:
+        name:
+          title: name
+          description: The role's name
+          type: string
+          maxLength: 80
+          minLength: 1
+          example: admin
+      required:
+        - name
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index bbc8958923e241e2f7e2c57813db53bb8ed0d937..e3669c9bcd67ff7000abec1fdf3340ff57c413a9 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -34,3 +34,8 @@ logging.level.org.springframework=INFO
 # enable the desired authentication type
 # by default the authentication is disabled
 petclinic.security.enable=false
+
+# ------------------------------------------------
+# Spring doc configuration
+springdoc.api-docs.enabled=true
+springdoc.writer-with-default-pretty-printer= true
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/OwnerRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/OwnerRestControllerTests.java
index 57147a55211a1a2db7e7bd96d09addecc32a411a..cc59b20e84f78bbeb57f82937ae59b574453fdf5 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/OwnerRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/OwnerRestControllerTests.java
@@ -16,17 +16,7 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import static org.mockito.BDDMockito.given;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,12 +24,14 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.http.MediaType;
+import org.springframework.samples.petclinic.dto.OwnerDto;
+import org.springframework.samples.petclinic.dto.PetDto;
+import org.springframework.samples.petclinic.dto.PetTypeDto;
+import org.springframework.samples.petclinic.dto.VisitDto;
+import org.springframework.samples.petclinic.mapper.OwnerMapper;
 import org.springframework.samples.petclinic.model.Owner;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.PetType;
-import org.springframework.samples.petclinic.model.Visit;
-import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -47,7 +39,13 @@ import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
 
 /**
@@ -57,94 +55,95 @@ import com.fasterxml.jackson.databind.ObjectMapper;
  */
 @SpringBootTest
 @RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes=ApplicationTestConfig.class)
+@ContextConfiguration(classes = ApplicationTestConfig.class)
 @WebAppConfiguration
 public class OwnerRestControllerTests {
 
     @Autowired
     private OwnerRestController ownerRestController;
 
+    @Autowired
+    OwnerMapper ownerMapper;
+
     @MockBean
     private ClinicService clinicService;
 
     private MockMvc mockMvc;
 
-    private List<Owner> owners;
+    private List<OwnerDto> owners;
 
     @Before
-    public void initOwners(){
-    	this.mockMvc = MockMvcBuilders.standaloneSetup(ownerRestController)
-    			.setControllerAdvice(new ExceptionControllerAdvice())
-    			.build();
-    	owners = new ArrayList<Owner>();
-
-    	Owner ownerWithPet = new Owner();
-    	ownerWithPet.setId(1);
-    	ownerWithPet.setFirstName("George");
-    	ownerWithPet.setLastName("Franklin");
-    	ownerWithPet.setAddress("110 W. Liberty St.");
-    	ownerWithPet.setCity("Madison");
-    	ownerWithPet.setTelephone("6085551023");
-    	ownerWithPet.addPet(getTestPetWithIdAndName(ownerWithPet, 1, "Rosy"));
-    	owners.add(ownerWithPet);
-
-        Owner owner = new Owner();
-    	owner.setId(2);
-    	owner.setFirstName("Betty");
-    	owner.setLastName("Davis");
-    	owner.setAddress("638 Cardinal Ave.");
-    	owner.setCity("Sun Prairie");
-    	owner.setTelephone("6085551749");
-    	owners.add(owner);
-
-    	owner = new Owner();
-    	owner.setId(3);
-    	owner.setFirstName("Eduardo");
-    	owner.setLastName("Rodriquez");
-    	owner.setAddress("2693 Commerce St.");
-    	owner.setCity("McFarland");
-    	owner.setTelephone("6085558763");
-    	owners.add(owner);
-
-    	owner = new Owner();
-    	owner.setId(4);
-    	owner.setFirstName("Harold");
-    	owner.setLastName("Davis");
-    	owner.setAddress("563 Friendly St.");
-    	owner.setCity("Windsor");
-    	owner.setTelephone("6085553198");
-    	owners.add(owner);
+    public void initOwners() {
+        this.mockMvc = MockMvcBuilders.standaloneSetup(ownerRestController)
+            .setControllerAdvice(new ExceptionControllerAdvice())
+            .build();
+        owners = new ArrayList<OwnerDto>();
+
+        OwnerDto ownerWithPet = new OwnerDto();
+        ownerWithPet.setId(1);
+        ownerWithPet.setFirstName("George");
+        ownerWithPet.setLastName("Franklin");
+        ownerWithPet.setAddress("110 W. Liberty St.");
+        ownerWithPet.setCity("Madison");
+        ownerWithPet.setTelephone("6085551023");
+        ownerWithPet.addPetsItem(getTestPetWithIdAndName(ownerWithPet, 1, "Rosy"));
+        owners.add(ownerWithPet);
+
+        OwnerDto owner = new OwnerDto();
+        owner.setId(2);
+        owner.setFirstName("Betty");
+        owner.setLastName("Davis");
+        owner.setAddress("638 Cardinal Ave.");
+        owner.setCity("Sun Prairie");
+        owner.setTelephone("6085551749");
+        owners.add(owner);
+
+        owner = new OwnerDto();
+        owner.setId(3);
+        owner.setFirstName("Eduardo");
+        owner.setLastName("Rodriquez");
+        owner.setAddress("2693 Commerce St.");
+        owner.setCity("McFarland");
+        owner.setTelephone("6085558763");
+        owners.add(owner);
+
+        owner = new OwnerDto();
+        owner.setId(4);
+        owner.setFirstName("Harold");
+        owner.setLastName("Davis");
+        owner.setAddress("563 Friendly St.");
+        owner.setCity("Windsor");
+        owner.setTelephone("6085553198");
+        owners.add(owner);
     }
 
-    private Pet getTestPetWithIdAndName(final Owner owner, final int id, final String name) {
-        PetType petType = new PetType();
+    private PetDto getTestPetWithIdAndName(final OwnerDto owner, final int id, final String name) {
+        PetTypeDto petType = new PetTypeDto();
         petType.setId(2);
         petType.setName("dog");
-        Pet pet = new Pet();
+        PetDto pet = new PetDto();
         pet.setId(id);
         pet.setName(name);
         pet.setBirthDate(new Date());
-        pet.setOwner(owner);
         pet.setType(petType);
-        pet.addVisit(getTestVisitForPet(pet, 1));
+        pet.addVisitsItem(getTestVisitForPet(pet, 1));
         return pet;
     }
 
-    private Visit getTestVisitForPet(final Pet pet, final int id) {
-        Visit visit = new Visit();
+    private VisitDto getTestVisitForPet(final PetDto pet, final int id) {
+        VisitDto visit = new VisitDto();
         visit.setId(id);
-        visit.setPet(pet);
         visit.setDate(new Date());
         visit.setDescription("test" + id);
         return visit;
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testGetOwnerSuccess() throws Exception {
-    	given(this.clinicService.findOwnerById(1)).willReturn(owners.get(0));
+        given(this.clinicService.findOwnerById(1)).willReturn(ownerMapper.toOwner(owners.get(0)));
         this.mockMvc.perform(get("/api/owners/1")
-        	.accept(MediaType.APPLICATION_JSON_VALUE))
+                .accept(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(status().isOk())
             .andExpect(content().contentType("application/json"))
             .andExpect(jsonPath("$.id").value(1))
@@ -152,22 +151,22 @@ public class OwnerRestControllerTests {
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testGetOwnerNotFound() throws Exception {
-    	given(this.clinicService.findOwnerById(-1)).willReturn(null);
+        given(this.clinicService.findOwnerById(-1)).willReturn(null);
         this.mockMvc.perform(get("/api/owners/-1")
-        	.accept(MediaType.APPLICATION_JSON))
+                .accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isNotFound());
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testGetOwnersListSuccess() throws Exception {
-    	owners.remove(0);
-    	owners.remove(1);
-    	given(this.clinicService.findOwnerByLastName("Davis")).willReturn(owners);
+        owners.remove(0);
+        owners.remove(1);
+        given(this.clinicService.findOwnerByLastName("Davis")).willReturn(ownerMapper.toOwners(owners));
         this.mockMvc.perform(get("/api/owners/*/lastname/Davis")
-        	.accept(MediaType.APPLICATION_JSON))
+                .accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isOk())
             .andExpect(content().contentType("application/json"))
             .andExpect(jsonPath("$.[0].id").value(2))
@@ -177,23 +176,23 @@ public class OwnerRestControllerTests {
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testGetOwnersListNotFound() throws Exception {
-    	owners.clear();
-    	given(this.clinicService.findOwnerByLastName("0")).willReturn(owners);
+        owners.clear();
+        given(this.clinicService.findOwnerByLastName("0")).willReturn(ownerMapper.toOwners(owners));
         this.mockMvc.perform(get("/api/owners/?lastName=0")
-        	.accept(MediaType.APPLICATION_JSON))
+                .accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isNotFound());
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testGetAllOwnersSuccess() throws Exception {
-    	owners.remove(0);
-    	owners.remove(1);
-    	given(this.clinicService.findAllOwners()).willReturn(owners);
+        owners.remove(0);
+        owners.remove(1);
+        given(this.clinicService.findAllOwners()).willReturn(ownerMapper.toOwners(owners));
         this.mockMvc.perform(get("/api/owners/")
-        	.accept(MediaType.APPLICATION_JSON))
+                .accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isOk())
             .andExpect(content().contentType("application/json"))
             .andExpect(jsonPath("$.[0].id").value(2))
@@ -203,164 +202,167 @@ public class OwnerRestControllerTests {
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testGetAllOwnersNotFound() throws Exception {
-    	owners.clear();
-    	given(this.clinicService.findAllOwners()).willReturn(owners);
+        owners.clear();
+        given(this.clinicService.findAllOwners()).willReturn(ownerMapper.toOwners(owners));
         this.mockMvc.perform(get("/api/owners/")
-        	.accept(MediaType.APPLICATION_JSON))
+                .accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isNotFound());
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testCreateOwnerSuccess() throws Exception {
-    	Owner newOwner = owners.get(0);
-    	newOwner.setId(null);
-    	ObjectMapper mapper = new ObjectMapper();
-    	String newOwnerAsJSON = mapper.writeValueAsString(newOwner);
-    	this.mockMvc.perform(post("/api/owners/")
-    		.content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
-    		.andExpect(status().isCreated());
+        OwnerDto newOwnerDto = owners.get(0);
+        newOwnerDto.setId(null);
+        ObjectMapper mapper = new ObjectMapper();
+        String newOwnerAsJSON = mapper.writeValueAsString(newOwnerDto);
+        this.mockMvc.perform(post("/api/owners/")
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isCreated());
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testCreateOwnerErrorIdSpecified() throws Exception {
-        Owner newOwner = owners.get(0);
-        newOwner.setId(999);
+        OwnerDto newOwnerDto = owners.get(0);
+        newOwnerDto.setId(999);
         ObjectMapper mapper = new ObjectMapper();
-        String newOwnerAsJSON = mapper.writeValueAsString(newOwner);
+        String newOwnerAsJSON = mapper.writeValueAsString(newOwnerDto);
         this.mockMvc.perform(post("/api/owners/")
-            .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(status().isBadRequest())
             .andExpect(header().string("errors",
                 "[{\"objectName\":\"body\",\"fieldName\":\"id\",\"fieldValue\":\"999\",\"errorMessage\":\"must not be specified\"}]"));
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testCreateOwnerError() throws Exception {
-    	Owner newOwner = owners.get(0);
-    	newOwner.setId(null);
-    	newOwner.setFirstName(null);
-    	ObjectMapper mapper = new ObjectMapper();
-    	String newOwnerAsJSON = mapper.writeValueAsString(newOwner);
-    	this.mockMvc.perform(post("/api/owners/")
-        		.content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
-        		.andExpect(status().isBadRequest());
-     }
+        OwnerDto newOwnerDto = owners.get(0);
+        newOwnerDto.setId(null);
+        newOwnerDto.setFirstName(null);
+        ObjectMapper mapper = new ObjectMapper();
+        String newOwnerAsJSON = mapper.writeValueAsString(newOwnerDto);
+        this.mockMvc.perform(post("/api/owners/")
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isBadRequest());
+    }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testUpdateOwnerSuccess() throws Exception {
-        given(this.clinicService.findOwnerById(1)).willReturn(owners.get(0));
+        given(this.clinicService.findOwnerById(1)).willReturn(ownerMapper.toOwner(owners.get(0)));
         int ownerId = owners.get(0).getId();
-        Owner updatedOwner = new Owner();
+        OwnerDto updatedOwnerDto = new OwnerDto();
         // body.id = ownerId which is used in url path
-        updatedOwner.setId(ownerId);
-        updatedOwner.setFirstName("George I");
-        updatedOwner.setLastName("Franklin");
-        updatedOwner.setAddress("110 W. Liberty St.");
-        updatedOwner.setCity("Madison");
-        updatedOwner.setTelephone("6085551023");
+        updatedOwnerDto.setId(ownerId);
+        updatedOwnerDto.setFirstName("GeorgeI");
+        updatedOwnerDto.setLastName("Franklin");
+        updatedOwnerDto.setAddress("110 W. Liberty St.");
+        updatedOwnerDto.setCity("Madison");
+        updatedOwnerDto.setTelephone("6085551023");
         ObjectMapper mapper = new ObjectMapper();
-        String newOwnerAsJSON = mapper.writeValueAsString(updatedOwner);
+        String newOwnerAsJSON = mapper.writeValueAsString(updatedOwnerDto);
         this.mockMvc.perform(put("/api/owners/" + ownerId)
-            .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(content().contentType("application/json"))
             .andExpect(status().isNoContent());
 
         this.mockMvc.perform(get("/api/owners/" + ownerId)
-            .accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON_VALUE))
+                .accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(status().isOk())
             .andExpect(content().contentType("application/json"))
             .andExpect(jsonPath("$.id").value(ownerId))
-            .andExpect(jsonPath("$.firstName").value("George I"));
+            .andExpect(jsonPath("$.firstName").value("GeorgeI"));
 
     }
+
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testUpdateOwnerSuccessNoBodyId() throws Exception {
-    	given(this.clinicService.findOwnerById(1)).willReturn(owners.get(0));
+        given(this.clinicService.findOwnerById(1)).willReturn(ownerMapper.toOwner(owners.get(0)));
         int ownerId = owners.get(0).getId();
-        Owner updatedOwner = new Owner();
-        updatedOwner.setFirstName("George I");
-        updatedOwner.setLastName("Franklin");
-        updatedOwner.setAddress("110 W. Liberty St.");
-        updatedOwner.setCity("Madison");
-        updatedOwner.setTelephone("6085551023");
-    	ObjectMapper mapper = new ObjectMapper();
-    	String newOwnerAsJSON = mapper.writeValueAsString(updatedOwner);
-    	this.mockMvc.perform(put("/api/owners/" + ownerId)
-    		.content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
-        	.andExpect(content().contentType("application/json"))
-        	.andExpect(status().isNoContent());
-
-    	this.mockMvc.perform(get("/api/owners/" + ownerId)
-           	.accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON_VALUE))
+        OwnerDto updatedOwnerDto = new OwnerDto();
+        updatedOwnerDto.setFirstName("GeorgeI");
+        updatedOwnerDto.setLastName("Franklin");
+        updatedOwnerDto.setAddress("110 W. Liberty St.");
+        updatedOwnerDto.setCity("Madison");
+
+        updatedOwnerDto.setTelephone("6085551023");
+        ObjectMapper mapper = new ObjectMapper();
+        String newOwnerAsJSON = mapper.writeValueAsString(updatedOwnerDto);
+        this.mockMvc.perform(put("/api/owners/" + ownerId)
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(content().contentType("application/json"))
+            .andExpect(status().isNoContent());
+
+        this.mockMvc.perform(get("/api/owners/" + ownerId)
+                .accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(status().isOk())
             .andExpect(content().contentType("application/json"))
             .andExpect(jsonPath("$.id").value(ownerId))
-            .andExpect(jsonPath("$.firstName").value("George I"));
+            .andExpect(jsonPath("$.firstName").value("GeorgeI"));
 
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testUpdateOwnerErrorBodyIdMismatchWithPathId() throws Exception {
         int ownerId = owners.get(0).getId();
-        Owner updatedOwner = new Owner();
+        OwnerDto updatedOwnerDto = new OwnerDto();
         // body.id != ownerId
-        updatedOwner.setId(-1);
-        updatedOwner.setFirstName("George I");
-        updatedOwner.setLastName("Franklin");
-        updatedOwner.setAddress("110 W. Liberty St.");
-        updatedOwner.setCity("Madison");
-        updatedOwner.setTelephone("6085551023");
+        updatedOwnerDto.setId(-1);
+        updatedOwnerDto.setFirstName("GeorgeI");
+        updatedOwnerDto.setLastName("Franklin");
+        updatedOwnerDto.setAddress("110 W. Liberty St.");
+        updatedOwnerDto.setCity("Madison");
+        updatedOwnerDto.setTelephone("6085551023");
         ObjectMapper mapper = new ObjectMapper();
-        String newOwnerAsJSON = mapper.writeValueAsString(updatedOwner);
+        String newOwnerAsJSON = mapper.writeValueAsString(updatedOwnerDto);
         this.mockMvc.perform(put("/api/owners/" + ownerId)
-            .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(status().isBadRequest())
             .andExpect(header().string("errors",
-                "[{\"objectName\":\"body\",\"fieldName\":\"id\",\"fieldValue\":\"-1\",\"errorMessage\":\"does not match pathId: 1\"}]"));
+                "[{\"objectName\":\"body\",\"fieldName\":\"id\",\"fieldValue\":\"-1\",\"errorMessage\":\"does not match pathId: 1\"},{\"objectName\":\"ownerDto\",\"fieldName\":\"id\",\"fieldValue\":\"-1\",\"errorMessage\":\"must be greater than or equal to 0\"}]"));
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testUpdateOwnerError() throws Exception {
-    	Owner newOwner = owners.get(0);
-    	newOwner.setFirstName("");
-    	ObjectMapper mapper = new ObjectMapper();
-    	String newOwnerAsJSON = mapper.writeValueAsString(newOwner);
-    	this.mockMvc.perform(put("/api/owners/1")
-    		.content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
-        	.andExpect(status().isBadRequest());
-     }
+        OwnerDto newOwnerDto = owners.get(0);
+        newOwnerDto.setFirstName("");
+        ObjectMapper mapper = new ObjectMapper();
+        String newOwnerAsJSON = mapper.writeValueAsString(newOwnerDto);
+        this.mockMvc.perform(put("/api/owners/1")
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isBadRequest());
+    }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testDeleteOwnerSuccess() throws Exception {
-    	Owner newOwner = owners.get(0);
-    	ObjectMapper mapper = new ObjectMapper();
-    	String newOwnerAsJSON = mapper.writeValueAsString(newOwner);
-    	given(this.clinicService.findOwnerById(1)).willReturn(owners.get(0));
-    	this.mockMvc.perform(delete("/api/owners/1")
-    		.content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
-        	.andExpect(status().isNoContent());
+        OwnerDto newOwnerDto = owners.get(0);
+        ObjectMapper mapper = new ObjectMapper();
+        String newOwnerAsJSON = mapper.writeValueAsString(newOwnerDto);
+        final Owner owner = ownerMapper.toOwner(owners.get(0));
+        given(this.clinicService.findOwnerById(1)).willReturn(owner);
+        this.mockMvc.perform(delete("/api/owners/1")
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isNoContent());
     }
 
     @Test
-    @WithMockUser(roles="OWNER_ADMIN")
+    @WithMockUser(roles = "OWNER_ADMIN")
     public void testDeleteOwnerError() throws Exception {
-    	Owner newOwner = owners.get(0);
-    	ObjectMapper mapper = new ObjectMapper();
-    	String newOwnerAsJSON = mapper.writeValueAsString(newOwner);
-    	given(this.clinicService.findOwnerById(-1)).willReturn(null);
-    	this.mockMvc.perform(delete("/api/owners/-1")
-    		.content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
-        	.andExpect(status().isNotFound());
+        OwnerDto newOwnerDto = owners.get(0);
+        ObjectMapper mapper = new ObjectMapper();
+        String newOwnerAsJSON = mapper.writeValueAsString(newOwnerDto);
+        given(this.clinicService.findOwnerById(-1)).willReturn(null);
+        this.mockMvc.perform(delete("/api/owners/-1")
+                .content(newOwnerAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isNotFound());
     }
 
 }
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/PetRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/PetRestControllerTests.java
index 9513f34b461e84b2e98d5f997130db43245fe424..be3bddd13f357bcdb128e05c1f4ddb1c7cf79264 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/PetRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/PetRestControllerTests.java
@@ -16,19 +16,8 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import static org.mockito.BDDMockito.given;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -36,11 +25,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.http.MediaType;
-import org.springframework.samples.petclinic.model.Owner;
+import org.springframework.samples.petclinic.dto.OwnerDto;
+import org.springframework.samples.petclinic.dto.PetDto;
+import org.springframework.samples.petclinic.dto.PetTypeDto;
+import org.springframework.samples.petclinic.mapper.PetMapper;
 import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.PetType;
-import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -49,7 +40,16 @@ import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
 
 /**
@@ -67,21 +67,24 @@ public class PetRestControllerTests {
     @Autowired
     private PetRestController petRestController;
 
+    @Autowired
+    private PetMapper petMapper;
+
     @MockBean
     protected ClinicService clinicService;
 
     private MockMvc mockMvc;
 
-    private List<Pet> pets;
+    private List<PetDto> pets;
 
     @Before
     public void initPets(){
     	this.mockMvc = MockMvcBuilders.standaloneSetup(petRestController)
     			.setControllerAdvice(new ExceptionControllerAdvice())
     			.build();
-    	pets = new ArrayList<Pet>();
+    	pets = new ArrayList<>();
 
-    	Owner owner = new Owner();
+    	OwnerDto owner = new OwnerDto();
     	owner.setId(1);
     	owner.setFirstName("Eduardo");
     	owner.setLastName("Rodriquez");
@@ -89,23 +92,21 @@ public class PetRestControllerTests {
     	owner.setCity("McFarland");
     	owner.setTelephone("6085558763");
 
-    	PetType petType = new PetType();
+    	PetTypeDto petType = new PetTypeDto();
     	petType.setId(2);
     	petType.setName("dog");
 
-    	Pet pet = new Pet();
+    	PetDto pet = new PetDto();
     	pet.setId(3);
     	pet.setName("Rosy");
     	pet.setBirthDate(new Date());
-    	pet.setOwner(owner);
     	pet.setType(petType);
     	pets.add(pet);
 
-    	pet = new Pet();
+    	pet = new PetDto();
     	pet.setId(4);
     	pet.setName("Jewel");
     	pet.setBirthDate(new Date());
-    	pet.setOwner(owner);
     	pet.setType(petType);
     	pets.add(pet);
     }
@@ -113,7 +114,7 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testGetPetSuccess() throws Exception {
-    	given(this.clinicService.findPetById(3)).willReturn(pets.get(0));
+    	given(this.clinicService.findPetById(3)).willReturn(petMapper.toPet(pets.get(0)));
         this.mockMvc.perform(get("/api/pets/3")
         	.accept(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(status().isOk())
@@ -125,7 +126,7 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testGetPetNotFound() throws Exception {
-    	given(this.clinicService.findPetById(-1)).willReturn(null);
+    	given(petMapper.toPetDto(this.clinicService.findPetById(-1))).willReturn(null);
         this.mockMvc.perform(get("/api/pets/-1")
         	.accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isNotFound());
@@ -134,7 +135,10 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testGetAllPetsSuccess() throws Exception {
-    	given(this.clinicService.findAllPets()).willReturn(pets);
+        final Collection<Pet> pets = petMapper.toPets(this.pets);
+        System.err.println(pets);
+        when(this.clinicService.findAllPets()).thenReturn(pets);
+        //given(this.clinicService.findAllPets()).willReturn(petMapper.toPets(pets));
         this.mockMvc.perform(get("/api/pets/")
         	.accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isOk())
@@ -149,7 +153,7 @@ public class PetRestControllerTests {
     @WithMockUser(roles="OWNER_ADMIN")
     public void testGetAllPetsNotFound() throws Exception {
     	pets.clear();
-    	given(this.clinicService.findAllPets()).willReturn(pets);
+    	given(this.clinicService.findAllPets()).willReturn(petMapper.toPets(pets));
         this.mockMvc.perform(get("/api/pets/")
         	.accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isNotFound());
@@ -158,10 +162,13 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testCreatePetSuccess() throws Exception {
-    	Pet newPet = pets.get(0);
+    	PetDto newPet = pets.get(0);
     	newPet.setId(999);
     	ObjectMapper mapper = new ObjectMapper();
+        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
+        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
     	String newPetAsJSON = mapper.writeValueAsString(newPet);
+        System.err.println("--> newPetAsJSON="+newPetAsJSON);
     	this.mockMvc.perform(post("/api/pets/")
     		.content(newPetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
     		.andExpect(status().isCreated());
@@ -170,10 +177,12 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testCreatePetError() throws Exception {
-    	Pet newPet = pets.get(0);
+    	PetDto newPet = pets.get(0);
     	newPet.setId(null);
     	newPet.setName(null);
     	ObjectMapper mapper = new ObjectMapper();
+        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
+        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
     	String newPetAsJSON = mapper.writeValueAsString(newPet);
     	this.mockMvc.perform(post("/api/pets/")
         		.content(newPetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -183,10 +192,13 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testUpdatePetSuccess() throws Exception {
-    	given(this.clinicService.findPetById(3)).willReturn(pets.get(0));
-    	Pet newPet = pets.get(0);
+    	given(this.clinicService.findPetById(3)).willReturn(petMapper.toPet(pets.get(0)));
+    	PetDto newPet = pets.get(0);
     	newPet.setName("Rosy I");
     	ObjectMapper mapper = new ObjectMapper();
+        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
+        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+
     	String newPetAsJSON = mapper.writeValueAsString(newPet);
     	this.mockMvc.perform(put("/api/pets/3")
     		.content(newPetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -205,10 +217,13 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testUpdatePetError() throws Exception {
-    	Pet newPet = pets.get(0);
-    	newPet.setName("");
+    	PetDto newPet = pets.get(0);
+    	newPet.setName(null);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newPetAsJSON = mapper.writeValueAsString(newPet);
+        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
+        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+        String newPetAsJSON = mapper.writeValueAsString(newPet);
+
     	this.mockMvc.perform(put("/api/pets/3")
     		.content(newPetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(status().isBadRequest());
@@ -217,10 +232,10 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testDeletePetSuccess() throws Exception {
-    	Pet newPet = pets.get(0);
+    	PetDto newPet = pets.get(0);
     	ObjectMapper mapper = new ObjectMapper();
     	String newPetAsJSON = mapper.writeValueAsString(newPet);
-    	given(this.clinicService.findPetById(3)).willReturn(pets.get(0));
+    	given(this.clinicService.findPetById(3)).willReturn(petMapper.toPet(pets.get(0)));
     	this.mockMvc.perform(delete("/api/pets/3")
     		.content(newPetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(status().isNoContent());
@@ -229,7 +244,7 @@ public class PetRestControllerTests {
     @Test
     @WithMockUser(roles="OWNER_ADMIN")
     public void testDeletePetError() throws Exception {
-    	Pet newPet = pets.get(0);
+    	PetDto newPet = pets.get(0);
     	ObjectMapper mapper = new ObjectMapper();
     	String newPetAsJSON = mapper.writeValueAsString(newPet);
     	given(this.clinicService.findPetById(-1)).willReturn(null);
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/PetTypeRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/PetTypeRestControllerTests.java
index 089cebfbbc1fa19c4b6ddac5ee9d83054dcaa285..baeb6983cd07d377996df862a4ad1f3f7c95af81 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/PetTypeRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/PetTypeRestControllerTests.java
@@ -16,18 +16,7 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import static org.mockito.BDDMockito.given;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-import java.util.ArrayList;
-import java.util.List;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,9 +24,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.http.MediaType;
+import org.springframework.samples.petclinic.mapper.PetTypeMapper;
 import org.springframework.samples.petclinic.model.PetType;
-import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -45,7 +35,12 @@ import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
 
 /**
@@ -62,6 +57,9 @@ public class PetTypeRestControllerTests {
     @Autowired
     private PetTypeRestController petTypeRestController;
 
+    @Autowired
+    private PetTypeMapper petTypeMapper;
+
     @MockBean
     private ClinicService clinicService;
 
@@ -178,7 +176,7 @@ public class PetTypeRestControllerTests {
     	PetType newPetType = petTypes.get(0);
     	newPetType.setId(999);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newPetTypeAsJSON = mapper.writeValueAsString(newPetType);
+        String newPetTypeAsJSON = mapper.writeValueAsString(petTypeMapper.toPetTypeDto(newPetType));
     	this.mockMvc.perform(post("/api/pettypes/")
     		.content(newPetTypeAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
     		.andExpect(status().isCreated());
@@ -191,7 +189,7 @@ public class PetTypeRestControllerTests {
     	newPetType.setId(null);
     	newPetType.setName(null);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newPetTypeAsJSON = mapper.writeValueAsString(newPetType);
+        String newPetTypeAsJSON = mapper.writeValueAsString(petTypeMapper.toPetTypeDto(newPetType));
     	this.mockMvc.perform(post("/api/pettypes/")
         		.content(newPetTypeAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         		.andExpect(status().isBadRequest());
@@ -204,7 +202,7 @@ public class PetTypeRestControllerTests {
     	PetType newPetType = petTypes.get(1);
     	newPetType.setName("dog I");
     	ObjectMapper mapper = new ObjectMapper();
-    	String newPetTypeAsJSON = mapper.writeValueAsString(newPetType);
+        String newPetTypeAsJSON = mapper.writeValueAsString(petTypeMapper.toPetTypeDto(newPetType));
     	this.mockMvc.perform(put("/api/pettypes/2")
     		.content(newPetTypeAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(content().contentType("application/json"))
@@ -224,7 +222,7 @@ public class PetTypeRestControllerTests {
     	PetType newPetType = petTypes.get(0);
     	newPetType.setName("");
     	ObjectMapper mapper = new ObjectMapper();
-    	String newPetTypeAsJSON = mapper.writeValueAsString(newPetType);
+        String newPetTypeAsJSON = mapper.writeValueAsString(petTypeMapper.toPetTypeDto(newPetType));
     	this.mockMvc.perform(put("/api/pettypes/1")
     		.content(newPetTypeAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(status().isBadRequest());
@@ -247,7 +245,7 @@ public class PetTypeRestControllerTests {
     public void testDeletePetTypeError() throws Exception {
     	PetType newPetType = petTypes.get(0);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newPetTypeAsJSON = mapper.writeValueAsString(newPetType);
+        String newPetTypeAsJSON = mapper.writeValueAsString(petTypeMapper.toPetTypeDto(newPetType));
     	given(this.clinicService.findPetTypeById(-1)).willReturn(null);
     	this.mockMvc.perform(delete("/api/pettypes/-1")
     		.content(newPetTypeAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/SpecialtyRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/SpecialtyRestControllerTests.java
index c4592101d597836257dc449e53a9cefe65a91d2b..023a8663dc5d27998dd549d1ad292118359497d3 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/SpecialtyRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/SpecialtyRestControllerTests.java
@@ -16,18 +16,7 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import static org.mockito.BDDMockito.given;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-import java.util.ArrayList;
-import java.util.List;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,9 +24,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.http.MediaType;
+import org.springframework.samples.petclinic.mapper.SpecialtyMapper;
 import org.springframework.samples.petclinic.model.Specialty;
-import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -45,7 +35,12 @@ import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
 /**
  * Test class for {@link SpecialtyRestController}
@@ -61,6 +56,9 @@ public class SpecialtyRestControllerTests {
     @Autowired
     private SpecialtyRestController specialtyRestController;
 
+    @Autowired
+    private SpecialtyMapper specialtyMapper;
+
 	@MockBean
     private ClinicService clinicService;
 
@@ -144,7 +142,7 @@ public class SpecialtyRestControllerTests {
     	Specialty newSpecialty = specialties.get(0);
     	newSpecialty.setId(999);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newSpecialtyAsJSON = mapper.writeValueAsString(newSpecialty);
+        String newSpecialtyAsJSON = mapper.writeValueAsString(specialtyMapper.toSpecialtyDto(newSpecialty));
     	this.mockMvc.perform(post("/api/specialties/")
     		.content(newSpecialtyAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
     		.andExpect(status().isCreated());
@@ -157,7 +155,7 @@ public class SpecialtyRestControllerTests {
     	newSpecialty.setId(null);
     	newSpecialty.setName(null);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newSpecialtyAsJSON = mapper.writeValueAsString(newSpecialty);
+        String newSpecialtyAsJSON = mapper.writeValueAsString(specialtyMapper.toSpecialtyDto(newSpecialty));
     	this.mockMvc.perform(post("/api/specialties/")
         		.content(newSpecialtyAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         		.andExpect(status().isBadRequest());
@@ -170,7 +168,7 @@ public class SpecialtyRestControllerTests {
     	Specialty newSpecialty = specialties.get(1);
     	newSpecialty.setName("surgery I");
     	ObjectMapper mapper = new ObjectMapper();
-    	String newSpecialtyAsJSON = mapper.writeValueAsString(newSpecialty);
+        String newSpecialtyAsJSON = mapper.writeValueAsString(specialtyMapper.toSpecialtyDto(newSpecialty));
     	this.mockMvc.perform(put("/api/specialties/2")
     		.content(newSpecialtyAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(content().contentType("application/json"))
@@ -190,7 +188,7 @@ public class SpecialtyRestControllerTests {
     	Specialty newSpecialty = specialties.get(0);
     	newSpecialty.setName("");
     	ObjectMapper mapper = new ObjectMapper();
-    	String newSpecialtyAsJSON = mapper.writeValueAsString(newSpecialty);
+        String newSpecialtyAsJSON = mapper.writeValueAsString(specialtyMapper.toSpecialtyDto(newSpecialty));
     	this.mockMvc.perform(put("/api/specialties/1")
     		.content(newSpecialtyAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(status().isBadRequest());
@@ -201,7 +199,7 @@ public class SpecialtyRestControllerTests {
     public void testDeleteSpecialtySuccess() throws Exception {
     	Specialty newSpecialty = specialties.get(0);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newSpecialtyAsJSON = mapper.writeValueAsString(newSpecialty);
+        String newSpecialtyAsJSON = mapper.writeValueAsString(specialtyMapper.toSpecialtyDto(newSpecialty));
     	given(this.clinicService.findSpecialtyById(1)).willReturn(specialties.get(0));
     	this.mockMvc.perform(delete("/api/specialties/1")
     		.content(newSpecialtyAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -213,7 +211,7 @@ public class SpecialtyRestControllerTests {
     public void testDeleteSpecialtyError() throws Exception {
     	Specialty newSpecialty = specialties.get(0);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newSpecialtyAsJSON = mapper.writeValueAsString(newSpecialty);
+        String newSpecialtyAsJSON = mapper.writeValueAsString(specialtyMapper.toSpecialtyDto(newSpecialty));
     	given(this.clinicService.findSpecialtyById(-1)).willReturn(null);
     	this.mockMvc.perform(delete("/api/specialties/-1")
     		.content(newSpecialtyAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/UserRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/UserRestControllerTests.java
index c16676407ec4a00a3967d6f473c1f527b34a6c8b..72d70c36149a98e711c9f941c04aece4e48c59bc 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/UserRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/UserRestControllerTests.java
@@ -1,9 +1,6 @@
 package org.springframework.samples.petclinic.rest;
 
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -11,9 +8,10 @@ import org.mockito.Mock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.http.MediaType;
+import org.springframework.samples.petclinic.mapper.UserMapper;
 import org.springframework.samples.petclinic.model.User;
-import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.samples.petclinic.service.UserService;
+import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -21,7 +19,8 @@ import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 @SpringBootTest
 @RunWith(SpringJUnit4ClassRunner.class)
@@ -32,6 +31,9 @@ public class UserRestControllerTests {
     @Mock
     private UserService userService;
 
+    @Autowired
+    private UserMapper userMapper;
+
     @Autowired
     private UserRestController userRestController;
 
@@ -44,29 +46,29 @@ public class UserRestControllerTests {
     }
 
     @Test
-    @WithMockUser(roles="ADMIN")
+    @WithMockUser(roles = "ADMIN")
     public void testCreateUserSuccess() throws Exception {
         User user = new User();
         user.setUsername("username");
         user.setPassword("password");
         user.setEnabled(true);
-        user.addRole( "OWNER_ADMIN" );
+        user.addRole("OWNER_ADMIN");
         ObjectMapper mapper = new ObjectMapper();
-        String newVetAsJSON = mapper.writeValueAsString(user);
+        String newVetAsJSON = mapper.writeValueAsString(userMapper.toUserDto(user));
         this.mockMvc.perform(post("/api/users/")
             .content(newVetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(status().isCreated());
     }
 
     @Test
-    @WithMockUser(roles="ADMIN")
+    @WithMockUser(roles = "ADMIN")
     public void testCreateUserError() throws Exception {
         User user = new User();
         user.setUsername("username");
         user.setPassword("password");
         user.setEnabled(true);
         ObjectMapper mapper = new ObjectMapper();
-        String newVetAsJSON = mapper.writeValueAsString(user);
+        String newVetAsJSON = mapper.writeValueAsString(userMapper.toUserDto(user));
         this.mockMvc.perform(post("/api/users/")
             .content(newVetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
             .andExpect(status().isBadRequest());
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/VetRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/VetRestControllerTests.java
index a6ab35ced9b47b6317a34b9a69c8904ce7df8cbe..7b90a41f60a04e21eedd2f0e0dcd019ff264f850 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/VetRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/VetRestControllerTests.java
@@ -16,18 +16,7 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import static org.mockito.BDDMockito.given;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-import java.util.ArrayList;
-import java.util.List;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,9 +24,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.http.MediaType;
+import org.springframework.samples.petclinic.mapper.VetMapper;
 import org.springframework.samples.petclinic.model.Vet;
-import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -45,7 +35,12 @@ import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
 /**
  * Test class for {@link VetRestController}
@@ -61,6 +56,9 @@ public class VetRestControllerTests {
     @Autowired
     private VetRestController vetRestController;
 
+    @Autowired
+    private VetMapper vetMapper;
+
 	@MockBean
     private ClinicService clinicService;
 
@@ -146,7 +144,7 @@ public class VetRestControllerTests {
     	Vet newVet = vets.get(0);
     	newVet.setId(999);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVetAsJSON = mapper.writeValueAsString(newVet);
+        String newVetAsJSON = mapper.writeValueAsString(vetMapper.toVetDto(newVet));
     	this.mockMvc.perform(post("/api/vets/")
     		.content(newVetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
     		.andExpect(status().isCreated());
@@ -159,7 +157,7 @@ public class VetRestControllerTests {
     	newVet.setId(null);
     	newVet.setFirstName(null);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVetAsJSON = mapper.writeValueAsString(newVet);
+        String newVetAsJSON = mapper.writeValueAsString(vetMapper.toVetDto(newVet));
     	this.mockMvc.perform(post("/api/vets/")
         		.content(newVetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         		.andExpect(status().isBadRequest());
@@ -172,7 +170,7 @@ public class VetRestControllerTests {
     	Vet newVet = vets.get(0);
     	newVet.setFirstName("James");
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVetAsJSON = mapper.writeValueAsString(newVet);
+        String newVetAsJSON = mapper.writeValueAsString(vetMapper.toVetDto(newVet));
     	this.mockMvc.perform(put("/api/vets/1")
     		.content(newVetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(content().contentType("application/json"))
@@ -191,9 +189,9 @@ public class VetRestControllerTests {
     @WithMockUser(roles="VET_ADMIN")
     public void testUpdateVetError() throws Exception {
     	Vet newVet = vets.get(0);
-    	newVet.setFirstName("");
+    	newVet.setFirstName(null);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVetAsJSON = mapper.writeValueAsString(newVet);
+        String newVetAsJSON = mapper.writeValueAsString(vetMapper.toVetDto(newVet));
     	this.mockMvc.perform(put("/api/vets/1")
     		.content(newVetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(status().isBadRequest());
@@ -204,7 +202,7 @@ public class VetRestControllerTests {
     public void testDeleteVetSuccess() throws Exception {
     	Vet newVet = vets.get(0);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVetAsJSON = mapper.writeValueAsString(newVet);
+        String newVetAsJSON = mapper.writeValueAsString(vetMapper.toVetDto(newVet));
     	given(this.clinicService.findVetById(1)).willReturn(vets.get(0));
     	this.mockMvc.perform(delete("/api/vets/1")
     		.content(newVetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -216,7 +214,7 @@ public class VetRestControllerTests {
     public void testDeleteVetError() throws Exception {
     	Vet newVet = vets.get(0);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVetAsJSON = mapper.writeValueAsString(newVet);
+        String newVetAsJSON = mapper.writeValueAsString(vetMapper.toVetDto(newVet));
     	given(this.clinicService.findVetById(-1)).willReturn(null);
     	this.mockMvc.perform(delete("/api/vets/-1")
     		.content(newVetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -224,4 +222,3 @@ public class VetRestControllerTests {
     }
 
 }
-
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/VisitRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/VisitRestControllerTests.java
index e318080e28887a10f4bb1d98a163320d078141d2..cd51385e9980ec2ea5d1a72a3fa750d92fb88d85 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/VisitRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/VisitRestControllerTests.java
@@ -16,20 +16,7 @@
 
 package org.springframework.samples.petclinic.rest;
 
-import static org.mockito.BDDMockito.given;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -37,12 +24,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.http.MediaType;
+import org.springframework.samples.petclinic.mapper.VisitMapper;
 import org.springframework.samples.petclinic.model.Owner;
 import org.springframework.samples.petclinic.model.Pet;
 import org.springframework.samples.petclinic.model.PetType;
 import org.springframework.samples.petclinic.model.Visit;
-import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.service.clinicService.ApplicationTestConfig;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -50,7 +38,14 @@ import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
 /**
  * Test class for {@link VisitRestController}
@@ -69,6 +64,9 @@ public class VisitRestControllerTests {
     @MockBean
     private ClinicService clinicService;
 
+    @Autowired
+    private VisitMapper visitMapper;
+
     private MockMvc mockMvc;
 
     private List<Visit> visits;
@@ -79,7 +77,7 @@ public class VisitRestControllerTests {
     			.setControllerAdvice(new ExceptionControllerAdvice())
     			.build();
 
-    	visits = new ArrayList<Visit>();
+        visits = new ArrayList<>();
 
     	Owner owner = new Owner();
     	owner.setId(1);
@@ -169,21 +167,20 @@ public class VisitRestControllerTests {
     	Visit newVisit = visits.get(0);
     	newVisit.setId(999);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVisitAsJSON = mapper.writeValueAsString(newVisit);
+        String newVisitAsJSON = mapper.writeValueAsString(visitMapper.toVisitDto(newVisit));
     	System.out.println("newVisitAsJSON " + newVisitAsJSON);
     	this.mockMvc.perform(post("/api/visits/")
     		.content(newVisitAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
     		.andExpect(status().isCreated());
     }
 
-    @Test(expected = IOException.class)
     @WithMockUser(roles="OWNER_ADMIN")
     public void testCreateVisitError() throws Exception {
     	Visit newVisit = visits.get(0);
     	newVisit.setId(null);
-    	newVisit.setPet(null);
+        newVisit.setDescription(null);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVisitAsJSON = mapper.writeValueAsString(newVisit);
+        String newVisitAsJSON = mapper.writeValueAsString(visitMapper.toVisitDto(newVisit));
     	this.mockMvc.perform(post("/api/visits/")
         		.content(newVisitAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         		.andExpect(status().isBadRequest());
@@ -196,7 +193,7 @@ public class VisitRestControllerTests {
     	Visit newVisit = visits.get(0);
     	newVisit.setDescription("rabies shot test");
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVisitAsJSON = mapper.writeValueAsString(newVisit);
+        String newVisitAsJSON = mapper.writeValueAsString(visitMapper.toVisitDto(newVisit));
     	this.mockMvc.perform(put("/api/visits/2")
     		.content(newVisitAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(content().contentType("application/json"))
@@ -210,13 +207,12 @@ public class VisitRestControllerTests {
             .andExpect(jsonPath("$.description").value("rabies shot test"));
     }
 
-    @Test(expected = IOException.class)
     @WithMockUser(roles="OWNER_ADMIN")
     public void testUpdateVisitError() throws Exception {
     	Visit newVisit = visits.get(0);
-    	newVisit.setPet(null);
+        newVisit.setDescription(null);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVisitAsJSON = mapper.writeValueAsString(newVisit);
+        String newVisitAsJSON = mapper.writeValueAsString(visitMapper.toVisitDto(newVisit));
     	this.mockMvc.perform(put("/api/visits/2")
     		.content(newVisitAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(status().isBadRequest());
@@ -227,7 +223,7 @@ public class VisitRestControllerTests {
     public void testDeleteVisitSuccess() throws Exception {
     	Visit newVisit = visits.get(0);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVisitAsJSON = mapper.writeValueAsString(newVisit);
+        String newVisitAsJSON = mapper.writeValueAsString(visitMapper.toVisitDto(newVisit));
     	given(this.clinicService.findVisitById(2)).willReturn(visits.get(0));
     	this.mockMvc.perform(delete("/api/visits/2")
     		.content(newVisitAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -239,7 +235,7 @@ public class VisitRestControllerTests {
     public void testDeleteVisitError() throws Exception {
     	Visit newVisit = visits.get(0);
     	ObjectMapper mapper = new ObjectMapper();
-    	String newVisitAsJSON = mapper.writeValueAsString(newVisit);
+        String newVisitAsJSON = mapper.writeValueAsString(visitMapper.toVisitDto(newVisit));
     	given(this.clinicService.findVisitById(-1)).willReturn(null);
     	this.mockMvc.perform(delete("/api/visits/-1")
     		.content(newVisitAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index 59e2ae413a2e719a7801a482f03d0bb0551175b9..d14cb703554f8dcc4d856aa34e47064cbe1a39aa 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -24,7 +24,6 @@ server.port=9966
 server.context-path=/petclinic/
 
 spring.messages.basename=messages/messages
-
 logging.level.org.springframework=INFO
 #logging.level.org.springframework=DEBUG
 
@@ -35,3 +34,7 @@ logging.level.org.springframework=INFO
 # by default the authentication is disabled
 security.ignored=/**
 basic.authentication.enabled=true
+# ------------------------------------------------
+# Spring doc configuration
+springdoc.api-docs.enabled=true
+springdoc.writer-with-default-pretty-printer=true