diff --git a/.springBeans b/.springBeans deleted file mode 100644 index 44f18becd..000000000 --- a/.springBeans +++ /dev/null @@ -1,20 +0,0 @@ - - - 1 - - - - - - - src/main/resources/spring/datasource-config.xml - src/main/resources/spring/mvc-core-config.xml - src/main/resources/spring/mvc-view-config.xml - src/main/resources/spring/business-config.xml - - - src/main/resources/spring/tools-config.xml - - - - diff --git a/pom.xml b/pom.xml index e25429136..46520d942 100644 --- a/pom.xml +++ b/pom.xml @@ -5,13 +5,12 @@ 4.0.0 org.springframework.samples spring-petclinic - 1.4.2 - Spring Pet Clinic + 2.0.0 org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 2.0.0.BUILD-SNAPSHOT @@ -26,16 +25,8 @@ 2.2.4 1.8.0 - 3.0.2.RELEASE - 2.0.4 + 2.7 - http://mssonarstg81.morningstar.com:9000 - target/surefire-reports - - UTF-8 + javax.cache cache-api @@ -176,7 +161,7 @@ spring-boot-maven-plugin - build-info @@ -201,7 +186,7 @@ - @@ -261,53 +247,11 @@ - - org.codehaus.gmavenplus - gmavenplus-plugin - 1.5 - - - - compile - testCompile - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 2.4 - - - copy-dependencies - package - copy-dependencies - - - - - - org.jacoco - jacoco-maven-plugin - 0.7.9 - - - jacoco-initialize - - prepare-agent - - - - jacoco-site - package - - report - - - - - - + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + diff --git a/readme.md b/readme.md index 06de8b253..a7d188867 100644 --- a/readme.md +++ b/readme.md @@ -61,7 +61,7 @@ File -> Import -> Maven -> Existing Maven project |--------------------------|---| |The Main Class | [PetClinicApplication](https://github.com/spring-projects/spring-petclinic/blob/master/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java) | |Properties Files | [application.properties](https://github.com/spring-projects/spring-petclinic/blob/master/src/main/resources) | -|Caching | EhCache [CacheConfig](https://github.com/spring-projects/spring-petclinic/blob/master/src/main/java/org/springframework/samples/petclinic/config/CacheConfig.java) | +|Caching | [CacheConfig](https://github.com/spring-projects/spring-petclinic/blob/master/src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java) | ## Interesting Spring Petclinic branches and forks @@ -74,13 +74,17 @@ you have a special interest in a different technology stack that could be used to implement the Pet Clinic then please join the community there. -| Link | Main technologies | -|----------------|-------------------| -| [spring-framework-petclinic](https://github.com/spring-petclinic/spring-framework-petclinic) | Spring Framework XML configuration, JSP pages, 3 persistence layers: JDBC, JPA and Spring Data JPA | -| [javaconfig branch](https://github.com/spring-petclinic/spring-framework-petclinic/tree/javaconfig) | Same frameworks as the [spring-framework-petclinic](https://github.com/spring-petclinic/spring-framework-petclinic) but with Java Configuration instead of XML | -| [spring-petclinic-angular1](https://github.com/spring-petclinic/spring-petclinic-angular1) | AngularJS 1.x, Spring Boot and Spring Data JPA | -| [spring-petclinic-microservices](https://github.com/spring-petclinic/spring-petclinic-microservices) | Distributed version of Spring Petclinic built with Spring Cloud | -| [spring-petclinic-reactjs](https://github.com/spring-petclinic/spring-petclinic-reactjs) | ReactJS (with TypeScript) and Spring Boot | +| Link | Main technologies | +|------------------------------------|-------------------| +| [spring-framework-petclinic][] | Spring Framework XML configuration, JSP pages, 3 persistence layers: JDBC, JPA and Spring Data JPA | +| [javaconfig branch][] | Same frameworks as the [spring-framework-petclinic][] but with Java Configuration instead of XML | +| [spring-petclinic-angularjs][] | AngularJS 1.x, Spring Boot and Spring Data JPA | +| [spring-petclinic-angular][] | Angular 4 front-end of the Petclinic REST API [spring-petclinic-rest][] | +| [spring-petclinic-microservices][] | Distributed version of Spring Petclinic built with Spring Cloud | +| [spring-petclinic-reactjs][] | ReactJS (with TypeScript) and Spring Boot | +| [spring-petclinic-graphql][] | GraphQL version based on React Appolo, TypeScript and GraphQL Spring boot starter | +| [spring-petclinic-kotlin][] | Kotlin version of [spring-petclinic][] | +| [spring-petclinic-rest][] | Backend REST API | ## Interaction with other open source projects @@ -99,10 +103,16 @@ Here is a list of them: The [issue tracker](https://github.com/spring-projects/spring-petclinic/issues) is the preferred channel for bug reports, features requests and submitting pull requests. -For pull requests, editor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at . +For pull requests, editor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at . If you have not previously done so, please fill out and submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement]. +The Spring PetClinic sample application is released under version 2.0 of the [Apache License](http://www.apache.org/licenses/LICENSE-2.0). -# Experimentation - -This is a trivial change to demonstrate the functionality of Github's pull request capabilities. - +[spring-petclinic]: https://github.com/spring-projects/spring-petclinic +[spring-framework-petclinic]: https://github.com/spring-petclinic/spring-framework-petclinic +[spring-petclinic-angularjs]: https://github.com/spring-petclinic/spring-petclinic-angularjs +[javaconfig branch]: https://github.com/spring-petclinic/spring-framework-petclinic/tree/javaconfig +[spring-petclinic-angular]: https://github.com/spring-petclinic/spring-petclinic-angular +[spring-petclinic-microservices]: https://github.com/spring-petclinic/spring-petclinic-microservices +[spring-petclinic-reactjs]: https://github.com/spring-petclinic/spring-petclinic-reactjs +[spring-petclinic-graphql]: https://github.com/spring-petclinic/spring-petclinic-graphql +[spring-petclinic-kotlin]: https://github.com/spring-petclinic/spring-petclinic-kotlin diff --git a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java index 14603c1ff..86cc21092 100644 --- a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java +++ b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java @@ -15,22 +15,25 @@ */ package org.springframework.samples.petclinic.model; +import java.io.Serializable; + import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; /** - * Simple JavaBean domain object with an id property. Used as a base class for objects needing this property. + * Simple JavaBean domain object with an id property. Used as a base class for objects + * needing this property. * * @author Ken Krebs * @author Juergen Hoeller */ @MappedSuperclass -public class BaseEntity { +public class BaseEntity implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - protected Integer id; + private Integer id; public Integer getId() { return id; diff --git a/src/main/java/org/springframework/samples/petclinic/model/Person.java b/src/main/java/org/springframework/samples/petclinic/model/Person.java index d3e03c0dd..5d23523bd 100644 --- a/src/main/java/org/springframework/samples/petclinic/model/Person.java +++ b/src/main/java/org/springframework/samples/petclinic/model/Person.java @@ -17,8 +17,7 @@ package org.springframework.samples.petclinic.model; import javax.persistence.Column; import javax.persistence.MappedSuperclass; - -import org.hibernate.validator.constraints.NotEmpty; +import javax.validation.constraints.NotEmpty; /** * Simple JavaBean domain object representing an person. @@ -30,11 +29,11 @@ public class Person extends BaseEntity { @Column(name = "first_name") @NotEmpty - protected String firstName; + private String firstName; @Column(name = "last_name") @NotEmpty - protected String lastName; + private String lastName; public String getFirstName() { return this.firstName; @@ -52,5 +51,4 @@ public class Person extends BaseEntity { this.lastName = lastName; } - } diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java index f6fcae7ac..89aad2c2c 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java @@ -27,8 +27,8 @@ import javax.persistence.Entity; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.validation.constraints.Digits; +import javax.validation.constraints.NotEmpty; -import org.hibernate.validator.constraints.NotEmpty; import org.springframework.beans.support.MutableSortDefinition; import org.springframework.beans.support.PropertyComparator; import org.springframework.core.style.ToStringCreator; @@ -61,7 +61,6 @@ public class Owner extends Person { @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner") private Set pets; - public String getAddress() { return this.address; } @@ -99,7 +98,8 @@ public class Owner extends Person { public List getPets() { List sortedPets = new ArrayList<>(getPetsInternal()); - PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true)); + PropertyComparator.sort(sortedPets, + new MutableSortDefinition("name", true, true)); return Collections.unmodifiableList(sortedPets); } @@ -144,13 +144,9 @@ public class Owner extends Person { public String toString() { return new ToStringCreator(this) - .append("id", this.getId()) - .append("new", this.isNew()) - .append("lastName", this.getLastName()) - .append("firstName", this.getFirstName()) - .append("address", this.address) - .append("city", this.city) - .append("telephone", this.telephone) - .toString(); + .append("id", this.getId()).append("new", this.isNew()) + .append("lastName", this.getLastName()) + .append("firstName", this.getFirstName()).append("address", this.address) + .append("city", this.city).append("telephone", this.telephone).toString(); } } diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java index ef3169b70..d914ed745 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java @@ -15,22 +15,21 @@ */ package org.springframework.samples.petclinic.owner; -import java.util.Collection; -import java.util.Map; - -import javax.validation.Valid; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.ModelAndView; +import javax.validation.Valid; +import java.util.Collection; +import java.util.Map; + /** * @author Juergen Hoeller * @author Ken Krebs @@ -54,14 +53,14 @@ class OwnerController { dataBinder.setDisallowedFields("id"); } - @RequestMapping(value = "/owners/new", method = RequestMethod.GET) + @GetMapping("/owners/new") public String initCreationForm(Map model) { Owner owner = new Owner(); model.put("owner", owner); return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; } - @RequestMapping(value = "/owners/new", method = RequestMethod.POST) + @PostMapping("/owners/new") public String processCreationForm(@Valid Owner owner, BindingResult result) { if (result.hasErrors()) { return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; @@ -71,13 +70,13 @@ class OwnerController { } } - @RequestMapping(value = "/owners/find", method = RequestMethod.GET) + @GetMapping("/owners/find") public String initFindForm(Map model) { model.put("owner", new Owner()); return "owners/findOwners"; } - @RequestMapping(value = "/owners", method = RequestMethod.GET) + @GetMapping("/owners") public String processFindForm(Owner owner, BindingResult result, Map model) { // allow parameterless GET request for /owners to return all records @@ -102,14 +101,14 @@ class OwnerController { } } - @RequestMapping(value = "/owners/{ownerId}/edit", method = RequestMethod.GET) + @GetMapping("/owners/{ownerId}/edit") public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) { Owner owner = this.owners.findById(ownerId); model.addAttribute(owner); return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; } - @RequestMapping(value = "/owners/{ownerId}/edit", method = RequestMethod.POST) + @PostMapping("/owners/{ownerId}/edit") public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @PathVariable("ownerId") int ownerId) { if (result.hasErrors()) { return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; @@ -126,7 +125,7 @@ class OwnerController { * @param ownerId the ID of the owner to display * @return a ModelMap with the model attributes for the view */ - @RequestMapping("/owners/{ownerId}") + @GetMapping("/owners/{ownerId}") public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) { ModelAndView mav = new ModelAndView("owners/ownerDetails"); mav.addObject(this.owners.findById(ownerId)); diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java old mode 100644 new mode 100755 index 5b4e31790..5e226a180 --- a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java @@ -15,11 +15,13 @@ */ 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 java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -29,16 +31,14 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; - import javax.persistence.Temporal; import javax.persistence.TemporalType; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; + +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; /** * Simple business object representing a pet. @@ -53,7 +53,7 @@ public class Pet extends NamedEntity { @Column(name = "birth_date") @Temporal(TemporalType.DATE) - @DateTimeFormat(pattern = "yyyy/MM/dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") private Date birthDate; @ManyToOne @@ -64,7 +64,7 @@ public class Pet extends NamedEntity { @JoinColumn(name = "owner_id") private Owner owner; - @OneToMany(cascade = CascadeType.ALL, mappedBy="petId", fetch = FetchType.EAGER) + @OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.EAGER) private Set visits = new LinkedHashSet<>(); public void setBirthDate(Date birthDate) { @@ -104,13 +104,14 @@ public class Pet extends NamedEntity { public List getVisits() { List sortedVisits = new ArrayList<>(getVisitsInternal()); - PropertyComparator.sort(sortedVisits, new MutableSortDefinition("date", false, false)); + PropertyComparator.sort(sortedVisits, + new MutableSortDefinition("date", false, false)); return Collections.unmodifiableList(sortedVisits); } public void addVisit(Visit visit) { getVisitsInternal().add(visit); - visit.setPetId(this.id); + visit.setPetId(this.getId()); } } diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetController.java b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java index 0599faf2c..9c52e0309 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/PetController.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java @@ -15,21 +15,16 @@ */ package org.springframework.samples.petclinic.owner; -import java.util.Collection; - -import javax.validation.Valid; - import org.springframework.beans.factory.annotation.Autowired; 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.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; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.Collection; /** * @author Juergen Hoeller @@ -70,7 +65,7 @@ class PetController { dataBinder.setValidator(new PetValidator()); } - @RequestMapping(value = "/pets/new", method = RequestMethod.GET) + @GetMapping("/pets/new") public String initCreationForm(Owner owner, ModelMap model) { Pet pet = new Pet(); owner.addPet(pet); @@ -78,29 +73,29 @@ class PetController { return VIEWS_PETS_CREATE_OR_UPDATE_FORM; } - @RequestMapping(value = "/pets/new", method = RequestMethod.POST) + @PostMapping("/pets/new") public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult result, ModelMap model) { if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null){ result.rejectValue("name", "duplicate", "already exists"); } + owner.addPet(pet); if (result.hasErrors()) { model.put("pet", pet); return VIEWS_PETS_CREATE_OR_UPDATE_FORM; } else { - owner.addPet(pet); this.pets.save(pet); return "redirect:/owners/{ownerId}"; } } - @RequestMapping(value = "/pets/{petId}/edit", method = RequestMethod.GET) + @GetMapping("/pets/{petId}/edit") public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) { Pet pet = this.pets.findById(petId); model.put("pet", pet); return VIEWS_PETS_CREATE_OR_UPDATE_FORM; } - @RequestMapping(value = "/pets/{petId}/edit", method = RequestMethod.POST) + @PostMapping("/pets/{petId}/edit") public String processUpdateForm(@Valid Pet pet, BindingResult result, Owner owner, ModelMap model) { if (result.hasErrors()) { pet.setOwner(owner); diff --git a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java index d98c5dd0f..d7afed12e 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java @@ -15,21 +15,16 @@ */ 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.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; -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; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.Map; /** * @author Juergen Hoeller @@ -76,13 +71,13 @@ class VisitController { } // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called - @RequestMapping(value = "/owners/*/pets/{petId}/visits/new", method = RequestMethod.GET) + @GetMapping("/owners/*/pets/{petId}/visits/new") public String initNewVisitForm(@PathVariable("petId") int petId, Map model) { return "pets/createOrUpdateVisitForm"; } // Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called - @RequestMapping(value = "/owners/{ownerId}/pets/{petId}/visits/new", method = RequestMethod.POST) + @PostMapping("/owners/{ownerId}/pets/{petId}/visits/new") public String processNewVisitForm(@Valid Visit visit, BindingResult result) { if (result.hasErrors()) { return "pets/createOrUpdateVisitForm"; diff --git a/src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java b/src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java index 9aded41b6..7d2128e2f 100755 --- a/src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java +++ b/src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java @@ -1,40 +1,34 @@ package org.springframework.samples.petclinic.system; -import java.util.concurrent.TimeUnit; - -import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.config.builders.ResourcePoolsBuilder; -import org.ehcache.config.units.EntryUnit; -import org.ehcache.expiry.Duration; -import org.ehcache.expiry.Expirations; -import org.ehcache.jsr107.Eh107Configuration; +import javax.cache.configuration.Configuration; +import javax.cache.configuration.MutableConfiguration; import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; + import org.springframework.context.annotation.Profile; /** - * Cache could be disable in unit test. + * Cache could be disabled in unit test. */ -@Configuration +@org.springframework.context.annotation.Configuration @EnableCaching @Profile("production") class CacheConfig { - + + @Bean public JCacheManagerCustomizer cacheManagerCustomizer() { - return cacheManager -> { - CacheConfiguration config = CacheConfigurationBuilder - .newCacheConfigurationBuilder(Object.class, Object.class, - ResourcePoolsBuilder.newResourcePoolsBuilder() - .heap(100, EntryUnit.ENTRIES)) - .withExpiry(Expirations.timeToLiveExpiration(Duration.of(60, TimeUnit.SECONDS))) - .build(); - cacheManager.createCache("vets", Eh107Configuration.fromEhcacheCacheConfiguration(config)); + return cm -> { + Configuration cacheConfiguration = createCacheConfiguration(); + cm.createCache("vets", cacheConfiguration); }; } -} \ No newline at end of file + private Configuration createCacheConfiguration() { + // Create a cache using infinite heap. A real application will want to use an + // implementation dependent configuration that will better fit your needs + return new MutableConfiguration<>().setStatisticsEnabled(true); + } +} diff --git a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java index a702cfc8f..2f5e7a348 100644 --- a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java +++ b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java @@ -16,8 +16,7 @@ package org.springframework.samples.petclinic.system; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.GetMapping; /** * Controller used to showcase what happens when an exception is thrown @@ -29,10 +28,10 @@ import org.springframework.web.bind.annotation.RequestMethod; @Controller class CrashController { - @RequestMapping(value = "/oups", method = RequestMethod.GET) + @GetMapping("/oups") public String triggerException() { - throw new RuntimeException( - "Expected: controller used to showcase what " + "happens when an exception is thrown"); + throw new RuntimeException("Expected: controller used to showcase what " + + "happens when an exception is thrown"); } } diff --git a/src/main/java/org/springframework/samples/petclinic/system/WelcomeController.java b/src/main/java/org/springframework/samples/petclinic/system/WelcomeController.java index b5af0f7d7..00430a790 100644 --- a/src/main/java/org/springframework/samples/petclinic/system/WelcomeController.java +++ b/src/main/java/org/springframework/samples/petclinic/system/WelcomeController.java @@ -2,12 +2,12 @@ package org.springframework.samples.petclinic.system; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.GetMapping; @Controller class WelcomeController { - @RequestMapping("/") + @GetMapping("/") public String welcome() { return "welcome"; } diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java index 826e04afc..5691c2434 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java @@ -15,6 +15,8 @@ */ package org.springframework.samples.petclinic.vet; +import java.io.Serializable; + import javax.persistence.Entity; import javax.persistence.Table; @@ -27,6 +29,6 @@ import org.springframework.samples.petclinic.model.NamedEntity; */ @Entity @Table(name = "specialties") -public class Specialty extends NamedEntity { +public class Specialty extends NamedEntity implements Serializable { } diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java index 829423782..43aecc41e 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java @@ -46,8 +46,7 @@ import org.springframework.samples.petclinic.model.Person; public class Vet extends Person { @ManyToMany(fetch = FetchType.EAGER) - @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), - inverseJoinColumns = @JoinColumn(name = "specialty_id")) + @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), inverseJoinColumns = @JoinColumn(name = "specialty_id")) private Set specialties; protected Set getSpecialtiesInternal() { @@ -64,7 +63,8 @@ public class Vet extends Person { @XmlElement public List getSpecialties() { List sortedSpecs = new ArrayList<>(getSpecialtiesInternal()); - PropertyComparator.sort(sortedSpecs, new MutableSortDefinition("name", true, true)); + PropertyComparator.sort(sortedSpecs, + new MutableSortDefinition("name", true, true)); return Collections.unmodifiableList(sortedSpecs); } diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java index 8ddcca60a..7ce8374ec 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java @@ -15,13 +15,13 @@ */ package org.springframework.samples.petclinic.vet; -import java.util.Map; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; +import java.util.Map; + /** * @author Juergen Hoeller * @author Mark Fisher @@ -38,7 +38,7 @@ class VetController { this.vets = clinicService; } - @RequestMapping(value = { "/vets.html" }) + @GetMapping("/vets.html") public String showVetList(Map model) { // Here we are returning an object of type 'Vets' rather than a collection of Vet // objects so it is simpler for Object-Xml mapping @@ -48,7 +48,7 @@ class VetController { return "vets/vetList"; } - @RequestMapping(value = { "/vets.json", "/vets.xml" }) + @GetMapping({ "/vets.json", "/vets.xml" }) public @ResponseBody Vets showResourcesVetList() { // Here we are returning an object of type 'Vets' rather than a collection of Vet // objects so it is simpler for JSon/Object mapping diff --git a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java index 25e7cc5ad..ce10d7b12 100755 --- a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java +++ b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java @@ -22,8 +22,8 @@ import javax.persistence.Entity; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import javax.validation.constraints.NotEmpty; -import org.hibernate.validator.constraints.NotEmpty; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.samples.petclinic.model.BaseEntity; @@ -37,28 +37,18 @@ import org.springframework.samples.petclinic.model.BaseEntity; @Table(name = "visits") public class Visit extends BaseEntity { - /** - * Holds value of property date. - */ @Column(name = "visit_date") @Temporal(TemporalType.TIMESTAMP) - @DateTimeFormat(pattern = "yyyy/MM/dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") private Date date; - /** - * Holds value of property description. - */ @NotEmpty @Column(name = "description") private String description; - /** - * Holds value of property pet. - */ @Column(name = "pet_id") private Integer petId; - /** * Creates a new instance of Visit for the current date */ @@ -66,57 +56,26 @@ public class Visit extends BaseEntity { this.date = new Date(); } - - /** - * Getter for property date. - * - * @return Value of property date. - */ public Date getDate() { return this.date; } - /** - * Setter for property date. - * - * @param date New value of property date. - */ public void setDate(Date date) { this.date = date; } - /** - * Getter for property description. - * - * @return Value of property description. - */ public String getDescription() { return this.description; } - /** - * Setter for property description. - * - * @param description New value of property description. - */ public void setDescription(String description) { this.description = description; } - /** - * Getter for property pet id. - * - * @return Value of property pet id. - */ public Integer getPetId() { return this.petId; } - /** - * Setter for property pet id. - * - * @param petId New value of property pet id. - */ public void setPetId(Integer petId) { this.petId = petId; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3562d7d03..ed5392afe 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -13,7 +13,9 @@ spring.jpa.hibernate.ddl-auto=none spring.messages.basename=messages/messages # Actuator / Management -management.contextPath=/manage +management.endpoints.web.base-path=/manage +# Spring Boot 1.5 makes actuator secure by default +management.endpoints.web.enabled=true # Logging logging.level.org.springframework=INFO diff --git a/src/main/resources/templates/owners/findOwners.html b/src/main/resources/templates/owners/findOwners.html index 911ac9581..982be5e81 100644 --- a/src/main/resources/templates/owners/findOwners.html +++ b/src/main/resources/templates/owners/findOwners.html @@ -8,7 +8,7 @@
-
+
- + diff --git a/src/main/resources/templates/pets/createOrUpdatePetForm.html b/src/main/resources/templates/pets/createOrUpdatePetForm.html index bfa07d1ff..e4726e155 100644 --- a/src/main/resources/templates/pets/createOrUpdatePetForm.html +++ b/src/main/resources/templates/pets/createOrUpdatePetForm.html @@ -26,7 +26,7 @@
diff --git a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java index b836d0cc2..7da0d3dea 100644 --- a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java +++ b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java @@ -1,7 +1,5 @@ package org.springframework.samples.petclinic.model; -import static org.assertj.core.api.Assertions.assertThat; - import java.util.Locale; import java.util.Set; @@ -9,13 +7,15 @@ import javax.validation.ConstraintViolation; import javax.validation.Validator; import org.junit.Test; + import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; +import static org.assertj.core.api.Assertions.assertThat; + /** - * @author Michael Isvy - * Simple test to make sure that Bean Validation is working - * (useful when upgrading to a new version of Hibernate Validator/ Bean Validation) + * @author Michael Isvy Simple test to make sure that Bean Validation is working (useful + * when upgrading to a new version of Hibernate Validator/ Bean Validation) */ public class ValidatorTests { @@ -34,12 +34,13 @@ public class ValidatorTests { person.setLastName("smith"); Validator validator = createValidator(); - Set> constraintViolations = validator.validate(person); + Set> constraintViolations = validator + .validate(person); assertThat(constraintViolations.size()).isEqualTo(1); ConstraintViolation violation = constraintViolations.iterator().next(); assertThat(violation.getPropertyPath().toString()).isEqualTo("firstName"); - assertThat(violation.getMessage()).isEqualTo("may not be empty"); + assertThat(violation.getMessage()).isEqualTo("must not be empty"); } } diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java old mode 100644 new mode 100755 index f56931cb6..f95d7c87c --- a/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java @@ -75,7 +75,7 @@ public class PetControllerTests { mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID) .param("name", "Betty") .param("type", "hamster") - .param("birthDate", "2015/02/12") + .param("birthDate", "2015-02-12") ) .andExpect(status().is3xxRedirection()) .andExpect(view().name("redirect:/owners/{ownerId}")); @@ -83,12 +83,14 @@ public class PetControllerTests { @Test public void testProcessCreationFormHasErrors() throws Exception { - mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID) + mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID) .param("name", "Betty") - .param("birthDate", "2015/02/12") + .param("birthDate", "2015-02-12") ) .andExpect(model().attributeHasNoErrors("owner")) .andExpect(model().attributeHasErrors("pet")) + .andExpect(model().attributeHasFieldErrors("pet", "type")) + .andExpect(model().attributeHasFieldErrorCode("pet", "type", "required")) .andExpect(status().isOk()) .andExpect(view().name("pets/createOrUpdatePetForm")); } @@ -106,7 +108,7 @@ public class PetControllerTests { mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID) .param("name", "Betty") .param("type", "hamster") - .param("birthDate", "2015/02/12") + .param("birthDate", "2015-02-12") ) .andExpect(status().is3xxRedirection()) .andExpect(view().name("redirect:/owners/{ownerId}")); diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java index f332257bc..4e8e36c14 100644 --- a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java +++ b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java @@ -1,7 +1,5 @@ package org.springframework.samples.petclinic.owner; -import static org.junit.Assert.assertEquals; - import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; @@ -13,10 +11,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.samples.petclinic.owner.PetRepository; -import org.springframework.samples.petclinic.owner.PetType; -import org.springframework.samples.petclinic.owner.PetTypeFormatter; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.junit.Assert.assertEquals; /** * Test class for {@link PetTypeFormatter} @@ -64,12 +61,12 @@ public class PetTypeFormatterTests { */ private List makePetTypes() { List petTypes = new ArrayList<>(); - petTypes.add(new PetType(){ + petTypes.add(new PetType() { { setName("Dog"); } }); - petTypes.add(new PetType(){ + petTypes.add(new PetType() { { setName("Bird"); } diff --git a/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java index 161769254..3f108bfe9 100644 --- a/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java @@ -1,20 +1,19 @@ package org.springframework.samples.petclinic.system; -import org.junit.Before; import org.junit.Ignore; import org.junit.Test; 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.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; +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; /** * Test class for {@link CrashController} @@ -22,31 +21,18 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Colin But */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = PetClinicApplication.class) -@WebAppConfiguration // Waiting https://github.com/spring-projects/spring-boot/issues/5574 @Ignore +@WebMvcTest(controllers = CrashController.class) public class CrashControllerTests { @Autowired - private CrashController crashController; - private MockMvc mockMvc; - @Before - public void setup() { - this.mockMvc = MockMvcBuilders - .standaloneSetup(crashController) - //.setHandlerExceptionResolvers(new SimpleMappingExceptionResolver()) - .build(); - } - @Test public void testTriggerException() throws Exception { - mockMvc.perform(get("/oups")) - .andExpect(view().name("exception")) - .andExpect(model().attributeExists("exception")) - .andExpect(forwardedUrl("exception")) - .andExpect(status().isOk()); + mockMvc.perform(get("/oups")).andExpect(view().name("exception")) + .andExpect(model().attributeExists("exception")) + .andExpect(forwardedUrl("exception")).andExpect(status().isOk()); } } diff --git a/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java b/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java new file mode 100644 index 000000000..9636e3623 --- /dev/null +++ b/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java @@ -0,0 +1,23 @@ +package org.springframework.samples.petclinic.system; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.samples.petclinic.vet.VetRepository; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ProductionConfigurationTests { + + @Autowired + private VetRepository vets; + + @Test + public void testFindAll() throws Exception { + vets.findAll(); + vets.findAll(); // served from cache + } +} diff --git a/src/test/java/org/springframework/samples/petclinic/vet/VetTests.java b/src/test/java/org/springframework/samples/petclinic/vet/VetTests.java new file mode 100644 index 000000000..de3a7b9bb --- /dev/null +++ b/src/test/java/org/springframework/samples/petclinic/vet/VetTests.java @@ -0,0 +1,43 @@ +/* + * Copyright 2016-2017 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.vet; + +import org.junit.Test; + +import org.springframework.util.SerializationUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Dave Syer + * + */ +public class VetTests { + + @Test + public void testSerialization() { + Vet vet = new Vet(); + vet.setFirstName("Zaphod"); + vet.setLastName("Beeblebrox"); + vet.setId(123); + Vet other = (Vet) SerializationUtils + .deserialize(SerializationUtils.serialize(vet)); + assertThat(other.getFirstName()).isEqualTo(vet.getFirstName()); + assertThat(other.getLastName()).isEqualTo(vet.getLastName()); + assertThat(other.getId()).isEqualTo(vet.getId()); + } + +}