Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • s51119/broken-petclinic
  • s72462/broken-petclinic
  • s61200/broken-petclinic
  • s76620/broken-petclinic
  • s76545/broken-petclinic
  • s76915/broken-petclinic
  • s70130/broken-petclinic
  • s72523/broken-petclinic
  • s77047/broken-petclinic
  • s70178/broken-petclinic
  • s76522/broken-petclinic
  • s76426/broken-petclinic
  • s76863/broken-petclinic
  • s76856/broken-petclinic
  • s76728/broken-petclinic
  • williamreetz/broken-petclinic
  • s77034/broken-petclinic
  • s76400/broken-petclinic
  • s72288/broken-petclinic
  • s76608/broken-petclinic
20 results
Show changes
Showing
with 263 additions and 352 deletions
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -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;
}
}
/**
* The classes in this package represent PetClinic's business layer.
*/
package org.springframework.samples.petclinic.model;
/*
* Copyright 2012-2019 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
*
* https://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.
*/
/**
* The classes in this package represent utilities used by the domain.
*/
package org.springframework.samples.petclinic.model;
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.owner;
import java.util.ArrayList;
import java.util.Collections;
......@@ -27,11 +27,12 @@ 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;
import org.springframework.samples.petclinic.model.Person;
/**
* Simple JavaBean domain object representing an owner.
......@@ -60,7 +61,6 @@ public class Owner extends Person {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
private Set<Pet> pets;
public String getAddress() {
return this.address;
}
......@@ -98,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);
}
......@@ -143,13 +144,9 @@ public class Owner extends Person {
public String toString() {
return new ToStringCreator(this)
.append("id", this.getId())
.append("new", this.isNew())
.append("lastName", this.getLastName())
.append("firstName", this.getFirstName())
.append("address", this.address)
.append("city", this.city)
.append("telephone", this.telephone)
.toString();
.append("id", this.getId()).append("new", this.isNew())
.append("lastName", this.getLastName())
.append("firstName", this.getFirstName()).append("address", this.address)
.append("city", this.city).append("telephone", this.telephone).toString();
}
}
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,26 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import java.util.Collection;
import java.util.Map;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
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
......@@ -40,15 +36,14 @@ import org.springframework.web.servlet.ModelAndView;
* @author Michael Isvy
*/
@Controller
public class OwnerController {
class OwnerController {
private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
private final ClinicService clinicService;
private final OwnerRepository owners;
@Autowired
public OwnerController(ClinicService clinicService) {
this.clinicService = clinicService;
public OwnerController(OwnerRepository clinicService) {
this.owners = clinicService;
}
@InitBinder
......@@ -56,30 +51,30 @@ public 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;
} else {
this.clinicService.saveOwner(owner);
this.owners.save(owner);
return "redirect:/owners/" + owner.getId();
}
}
@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
......@@ -88,7 +83,7 @@ public class OwnerController {
}
// find owners by last name
Collection<Owner> results = this.clinicService.findOwnerByLastName(owner.getLastName());
Collection<Owner> results = this.owners.findByLastName(owner.getLastName());
if (results.isEmpty()) {
// no owners found
result.rejectValue("lastName", "notFound", "not found");
......@@ -104,20 +99,20 @@ public 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.clinicService.findOwnerById(ownerId);
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;
} else {
owner.setId(ownerId);
this.clinicService.saveOwner(owner);
this.owners.save(owner);
return "redirect:/owners/{ownerId}";
}
}
......@@ -128,10 +123,10 @@ public 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.clinicService.findOwnerById(ownerId));
mav.addObject(this.owners.findById(ownerId));
return mav;
}
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,20 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
package org.springframework.samples.petclinic.owner;
import java.util.Collection;
import org.springframework.dao.DataAccessException;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.transaction.annotation.Transactional;
/**
* Repository class for <code>Owner</code> domain objects All method names are compliant with Spring Data naming
* conventions so this interface can easily be extended for Spring Data See here: http://static.springsource.org/spring-data/jpa/docs/current/reference/html/jpa.repositories.html#jpa.query-methods.query-creation
* conventions so this interface can easily be extended for Spring Data.
* See: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation
*
* @author Ken Krebs
* @author Juergen Hoeller
......@@ -43,6 +42,7 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
* found)
*/
@Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName%")
@Transactional(readOnly = true)
Collection<Owner> findByLastName(@Param("lastName") String lastName);
/**
......@@ -51,7 +51,8 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
* @return the {@link Owner} if found
*/
@Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id")
Owner findById(@Param("id") int id);
@Transactional(readOnly = true)
Owner findById(@Param("id") Integer id);
/**
* Save an {@link Owner} to the data store, either inserting or updating it.
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.owner;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
......@@ -30,12 +32,11 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
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.
......@@ -49,8 +50,7 @@ import org.springframework.format.annotation.DateTimeFormat;
public class Pet extends NamedEntity {
@Column(name = "birth_date")
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
@DateTimeFormat(pattern = "yyyy/MM/dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate birthDate;
@ManyToOne
......@@ -61,17 +61,17 @@ public class Pet extends NamedEntity {
@JoinColumn(name = "owner_id")
private Owner owner;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "pet", fetch = FetchType.EAGER)
private Set<Visit> visits;
public LocalDate getBirthDate() {
return this.birthDate;
}
@OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.EAGER)
private Set<Visit> visits = new LinkedHashSet<>();
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public LocalDate getBirthDate() {
return this.birthDate;
}
public PetType getType() {
return this.type;
}
......@@ -101,17 +101,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.setPet(this);
visit.setPetId(this.getId());
}
}
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,13 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
......@@ -28,7 +23,6 @@ import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Collection;
/**
......@@ -38,24 +32,25 @@ import java.util.Collection;
*/
@Controller
@RequestMapping("/owners/{ownerId}")
public class PetController {
class PetController {
private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm";
private final ClinicService clinicService;
private final PetRepository pets;
private final OwnerRepository owners;
@Autowired
public PetController(ClinicService clinicService) {
this.clinicService = clinicService;
public PetController(PetRepository pets, OwnerRepository owners) {
this.pets = pets;
this.owners = owners;
}
@ModelAttribute("types")
public Collection<PetType> populatePetTypes() {
return this.clinicService.findPetTypes();
return this.pets.findPetTypes();
}
@ModelAttribute("owner")
public Owner findOwner(@PathVariable("ownerId") int ownerId) {
return this.clinicService.findOwnerById(ownerId);
return this.owners.findById(ownerId);
}
@InitBinder("owner")
......@@ -68,7 +63,7 @@ public 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);
......@@ -76,36 +71,37 @@ public 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.clinicService.savePet(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.clinicService.findPetById(petId);
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);
model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
} else {
owner.addPet(pet);
this.clinicService.savePet(pet);
this.pets.save(pet);
return "redirect:/owners/{ownerId}";
}
}
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,20 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
package org.springframework.samples.petclinic.owner;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.transaction.annotation.Transactional;
/**
* Repository class for <code>Pet</code> domain objects All method names are compliant with Spring Data naming
* conventions so this interface can easily be extended for Spring Data See here: http://static.springsource.org/spring-data/jpa/docs/current/reference/html/jpa.repositories.html#jpa.query-methods.query-creation
* conventions so this interface can easily be extended for Spring Data.
* See: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation
*
* @author Ken Krebs
* @author Juergen Hoeller
......@@ -40,6 +38,7 @@ public interface PetRepository extends Repository<Pet, Integer> {
* @return a Collection of {@link PetType}s.
*/
@Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name")
@Transactional(readOnly = true)
List<PetType> findPetTypes();
/**
......@@ -47,7 +46,8 @@ public interface PetRepository extends Repository<Pet, Integer> {
* @param id the id to search for
* @return the {@link Pet} if found
*/
Pet findById(int id);
@Transactional(readOnly = true)
Pet findById(Integer id);
/**
* Save a {@link Pet} to the data store, either inserting or updating it.
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.owner;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.springframework.samples.petclinic.model.NamedEntity;
/**
* @author Juergen Hoeller
* Can be Cat, Dog, Hamster...
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import java.text.ParseException;
import java.util.Collection;
......@@ -22,17 +21,12 @@ import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.Formatter;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Component;
/**
* Instructs Spring MVC on how to parse and print elements of type 'PetType'. Starting from Spring 3.0, Formatters have
* come as an improvement in comparison to legacy PropertyEditors. See the following links for more details: - The
* Spring ref doc: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html#format-Formatter-SPI
* - A nice blog entry from Gordon Dickens: http://gordondickens.com/wordpress/2010/09/30/using-spring-3-0-custom-type-converter/
* <p/>
* Also see how the bean 'conversionService' has been declared inside /WEB-INF/mvc-core-config.xml
* Spring ref doc: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#format
*
* @author Mark Fisher
* @author Juergen Hoeller
......@@ -41,12 +35,12 @@ import org.springframework.stereotype.Component;
@Component
public class PetTypeFormatter implements Formatter<PetType> {
private final ClinicService clinicService;
private final PetRepository pets;
@Autowired
public PetTypeFormatter(ClinicService clinicService) {
this.clinicService = clinicService;
public PetTypeFormatter(PetRepository pets) {
this.pets = pets;
}
@Override
......@@ -56,7 +50,7 @@ public class PetTypeFormatter implements Formatter<PetType> {
@Override
public PetType parse(String text, Locale locale) throws ParseException {
Collection<PetType> findPetTypes = this.clinicService.findPetTypes();
Collection<PetType> findPetTypes = this.pets.findPetTypes();
for (PetType type : findPetTypes) {
if (type.getName().equals(text)) {
return type;
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,40 +13,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import java.util.Map;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.samples.petclinic.visit.Visit;
import org.springframework.samples.petclinic.visit.VisitRepository;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
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
* @author Ken Krebs
* @author Arjen Poutsma
* @author Michael Isvy
* @author Dave Syer
*/
@Controller
public class VisitController {
class VisitController {
private final ClinicService clinicService;
private final VisitRepository visits;
private final PetRepository pets;
@Autowired
public VisitController(ClinicService clinicService) {
this.clinicService = clinicService;
public VisitController(VisitRepository visits, PetRepository pets) {
this.visits = visits;
this.pets = pets;
}
@InitBinder
......@@ -65,34 +60,29 @@ public class VisitController {
* @return Pet
*/
@ModelAttribute("visit")
public Visit loadPetWithVisit(@PathVariable("petId") int petId) {
Pet pet = this.clinicService.findPetById(petId);
public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map<String, Object> model) {
Pet pet = this.pets.findById(petId);
model.put("pet", pet);
Visit visit = new Visit();
pet.addVisit(visit);
return visit;
}
// 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";
} else {
this.clinicService.saveVisit(visit);
this.visits.save(visit);
return "redirect:/owners/{ownerId}";
}
}
@RequestMapping(value = "/owners/*/pets/{petId}/visits", method = RequestMethod.GET)
public String showVisits(@PathVariable int petId, Map<String, Object> model) {
model.put("visits", this.clinicService.findPetById(petId).getVisits());
return "visitList";
}
}
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.service;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.DataAccessException;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.repository.OwnerRepository;
import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Mostly used as a facade for all Petclinic controllers
* Also a placeholder for @Transactional and @Cacheable annotations
*
* @author Michael Isvy
*/
@Service
public class ClinicServiceImpl implements ClinicService {
private PetRepository petRepository;
private VetRepository vetRepository;
private OwnerRepository ownerRepository;
private VisitRepository visitRepository;
@Autowired
public ClinicServiceImpl(PetRepository petRepository, VetRepository vetRepository, OwnerRepository ownerRepository, VisitRepository visitRepository) {
this.petRepository = petRepository;
this.vetRepository = vetRepository;
this.ownerRepository = ownerRepository;
this.visitRepository = visitRepository;
}
@Override
@Transactional(readOnly = true)
public Collection<PetType> findPetTypes() throws DataAccessException {
return petRepository.findPetTypes();
}
@Override
@Transactional(readOnly = true)
public Owner findOwnerById(int id) throws DataAccessException {
return ownerRepository.findById(id);
}
@Override
@Transactional(readOnly = true)
public Collection<Owner> findOwnerByLastName(String lastName) throws DataAccessException {
return ownerRepository.findByLastName(lastName);
}
@Override
@Transactional
public void saveOwner(Owner owner) throws DataAccessException {
ownerRepository.save(owner);
}
@Override
@Transactional
public void saveVisit(Visit visit) throws DataAccessException {
visitRepository.save(visit);
}
@Override
@Transactional(readOnly = true)
public Pet findPetById(int id) throws DataAccessException {
return petRepository.findById(id);
}
@Override
@Transactional
public void savePet(Pet pet) throws DataAccessException {
petRepository.save(pet);
}
@Override
@Transactional(readOnly = true)
@Cacheable(value = "vets")
public Collection<Vet> findVets() throws DataAccessException {
return vetRepository.findAll();
}
@Override
public Collection<Visit> findVisitsByPetId(int petId) {
return visitRepository.findByPetId(petId);
}
}
/*
* Copyright 2012-2019 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
*
* https://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.system;
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 javax.cache.configuration.MutableConfiguration;
/**
* Cache configuration intended for caches providing the JCache API. This configuration creates the used cache for the
* application and enables statistics that become accessible via JMX.
*/
@Configuration
@EnableCaching
class CacheConfiguration {
@Bean
public JCacheManagerCustomizer petclinicCacheConfigurationCustomizer() {
return cm -> {
cm.createCache("vets", cacheConfiguration());
};
}
/**
* Create a simple configuration that enable statistics via the JCache programmatic configuration API.
* <p>
* Within the configuration object that is provided by the JCache API standard, there is only a very limited set of
* configuration options. The really relevant configuration options (like the size limit) must be set via a
* configuration mechanism that is provided by the selected JCache implementation.
*/
private javax.cache.configuration.Configuration<Object, Object> cacheConfiguration() {
return new MutableConfiguration<>().setStatisticsEnabled(true);
}
}
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,28 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.system;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
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
*
* @author Michael Isvy
* <p/>
* Also see how the bean of type 'SimpleMappingExceptionResolver' has been declared inside
* /WEB-INF/mvc-core-config.xml
* <p/>
* Also see how a view that resolves to "error" has been added ("error.html").
*/
@Controller
public class CrashController {
class CrashController {
@RequestMapping(value = "/oups", method = RequestMethod.GET)
@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");
}
}
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -14,22 +14,17 @@
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.system;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class CustomErrorController implements ErrorController {
@RequestMapping(value = "/error")
public String error() {
return "exception";
}
class WelcomeController {
@Override
public String getErrorPath() {
return "/error";
}
@GetMapping("/")
public String welcome() {
return "welcome";
}
}
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,11 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.vet;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.springframework.samples.petclinic.model.NamedEntity;
/**
* Models a {@link Vet Vet's} specialty (for example, dentistry).
*
......@@ -25,6 +29,6 @@ import javax.persistence.Table;
*/
@Entity
@Table(name = "specialties")
public class Specialty extends NamedEntity {
public class Specialty extends NamedEntity implements Serializable {
}
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.vet;
import java.util.ArrayList;
import java.util.Collections;
......@@ -31,6 +31,7 @@ import javax.xml.bind.annotation.XmlElement;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.samples.petclinic.model.Person;
/**
* Simple JavaBean domain object representing a veterinarian.
......@@ -45,8 +46,7 @@ import org.springframework.beans.support.PropertyComparator;
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() {
......@@ -63,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);
}
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2012-2019 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
* https://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,
......@@ -13,18 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.vet;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.samples.petclinic.model.Vets;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;
/**
* @author Juergen Hoeller
* @author Mark Fisher
......@@ -32,36 +28,31 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @author Arjen Poutsma
*/
@Controller
public class VetController {
private final ClinicService clinicService;
class VetController {
private final VetRepository vets;
@Autowired
public VetController(ClinicService clinicService) {
this.clinicService = clinicService;
public VetController(VetRepository clinicService) {
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
// Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for Object-Xml mapping
Vets vets = new Vets();
vets.getVetList().addAll(this.clinicService.findVets());
vets.getVetList().addAll(this.vets.findAll());
model.put("vets", vets);
return "vets/vetList";
}
@RequestMapping(value = {"/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
@GetMapping({ "/vets" })
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
Vets vets = new Vets();
vets.getVetList().addAll(this.clinicService.findVets());
vets.getVetList().addAll(this.vets.findAll());
return vets;
}
}