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>

88
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>
@ -176,7 +161,7 @@
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<executions> <executions>
<execution> <execution>
<!-- Spring Boot Actuator displays build-related information <!-- Spring Boot Actuator displays build-related information
if a META-INF/build-info.properties file is present --> if a META-INF/build-info.properties file is present -->
<goals> <goals>
<goal>build-info</goal> <goal>build-info</goal>
@ -201,7 +186,7 @@
</configuration> </configuration>
</plugin> </plugin>
<!-- Spring Boot Actuator displays build-related information if a git.properties <!-- Spring Boot Actuator displays build-related information if a git.properties
file is present at the classpath --> file is present at the classpath -->
<!-- <!--
<plugin> <plugin>
@ -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
@ -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 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("address", this.address)
.append("firstName", this.getFirstName()) .append("city", this.city).append("telephone", this.telephone).toString();
.append("address", this.address)
.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
@ -64,7 +64,7 @@ public class Pet extends NamedEntity {
@JoinColumn(name = "owner_id") @JoinColumn(name = "owner_id")
private Owner owner; private Owner owner;
@OneToMany(cascade = CascadeType.ALL, mappedBy="petId", fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.EAGER)
private Set<Visit> visits = new LinkedHashSet<>(); private Set<Visit> visits = new LinkedHashSet<>();
public void setBirthDate(Date birthDate) { public void setBirthDate(Date birthDate) {
@ -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}
@ -64,12 +61,12 @@ public class PetTypeFormatterTests {
*/ */
private List<PetType> makePetTypes() { private List<PetType> makePetTypes() {
List<PetType> petTypes = new ArrayList<>(); List<PetType> petTypes = new ArrayList<>();
petTypes.add(new PetType(){ petTypes.add(new PetType() {
{ {
setName("Dog"); setName("Dog");
} }
}); });
petTypes.add(new PetType(){ petTypes.add(new PetType() {
{ {
setName("Bird"); setName("Bird");
} }

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(status().isOk());
.andExpect(forwardedUrl("exception"))
.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());
}
}