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