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>
<groupId>org.springframework.samples</groupId>
<artifactId>spring-petclinic</artifactId>
<version>1.4.2</version>
<name>Spring Pet Clinic</name>
<version>2.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<properties>
@ -26,16 +25,8 @@
<webjars-jquery.version>2.2.4</webjars-jquery.version>
<wro4j.version>1.8.0</wro4j.version>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
<cobertura.version>2.7</cobertura.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>
<!--
@ -85,12 +76,6 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<exclusions>
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -110,7 +95,7 @@
<scope>runtime</scope>
</dependency>
<!-- EhCache -->
<!-- caching -->
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
@ -218,8 +203,9 @@
<verbose>true</verbose>
<dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties
</generateGitPropertiesFilename>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
</configuration>
</plugin>
-->
@ -261,53 +247,11 @@
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<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>
<!-- Apache 2 license -->
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
</license>
</licenses>
</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) |
|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
@ -75,12 +75,16 @@ be used to implement the Pet Clinic then please join the community
there.
| Link | Main technologies |
|----------------|-------------------|
| [spring-framework-petclinic](https://github.com/spring-petclinic/spring-framework-petclinic) | Spring Framework XML configuration, JSP pages, 3 persistence layers: JDBC, JPA and Spring Data JPA |
| [javaconfig branch](https://github.com/spring-petclinic/spring-framework-petclinic/tree/javaconfig) | Same frameworks as the [spring-framework-petclinic](https://github.com/spring-petclinic/spring-framework-petclinic) but with Java Configuration instead of XML |
| [spring-petclinic-angular1](https://github.com/spring-petclinic/spring-petclinic-angular1) | AngularJS 1.x, Spring Boot and Spring Data JPA |
| [spring-petclinic-microservices](https://github.com/spring-petclinic/spring-petclinic-microservices) | Distributed version of Spring Petclinic built with Spring Cloud |
| [spring-petclinic-reactjs](https://github.com/spring-petclinic/spring-petclinic-reactjs) | ReactJS (with TypeScript) and Spring Boot |
|------------------------------------|-------------------|
| [spring-framework-petclinic][] | Spring Framework XML configuration, JSP pages, 3 persistence layers: JDBC, JPA and Spring Data JPA |
| [javaconfig branch][] | Same frameworks as the [spring-framework-petclinic][] but with Java Configuration instead of XML |
| [spring-petclinic-angularjs][] | AngularJS 1.x, Spring Boot and Spring Data JPA |
| [spring-petclinic-angular][] | Angular 4 front-end of the Petclinic REST API [spring-petclinic-rest][] |
| [spring-petclinic-microservices][] | Distributed version of Spring Petclinic built with Spring Cloud |
| [spring-petclinic-reactjs][] | ReactJS (with TypeScript) and Spring Boot |
| [spring-petclinic-graphql][] | GraphQL version based on React Appolo, TypeScript and GraphQL Spring boot starter |
| [spring-petclinic-kotlin][] | Kotlin version of [spring-petclinic][] |
| [spring-petclinic-rest][] | Backend REST API |
## Interaction with other open source projects
@ -99,10 +103,16 @@ Here is a list of them:
The [issue tracker](https://github.com/spring-projects/spring-petclinic/issues) is the preferred channel for bug reports, features requests and submitting pull requests.
For pull requests, editor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at <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
This is a trivial change to demonstrate the functionality of Github's pull request capabilities.
[spring-petclinic]: https://github.com/spring-projects/spring-petclinic
[spring-framework-petclinic]: https://github.com/spring-petclinic/spring-framework-petclinic
[spring-petclinic-angularjs]: https://github.com/spring-petclinic/spring-petclinic-angularjs
[javaconfig branch]: https://github.com/spring-petclinic/spring-framework-petclinic/tree/javaconfig
[spring-petclinic-angular]: https://github.com/spring-petclinic/spring-petclinic-angular
[spring-petclinic-microservices]: https://github.com/spring-petclinic/spring-petclinic-microservices
[spring-petclinic-reactjs]: https://github.com/spring-petclinic/spring-petclinic-reactjs
[spring-petclinic-graphql]: https://github.com/spring-petclinic/spring-petclinic-graphql
[spring-petclinic-kotlin]: https://github.com/spring-petclinic/spring-petclinic-kotlin

View file

@ -15,22 +15,25 @@
*/
package org.springframework.samples.petclinic.model;
import java.io.Serializable;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
/**
* Simple JavaBean domain object with an id property. Used as a base class for objects needing this property.
* Simple JavaBean domain object with an id property. Used as a base class for objects
* needing this property.
*
* @author Ken Krebs
* @author Juergen Hoeller
*/
@MappedSuperclass
public class BaseEntity {
public class BaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer id;
private Integer id;
public Integer getId() {
return id;

View file

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

View file

@ -27,8 +27,8 @@ import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotEmpty;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.core.style.ToStringCreator;
@ -61,7 +61,6 @@ public class Owner extends Person {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
private Set<Pet> pets;
public String getAddress() {
return this.address;
}
@ -99,7 +98,8 @@ public class Owner extends Person {
public List<Pet> getPets() {
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);
}
@ -144,13 +144,9 @@ public class Owner extends Person {
public String toString() {
return new ToStringCreator(this)
.append("id", this.getId())
.append("new", this.isNew())
.append("id", this.getId()).append("new", this.isNew())
.append("lastName", this.getLastName())
.append("firstName", this.getFirstName())
.append("address", this.address)
.append("city", this.city)
.append("telephone", this.telephone)
.toString();
.append("firstName", this.getFirstName()).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;
import java.util.Collection;
import java.util.Map;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import java.util.Collection;
import java.util.Map;
/**
* @author Juergen Hoeller
* @author Ken Krebs
@ -54,14 +53,14 @@ class OwnerController {
dataBinder.setDisallowedFields("id");
}
@RequestMapping(value = "/owners/new", method = RequestMethod.GET)
@GetMapping("/owners/new")
public String initCreationForm(Map<String, Object> model) {
Owner owner = new Owner();
model.put("owner", owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
@RequestMapping(value = "/owners/new", method = RequestMethod.POST)
@PostMapping("/owners/new")
public String processCreationForm(@Valid Owner owner, BindingResult result) {
if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
@ -71,13 +70,13 @@ class OwnerController {
}
}
@RequestMapping(value = "/owners/find", method = RequestMethod.GET)
@GetMapping("/owners/find")
public String initFindForm(Map<String, Object> model) {
model.put("owner", new Owner());
return "owners/findOwners";
}
@RequestMapping(value = "/owners", method = RequestMethod.GET)
@GetMapping("/owners")
public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) {
// allow parameterless GET request for /owners to return all records
@ -102,14 +101,14 @@ class OwnerController {
}
}
@RequestMapping(value = "/owners/{ownerId}/edit", method = RequestMethod.GET)
@GetMapping("/owners/{ownerId}/edit")
public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
Owner owner = this.owners.findById(ownerId);
model.addAttribute(owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
@RequestMapping(value = "/owners/{ownerId}/edit", method = RequestMethod.POST)
@PostMapping("/owners/{ownerId}/edit")
public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @PathVariable("ownerId") int ownerId) {
if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
@ -126,7 +125,7 @@ class OwnerController {
* @param ownerId the ID of the owner to display
* @return a ModelMap with the model attributes for the view
*/
@RequestMapping("/owners/{ownerId}")
@GetMapping("/owners/{ownerId}")
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
ModelAndView mav = new ModelAndView("owners/ownerDetails");
mav.addObject(this.owners.findById(ownerId));

View file

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

View file

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

View file

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

View file

@ -1,40 +1,34 @@
package org.springframework.samples.petclinic.system;
import java.util.concurrent.TimeUnit;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.expiry.Duration;
import org.ehcache.expiry.Expirations;
import org.ehcache.jsr107.Eh107Configuration;
import javax.cache.configuration.Configuration;
import javax.cache.configuration.MutableConfiguration;
import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/**
* Cache could be disable in unit test.
* Cache could be disabled in unit test.
*/
@Configuration
@org.springframework.context.annotation.Configuration
@EnableCaching
@Profile("production")
class CacheConfig {
@Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
return cacheManager -> {
CacheConfiguration<Object, Object> config = CacheConfigurationBuilder
.newCacheConfigurationBuilder(Object.class, Object.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(100, EntryUnit.ENTRIES))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(60, TimeUnit.SECONDS)))
.build();
cacheManager.createCache("vets", Eh107Configuration.fromEhcacheCacheConfiguration(config));
return cm -> {
Configuration<Object, Object> cacheConfiguration = createCacheConfiguration();
cm.createCache("vets", cacheConfiguration);
};
}
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;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.GetMapping;
/**
* Controller used to showcase what happens when an exception is thrown
@ -29,10 +28,10 @@ import org.springframework.web.bind.annotation.RequestMethod;
@Controller
class CrashController {
@RequestMapping(value = "/oups", method = RequestMethod.GET)
@GetMapping("/oups")
public String triggerException() {
throw new RuntimeException(
"Expected: controller used to showcase what " + "happens when an exception is thrown");
throw new RuntimeException("Expected: controller used to showcase what "
+ "happens when an exception is thrown");
}
}

View file

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

View file

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

View file

@ -46,8 +46,7 @@ import org.springframework.samples.petclinic.model.Person;
public class Vet extends Person {
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"),
inverseJoinColumns = @JoinColumn(name = "specialty_id"))
@JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), inverseJoinColumns = @JoinColumn(name = "specialty_id"))
private Set<Specialty> specialties;
protected Set<Specialty> getSpecialtiesInternal() {
@ -64,7 +63,8 @@ public class Vet extends Person {
@XmlElement
public List<Specialty> getSpecialties() {
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);
}

View file

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

View file

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

View file

@ -13,7 +13,9 @@ spring.jpa.hibernate.ddl-auto=none
spring.messages.basename=messages/messages
# Actuator / Management
management.contextPath=/manage
management.endpoints.web.base-path=/manage
# Spring Boot 1.5 makes actuator secure by default
management.endpoints.web.enabled=true
# Logging
logging.level.org.springframework=INFO

View file

@ -8,7 +8,7 @@
<form th:object="${owner}" th:action="@{/owners}" method="get"
class="form-horizontal" id="search-owner-form">
<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>
<div class="col-sm-10">
<input class="form-control" th:field="*{lastName}" size="30"

View file

@ -19,7 +19,7 @@
<tbody>
<tr th:each="owner : ${selections}">
<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 th:text="${owner.address}"/>
<td th:text="${owner.city}"/>

View file

@ -26,7 +26,7 @@
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<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
Pet</button>
</div>

View file

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

View file

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

View file

@ -1,7 +1,5 @@
package org.springframework.samples.petclinic.owner;
import static org.junit.Assert.assertEquals;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
@ -13,10 +11,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.samples.petclinic.owner.PetRepository;
import org.springframework.samples.petclinic.owner.PetType;
import org.springframework.samples.petclinic.owner.PetTypeFormatter;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
/**
* Test class for {@link PetTypeFormatter}
@ -64,12 +61,12 @@ public class PetTypeFormatterTests {
*/
private List<PetType> makePetTypes() {
List<PetType> petTypes = new ArrayList<>();
petTypes.add(new PetType(){
petTypes.add(new PetType() {
{
setName("Dog");
}
});
petTypes.add(new PetType(){
petTypes.add(new PetType() {
{
setName("Bird");
}

View file

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