Merge branch 'master' into master

This commit is contained in:
raynfall 2018-01-13 16:29:12 -06:00 committed by GitHub
commit 90338430c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 237 additions and 308 deletions

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[3.5.0.201404011509-RELEASE]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
<config>src/main/resources/spring/datasource-config.xml</config>
<config>src/main/resources/spring/mvc-core-config.xml</config>
<config>src/main/resources/spring/mvc-view-config.xml</config>
<config>src/main/resources/spring/business-config.xml</config>
</configs>
<autoconfigs>
<config>src/main/resources/spring/tools-config.xml</config>
</autoconfigs>
<configSets>
</configSets>
</beansProjectDescription>

84
pom.xml
View file

@ -5,13 +5,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId> <groupId>org.springframework.samples</groupId>
<artifactId>spring-petclinic</artifactId> <artifactId>spring-petclinic</artifactId>
<version>1.4.2</version> <version>2.0.0</version>
<name>Spring Pet Clinic</name>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version> <version>2.0.0.BUILD-SNAPSHOT</version>
</parent> </parent>
<properties> <properties>
@ -26,16 +25,8 @@
<webjars-jquery.version>2.2.4</webjars-jquery.version> <webjars-jquery.version>2.2.4</webjars-jquery.version>
<wro4j.version>1.8.0</wro4j.version> <wro4j.version>1.8.0</wro4j.version>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> <cobertura.version>2.7</cobertura.version>
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
<sonar.host.url>http://mssonarstg81.morningstar.com:9000</sonar.host.url>
<sonar.junit.reportsPath>target/surefire-reports</sonar.junit.reportsPath>
<!--
<sonar.branch>master</sonar.branch>
<sonar.sources>src/main/java,src/main/less,src/main/resources,src/main/wro</sonar.sources>
-->
<sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
</properties> </properties>
<!-- <!--
@ -85,12 +76,6 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId> <artifactId>spring-boot-starter-thymeleaf</artifactId>
<exclusions>
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -110,7 +95,7 @@
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<!-- EhCache --> <!-- caching -->
<dependency> <dependency>
<groupId>javax.cache</groupId> <groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId> <artifactId>cache-api</artifactId>
@ -218,8 +203,9 @@
<verbose>true</verbose> <verbose>true</verbose>
<dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat> <dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
<generateGitPropertiesFile>true</generateGitPropertiesFile> <generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename> <generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory> </generateGitPropertiesFilename>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
</configuration> </configuration>
</plugin> </plugin>
--> -->
@ -261,53 +247,11 @@
</configuration> </configuration>
</plugin> </plugin>
<plugin> <!-- Apache 2 license -->
<groupId>org.codehaus.gmavenplus</groupId> <licenses>
<artifactId>gmavenplus-plugin</artifactId> <license>
<version>1.5</version> <name>Apache License, Version 2.0</name>
<executions> <url>http://www.apache.org/licenses/LICENSE-2.0</url>
<execution> </license>
<goals> </licenses>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals><goal>copy-dependencies</goal></goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project> </project>

View file

@ -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) | |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) | |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 ## Interesting Spring Petclinic branches and forks
@ -75,12 +75,16 @@ be used to implement the Pet Clinic then please join the community
there. there.
| Link | Main technologies | | 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 | | [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 | | [javaconfig branch][] | Same frameworks as the [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-angularjs][] | 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-angular][] | Angular 4 front-end of the Petclinic REST API [spring-petclinic-rest][] |
| [spring-petclinic-reactjs](https://github.com/spring-petclinic/spring-petclinic-reactjs) | ReactJS (with TypeScript) and Spring Boot | | [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 ## 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. 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 <http://editorconfig.org>. 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 <http://editorconfig.org>. 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 [spring-petclinic]: https://github.com/spring-projects/spring-petclinic
[spring-framework-petclinic]: https://github.com/spring-petclinic/spring-framework-petclinic
This is a trivial change to demonstrate the functionality of Github's pull request capabilities. [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

View file

@ -15,22 +15,25 @@
*/ */
package org.springframework.samples.petclinic.model; package org.springframework.samples.petclinic.model;
import java.io.Serializable;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType; import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.MappedSuperclass; 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 Ken Krebs
* @author Juergen Hoeller * @author Juergen Hoeller
*/ */
@MappedSuperclass @MappedSuperclass
public class BaseEntity { public class BaseEntity implements Serializable {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer id; private Integer id;
public Integer getId() { public Integer getId() {
return id; return id;

View file

@ -17,8 +17,7 @@ package org.springframework.samples.petclinic.model;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotEmpty;
import org.hibernate.validator.constraints.NotEmpty;
/** /**
* Simple JavaBean domain object representing an person. * Simple JavaBean domain object representing an person.
@ -30,11 +29,11 @@ public class Person extends BaseEntity {
@Column(name = "first_name") @Column(name = "first_name")
@NotEmpty @NotEmpty
protected String firstName; private String firstName;
@Column(name = "last_name") @Column(name = "last_name")
@NotEmpty @NotEmpty
protected String lastName; private String lastName;
public String getFirstName() { public String getFirstName() {
return this.firstName; return this.firstName;
@ -52,5 +51,4 @@ public class Person extends BaseEntity {
this.lastName = lastName; this.lastName = lastName;
} }
} }

View file

@ -27,8 +27,8 @@ import javax.persistence.Entity;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.validation.constraints.Digits; 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.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator; import org.springframework.beans.support.PropertyComparator;
import org.springframework.core.style.ToStringCreator; import org.springframework.core.style.ToStringCreator;
@ -61,7 +61,6 @@ public class Owner extends Person {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner") @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
private Set<Pet> pets; private Set<Pet> pets;
public String getAddress() { public String getAddress() {
return this.address; return this.address;
} }
@ -99,7 +98,8 @@ public class Owner extends Person {
public List<Pet> getPets() { public List<Pet> getPets() {
List<Pet> sortedPets = new ArrayList<>(getPetsInternal()); List<Pet> sortedPets = new ArrayList<>(getPetsInternal());
PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true)); PropertyComparator.sort(sortedPets,
new MutableSortDefinition("name", true, true));
return Collections.unmodifiableList(sortedPets); return Collections.unmodifiableList(sortedPets);
} }
@ -144,13 +144,9 @@ public class Owner extends Person {
public String toString() { public String toString() {
return new ToStringCreator(this) return new ToStringCreator(this)
.append("id", this.getId()) .append("id", this.getId()).append("new", this.isNew())
.append("new", this.isNew())
.append("lastName", this.getLastName()) .append("lastName", this.getLastName())
.append("firstName", this.getFirstName()) .append("firstName", this.getFirstName()).append("address", this.address)
.append("address", this.address) .append("city", this.city).append("telephone", this.telephone).toString();
.append("city", this.city)
.append("telephone", this.telephone)
.toString();
} }
} }

View file

@ -15,22 +15,21 @@
*/ */
package org.springframework.samples.petclinic.owner; 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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder; 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.InitBinder;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import java.util.Collection;
import java.util.Map;
/** /**
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Ken Krebs * @author Ken Krebs
@ -54,14 +53,14 @@ class OwnerController {
dataBinder.setDisallowedFields("id"); dataBinder.setDisallowedFields("id");
} }
@RequestMapping(value = "/owners/new", method = RequestMethod.GET) @GetMapping("/owners/new")
public String initCreationForm(Map<String, Object> model) { public String initCreationForm(Map<String, Object> model) {
Owner owner = new Owner(); Owner owner = new Owner();
model.put("owner", owner); model.put("owner", owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; 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) { public String processCreationForm(@Valid Owner owner, BindingResult result) {
if (result.hasErrors()) { if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; 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<String, Object> model) { public String initFindForm(Map<String, Object> model) {
model.put("owner", new Owner()); model.put("owner", new Owner());
return "owners/findOwners"; return "owners/findOwners";
} }
@RequestMapping(value = "/owners", method = RequestMethod.GET) @GetMapping("/owners")
public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) { public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) {
// allow parameterless GET request for /owners to return all records // 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) { public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
Owner owner = this.owners.findById(ownerId); Owner owner = this.owners.findById(ownerId);
model.addAttribute(owner); model.addAttribute(owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; 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) { public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @PathVariable("ownerId") int ownerId) {
if (result.hasErrors()) { if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
@ -126,7 +125,7 @@ class OwnerController {
* @param ownerId the ID of the owner to display * @param ownerId the ID of the owner to display
* @return a ModelMap with the model attributes for the view * @return a ModelMap with the model attributes for the view
*/ */
@RequestMapping("/owners/{ownerId}") @GetMapping("/owners/{ownerId}")
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) { public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
ModelAndView mav = new ModelAndView("owners/ownerDetails"); ModelAndView mav = new ModelAndView("owners/ownerDetails");
mav.addObject(this.owners.findById(ownerId)); mav.addObject(this.owners.findById(ownerId));

View file

@ -15,11 +15,13 @@
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.owner;
import org.springframework.beans.support.MutableSortDefinition; import java.util.ArrayList;
import org.springframework.beans.support.PropertyComparator; import java.util.Collections;
import org.springframework.format.annotation.DateTimeFormat; import java.util.Date;
import org.springframework.samples.petclinic.model.NamedEntity; import java.util.HashSet;
import org.springframework.samples.petclinic.visit.Visit; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
@ -29,16 +31,14 @@ import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import java.util.ArrayList;
import java.util.Collections; import org.springframework.beans.support.MutableSortDefinition;
import java.util.Date; import org.springframework.beans.support.PropertyComparator;
import java.util.HashSet; import org.springframework.format.annotation.DateTimeFormat;
import java.util.LinkedHashSet; import org.springframework.samples.petclinic.model.NamedEntity;
import java.util.List; import org.springframework.samples.petclinic.visit.Visit;
import java.util.Set;
/** /**
* Simple business object representing a pet. * Simple business object representing a pet.
@ -53,7 +53,7 @@ public class Pet extends NamedEntity {
@Column(name = "birth_date") @Column(name = "birth_date")
@Temporal(TemporalType.DATE) @Temporal(TemporalType.DATE)
@DateTimeFormat(pattern = "yyyy/MM/dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthDate; private Date birthDate;
@ManyToOne @ManyToOne
@ -104,13 +104,14 @@ public class Pet extends NamedEntity {
public List<Visit> getVisits() { public List<Visit> getVisits() {
List<Visit> sortedVisits = new ArrayList<>(getVisitsInternal()); List<Visit> sortedVisits = new ArrayList<>(getVisitsInternal());
PropertyComparator.sort(sortedVisits, new MutableSortDefinition("date", false, false)); PropertyComparator.sort(sortedVisits,
new MutableSortDefinition("date", false, false));
return Collections.unmodifiableList(sortedVisits); return Collections.unmodifiableList(sortedVisits);
} }
public void addVisit(Visit visit) { public void addVisit(Visit visit) {
getVisitsInternal().add(visit); getVisitsInternal().add(visit);
visit.setPetId(this.id); visit.setPetId(this.getId());
} }
} }

View file

@ -15,21 +15,16 @@
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.owner;
import java.util.Collection;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable; import javax.validation.Valid;
import org.springframework.web.bind.annotation.RequestMapping; import java.util.Collection;
import org.springframework.web.bind.annotation.RequestMethod;
/** /**
* @author Juergen Hoeller * @author Juergen Hoeller
@ -70,7 +65,7 @@ class PetController {
dataBinder.setValidator(new PetValidator()); dataBinder.setValidator(new PetValidator());
} }
@RequestMapping(value = "/pets/new", method = RequestMethod.GET) @GetMapping("/pets/new")
public String initCreationForm(Owner owner, ModelMap model) { public String initCreationForm(Owner owner, ModelMap model) {
Pet pet = new Pet(); Pet pet = new Pet();
owner.addPet(pet); owner.addPet(pet);
@ -78,29 +73,29 @@ class PetController {
return VIEWS_PETS_CREATE_OR_UPDATE_FORM; 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) { 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){ if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null){
result.rejectValue("name", "duplicate", "already exists"); result.rejectValue("name", "duplicate", "already exists");
} }
owner.addPet(pet);
if (result.hasErrors()) { if (result.hasErrors()) {
model.put("pet", pet); model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM; return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
} else { } else {
owner.addPet(pet);
this.pets.save(pet); this.pets.save(pet);
return "redirect:/owners/{ownerId}"; 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) { public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) {
Pet pet = this.pets.findById(petId); Pet pet = this.pets.findById(petId);
model.put("pet", pet); model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM; 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) { public String processUpdateForm(@Valid Pet pet, BindingResult result, Owner owner, ModelMap model) {
if (result.hasErrors()) { if (result.hasErrors()) {
pet.setOwner(owner); pet.setOwner(owner);

View file

@ -15,21 +15,16 @@
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.owner;
import java.util.Map;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.visit.Visit; import org.springframework.samples.petclinic.visit.Visit;
import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.samples.petclinic.visit.VisitRepository;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable; import javax.validation.Valid;
import org.springframework.web.bind.annotation.RequestMapping; import java.util.Map;
import org.springframework.web.bind.annotation.RequestMethod;
/** /**
* @author Juergen Hoeller * @author Juergen Hoeller
@ -76,13 +71,13 @@ class VisitController {
} }
// Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called // 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<String, Object> model) { public String initNewVisitForm(@PathVariable("petId") int petId, Map<String, Object> model) {
return "pets/createOrUpdateVisitForm"; return "pets/createOrUpdateVisitForm";
} }
// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called // 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) { public String processNewVisitForm(@Valid Visit visit, BindingResult result) {
if (result.hasErrors()) { if (result.hasErrors()) {
return "pets/createOrUpdateVisitForm"; return "pets/createOrUpdateVisitForm";

View file

@ -1,40 +1,34 @@
package org.springframework.samples.petclinic.system; package org.springframework.samples.petclinic.system;
import java.util.concurrent.TimeUnit; import javax.cache.configuration.Configuration;
import javax.cache.configuration.MutableConfiguration;
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 org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer; import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile; 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 @EnableCaching
@Profile("production") @Profile("production")
class CacheConfig { class CacheConfig {
@Bean @Bean
public JCacheManagerCustomizer cacheManagerCustomizer() { public JCacheManagerCustomizer cacheManagerCustomizer() {
return cacheManager -> { return cm -> {
CacheConfiguration<Object, Object> config = CacheConfigurationBuilder Configuration<Object, Object> cacheConfiguration = createCacheConfiguration();
.newCacheConfigurationBuilder(Object.class, Object.class, cm.createCache("vets", cacheConfiguration);
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(100, EntryUnit.ENTRIES))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(60, TimeUnit.SECONDS)))
.build();
cacheManager.createCache("vets", Eh107Configuration.fromEhcacheCacheConfiguration(config));
}; };
} }
private Configuration<Object, Object> 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);
}
} }

View file

@ -16,8 +16,7 @@
package org.springframework.samples.petclinic.system; package org.springframework.samples.petclinic.system;
import org.springframework.stereotype.Controller; 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.RequestMethod;
/** /**
* Controller used to showcase what happens when an exception is thrown * Controller used to showcase what happens when an exception is thrown
@ -29,10 +28,10 @@ import org.springframework.web.bind.annotation.RequestMethod;
@Controller @Controller
class CrashController { class CrashController {
@RequestMapping(value = "/oups", method = RequestMethod.GET) @GetMapping("/oups")
public String triggerException() { public String triggerException() {
throw new RuntimeException( throw new RuntimeException("Expected: controller used to showcase what "
"Expected: controller used to showcase what " + "happens when an exception is thrown"); + "happens when an exception is thrown");
} }
} }

View file

@ -2,12 +2,12 @@ package org.springframework.samples.petclinic.system;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.GetMapping;
@Controller @Controller
class WelcomeController { class WelcomeController {
@RequestMapping("/") @GetMapping("/")
public String welcome() { public String welcome() {
return "welcome"; return "welcome";
} }

View file

@ -15,6 +15,8 @@
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.vet;
import java.io.Serializable;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Table; import javax.persistence.Table;
@ -27,6 +29,6 @@ import org.springframework.samples.petclinic.model.NamedEntity;
*/ */
@Entity @Entity
@Table(name = "specialties") @Table(name = "specialties")
public class Specialty extends NamedEntity { public class Specialty extends NamedEntity implements Serializable {
} }

View file

@ -46,8 +46,7 @@ import org.springframework.samples.petclinic.model.Person;
public class Vet extends Person { public class Vet extends Person {
@ManyToMany(fetch = FetchType.EAGER) @ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), inverseJoinColumns = @JoinColumn(name = "specialty_id"))
inverseJoinColumns = @JoinColumn(name = "specialty_id"))
private Set<Specialty> specialties; private Set<Specialty> specialties;
protected Set<Specialty> getSpecialtiesInternal() { protected Set<Specialty> getSpecialtiesInternal() {
@ -64,7 +63,8 @@ public class Vet extends Person {
@XmlElement @XmlElement
public List<Specialty> getSpecialties() { public List<Specialty> getSpecialties() {
List<Specialty> sortedSpecs = new ArrayList<>(getSpecialtiesInternal()); List<Specialty> sortedSpecs = new ArrayList<>(getSpecialtiesInternal());
PropertyComparator.sort(sortedSpecs, new MutableSortDefinition("name", true, true)); PropertyComparator.sort(sortedSpecs,
new MutableSortDefinition("name", true, true));
return Collections.unmodifiableList(sortedSpecs); return Collections.unmodifiableList(sortedSpecs);
} }

View file

@ -15,13 +15,13 @@
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.vet;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; 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 org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;
/** /**
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Mark Fisher * @author Mark Fisher
@ -38,7 +38,7 @@ class VetController {
this.vets = clinicService; this.vets = clinicService;
} }
@RequestMapping(value = { "/vets.html" }) @GetMapping("/vets.html")
public String showVetList(Map<String, Object> model) { public String showVetList(Map<String, Object> model) {
// Here we are returning an object of type 'Vets' rather than a collection of Vet // Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for Object-Xml mapping // objects so it is simpler for Object-Xml mapping
@ -48,7 +48,7 @@ class VetController {
return "vets/vetList"; return "vets/vetList";
} }
@RequestMapping(value = { "/vets.json", "/vets.xml" }) @GetMapping({ "/vets.json", "/vets.xml" })
public @ResponseBody Vets showResourcesVetList() { public @ResponseBody Vets showResourcesVetList() {
// Here we are returning an object of type 'Vets' rather than a collection of Vet // Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for JSon/Object mapping // objects so it is simpler for JSon/Object mapping

View file

@ -22,8 +22,8 @@ import javax.persistence.Entity;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.validation.constraints.NotEmpty;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.samples.petclinic.model.BaseEntity; import org.springframework.samples.petclinic.model.BaseEntity;
@ -37,28 +37,18 @@ import org.springframework.samples.petclinic.model.BaseEntity;
@Table(name = "visits") @Table(name = "visits")
public class Visit extends BaseEntity { public class Visit extends BaseEntity {
/**
* Holds value of property date.
*/
@Column(name = "visit_date") @Column(name = "visit_date")
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "yyyy/MM/dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date; private Date date;
/**
* Holds value of property description.
*/
@NotEmpty @NotEmpty
@Column(name = "description") @Column(name = "description")
private String description; private String description;
/**
* Holds value of property pet.
*/
@Column(name = "pet_id") @Column(name = "pet_id")
private Integer petId; private Integer petId;
/** /**
* Creates a new instance of Visit for the current date * Creates a new instance of Visit for the current date
*/ */
@ -66,57 +56,26 @@ public class Visit extends BaseEntity {
this.date = new Date(); this.date = new Date();
} }
/**
* Getter for property date.
*
* @return Value of property date.
*/
public Date getDate() { public Date getDate() {
return this.date; return this.date;
} }
/**
* Setter for property date.
*
* @param date New value of property date.
*/
public void setDate(Date date) { public void setDate(Date date) {
this.date = date; this.date = date;
} }
/**
* Getter for property description.
*
* @return Value of property description.
*/
public String getDescription() { public String getDescription() {
return this.description; return this.description;
} }
/**
* Setter for property description.
*
* @param description New value of property description.
*/
public void setDescription(String description) { public void setDescription(String description) {
this.description = description; this.description = description;
} }
/**
* Getter for property pet id.
*
* @return Value of property pet id.
*/
public Integer getPetId() { public Integer getPetId() {
return this.petId; return this.petId;
} }
/**
* Setter for property pet id.
*
* @param petId New value of property pet id.
*/
public void setPetId(Integer petId) { public void setPetId(Integer petId) {
this.petId = petId; this.petId = petId;
} }

View file

@ -13,7 +13,9 @@ spring.jpa.hibernate.ddl-auto=none
spring.messages.basename=messages/messages spring.messages.basename=messages/messages
# Actuator / Management # 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
logging.level.org.springframework=INFO logging.level.org.springframework=INFO

View file

@ -8,7 +8,7 @@
<form th:object="${owner}" th:action="@{/owners}" method="get" <form th:object="${owner}" th:action="@{/owners}" method="get"
class="form-horizontal" id="search-owner-form"> class="form-horizontal" id="search-owner-form">
<div class="form-group"> <div class="form-group">
<div class="control-group" id="lastName"> <div class="control-group" id="lastNameGroup">
<label class="col-sm-2 control-label">Last name </label> <label class="col-sm-2 control-label">Last name </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input class="form-control" th:field="*{lastName}" size="30" <input class="form-control" th:field="*{lastName}" size="30"

View file

@ -19,7 +19,7 @@
<tbody> <tbody>
<tr th:each="owner : ${selections}"> <tr th:each="owner : ${selections}">
<td> <td>
<a th:href="@{owners/__${owner.id}__}" th:text="${owner.firstName + ' ' + owner.lastName}"/></a> <a th:href="@{/owners/__${owner.id}__}" th:text="${owner.firstName + ' ' + owner.lastName}"/></a>
</td> </td>
<td th:text="${owner.address}"/> <td th:text="${owner.address}"/>
<td th:text="${owner.city}"/> <td th:text="${owner.city}"/>

View file

@ -26,7 +26,7 @@
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <div class="col-sm-offset-2 col-sm-10">
<button <button
th:with="text=${owner['new']} ? 'Add Pet' : 'Update Pet'" th:with="text=${pet['new']} ? 'Add Pet' : 'Update Pet'"
class="btn btn-default" type="submit" th:text="${text}">Add class="btn btn-default" type="submit" th:text="${text}">Add
Pet</button> Pet</button>
</div> </div>

View file

@ -1,7 +1,5 @@
package org.springframework.samples.petclinic.model; package org.springframework.samples.petclinic.model;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
@ -9,13 +7,15 @@ import javax.validation.ConstraintViolation;
import javax.validation.Validator; import javax.validation.Validator;
import org.junit.Test; import org.junit.Test;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import static org.assertj.core.api.Assertions.assertThat;
/** /**
* @author Michael Isvy * @author Michael Isvy Simple test to make sure that Bean Validation is working (useful
* Simple test to make sure that Bean Validation is working * when upgrading to a new version of Hibernate Validator/ Bean Validation)
* (useful when upgrading to a new version of Hibernate Validator/ Bean Validation)
*/ */
public class ValidatorTests { public class ValidatorTests {
@ -34,12 +34,13 @@ public class ValidatorTests {
person.setLastName("smith"); person.setLastName("smith");
Validator validator = createValidator(); Validator validator = createValidator();
Set<ConstraintViolation<Person>> constraintViolations = validator.validate(person); Set<ConstraintViolation<Person>> constraintViolations = validator
.validate(person);
assertThat(constraintViolations.size()).isEqualTo(1); assertThat(constraintViolations.size()).isEqualTo(1);
ConstraintViolation<Person> violation = constraintViolations.iterator().next(); ConstraintViolation<Person> violation = constraintViolations.iterator().next();
assertThat(violation.getPropertyPath().toString()).isEqualTo("firstName"); assertThat(violation.getPropertyPath().toString()).isEqualTo("firstName");
assertThat(violation.getMessage()).isEqualTo("may not be empty"); assertThat(violation.getMessage()).isEqualTo("must not be empty");
} }
} }

View file

@ -75,7 +75,7 @@ public class PetControllerTests {
mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID) mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID)
.param("name", "Betty") .param("name", "Betty")
.param("type", "hamster") .param("type", "hamster")
.param("birthDate", "2015/02/12") .param("birthDate", "2015-02-12")
) )
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/owners/{ownerId}")); .andExpect(view().name("redirect:/owners/{ownerId}"));
@ -83,12 +83,14 @@ public class PetControllerTests {
@Test @Test
public void testProcessCreationFormHasErrors() throws Exception { 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("name", "Betty")
.param("birthDate", "2015/02/12") .param("birthDate", "2015-02-12")
) )
.andExpect(model().attributeHasNoErrors("owner")) .andExpect(model().attributeHasNoErrors("owner"))
.andExpect(model().attributeHasErrors("pet")) .andExpect(model().attributeHasErrors("pet"))
.andExpect(model().attributeHasFieldErrors("pet", "type"))
.andExpect(model().attributeHasFieldErrorCode("pet", "type", "required"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(view().name("pets/createOrUpdatePetForm")); .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) mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID)
.param("name", "Betty") .param("name", "Betty")
.param("type", "hamster") .param("type", "hamster")
.param("birthDate", "2015/02/12") .param("birthDate", "2015-02-12")
) )
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/owners/{ownerId}")); .andExpect(view().name("redirect:/owners/{ownerId}"));

View file

@ -1,7 +1,5 @@
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.owner;
import static org.junit.Assert.assertEquals;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -13,10 +11,9 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.samples.petclinic.owner.PetRepository;
import org.springframework.samples.petclinic.owner.PetType; import static org.junit.Assert.assertEquals;
import org.springframework.samples.petclinic.owner.PetTypeFormatter;
/** /**
* Test class for {@link PetTypeFormatter} * Test class for {@link PetTypeFormatter}

View file

@ -1,20 +1,19 @@
package org.springframework.samples.petclinic.system; package org.springframework.samples.petclinic.system;
import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
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.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc; 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.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} * Test class for {@link CrashController}
@ -22,31 +21,18 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @author Colin But * @author Colin But
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = PetClinicApplication.class)
@WebAppConfiguration
// Waiting https://github.com/spring-projects/spring-boot/issues/5574 // Waiting https://github.com/spring-projects/spring-boot/issues/5574
@Ignore @Ignore
@WebMvcTest(controllers = CrashController.class)
public class CrashControllerTests { public class CrashControllerTests {
@Autowired @Autowired
private CrashController crashController;
private MockMvc mockMvc; private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders
.standaloneSetup(crashController)
//.setHandlerExceptionResolvers(new SimpleMappingExceptionResolver())
.build();
}
@Test @Test
public void testTriggerException() throws Exception { public void testTriggerException() throws Exception {
mockMvc.perform(get("/oups")) mockMvc.perform(get("/oups")).andExpect(view().name("exception"))
.andExpect(view().name("exception"))
.andExpect(model().attributeExists("exception")) .andExpect(model().attributeExists("exception"))
.andExpect(forwardedUrl("exception")) .andExpect(forwardedUrl("exception")).andExpect(status().isOk());
.andExpect(status().isOk());
} }
} }

View file

@ -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
}
}

View file

@ -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());
}
}