From 83ff9a50e378529993f4f772457dd24791b46438 Mon Sep 17 00:00:00 2001
From: Dave Syer <dsyer@pivotal.io>
Date: Thu, 10 Nov 2016 22:10:56 +0000
Subject: [PATCH] Modularize and migrate to aggregate-oriented domain

Vet, Owner, Visit. The Visit "aggregate" is a little artificial
but it demonstrates a useful point about not holding on to
references of "parent" (reference data) objects, i.e. the Visit has
an Integer petId, instead of a Pet field. In principle this app is
now almost ready to migrate to multiple services if anyone wanted
to do that.
---
 .../petclinic/PetClinicApplication.java       |   2 +
 .../samples/petclinic/model/package-info.java |  10 +-
 .../petclinic/{model => owner}/Owner.java     |   3 +-
 .../{web => owner}/OwnerController.java       |  22 ++--
 .../OwnerRepository.java                      |   6 +-
 .../petclinic/{model => owner}/Pet.java       |  13 +--
 .../{web => owner}/PetController.java         |  40 ++++---
 .../{repository => owner}/PetRepository.java  |   7 +-
 .../petclinic/{model => owner}/PetType.java   |   4 +-
 .../{web => owner}/PetTypeFormatter.java      |  13 +--
 .../{web => owner}/PetValidator.java          |   3 +-
 .../{web => owner}/VisitController.java       |  25 ++--
 .../petclinic/service/ClinicService.java      |  53 ---------
 .../petclinic/service/ClinicServiceImpl.java  | 108 ------------------
 .../{config => system}/CacheConfig.java       |   4 +-
 .../{web => system}/CrashController.java      |   4 +-
 .../{web => system}/WelcomeController.java    |   4 +-
 .../petclinic/{model => vet}/Specialty.java   |   4 +-
 .../samples/petclinic/{model => vet}/Vet.java |   3 +-
 .../petclinic/{web => vet}/VetController.java |  16 ++-
 .../{repository => vet}/VetRepository.java    |   8 +-
 .../petclinic/{model => vet}/Vets.java        |   2 +-
 .../petclinic/{model => visit}/Visit.java     |  34 +++---
 .../VisitRepository.java                      |   3 +-
 .../samples/petclinic/web/package-info.java   |   5 -
 .../pets/createOrUpdateVisitForm.html         |  12 +-
 .../{web => owner}/OwnerControllerTests.java  |  31 ++---
 .../{web => owner}/PetControllerTests.java    |  36 +++---
 .../{web => owner}/PetTypeFormatterTests.java |  34 +++---
 .../{web => owner}/VisitControllerTests.java  |  27 +++--
 .../petclinic/service/ClinicServiceTests.java |  86 ++++++++------
 .../{util => service}/EntityUtils.java        |   2 +-
 .../{web => system}/CrashControllerTests.java |   3 +-
 .../{web => vet}/VetControllerTests.java      |  27 +++--
 34 files changed, 270 insertions(+), 384 deletions(-)
 rename src/main/java/org/springframework/samples/petclinic/{model => owner}/Owner.java (97%)
 rename src/main/java/org/springframework/samples/petclinic/{web => owner}/OwnerController.java (86%)
 rename src/main/java/org/springframework/samples/petclinic/{repository => owner}/OwnerRepository.java (92%)
 rename src/main/java/org/springframework/samples/petclinic/{model => owner}/Pet.java (91%)
 rename src/main/java/org/springframework/samples/petclinic/{web => owner}/PetController.java (80%)
 rename src/main/java/org/springframework/samples/petclinic/{repository => owner}/PetRepository.java (90%)
 rename src/main/java/org/springframework/samples/petclinic/{model => owner}/PetType.java (87%)
 rename src/main/java/org/springframework/samples/petclinic/{web => owner}/PetTypeFormatter.java (79%)
 rename src/main/java/org/springframework/samples/petclinic/{web => owner}/PetValidator.java (94%)
 rename src/main/java/org/springframework/samples/petclinic/{web => owner}/VisitController.java (82%)
 delete mode 100644 src/main/java/org/springframework/samples/petclinic/service/ClinicService.java
 delete mode 100644 src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
 rename src/main/java/org/springframework/samples/petclinic/{config => system}/CacheConfig.java (95%)
 rename src/main/java/org/springframework/samples/petclinic/{web => system}/CrashController.java (93%)
 rename src/main/java/org/springframework/samples/petclinic/{web => system}/WelcomeController.java (72%)
 rename src/main/java/org/springframework/samples/petclinic/{model => vet}/Specialty.java (88%)
 rename src/main/java/org/springframework/samples/petclinic/{model => vet}/Vet.java (95%)
 rename src/main/java/org/springframework/samples/petclinic/{web => vet}/VetController.java (77%)
 rename src/main/java/org/springframework/samples/petclinic/{repository => vet}/VetRepository.java (86%)
 rename src/main/java/org/springframework/samples/petclinic/{model => vet}/Vets.java (95%)
 rename src/main/java/org/springframework/samples/petclinic/{model => visit}/Visit.java (83%)
 rename src/main/java/org/springframework/samples/petclinic/{repository => visit}/VisitRepository.java (93%)
 delete mode 100644 src/main/java/org/springframework/samples/petclinic/web/package-info.java
 rename src/test/java/org/springframework/samples/petclinic/{web => owner}/OwnerControllerTests.java (89%)
 rename src/test/java/org/springframework/samples/petclinic/{web => owner}/PetControllerTests.java (79%)
 rename src/test/java/org/springframework/samples/petclinic/{web => owner}/PetTypeFormatterTests.java (65%)
 rename src/test/java/org/springframework/samples/petclinic/{web => owner}/VisitControllerTests.java (75%)
 rename src/test/java/org/springframework/samples/petclinic/{util => service}/EntityUtils.java (97%)
 rename src/test/java/org/springframework/samples/petclinic/{web => system}/CrashControllerTests.java (93%)
 rename src/test/java/org/springframework/samples/petclinic/{web => vet}/VetControllerTests.java (75%)

diff --git a/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java b/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
index 80859de..224c326 100644
--- a/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
+++ b/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
@@ -21,6 +21,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 /**
  * PetClinic Spring Boot Application.
+ * 
+ * @author Dave Syer
  *
  */
 @SpringBootApplication
diff --git a/src/main/java/org/springframework/samples/petclinic/model/package-info.java b/src/main/java/org/springframework/samples/petclinic/model/package-info.java
index 2730958..78294d1 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/package-info.java
+++ b/src/main/java/org/springframework/samples/petclinic/model/package-info.java
@@ -1,5 +1,5 @@
-/**
- * The classes in this package represent PetClinic's business layer.
- */
-package org.springframework.samples.petclinic.model;
-
+/**
+ * The classes in this package represent utilities used by the domain.
+ */
+package org.springframework.samples.petclinic.model;
+
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Owner.java b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java
similarity index 97%
rename from src/main/java/org/springframework/samples/petclinic/model/Owner.java
rename to src/main/java/org/springframework/samples/petclinic/owner/Owner.java
index 9a09bd7..f6fcae7 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Owner.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.model;
+package org.springframework.samples.petclinic.owner;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -32,6 +32,7 @@ import org.hibernate.validator.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.model.Person;
 
 /**
  * Simple JavaBean domain object representing an owner.
diff --git a/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java
similarity index 86%
rename from src/main/java/org/springframework/samples/petclinic/web/OwnerController.java
rename to src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java
index dfc8d0b..ef3169b 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
 
 import java.util.Collection;
 import java.util.Map;
@@ -21,8 +21,6 @@ import java.util.Map;
 import javax.validation.Valid;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.model.Owner;
-import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.validation.BindingResult;
@@ -40,15 +38,15 @@ import org.springframework.web.servlet.ModelAndView;
  * @author Michael Isvy
  */
 @Controller
-public class OwnerController {
+class OwnerController {
 
     private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
-    private final ClinicService clinicService;
+    private final OwnerRepository owners;
 
 
     @Autowired
-    public OwnerController(ClinicService clinicService) {
-        this.clinicService = clinicService;
+    public OwnerController(OwnerRepository clinicService) {
+        this.owners = clinicService;
     }
 
     @InitBinder
@@ -68,7 +66,7 @@ public class OwnerController {
         if (result.hasErrors()) {
             return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
         } else {
-            this.clinicService.saveOwner(owner);
+            this.owners.save(owner);
             return "redirect:/owners/" + owner.getId();
         }
     }
@@ -88,7 +86,7 @@ public class OwnerController {
         }
 
         // find owners by last name
-        Collection<Owner> results = this.clinicService.findOwnerByLastName(owner.getLastName());
+        Collection<Owner> results = this.owners.findByLastName(owner.getLastName());
         if (results.isEmpty()) {
             // no owners found
             result.rejectValue("lastName", "notFound", "not found");
@@ -106,7 +104,7 @@ public class OwnerController {
 
     @RequestMapping(value = "/owners/{ownerId}/edit", method = RequestMethod.GET)
     public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
-        Owner owner = this.clinicService.findOwnerById(ownerId);
+        Owner owner = this.owners.findById(ownerId);
         model.addAttribute(owner);
         return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
     }
@@ -117,7 +115,7 @@ public class OwnerController {
             return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
         } else {
             owner.setId(ownerId);
-            this.clinicService.saveOwner(owner);
+            this.owners.save(owner);
             return "redirect:/owners/{ownerId}";
         }
     }
@@ -131,7 +129,7 @@ public class OwnerController {
     @RequestMapping("/owners/{ownerId}")
     public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
         ModelAndView mav = new ModelAndView("owners/ownerDetails");
-        mav.addObject(this.clinicService.findOwnerById(ownerId));
+        mav.addObject(this.owners.findById(ownerId));
         return mav;
     }
 
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java
similarity index 92%
rename from src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
rename to src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java
index 4b0a0ad..068f524 100644
--- a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java
@@ -13,14 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.repository;
+package org.springframework.samples.petclinic.owner;
 
 import java.util.Collection;
 
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.Repository;
 import org.springframework.data.repository.query.Param;
-import org.springframework.samples.petclinic.model.Owner;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * Repository class for <code>Owner</code> domain objects All method names are compliant with Spring Data naming
@@ -41,6 +41,7 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
      * found)
      */
     @Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName%")
+    @Transactional(readOnly = true)
     Collection<Owner> findByLastName(@Param("lastName") String lastName);
 
     /**
@@ -49,6 +50,7 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
      * @return the {@link Owner} if found
      */
     @Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id")
+    @Transactional(readOnly = true)
     Owner findById(@Param("id") Integer id);
 
     /**
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Pet.java b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java
similarity index 91%
rename from src/main/java/org/springframework/samples/petclinic/model/Pet.java
rename to src/main/java/org/springframework/samples/petclinic/owner/Pet.java
index d21db69..5b4e317 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Pet.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java
@@ -13,11 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.model;
+package org.springframework.samples.petclinic.owner;
 
 import org.springframework.beans.support.MutableSortDefinition;
 import org.springframework.beans.support.PropertyComparator;
 import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.samples.petclinic.model.NamedEntity;
+import org.springframework.samples.petclinic.visit.Visit;
 
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -62,10 +64,9 @@ public class Pet extends NamedEntity {
     @JoinColumn(name = "owner_id")
     private Owner owner;
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "pet", fetch = FetchType.EAGER)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy="petId", fetch = FetchType.EAGER)
     private Set<Visit> visits = new LinkedHashSet<>();
 
-
     public void setBirthDate(Date birthDate) {
         this.birthDate = birthDate;
     }
@@ -109,11 +110,7 @@ public class Pet extends NamedEntity {
 
     public void addVisit(Visit visit) {
         getVisitsInternal().add(visit);
-        visit.setPet(this);
+        visit.setPetId(this.id);
     }
 
-
-
-
-
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/web/PetController.java b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java
similarity index 80%
rename from src/main/java/org/springframework/samples/petclinic/web/PetController.java
rename to src/main/java/org/springframework/samples/petclinic/owner/PetController.java
index 6e2a59b..4720a40 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/PetController.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java
@@ -13,23 +13,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
+
+import java.util.Collection;
+
+import javax.validation.Valid;
 
 import org.springframework.beans.factory.annotation.Autowired;
-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.service.ClinicService;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.ModelMap;
 import org.springframework.util.StringUtils;
 import org.springframework.validation.BindingResult;
 import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.*;
-
-import javax.validation.Valid;
-
-import java.util.Collection;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
 
 /**
  * @author Juergen Hoeller
@@ -38,24 +38,26 @@ import java.util.Collection;
  */
 @Controller
 @RequestMapping("/owners/{ownerId}")
-public class PetController {
+class PetController {
 
     private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm";
-    private final ClinicService clinicService;
+    private final PetRepository pets;
+    private final OwnerRepository owners;
 
     @Autowired
-    public PetController(ClinicService clinicService) {
-        this.clinicService = clinicService;
+    public PetController(PetRepository pets, OwnerRepository owners) {
+        this.pets = pets;
+        this.owners = owners;
     }
 
     @ModelAttribute("types")
     public Collection<PetType> populatePetTypes() {
-        return this.clinicService.findPetTypes();
+        return this.pets.findPetTypes();
     }
 
     @ModelAttribute("owner")
     public Owner findOwner(@PathVariable("ownerId") int ownerId) {
-        return this.clinicService.findOwnerById(ownerId);
+        return this.owners.findById(ownerId);
     }
 
     @InitBinder("owner")
@@ -86,14 +88,14 @@ public class PetController {
             return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
         } else {
             owner.addPet(pet);
-            this.clinicService.savePet(pet);
+            this.pets.save(pet);
             return "redirect:/owners/{ownerId}";
         }
     }
 
     @RequestMapping(value = "/pets/{petId}/edit", method = RequestMethod.GET)
     public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) {
-        Pet pet = this.clinicService.findPetById(petId);
+        Pet pet = this.pets.findById(petId);
         model.put("pet", pet);
         return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
     }
@@ -105,7 +107,7 @@ public class PetController {
             return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
         } else {
             owner.addPet(pet);
-            this.clinicService.savePet(pet);
+            this.pets.save(pet);
             return "redirect:/owners/{ownerId}";
         }
     }
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java b/src/main/java/org/springframework/samples/petclinic/owner/PetRepository.java
similarity index 90%
rename from src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
rename to src/main/java/org/springframework/samples/petclinic/owner/PetRepository.java
index 2ddea85..b0ec5db 100644
--- a/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/PetRepository.java
@@ -13,14 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.repository;
+package org.springframework.samples.petclinic.owner;
 
 import java.util.List;
 
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.Repository;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.PetType;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * Repository class for <code>Pet</code> domain objects All method names are compliant with Spring Data naming
@@ -38,6 +37,7 @@ public interface PetRepository extends Repository<Pet, Integer> {
      * @return a Collection of {@link PetType}s.
      */
     @Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name")
+    @Transactional(readOnly = true)
     List<PetType> findPetTypes();
 
     /**
@@ -45,6 +45,7 @@ public interface PetRepository extends Repository<Pet, Integer> {
      * @param id the id to search for
      * @return the {@link Pet} if found
      */
+    @Transactional(readOnly = true)
     Pet findById(Integer id);
 
     /**
diff --git a/src/main/java/org/springframework/samples/petclinic/model/PetType.java b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java
similarity index 87%
rename from src/main/java/org/springframework/samples/petclinic/model/PetType.java
rename to src/main/java/org/springframework/samples/petclinic/owner/PetType.java
index f60a5cd..ac827b3 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/PetType.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java
@@ -13,11 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.model;
+package org.springframework.samples.petclinic.owner;
 
 import javax.persistence.Entity;
 import javax.persistence.Table;
 
+import org.springframework.samples.petclinic.model.NamedEntity;
+
 /**
  * @author Juergen Hoeller
  *         Can be Cat, Dog, Hamster...
diff --git a/src/main/java/org/springframework/samples/petclinic/web/PetTypeFormatter.java b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java
similarity index 79%
rename from src/main/java/org/springframework/samples/petclinic/web/PetTypeFormatter.java
rename to src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java
index 71a060c..78451ca 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/PetTypeFormatter.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
 
 
 import java.text.ParseException;
@@ -22,8 +22,6 @@ import java.util.Locale;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.format.Formatter;
-import org.springframework.samples.petclinic.model.PetType;
-import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.stereotype.Component;
 
 /**
@@ -32,7 +30,6 @@ import org.springframework.stereotype.Component;
  * Spring ref doc: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html#format-Formatter-SPI
  * - A nice blog entry from Gordon Dickens: http://gordondickens.com/wordpress/2010/09/30/using-spring-3-0-custom-type-converter/
  * <p/>
- * Also see how the bean 'conversionService' has been declared inside /WEB-INF/mvc-core-config.xml
  *
  * @author Mark Fisher
  * @author Juergen Hoeller
@@ -41,12 +38,12 @@ import org.springframework.stereotype.Component;
 @Component
 public class PetTypeFormatter implements Formatter<PetType> {
 
-    private final ClinicService clinicService;
+    private final PetRepository pets;
 
 
     @Autowired
-    public PetTypeFormatter(ClinicService clinicService) {
-        this.clinicService = clinicService;
+    public PetTypeFormatter(PetRepository pets) {
+        this.pets = pets;
     }
 
     @Override
@@ -56,7 +53,7 @@ public class PetTypeFormatter implements Formatter<PetType> {
 
     @Override
     public PetType parse(String text, Locale locale) throws ParseException {
-        Collection<PetType> findPetTypes = this.clinicService.findPetTypes();
+        Collection<PetType> findPetTypes = this.pets.findPetTypes();
         for (PetType type : findPetTypes) {
             if (type.getName().equals(text)) {
                 return type;
diff --git a/src/main/java/org/springframework/samples/petclinic/web/PetValidator.java b/src/main/java/org/springframework/samples/petclinic/owner/PetValidator.java
similarity index 94%
rename from src/main/java/org/springframework/samples/petclinic/web/PetValidator.java
rename to src/main/java/org/springframework/samples/petclinic/owner/PetValidator.java
index 3c04793..1a3d92e 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/PetValidator.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/PetValidator.java
@@ -13,9 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
 
-import org.springframework.samples.petclinic.model.Pet;
 import org.springframework.util.StringUtils;
 import org.springframework.validation.Errors;
 import org.springframework.validation.Validator;
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java
similarity index 82%
rename from src/main/java/org/springframework/samples/petclinic/web/VisitController.java
rename to src/main/java/org/springframework/samples/petclinic/owner/VisitController.java
index 7bd87ef..d98c5dd 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java
@@ -13,16 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
 
 import java.util.Map;
 
 import javax.validation.Valid;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.Visit;
-import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.visit.Visit;
+import org.springframework.samples.petclinic.visit.VisitRepository;
 import org.springframework.stereotype.Controller;
 import org.springframework.validation.BindingResult;
 import org.springframework.web.bind.WebDataBinder;
@@ -37,16 +36,19 @@ import org.springframework.web.bind.annotation.RequestMethod;
  * @author Ken Krebs
  * @author Arjen Poutsma
  * @author Michael Isvy
+ * @author Dave Syer
  */
 @Controller
-public class VisitController {
+class VisitController {
 
-    private final ClinicService clinicService;
+    private final VisitRepository visits;
+    private final PetRepository pets;
 
 
     @Autowired
-    public VisitController(ClinicService clinicService) {
-        this.clinicService = clinicService;
+    public VisitController(VisitRepository visits, PetRepository pets) {
+        this.visits = visits;
+        this.pets = pets;
     }
 
     @InitBinder
@@ -65,8 +67,9 @@ public class VisitController {
      * @return Pet
      */
     @ModelAttribute("visit")
-    public Visit loadPetWithVisit(@PathVariable("petId") int petId) {
-        Pet pet = this.clinicService.findPetById(petId);
+    public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map<String, Object> model) {
+        Pet pet = this.pets.findById(petId);
+        model.put("pet", pet);
         Visit visit = new Visit();
         pet.addVisit(visit);
         return visit;
@@ -84,7 +87,7 @@ public class VisitController {
         if (result.hasErrors()) {
             return "pets/createOrUpdateVisitForm";
         } else {
-            this.clinicService.saveVisit(visit);
+            this.visits.save(visit);
             return "redirect:/owners/{ownerId}";
         }
     }
diff --git a/src/main/java/org/springframework/samples/petclinic/service/ClinicService.java b/src/main/java/org/springframework/samples/petclinic/service/ClinicService.java
deleted file mode 100644
index 44b5ed9..0000000
--- a/src/main/java/org/springframework/samples/petclinic/service/ClinicService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2002-2013 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.service;
-
-import java.util.Collection;
-
-import org.springframework.dao.DataAccessException;
-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.Vet;
-import org.springframework.samples.petclinic.model.Visit;
-
-
-/**
- * Mostly used as a facade so all controllers have a single point of entry
- *
- * @author Michael Isvy
- */
-public interface ClinicService {
-
-    Collection<PetType> findPetTypes() throws DataAccessException;
-
-    Owner findOwnerById(int id) throws DataAccessException;
-
-    Pet findPetById(int id) throws DataAccessException;
-
-    void savePet(Pet pet) throws DataAccessException;
-
-    void saveVisit(Visit visit) throws DataAccessException;
-
-    Collection<Vet> findVets() throws DataAccessException;
-
-    void saveOwner(Owner owner) throws DataAccessException;
-
-    Collection<Owner> findOwnerByLastName(String lastName) throws DataAccessException;
-
-	Collection<Visit> findVisitsByPetId(int petId);
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java b/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
deleted file mode 100644
index 5c2e47a..0000000
--- a/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2002-2013 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.service;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.dao.DataAccessException;
-import org.springframework.samples.petclinic.model.*;
-import org.springframework.samples.petclinic.repository.OwnerRepository;
-import org.springframework.samples.petclinic.repository.PetRepository;
-import org.springframework.samples.petclinic.repository.VetRepository;
-import org.springframework.samples.petclinic.repository.VisitRepository;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.cache.annotation.CacheResult;
-import java.util.Collection;
-
-/**
- * Mostly used as a facade for all Petclinic controllers Also a placeholder
- * for @Transactional and @CacheResult annotations
- *
- * @author Michael Isvy
- */
-@Service
-public class ClinicServiceImpl implements ClinicService {
-
-    private PetRepository petRepository;
-    private VetRepository vetRepository;
-    private OwnerRepository ownerRepository;
-    private VisitRepository visitRepository;
-
-    @Autowired
-    public ClinicServiceImpl(PetRepository petRepository, VetRepository vetRepository, OwnerRepository ownerRepository,
-            VisitRepository visitRepository) {
-        this.petRepository = petRepository;
-        this.vetRepository = vetRepository;
-        this.ownerRepository = ownerRepository;
-        this.visitRepository = visitRepository;
-    }
-
-    @Override
-    @Transactional(readOnly = true)
-    public Collection<PetType> findPetTypes() throws DataAccessException {
-        return petRepository.findPetTypes();
-    }
-
-    @Override
-    @Transactional(readOnly = true)
-    public Owner findOwnerById(int id) throws DataAccessException {
-        return ownerRepository.findById(id);
-    }
-
-    @Override
-    @Transactional(readOnly = true)
-    public Collection<Owner> findOwnerByLastName(String lastName) throws DataAccessException {
-        return ownerRepository.findByLastName(lastName);
-    }
-
-    @Override
-    @Transactional
-    public void saveOwner(Owner owner) throws DataAccessException {
-        ownerRepository.save(owner);
-    }
-
-    @Override
-    @Transactional
-    public void saveVisit(Visit visit) throws DataAccessException {
-        visitRepository.save(visit);
-    }
-
-    @Override
-    @Transactional(readOnly = true)
-    public Pet findPetById(int id) throws DataAccessException {
-        return petRepository.findById(id);
-    }
-
-    @Override
-    @Transactional
-    public void savePet(Pet pet) throws DataAccessException {
-        petRepository.save(pet);
-    }
-
-    @Override
-    @Transactional(readOnly = true)
-    @CacheResult(cacheName = "vets")
-    public Collection<Vet> findVets() throws DataAccessException {
-        return vetRepository.findAll();
-    }
-
-    @Override
-    public Collection<Visit> findVisitsByPetId(int petId) {
-        return visitRepository.findByPetId(petId);
-    }
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/config/CacheConfig.java b/src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java
similarity index 95%
rename from src/main/java/org/springframework/samples/petclinic/config/CacheConfig.java
rename to src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java
index 4e1a6a0..b739db4 100644
--- a/src/main/java/org/springframework/samples/petclinic/config/CacheConfig.java
+++ b/src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java
@@ -1,4 +1,4 @@
-package org.springframework.samples.petclinic.config;
+package org.springframework.samples.petclinic.system;
 
 import java.util.concurrent.TimeUnit;
 import javax.cache.CacheManager;
@@ -23,7 +23,7 @@ import org.springframework.context.annotation.Profile;
 @Configuration
 @EnableCaching
 @Profile("production")
-public class CacheConfig {
+class CacheConfig {
 
     @Bean
     public JCacheManagerCustomizer cacheManagerCustomizer() {
diff --git a/src/main/java/org/springframework/samples/petclinic/web/CrashController.java b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java
similarity index 93%
rename from src/main/java/org/springframework/samples/petclinic/web/CrashController.java
rename to src/main/java/org/springframework/samples/petclinic/system/CrashController.java
index 303707b..a702cfc 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/CrashController.java
+++ b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.system;
 
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -27,7 +27,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
  * Also see how a view that resolves to "error" has been added ("error.html").
  */
 @Controller
-public class CrashController {
+class CrashController {
 
     @RequestMapping(value = "/oups", method = RequestMethod.GET)
     public String triggerException() {
diff --git a/src/main/java/org/springframework/samples/petclinic/web/WelcomeController.java b/src/main/java/org/springframework/samples/petclinic/system/WelcomeController.java
similarity index 72%
rename from src/main/java/org/springframework/samples/petclinic/web/WelcomeController.java
rename to src/main/java/org/springframework/samples/petclinic/system/WelcomeController.java
index efa9c32..b5af0f7 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/WelcomeController.java
+++ b/src/main/java/org/springframework/samples/petclinic/system/WelcomeController.java
@@ -1,11 +1,11 @@
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.system;
 
 
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 @Controller
-public class WelcomeController {
+class WelcomeController {
 
     @RequestMapping("/")
     public String welcome() {
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Specialty.java b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java
similarity index 88%
rename from src/main/java/org/springframework/samples/petclinic/model/Specialty.java
rename to src/main/java/org/springframework/samples/petclinic/vet/Specialty.java
index 6ea209c..826e04a 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Specialty.java
+++ b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java
@@ -13,11 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.model;
+package org.springframework.samples.petclinic.vet;
 
 import javax.persistence.Entity;
 import javax.persistence.Table;
 
+import org.springframework.samples.petclinic.model.NamedEntity;
+
 /**
  * Models a {@link Vet Vet's} specialty (for example, dentistry).
  *
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Vet.java b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java
similarity index 95%
rename from src/main/java/org/springframework/samples/petclinic/model/Vet.java
rename to src/main/java/org/springframework/samples/petclinic/vet/Vet.java
index d93e14c..8294237 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Vet.java
+++ b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.model;
+package org.springframework.samples.petclinic.vet;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -31,6 +31,7 @@ import javax.xml.bind.annotation.XmlElement;
 
 import org.springframework.beans.support.MutableSortDefinition;
 import org.springframework.beans.support.PropertyComparator;
+import org.springframework.samples.petclinic.model.Person;
 
 /**
  * Simple JavaBean domain object representing a veterinarian.
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VetController.java b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java
similarity index 77%
rename from src/main/java/org/springframework/samples/petclinic/web/VetController.java
rename to src/main/java/org/springframework/samples/petclinic/vet/VetController.java
index 5bc343e..8ddcca6 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/VetController.java
+++ b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java
@@ -13,13 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.vet;
 
 import java.util.Map;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.model.Vets;
-import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
@@ -31,13 +29,13 @@ import org.springframework.web.bind.annotation.ResponseBody;
  * @author Arjen Poutsma
  */
 @Controller
-public class VetController {
+class VetController {
 
-    private final ClinicService clinicService;
+    private final VetRepository vets;
 
     @Autowired
-    public VetController(ClinicService clinicService) {
-        this.clinicService = clinicService;
+    public VetController(VetRepository clinicService) {
+        this.vets = clinicService;
     }
 
     @RequestMapping(value = { "/vets.html" })
@@ -45,7 +43,7 @@ public class VetController {
         // Here we are returning an object of type 'Vets' rather than a collection of Vet
         // objects so it is simpler for Object-Xml mapping
         Vets vets = new Vets();
-        vets.getVetList().addAll(this.clinicService.findVets());
+        vets.getVetList().addAll(this.vets.findAll());
         model.put("vets", vets);
         return "vets/vetList";
     }
@@ -55,7 +53,7 @@ public class VetController {
         // Here we are returning an object of type 'Vets' rather than a collection of Vet
         // objects so it is simpler for JSon/Object mapping
         Vets vets = new Vets();
-        vets.getVetList().addAll(this.clinicService.findVets());
+        vets.getVetList().addAll(this.vets.findAll());
         return vets;
     }
 
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java b/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java
similarity index 86%
rename from src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java
rename to src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java
index aabdfd6..4f3a512 100644
--- a/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java
+++ b/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.repository;
+package org.springframework.samples.petclinic.vet;
 
 import java.util.Collection;
 
+import javax.cache.annotation.CacheResult;
+
 import org.springframework.dao.DataAccessException;
 import org.springframework.data.repository.Repository;
-import org.springframework.samples.petclinic.model.Vet;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * Repository class for <code>Vet</code> domain objects All method names are compliant with Spring Data naming
@@ -37,6 +39,8 @@ public interface VetRepository extends Repository<Vet, Integer> {
      *
      * @return a <code>Collection</code> of <code>Vet</code>s
      */
+    @Transactional(readOnly = true)
+    @CacheResult(cacheName = "vets")
     Collection<Vet> findAll() throws DataAccessException;
 
 
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Vets.java b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java
similarity index 95%
rename from src/main/java/org/springframework/samples/petclinic/model/Vets.java
rename to src/main/java/org/springframework/samples/petclinic/vet/Vets.java
index a6f05c6..f5b24c3 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Vets.java
+++ b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.model;
+package org.springframework.samples.petclinic.vet;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Visit.java b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java
similarity index 83%
rename from src/main/java/org/springframework/samples/petclinic/model/Visit.java
rename to src/main/java/org/springframework/samples/petclinic/visit/Visit.java
index 8fe9deb..61deb9b 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Visit.java
+++ b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java
@@ -13,24 +13,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.model;
+package org.springframework.samples.petclinic.visit;
 
-import org.hibernate.validator.constraints.NotEmpty;
-import org.springframework.format.annotation.DateTimeFormat;
+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 java.util.Date;
+
+import org.hibernate.validator.constraints.NotEmpty;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.samples.petclinic.model.BaseEntity;
 
 /**
  * Simple JavaBean domain object representing a visit.
  *
  * @author Ken Krebs
+ * @author Dave Syer
  */
 @Entity
 @Table(name = "visits")
@@ -54,9 +55,8 @@ public class Visit extends BaseEntity {
     /**
      * Holds value of property pet.
      */
-    @ManyToOne
-    @JoinColumn(name = "pet_id")
-    private Pet pet;
+    @Column(name = "pet_id")
+    private Integer petId;
 
 
     /**
@@ -104,21 +104,21 @@ public class Visit extends BaseEntity {
     }
 
     /**
-     * Getter for property pet.
+     * Getter for property pet id.
      *
-     * @return Value of property pet.
+     * @return Value of property pet id.
      */
-    public Pet getPet() {
-        return this.pet;
+    public Integer getPetId() {
+        return this.petId;
     }
 
     /**
-     * Setter for property pet.
+     * Setter for property pet id.
      *
-     * @param pet New value of property pet.
+     * @param pet New value of property pet id.
      */
-    public void setPet(Pet pet) {
-        this.pet = pet;
+    public void setPetId(Integer petId) {
+        this.petId = petId;
     }
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java b/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java
similarity index 93%
rename from src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java
rename to src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java
index e734f32..c7853d1 100644
--- a/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java
+++ b/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java
@@ -13,14 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.springframework.samples.petclinic.repository;
+package org.springframework.samples.petclinic.visit;
 
 import java.util.List;
 
 import org.springframework.dao.DataAccessException;
 import org.springframework.data.repository.Repository;
 import org.springframework.samples.petclinic.model.BaseEntity;
-import org.springframework.samples.petclinic.model.Visit;
 
 /**
  * Repository class for <code>Visit</code> domain objects All method names are compliant with Spring Data naming
diff --git a/src/main/java/org/springframework/samples/petclinic/web/package-info.java b/src/main/java/org/springframework/samples/petclinic/web/package-info.java
deleted file mode 100644
index ca189f1..0000000
--- a/src/main/java/org/springframework/samples/petclinic/web/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * The classes in this package represent PetClinic's web presentation layer.
- */
-package org.springframework.samples.petclinic.web;
-
diff --git a/src/main/resources/templates/pets/createOrUpdateVisitForm.html b/src/main/resources/templates/pets/createOrUpdateVisitForm.html
index c96c324..26a7137 100644
--- a/src/main/resources/templates/pets/createOrUpdateVisitForm.html
+++ b/src/main/resources/templates/pets/createOrUpdateVisitForm.html
@@ -19,12 +19,12 @@
       </tr>
     </thead>
     <tr>
-      <td th:text="${visit.pet.name}" /></td>
+      <td th:text="${pet.name}" /></td>
       <td
-        th:text="${#calendars.format(visit.pet.birthDate, 'yyyy-MM-dd')}" /></td>
-      <td th:text="${visit.pet.type}" /></td>
+        th:text="${#calendars.format(pet.birthDate, 'yyyy-MM-dd')}" /></td>
+      <td th:text="${pet.type}" /></td>
       <td
-        th:text="${visit.pet.owner?.firstName + ' ' + visit.pet.owner?.lastName}" /></td>
+        th:text="${pet.owner?.firstName + ' ' + pet.owner?.lastName}" /></td>
     </tr>
   </table>
 
@@ -38,7 +38,7 @@
 
     <div class="form-group">
       <div class="col-sm-offset-2 col-sm-10">
-        <input type="hidden" name="petId" th:value="${visit.pet.id}" />
+        <input type="hidden" name="petId" th:value="${pet.id}" />
         <button class="btn btn-default" type="submit">Add Visit</button>
       </div>
     </div>
@@ -51,7 +51,7 @@
       <th>Date</th>
       <th>Description</th>
     </tr>
-    <tr th:if="${!visit['new']}" th:each="visit : ${visit.pet.visits}">
+    <tr th:if="${!visit['new']}" th:each="visit : ${pet.visits}">
       <td th:text="${#calendars.format(visit.date, 'yyyy-MM-dd')}" /></td>
       <td th:text=" ${visit.description}" /></td>
     </tr>
diff --git a/src/test/java/org/springframework/samples/petclinic/web/OwnerControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java
similarity index 89%
rename from src/test/java/org/springframework/samples/petclinic/web/OwnerControllerTests.java
rename to src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java
index b39dccc..7fccb3b 100644
--- a/src/test/java/org/springframework/samples/petclinic/web/OwnerControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java
@@ -1,4 +1,13 @@
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
+
+import static org.hamcrest.Matchers.hasProperty;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.BDDMockito.given;
+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.result.MockMvcResultMatchers.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
 
 import org.assertj.core.util.Lists;
 import org.junit.Before;
@@ -7,18 +16,12 @@ import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.samples.petclinic.model.Owner;
-import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.owner.Owner;
+import org.springframework.samples.petclinic.owner.OwnerController;
+import org.springframework.samples.petclinic.owner.OwnerRepository;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.web.servlet.MockMvc;
 
-import static org.hamcrest.Matchers.hasProperty;
-import static org.hamcrest.Matchers.is;
-import static org.mockito.BDDMockito.given;
-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.result.MockMvcResultMatchers.*;
-
 /**
  * Test class for {@link OwnerController}
  *
@@ -34,7 +37,7 @@ public class OwnerControllerTests {
     private MockMvc mockMvc;
 
     @MockBean
-    private ClinicService clinicService;
+    private OwnerRepository owners;
 
     private Owner george;
 
@@ -47,7 +50,7 @@ public class OwnerControllerTests {
         george.setAddress("110 W. Liberty St.");
         george.setCity("Madison");
         george.setTelephone("6085551023");
-        given(this.clinicService.findOwnerById(TEST_OWNER_ID)).willReturn(george);
+        given(this.owners.findById(TEST_OWNER_ID)).willReturn(george);
     }
 
     @Test
@@ -94,7 +97,7 @@ public class OwnerControllerTests {
 
     @Test
     public void testProcessFindFormSuccess() throws Exception {
-        given(this.clinicService.findOwnerByLastName("")).willReturn(Lists.newArrayList(george, new Owner()));
+        given(this.owners.findByLastName("")).willReturn(Lists.newArrayList(george, new Owner()));
         mockMvc.perform(get("/owners"))
             .andExpect(status().isOk())
             .andExpect(view().name("owners/ownersList"));
@@ -102,7 +105,7 @@ public class OwnerControllerTests {
 
     @Test
     public void testProcessFindFormByLastName() throws Exception {
-        given(this.clinicService.findOwnerByLastName(george.getLastName())).willReturn(Lists.newArrayList(george));
+        given(this.owners.findByLastName(george.getLastName())).willReturn(Lists.newArrayList(george));
         mockMvc.perform(get("/owners")
             .param("lastName", "Franklin")
         )
diff --git a/src/test/java/org/springframework/samples/petclinic/web/PetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java
similarity index 79%
rename from src/test/java/org/springframework/samples/petclinic/web/PetControllerTests.java
rename to src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java
index ce01d95..f56931c 100644
--- a/src/test/java/org/springframework/samples/petclinic/web/PetControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java
@@ -1,4 +1,11 @@
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
+
+import static org.mockito.BDDMockito.given;
+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.result.MockMvcResultMatchers.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
 
 import org.assertj.core.util.Lists;
 import org.junit.Before;
@@ -9,18 +16,16 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.FilterType;
-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.service.ClinicService;
+import org.springframework.samples.petclinic.owner.Owner;
+import org.springframework.samples.petclinic.owner.OwnerRepository;
+import org.springframework.samples.petclinic.owner.Pet;
+import org.springframework.samples.petclinic.owner.PetController;
+import org.springframework.samples.petclinic.owner.PetRepository;
+import org.springframework.samples.petclinic.owner.PetType;
+import org.springframework.samples.petclinic.owner.PetTypeFormatter;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.web.servlet.MockMvc;
 
-import static org.mockito.BDDMockito.given;
-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.result.MockMvcResultMatchers.*;
-
 /**
  * Test class for the {@link PetController}
  *
@@ -41,16 +46,19 @@ public class PetControllerTests {
     private MockMvc mockMvc;
 
     @MockBean
-    private ClinicService clinicService;
+    private PetRepository pets;
+
+    @MockBean
+    private OwnerRepository owners;
 
     @Before
     public void setup() {
         PetType cat = new PetType();
         cat.setId(3);
         cat.setName("hamster");
-        given(this.clinicService.findPetTypes()).willReturn(Lists.newArrayList(cat));
-        given(this.clinicService.findOwnerById(TEST_OWNER_ID)).willReturn(new Owner());
-        given(this.clinicService.findPetById(TEST_PET_ID)).willReturn(new Pet());
+        given(this.pets.findPetTypes()).willReturn(Lists.newArrayList(cat));
+        given(this.owners.findById(TEST_OWNER_ID)).willReturn(new Owner());
+        given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet());
 
     }
 
diff --git a/src/test/java/org/springframework/samples/petclinic/web/PetTypeFormatterTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java
similarity index 65%
rename from src/test/java/org/springframework/samples/petclinic/web/PetTypeFormatterTests.java
rename to src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java
index e1b2a53..f332257 100644
--- a/src/test/java/org/springframework/samples/petclinic/web/PetTypeFormatterTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java
@@ -1,4 +1,12 @@
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
+
+import static org.junit.Assert.assertEquals;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -6,13 +14,9 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
-import org.springframework.samples.petclinic.model.PetType;
-import org.springframework.samples.petclinic.service.ClinicService;
-
-import java.text.ParseException;
-import java.util.*;
-
-import static org.junit.Assert.assertEquals;
+import org.springframework.samples.petclinic.owner.PetRepository;
+import org.springframework.samples.petclinic.owner.PetType;
+import org.springframework.samples.petclinic.owner.PetTypeFormatter;
 
 /**
  * Test class for {@link PetTypeFormatter}
@@ -23,33 +27,33 @@ import static org.junit.Assert.assertEquals;
 public class PetTypeFormatterTests {
 
     @Mock
-    private ClinicService clinicService;
+    private PetRepository pets;
 
     private PetTypeFormatter petTypeFormatter;
 
     @Before
     public void setup() {
-        petTypeFormatter = new PetTypeFormatter(clinicService);
+        this.petTypeFormatter = new PetTypeFormatter(pets);
     }
 
     @Test
     public void testPrint() {
         PetType petType = new PetType();
         petType.setName("Hamster");
-        String petTypeName = petTypeFormatter.print(petType, Locale.ENGLISH);
+        String petTypeName = this.petTypeFormatter.print(petType, Locale.ENGLISH);
         assertEquals("Hamster", petTypeName);
     }
 
     @Test
     public void shouldParse() throws ParseException {
-        Mockito.when(clinicService.findPetTypes()).thenReturn(makePetTypes());
+        Mockito.when(this.pets.findPetTypes()).thenReturn(makePetTypes());
         PetType petType = petTypeFormatter.parse("Bird", Locale.ENGLISH);
         assertEquals("Bird", petType.getName());
     }
 
     @Test(expected = ParseException.class)
     public void shouldThrowParseException() throws ParseException {
-        Mockito.when(clinicService.findPetTypes()).thenReturn(makePetTypes());
+        Mockito.when(this.pets.findPetTypes()).thenReturn(makePetTypes());
         petTypeFormatter.parse("Fish", Locale.ENGLISH);
     }
 
@@ -58,8 +62,8 @@ public class PetTypeFormatterTests {
      *
      * @return {@link Collection} of {@link PetType}
      */
-    private Collection<PetType> makePetTypes() {
-        Collection<PetType> petTypes = new ArrayList<>();
+    private List<PetType> makePetTypes() {
+        List<PetType> petTypes = new ArrayList<>();
         petTypes.add(new PetType(){
             {
                 setName("Dog");
diff --git a/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java
similarity index 75%
rename from src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java
rename to src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java
index 237f0f4..08d6136 100644
--- a/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java
@@ -1,4 +1,11 @@
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.owner;
+
+import static org.mockito.BDDMockito.given;
+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.result.MockMvcResultMatchers.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -6,16 +13,13 @@ import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.owner.Pet;
+import org.springframework.samples.petclinic.owner.PetRepository;
+import org.springframework.samples.petclinic.owner.VisitController;
+import org.springframework.samples.petclinic.visit.VisitRepository;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.web.servlet.MockMvc;
 
-import static org.mockito.BDDMockito.given;
-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.result.MockMvcResultMatchers.*;
-
 /**
  * Test class for {@link VisitController}
  *
@@ -31,11 +35,14 @@ public class VisitControllerTests {
     private MockMvc mockMvc;
 
     @MockBean
-    private ClinicService clinicService;
+    private VisitRepository visits;
+
+    @MockBean
+    private PetRepository pets;
 
     @Before
     public void init() {
-        given(this.clinicService.findPetById(TEST_PET_ID)).willReturn(new Pet());
+        given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet());
     }
 
     @Test
diff --git a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java
index f436335..7ed5bf8 100644
--- a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java
@@ -1,21 +1,28 @@
 package org.springframework.samples.petclinic.service;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Collection;
+import java.util.Date;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
 import org.springframework.context.annotation.ComponentScan;
-import org.springframework.samples.petclinic.model.*;
-import org.springframework.samples.petclinic.util.EntityUtils;
+import org.springframework.samples.petclinic.owner.Owner;
+import org.springframework.samples.petclinic.owner.OwnerRepository;
+import org.springframework.samples.petclinic.owner.Pet;
+import org.springframework.samples.petclinic.owner.PetRepository;
+import org.springframework.samples.petclinic.owner.PetType;
+import org.springframework.samples.petclinic.vet.Vet;
+import org.springframework.samples.petclinic.vet.VetRepository;
+import org.springframework.samples.petclinic.visit.Visit;
+import org.springframework.samples.petclinic.visit.VisitRepository;
 import org.springframework.stereotype.Service;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Collection;
-import java.util.Date;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
 /**
  * Integration test of the Service and the Repository layer.
  * <p>
@@ -34,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
  * @author Juergen Hoeller
  * @author Sam Brannen
  * @author Michael Isvy
+ * @author Dave Syer
  */
 
 @RunWith(SpringRunner.class)
@@ -41,20 +49,29 @@ import static org.assertj.core.api.Assertions.assertThat;
 public class ClinicServiceTests {
 
     @Autowired
-    protected ClinicService clinicService;
+    protected OwnerRepository owners;
+
+    @Autowired
+    protected PetRepository pets;
+
+    @Autowired
+    protected VisitRepository visits;
+
+    @Autowired
+    protected VetRepository vets;
 
     @Test
     public void shouldFindOwnersByLastName() {
-        Collection<Owner> owners = this.clinicService.findOwnerByLastName("Davis");
+        Collection<Owner> owners = this.owners.findByLastName("Davis");
         assertThat(owners.size()).isEqualTo(2);
 
-        owners = this.clinicService.findOwnerByLastName("Daviss");
+        owners = this.owners.findByLastName("Daviss");
         assertThat(owners.isEmpty()).isTrue();
     }
 
     @Test
     public void shouldFindSingleOwnerWithPet() {
-        Owner owner = this.clinicService.findOwnerById(1);
+        Owner owner = this.owners.findById(1);
         assertThat(owner.getLastName()).startsWith("Franklin");
         assertThat(owner.getPets().size()).isEqualTo(1);
         assertThat(owner.getPets().get(0).getType()).isNotNull();
@@ -64,7 +81,7 @@ public class ClinicServiceTests {
     @Test
     @Transactional
     public void shouldInsertOwner() {
-        Collection<Owner> owners = this.clinicService.findOwnerByLastName("Schultz");
+        Collection<Owner> owners = this.owners.findByLastName("Schultz");
         int found = owners.size();
 
         Owner owner = new Owner();
@@ -73,31 +90,31 @@ public class ClinicServiceTests {
         owner.setAddress("4, Evans Street");
         owner.setCity("Wollongong");
         owner.setTelephone("4444444444");
-        this.clinicService.saveOwner(owner);
+        this.owners.save(owner);
         assertThat(owner.getId().longValue()).isNotEqualTo(0);
 
-        owners = this.clinicService.findOwnerByLastName("Schultz");
+        owners = this.owners.findByLastName("Schultz");
         assertThat(owners.size()).isEqualTo(found + 1);
     }
 
     @Test
     @Transactional
     public void shouldUpdateOwner() {
-        Owner owner = this.clinicService.findOwnerById(1);
+        Owner owner = this.owners.findById(1);
         String oldLastName = owner.getLastName();
         String newLastName = oldLastName + "X";
 
         owner.setLastName(newLastName);
-        this.clinicService.saveOwner(owner);
+        this.owners.save(owner);
 
         // retrieving new name from database
-        owner = this.clinicService.findOwnerById(1);
+        owner = this.owners.findById(1);
         assertThat(owner.getLastName()).isEqualTo(newLastName);
     }
 
     @Test
     public void shouldFindPetWithCorrectId() {
-        Pet pet7 = this.clinicService.findPetById(7);
+        Pet pet7 = this.pets.findById(7);
         assertThat(pet7.getName()).startsWith("Samantha");
         assertThat(pet7.getOwner().getFirstName()).isEqualTo("Jean");
 
@@ -105,7 +122,7 @@ public class ClinicServiceTests {
 
     @Test
     public void shouldFindAllPetTypes() {
-        Collection<PetType> petTypes = this.clinicService.findPetTypes();
+        Collection<PetType> petTypes = this.pets.findPetTypes();
 
         PetType petType1 = EntityUtils.getById(petTypes, PetType.class, 1);
         assertThat(petType1.getName()).isEqualTo("cat");
@@ -116,21 +133,21 @@ public class ClinicServiceTests {
     @Test
     @Transactional
     public void shouldInsertPetIntoDatabaseAndGenerateId() {
-        Owner owner6 = this.clinicService.findOwnerById(6);
+        Owner owner6 = this.owners.findById(6);
         int found = owner6.getPets().size();
 
         Pet pet = new Pet();
         pet.setName("bowser");
-        Collection<PetType> types = this.clinicService.findPetTypes();
+        Collection<PetType> types = this.pets.findPetTypes();
         pet.setType(EntityUtils.getById(types, PetType.class, 2));
         pet.setBirthDate(new Date());
         owner6.addPet(pet);
         assertThat(owner6.getPets().size()).isEqualTo(found + 1);
 
-        this.clinicService.savePet(pet);
-        this.clinicService.saveOwner(owner6);
+        this.pets.save(pet);
+        this.owners.save(owner6);
 
-        owner6 = this.clinicService.findOwnerById(6);
+        owner6 = this.owners.findById(6);
         assertThat(owner6.getPets().size()).isEqualTo(found + 1);
         // checks that id has been generated
         assertThat(pet.getId()).isNotNull();
@@ -139,20 +156,20 @@ public class ClinicServiceTests {
     @Test
     @Transactional
     public void shouldUpdatePetName() throws Exception {
-        Pet pet7 = this.clinicService.findPetById(7);
+        Pet pet7 = this.pets.findById(7);
         String oldName = pet7.getName();
 
         String newName = oldName + "X";
         pet7.setName(newName);
-        this.clinicService.savePet(pet7);
+        this.pets.save(pet7);
 
-        pet7 = this.clinicService.findPetById(7);
+        pet7 = this.pets.findById(7);
         assertThat(pet7.getName()).isEqualTo(newName);
     }
 
     @Test
     public void shouldFindVets() {
-        Collection<Vet> vets = this.clinicService.findVets();
+        Collection<Vet> vets = this.vets.findAll();
 
         Vet vet = EntityUtils.getById(vets, Vet.class, 3);
         assertThat(vet.getLastName()).isEqualTo("Douglas");
@@ -164,27 +181,26 @@ public class ClinicServiceTests {
     @Test
     @Transactional
     public void shouldAddNewVisitForPet() {
-        Pet pet7 = this.clinicService.findPetById(7);
+        Pet pet7 = this.pets.findById(7);
         int found = pet7.getVisits().size();
         Visit visit = new Visit();
         pet7.addVisit(visit);
         visit.setDescription("test");
-        this.clinicService.saveVisit(visit);
-        this.clinicService.savePet(pet7);
+        this.visits.save(visit);
+        this.pets.save(pet7);
 
-        pet7 = this.clinicService.findPetById(7);
+        pet7 = this.pets.findById(7);
         assertThat(pet7.getVisits().size()).isEqualTo(found + 1);
         assertThat(visit.getId()).isNotNull();
     }
 
     @Test
     public void shouldFindVisitsByPetId() throws Exception {
-        Collection<Visit> visits = this.clinicService.findVisitsByPetId(7);
+        Collection<Visit> visits = this.visits.findByPetId(7);
         assertThat(visits.size()).isEqualTo(2);
         Visit[] visitArr = visits.toArray(new Visit[visits.size()]);
-        assertThat(visitArr[0].getPet()).isNotNull();
         assertThat(visitArr[0].getDate()).isNotNull();
-        assertThat(visitArr[0].getPet().getId()).isEqualTo(7);
+        assertThat(visitArr[0].getPetId()).isEqualTo(7);
     }
 
 }
diff --git a/src/test/java/org/springframework/samples/petclinic/util/EntityUtils.java b/src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java
similarity index 97%
rename from src/test/java/org/springframework/samples/petclinic/util/EntityUtils.java
rename to src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java
index eee3906..44dc6b1 100644
--- a/src/test/java/org/springframework/samples/petclinic/util/EntityUtils.java
+++ b/src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.springframework.samples.petclinic.util;
+package org.springframework.samples.petclinic.service;
 
 import java.util.Collection;
 
diff --git a/src/test/java/org/springframework/samples/petclinic/web/CrashControllerTests.java b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java
similarity index 93%
rename from src/test/java/org/springframework/samples/petclinic/web/CrashControllerTests.java
rename to src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java
index 551b900..1617692 100644
--- a/src/test/java/org/springframework/samples/petclinic/web/CrashControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java
@@ -1,4 +1,4 @@
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.system;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -7,6 +7,7 @@ import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.samples.petclinic.PetClinicApplication;
+import org.springframework.samples.petclinic.system.CrashController;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
diff --git a/src/test/java/org/springframework/samples/petclinic/web/VetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java
similarity index 75%
rename from src/test/java/org/springframework/samples/petclinic/web/VetControllerTests.java
rename to src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java
index 34296cf..ce6adf8 100644
--- a/src/test/java/org/springframework/samples/petclinic/web/VetControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java
@@ -1,4 +1,13 @@
-package org.springframework.samples.petclinic.web;
+package org.springframework.samples.petclinic.vet;
+
+import static org.hamcrest.xml.HasXPath.hasXPath;
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+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.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
 
 import org.assertj.core.util.Lists;
 import org.junit.Before;
@@ -8,18 +17,14 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.http.MediaType;
-import org.springframework.samples.petclinic.model.Specialty;
-import org.springframework.samples.petclinic.model.Vet;
-import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.vet.Specialty;
+import org.springframework.samples.petclinic.vet.Vet;
+import org.springframework.samples.petclinic.vet.VetController;
+import org.springframework.samples.petclinic.vet.VetRepository;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.ResultActions;
 
-import static org.hamcrest.xml.HasXPath.hasXPath;
-import static org.mockito.BDDMockito.given;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
 /**
  * Test class for the {@link VetController}
  */
@@ -31,7 +36,7 @@ public class VetControllerTests {
     private MockMvc mockMvc;
 
     @MockBean
-    private ClinicService clinicService;
+    private VetRepository vets;
 
     @Before
     public void setup() {
@@ -47,7 +52,7 @@ public class VetControllerTests {
         radiology.setId(1);
         radiology.setName("radiology");
         helen.addSpecialty(radiology);
-        given(this.clinicService.findVets()).willReturn(Lists.newArrayList(james, helen));
+        given(this.vets.findAll()).willReturn(Lists.newArrayList(james, helen));
     }
 
     @Test
-- 
GitLab