mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2026-01-13 21:31:11 +00:00
SPR-6447
SPR-6448 + commit the gross of the files + added maven pom
This commit is contained in:
parent
9dd07f05f3
commit
521d01db95
117 changed files with 6945 additions and 10 deletions
|
|
@ -0,0 +1,27 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object with an id property.
|
||||
* Used as a base class for objects needing this property.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class BaseEntity {
|
||||
|
||||
private Integer id;
|
||||
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean isNew() {
|
||||
return (this.id == null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* The high-level PetClinic business interface.
|
||||
*
|
||||
* <p>This is basically a data access object.
|
||||
* PetClinic doesn't have a dedicated business facade.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public interface Clinic {
|
||||
|
||||
/**
|
||||
* Retrieve all <code>Vet</code>s from the data store.
|
||||
* @return a <code>Collection</code> of <code>Vet</code>s
|
||||
*/
|
||||
Collection<Vet> getVets() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Retrieve all <code>PetType</code>s from the data store.
|
||||
* @return a <code>Collection</code> of <code>PetType</code>s
|
||||
*/
|
||||
Collection<PetType> getPetTypes() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Retrieve <code>Owner</code>s from the data store by last name,
|
||||
* returning all owners whose last name <i>starts</i> with the given name.
|
||||
* @param lastName Value to search for
|
||||
* @return a <code>Collection</code> of matching <code>Owner</code>s
|
||||
* (or an empty <code>Collection</code> if none found)
|
||||
*/
|
||||
Collection<Owner> findOwners(String lastName) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Retrieve an <code>Owner</code> from the data store by id.
|
||||
* @param id the id to search for
|
||||
* @return the <code>Owner</code> if found
|
||||
* @throws org.springframework.dao.DataRetrievalFailureException if not found
|
||||
*/
|
||||
Owner loadOwner(int id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Retrieve a <code>Pet</code> from the data store by id.
|
||||
* @param id the id to search for
|
||||
* @return the <code>Pet</code> if found
|
||||
* @throws org.springframework.dao.DataRetrievalFailureException if not found
|
||||
*/
|
||||
Pet loadPet(int id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Save an <code>Owner</code> to the data store, either inserting or updating it.
|
||||
* @param owner the <code>Owner</code> to save
|
||||
* @see BaseEntity#isNew
|
||||
*/
|
||||
void storeOwner(Owner owner) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Save a <code>Pet</code> to the data store, either inserting or updating it.
|
||||
* @param pet the <code>Pet</code> to save
|
||||
* @see BaseEntity#isNew
|
||||
*/
|
||||
void storePet(Pet pet) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Save a <code>Visit</code> to the data store, either inserting or updating it.
|
||||
* @param visit the <code>Visit</code> to save
|
||||
* @see BaseEntity#isNew
|
||||
*/
|
||||
void storeVisit(Visit visit) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Deletes a <code>Pet</code> from the data store.
|
||||
*/
|
||||
void deletePet(int id) throws DataAccessException;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object adds a name property to <code>BaseEntity</code>.
|
||||
* Used as a base class for objects needing these properties.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class NamedEntity extends BaseEntity {
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
}
|
||||
127
src/main/java/org/springframework/samples/petclinic/Owner.java
Normal file
127
src/main/java/org/springframework/samples/petclinic/Owner.java
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.support.MutableSortDefinition;
|
||||
import org.springframework.beans.support.PropertyComparator;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing an owner.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class Owner extends Person {
|
||||
|
||||
private String address;
|
||||
|
||||
private String city;
|
||||
|
||||
private String telephone;
|
||||
|
||||
private Set<Pet> pets;
|
||||
|
||||
|
||||
public String getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return this.city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getTelephone() {
|
||||
return this.telephone;
|
||||
}
|
||||
|
||||
public void setTelephone(String telephone) {
|
||||
this.telephone = telephone;
|
||||
}
|
||||
|
||||
protected void setPetsInternal(Set<Pet> pets) {
|
||||
this.pets = pets;
|
||||
}
|
||||
|
||||
protected Set<Pet> getPetsInternal() {
|
||||
if (this.pets == null) {
|
||||
this.pets = new HashSet<Pet>();
|
||||
}
|
||||
return this.pets;
|
||||
}
|
||||
|
||||
public List<Pet> getPets() {
|
||||
List<Pet> sortedPets = new ArrayList<Pet>(getPetsInternal());
|
||||
PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true));
|
||||
return Collections.unmodifiableList(sortedPets);
|
||||
}
|
||||
|
||||
public void addPet(Pet pet) {
|
||||
getPetsInternal().add(pet);
|
||||
pet.setOwner(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Pet with the given name, or null if none found for this Owner.
|
||||
*
|
||||
* @param name to test
|
||||
* @return true if pet name is already in use
|
||||
*/
|
||||
public Pet getPet(String name) {
|
||||
return getPet(name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Pet with the given name, or null if none found for this Owner.
|
||||
*
|
||||
* @param name to test
|
||||
* @return true if pet name is already in use
|
||||
*/
|
||||
public Pet getPet(String name, boolean ignoreNew) {
|
||||
name = name.toLowerCase();
|
||||
for (Pet pet : getPetsInternal()) {
|
||||
if (!ignoreNew || !pet.isNew()) {
|
||||
String compName = pet.getName();
|
||||
compName = compName.toLowerCase();
|
||||
if (compName.equals(name)) {
|
||||
return pet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing an person.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
*/
|
||||
public class Person extends BaseEntity {
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String lastName;
|
||||
|
||||
public String getFirstName() {
|
||||
return this.firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return this.lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
77
src/main/java/org/springframework/samples/petclinic/Pet.java
Normal file
77
src/main/java/org/springframework/samples/petclinic/Pet.java
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.support.MutableSortDefinition;
|
||||
import org.springframework.beans.support.PropertyComparator;
|
||||
|
||||
/**
|
||||
* Simple JavaBean business object representing a pet.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class Pet extends NamedEntity {
|
||||
|
||||
private Date birthDate;
|
||||
|
||||
private PetType type;
|
||||
|
||||
private Owner owner;
|
||||
|
||||
private Set<Visit> visits;
|
||||
|
||||
|
||||
public void setBirthDate(Date birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public Date getBirthDate() {
|
||||
return this.birthDate;
|
||||
}
|
||||
|
||||
public void setType(PetType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public PetType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
protected void setOwner(Owner owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Owner getOwner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
protected void setVisitsInternal(Set<Visit> visits) {
|
||||
this.visits = visits;
|
||||
}
|
||||
|
||||
protected Set<Visit> getVisitsInternal() {
|
||||
if (this.visits == null) {
|
||||
this.visits = new HashSet<Visit>();
|
||||
}
|
||||
return this.visits;
|
||||
}
|
||||
|
||||
public List<Visit> getVisits() {
|
||||
List<Visit> sortedVisits = new ArrayList<Visit>(getVisitsInternal());
|
||||
PropertyComparator.sort(sortedVisits, new MutableSortDefinition("date", false, false));
|
||||
return Collections.unmodifiableList(sortedVisits);
|
||||
}
|
||||
|
||||
public void addVisit(Visit visit) {
|
||||
getVisitsInternal().add(visit);
|
||||
visit.setPet(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class PetType extends NamedEntity {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
/**
|
||||
* Models a {@link Vet Vet's} specialty (for example, dentistry).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class Specialty extends NamedEntity {
|
||||
|
||||
}
|
||||
52
src/main/java/org/springframework/samples/petclinic/Vet.java
Normal file
52
src/main/java/org/springframework/samples/petclinic/Vet.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import org.springframework.beans.support.MutableSortDefinition;
|
||||
import org.springframework.beans.support.PropertyComparator;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing a veterinarian.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class Vet extends Person {
|
||||
|
||||
private Set<Specialty> specialties;
|
||||
|
||||
|
||||
protected void setSpecialtiesInternal(Set<Specialty> specialties) {
|
||||
this.specialties = specialties;
|
||||
}
|
||||
|
||||
protected Set<Specialty> getSpecialtiesInternal() {
|
||||
if (this.specialties == null) {
|
||||
this.specialties = new HashSet<Specialty>();
|
||||
}
|
||||
return this.specialties;
|
||||
}
|
||||
|
||||
@XmlElement
|
||||
public List<Specialty> getSpecialties() {
|
||||
List<Specialty> sortedSpecs = new ArrayList<Specialty>(getSpecialtiesInternal());
|
||||
PropertyComparator.sort(sortedSpecs, new MutableSortDefinition("name", true, true));
|
||||
return Collections.unmodifiableList(sortedSpecs);
|
||||
}
|
||||
|
||||
public int getNrOfSpecialties() {
|
||||
return getSpecialtiesInternal().size();
|
||||
}
|
||||
|
||||
public void addSpecialty(Specialty specialty) {
|
||||
getSpecialtiesInternal().add(specialty);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing a list of veterinarians. Mostly here to be used for the 'vets'
|
||||
* {@link org.springframework.web.servlet.view.xml.MarshallingView}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@XmlRootElement
|
||||
public class Vets {
|
||||
|
||||
private List<Vet> vets;
|
||||
|
||||
@XmlElement
|
||||
public List<Vet> getVetList() {
|
||||
if (vets == null) {
|
||||
vets = new ArrayList<Vet>();
|
||||
}
|
||||
return vets;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing a visit.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
*/
|
||||
public class Visit extends BaseEntity {
|
||||
|
||||
/** Holds value of property date. */
|
||||
private Date date;
|
||||
|
||||
/** Holds value of property description. */
|
||||
private String description;
|
||||
|
||||
/** Holds value of property pet. */
|
||||
private Pet pet;
|
||||
|
||||
|
||||
/** Creates a new instance of Visit for the current date */
|
||||
public Visit() {
|
||||
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.
|
||||
* @return Value of property pet.
|
||||
*/
|
||||
public Pet getPet() {
|
||||
return this.pet;
|
||||
}
|
||||
|
||||
/** Setter for property pet.
|
||||
* @param pet New value of property pet.
|
||||
*/
|
||||
public void setPet(Pet pet) {
|
||||
this.pet = pet;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package org.springframework.samples.petclinic.aspects;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
|
||||
/**
|
||||
* Aspect to illustrate Spring-driven load-time weaving.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.5
|
||||
*/
|
||||
@Aspect
|
||||
public abstract class AbstractTraceAspect {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AbstractTraceAspect.class);
|
||||
|
||||
@Pointcut
|
||||
public abstract void traced();
|
||||
|
||||
@Before("traced()")
|
||||
public void trace(JoinPoint.StaticPart jpsp) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Entering " + jpsp.getSignature().toLongString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package org.springframework.samples.petclinic.aspects;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
/**
|
||||
* Simple AspectJ aspect that monitors call count and call invocation time.
|
||||
* Implements the CallMonitor management interface.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
*/
|
||||
@ManagedResource("petclinic:type=CallMonitor")
|
||||
@Aspect
|
||||
public class CallMonitoringAspect {
|
||||
|
||||
private boolean isEnabled = true;
|
||||
|
||||
private int callCount = 0;
|
||||
|
||||
private long accumulatedCallTime = 0;
|
||||
|
||||
|
||||
@ManagedAttribute
|
||||
public void setEnabled(boolean enabled) {
|
||||
isEnabled = enabled;
|
||||
}
|
||||
|
||||
@ManagedAttribute
|
||||
public boolean isEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
@ManagedOperation
|
||||
public void reset() {
|
||||
this.callCount = 0;
|
||||
this.accumulatedCallTime = 0;
|
||||
}
|
||||
|
||||
@ManagedAttribute
|
||||
public int getCallCount() {
|
||||
return callCount;
|
||||
}
|
||||
|
||||
@ManagedAttribute
|
||||
public long getCallTime() {
|
||||
return (this.callCount > 0 ? this.accumulatedCallTime / this.callCount : 0);
|
||||
}
|
||||
|
||||
|
||||
@Around("within(@org.springframework.stereotype.Service *)")
|
||||
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
if (this.isEnabled) {
|
||||
StopWatch sw = new StopWatch(joinPoint.toShortString());
|
||||
|
||||
sw.start("invoke");
|
||||
try {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
finally {
|
||||
sw.stop();
|
||||
synchronized (this) {
|
||||
this.callCount++;
|
||||
this.accumulatedCallTime += sw.getTotalTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package org.springframework.samples.petclinic.aspects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
|
||||
/**
|
||||
* Sample AspectJ annotation-style aspect that saves
|
||||
* every owner name requested to the clinic.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@Aspect
|
||||
public class UsageLogAspect {
|
||||
|
||||
private int historySize = 100;
|
||||
|
||||
// Of course saving all names is not suitable for
|
||||
// production use, but this is a simple example.
|
||||
private List<String> namesRequested = new ArrayList<String>(this.historySize);
|
||||
|
||||
|
||||
public synchronized void setHistorySize(int historySize) {
|
||||
this.historySize = historySize;
|
||||
this.namesRequested = new ArrayList<String>(historySize);
|
||||
}
|
||||
|
||||
@Before("execution(* *.findOwners(String)) && args(name)")
|
||||
public synchronized void logNameRequest(String name) {
|
||||
// Not the most efficient implementation,
|
||||
// but we're aiming to illustrate the power of
|
||||
// @AspectJ AOP, not write perfect code here :-)
|
||||
if (this.namesRequested.size() > this.historySize) {
|
||||
this.namesRequested.remove(0);
|
||||
}
|
||||
this.namesRequested.add(name);
|
||||
}
|
||||
|
||||
public synchronized List<String> getNamesRequested() {
|
||||
return Collections.unmodifiableList(this.namesRequested);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Copyright 2002-2008 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.config;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.dbcp.BasicDataSource;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* A factory that creates a data source fit for use in a system environment. Creates a DBCP simple data source
|
||||
* from the provided connection properties.
|
||||
*
|
||||
* This factory returns a fully-initialized DataSource implementation. When the DataSource is returned, callers are
|
||||
* guaranteed that the database schema and data will have been loaded by that time.
|
||||
*
|
||||
* Is a FactoryBean, for exposing the fully-initialized DataSource as a Spring bean. See {@link #getObject()}.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class DbcpDataSourceFactory implements FactoryBean<DataSource>, DisposableBean {
|
||||
|
||||
// configurable properties
|
||||
|
||||
private String driverClassName;
|
||||
|
||||
private String url;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private boolean populate;
|
||||
|
||||
private Resource schemaLocation;
|
||||
|
||||
private Resource dataLocation;
|
||||
|
||||
private Resource dropLocation;
|
||||
|
||||
/**
|
||||
* The object created by this factory.
|
||||
*/
|
||||
private BasicDataSource dataSource;
|
||||
|
||||
public void setDriverClassName(String driverClassName) {
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The data source connection URL
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* The data source username
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
*The data source password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the data base should be populated from the schema and data locations
|
||||
*/
|
||||
public void setPopulate(boolean populate) {
|
||||
this.populate = populate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location of the file containing the schema DDL to export to the database.
|
||||
* @param schemaLocation the location of the database schema DDL
|
||||
*/
|
||||
public void setSchemaLocation(Resource schemaLocation) {
|
||||
this.schemaLocation = schemaLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location of the file containing the data to load into the database.
|
||||
* @param testDataLocation the location of the data file
|
||||
*/
|
||||
public void setDataLocation(Resource testDataLocation) {
|
||||
this.dataLocation = testDataLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location of the file containing the drop scripts for the database.
|
||||
* @param testDataLocation the location of the data file
|
||||
*/
|
||||
public void setDropLocation(Resource testDropLocation) {
|
||||
this.dropLocation = testDropLocation;
|
||||
}
|
||||
|
||||
// implementing FactoryBean
|
||||
|
||||
// this method is called by Spring to expose the DataSource as a bean
|
||||
public DataSource getObject() throws Exception {
|
||||
if (dataSource == null) {
|
||||
initDataSource();
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public Class<DataSource> getObjectType() {
|
||||
return DataSource.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// implementing DisposableBean
|
||||
|
||||
public void destroy() throws Exception {
|
||||
dataSource.close();
|
||||
}
|
||||
|
||||
// internal helper methods
|
||||
|
||||
// encapsulates the steps involved in initializing the data source: creating it, and populating it
|
||||
private void initDataSource() {
|
||||
// create the database source first
|
||||
this.dataSource = createDataSource();
|
||||
|
||||
if (this.populate) {
|
||||
// now populate the database by loading the schema and data
|
||||
populateDataSource();
|
||||
}
|
||||
}
|
||||
|
||||
private BasicDataSource createDataSource() {
|
||||
BasicDataSource dataSource = new BasicDataSource();
|
||||
dataSource.setDriverClassName(this.driverClassName);
|
||||
dataSource.setUrl(this.url);
|
||||
dataSource.setUsername(this.username);
|
||||
dataSource.setPassword(this.password);
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private void populateDataSource() {
|
||||
DatabasePopulator populator = new DatabasePopulator(dataSource);
|
||||
if (dropLocation != null) {
|
||||
try {
|
||||
populator.populate(this.dropLocation);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
populator.populate(this.schemaLocation);
|
||||
populator.populate(this.dataLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a in memory data source with data.
|
||||
*/
|
||||
private class DatabasePopulator {
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
/**
|
||||
* Creates a new database populator.
|
||||
* @param dataSource the data source that will be populated.
|
||||
*/
|
||||
public DatabasePopulator(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the database executing the statements in the provided resource against the database
|
||||
* @param sqlFile spring resource containing SQL to run against the db
|
||||
*/
|
||||
public void populate(Resource sqlFile) {
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = dataSource.getConnection();
|
||||
try {
|
||||
String sql = parseSqlIn(sqlFile);
|
||||
executeSql(sql, connection);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("I/O exception occurred accessing the database schema file", e);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("SQL exception occurred exporting database schema", e);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("SQL exception occurred acquiring connection", e);
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// utility method to read a .sql txt input stream
|
||||
private String parseSqlIn(Resource resource) throws IOException {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = resource.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
BufferedWriter writer = new BufferedWriter(sw);
|
||||
|
||||
for (int c=reader.read(); c != -1; c=reader.read()) {
|
||||
writer.write(c);
|
||||
}
|
||||
writer.flush();
|
||||
return sw.toString();
|
||||
|
||||
} finally {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// utility method to run the parsed sql
|
||||
private void executeSql(String sql, Connection connection) throws SQLException {
|
||||
Statement statement = connection.createStatement();
|
||||
statement.execute(sql);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package org.springframework.samples.petclinic.hibernate;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Owner;
|
||||
import org.springframework.samples.petclinic.Pet;
|
||||
import org.springframework.samples.petclinic.PetType;
|
||||
import org.springframework.samples.petclinic.Vet;
|
||||
import org.springframework.samples.petclinic.Visit;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the Clinic interface.
|
||||
*
|
||||
* <p>The mappings are defined in "petclinic.hbm.xml", located in the root of the
|
||||
* class path.
|
||||
*
|
||||
* <p>Note that transactions are declared with annotations and that some methods
|
||||
* contain "readOnly = true" which is an optimization that is particularly
|
||||
* valuable when using Hibernate (to suppress unnecessary flush attempts for
|
||||
* read-only operations).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Mark Fisher
|
||||
* @since 19.10.2003
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public class HibernateClinic implements Clinic {
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
@Autowired
|
||||
public HibernateClinic(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<Vet> getVets() {
|
||||
return sessionFactory.getCurrentSession().createQuery("from Vet vet order by vet.lastName, vet.firstName").list();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<PetType> getPetTypes() {
|
||||
return sessionFactory.getCurrentSession().createQuery("from PetType type order by type.name").list();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<Owner> findOwners(String lastName) {
|
||||
return sessionFactory.getCurrentSession().createQuery("from Owner owner where owner.lastName like :lastName")
|
||||
.setString("lastName", lastName + "%").list();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Owner loadOwner(int id) {
|
||||
return (Owner) sessionFactory.getCurrentSession().load(Owner.class, id);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Pet loadPet(int id) {
|
||||
return (Pet) sessionFactory.getCurrentSession().load(Pet.class, id);
|
||||
}
|
||||
|
||||
public void storeOwner(Owner owner) {
|
||||
// Note: Hibernate3's merge operation does not reassociate the object
|
||||
// with the current Hibernate Session. Instead, it will always copy the
|
||||
// state over to a registered representation of the entity. In case of a
|
||||
// new entity, it will register a copy as well, but will not update the
|
||||
// id of the passed-in object. To still update the ids of the original
|
||||
// objects too, we need to register Spring's
|
||||
// IdTransferringMergeEventListener on our SessionFactory.
|
||||
sessionFactory.getCurrentSession().merge(owner);
|
||||
}
|
||||
|
||||
public void storePet(Pet pet) {
|
||||
sessionFactory.getCurrentSession().merge(pet);
|
||||
}
|
||||
|
||||
public void storeVisit(Visit visit) {
|
||||
sessionFactory.getCurrentSession().merge(visit);
|
||||
}
|
||||
|
||||
public void deletePet(int id) throws DataAccessException {
|
||||
Pet pet = loadPet(id);
|
||||
sessionFactory.getCurrentSession().delete(pet);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* The classes in this package represent the Hibernate implementation
|
||||
* of PetClinic's persistence layer.
|
||||
*
|
||||
*/
|
||||
package org.springframework.samples.petclinic.hibernate;
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package org.springframework.samples.petclinic.jdbc;
|
||||
|
||||
import org.springframework.samples.petclinic.Pet;
|
||||
|
||||
/**
|
||||
* Subclass of Pet that carries temporary id properties which
|
||||
* are only relevant for a JDBC implmentation of the Clinic.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @see SimpleJdbcClinic
|
||||
*/
|
||||
class JdbcPet extends Pet {
|
||||
|
||||
private int typeId;
|
||||
|
||||
private int ownerId;
|
||||
|
||||
|
||||
public void setTypeId(int typeId) {
|
||||
this.typeId = typeId;
|
||||
}
|
||||
|
||||
public int getTypeId() {
|
||||
return this.typeId;
|
||||
}
|
||||
|
||||
public void setOwnerId(int ownerId) {
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
public int getOwnerId() {
|
||||
return this.ownerId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,342 @@
|
|||
package org.springframework.samples.petclinic.jdbc;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Owner;
|
||||
import org.springframework.samples.petclinic.Pet;
|
||||
import org.springframework.samples.petclinic.PetType;
|
||||
import org.springframework.samples.petclinic.Specialty;
|
||||
import org.springframework.samples.petclinic.Vet;
|
||||
import org.springframework.samples.petclinic.Visit;
|
||||
import org.springframework.samples.petclinic.util.EntityUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* A simple JDBC-based implementation of the {@link Clinic} interface.
|
||||
*
|
||||
* <p>This class uses Java 5 language features and the {@link SimpleJdbcTemplate}
|
||||
* plus {@link SimpleJdbcInsert}. It also takes advantage of classes like
|
||||
* {@link BeanPropertySqlParameterSource} and
|
||||
* {@link ParameterizedBeanPropertyRowMapper} which provide automatic mapping
|
||||
* between JavaBean properties and JDBC parameters or query results.
|
||||
*
|
||||
* <p>SimpleJdbcClinic is a rewrite of the AbstractJdbcClinic which was the base
|
||||
* class for JDBC implementations of the Clinic interface for Spring 2.0.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
* @author Thomas Risberg
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Service
|
||||
@ManagedResource("petclinic:type=Clinic")
|
||||
public class SimpleJdbcClinic implements Clinic, SimpleJdbcClinicMBean {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private SimpleJdbcTemplate simpleJdbcTemplate;
|
||||
|
||||
private SimpleJdbcInsert insertOwner;
|
||||
private SimpleJdbcInsert insertPet;
|
||||
private SimpleJdbcInsert insertVisit;
|
||||
|
||||
private final List<Vet> vets = new ArrayList<Vet>();
|
||||
|
||||
|
||||
@Autowired
|
||||
public void init(DataSource dataSource) {
|
||||
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
|
||||
this.insertOwner = new SimpleJdbcInsert(dataSource)
|
||||
.withTableName("owners")
|
||||
.usingGeneratedKeyColumns("id");
|
||||
this.insertPet = new SimpleJdbcInsert(dataSource)
|
||||
.withTableName("pets")
|
||||
.usingGeneratedKeyColumns("id");
|
||||
this.insertVisit = new SimpleJdbcInsert(dataSource)
|
||||
.withTableName("visits")
|
||||
.usingGeneratedKeyColumns("id");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh the cache of Vets that the Clinic is holding.
|
||||
* @see org.springframework.samples.petclinic.Clinic#getVets()
|
||||
*/
|
||||
@ManagedOperation
|
||||
@Transactional(readOnly = true)
|
||||
public void refreshVetsCache() throws DataAccessException {
|
||||
synchronized (this.vets) {
|
||||
this.logger.info("Refreshing vets cache");
|
||||
|
||||
// Retrieve the list of all vets.
|
||||
this.vets.clear();
|
||||
this.vets.addAll(this.simpleJdbcTemplate.query(
|
||||
"SELECT id, first_name, last_name FROM vets ORDER BY last_name,first_name",
|
||||
ParameterizedBeanPropertyRowMapper.newInstance(Vet.class)));
|
||||
|
||||
// Retrieve the list of all possible specialties.
|
||||
final List<Specialty> specialties = this.simpleJdbcTemplate.query(
|
||||
"SELECT id, name FROM specialties",
|
||||
ParameterizedBeanPropertyRowMapper.newInstance(Specialty.class));
|
||||
|
||||
// Build each vet's list of specialties.
|
||||
for (Vet vet : this.vets) {
|
||||
final List<Integer> vetSpecialtiesIds = this.simpleJdbcTemplate.query(
|
||||
"SELECT specialty_id FROM vet_specialties WHERE vet_id=?",
|
||||
new ParameterizedRowMapper<Integer>() {
|
||||
public Integer mapRow(ResultSet rs, int row) throws SQLException {
|
||||
return Integer.valueOf(rs.getInt(1));
|
||||
}},
|
||||
vet.getId().intValue());
|
||||
for (int specialtyId : vetSpecialtiesIds) {
|
||||
Specialty specialty = EntityUtils.getById(specialties, Specialty.class, specialtyId);
|
||||
vet.addSpecialty(specialty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// START of Clinic implementation section *******************************
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Vet> getVets() throws DataAccessException {
|
||||
synchronized (this.vets) {
|
||||
if (this.vets.isEmpty()) {
|
||||
refreshVetsCache();
|
||||
}
|
||||
return this.vets;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<PetType> getPetTypes() throws DataAccessException {
|
||||
return this.simpleJdbcTemplate.query(
|
||||
"SELECT id, name FROM types ORDER BY name",
|
||||
ParameterizedBeanPropertyRowMapper.newInstance(PetType.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads {@link Owner Owners} from the data store by last name, returning
|
||||
* all owners whose last name <i>starts</i> with the given name; also loads
|
||||
* the {@link Pet Pets} and {@link Visit Visits} for the corresponding
|
||||
* owners, if not already loaded.
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Owner> findOwners(String lastName) throws DataAccessException {
|
||||
List<Owner> owners = this.simpleJdbcTemplate.query(
|
||||
"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE last_name like ?",
|
||||
ParameterizedBeanPropertyRowMapper.newInstance(Owner.class),
|
||||
lastName + "%");
|
||||
loadOwnersPetsAndVisits(owners);
|
||||
return owners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the {@link Owner} with the supplied <code>id</code>; also loads
|
||||
* the {@link Pet Pets} and {@link Visit Visits} for the corresponding
|
||||
* owner, if not already loaded.
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Owner loadOwner(int id) throws DataAccessException {
|
||||
Owner owner;
|
||||
try {
|
||||
owner = this.simpleJdbcTemplate.queryForObject(
|
||||
"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE id=?",
|
||||
ParameterizedBeanPropertyRowMapper.newInstance(Owner.class),
|
||||
id);
|
||||
}
|
||||
catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(Owner.class, new Integer(id));
|
||||
}
|
||||
loadPetsAndVisits(owner);
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Pet loadPet(int id) throws DataAccessException {
|
||||
JdbcPet pet;
|
||||
try {
|
||||
pet = this.simpleJdbcTemplate.queryForObject(
|
||||
"SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE id=?",
|
||||
new JdbcPetRowMapper(),
|
||||
id);
|
||||
}
|
||||
catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(Pet.class, new Integer(id));
|
||||
}
|
||||
Owner owner = loadOwner(pet.getOwnerId());
|
||||
owner.addPet(pet);
|
||||
pet.setType(EntityUtils.getById(getPetTypes(), PetType.class, pet.getTypeId()));
|
||||
loadVisits(pet);
|
||||
return pet;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void storeOwner(Owner owner) throws DataAccessException {
|
||||
if (owner.isNew()) {
|
||||
Number newKey = this.insertOwner.executeAndReturnKey(
|
||||
new BeanPropertySqlParameterSource(owner));
|
||||
owner.setId(newKey.intValue());
|
||||
}
|
||||
else {
|
||||
this.simpleJdbcTemplate.update(
|
||||
"UPDATE owners SET first_name=:firstName, last_name=:lastName, address=:address, " +
|
||||
"city=:city, telephone=:telephone WHERE id=:id",
|
||||
new BeanPropertySqlParameterSource(owner));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void storePet(Pet pet) throws DataAccessException {
|
||||
if (pet.isNew()) {
|
||||
Number newKey = this.insertPet.executeAndReturnKey(
|
||||
createPetParameterSource(pet));
|
||||
pet.setId(newKey.intValue());
|
||||
}
|
||||
else {
|
||||
this.simpleJdbcTemplate.update(
|
||||
"UPDATE pets SET name=:name, birth_date=:birth_date, type_id=:type_id, " +
|
||||
"owner_id=:owner_id WHERE id=:id",
|
||||
createPetParameterSource(pet));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void storeVisit(Visit visit) throws DataAccessException {
|
||||
if (visit.isNew()) {
|
||||
Number newKey = this.insertVisit.executeAndReturnKey(
|
||||
createVisitParameterSource(visit));
|
||||
visit.setId(newKey.intValue());
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Visit update not supported");
|
||||
}
|
||||
}
|
||||
|
||||
public void deletePet(int id) throws DataAccessException {
|
||||
this.simpleJdbcTemplate.update("DELETE FROM pets WHERE id=?", id);
|
||||
}
|
||||
|
||||
// END of Clinic implementation section ************************************
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link MapSqlParameterSource} based on data values from the
|
||||
* supplied {@link Pet} instance.
|
||||
*/
|
||||
private MapSqlParameterSource createPetParameterSource(Pet pet) {
|
||||
return new MapSqlParameterSource()
|
||||
.addValue("id", pet.getId())
|
||||
.addValue("name", pet.getName())
|
||||
.addValue("birth_date", pet.getBirthDate())
|
||||
.addValue("type_id", pet.getType().getId())
|
||||
.addValue("owner_id", pet.getOwner().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MapSqlParameterSource} based on data values from the
|
||||
* supplied {@link Visit} instance.
|
||||
*/
|
||||
private MapSqlParameterSource createVisitParameterSource(Visit visit) {
|
||||
return new MapSqlParameterSource()
|
||||
.addValue("id", visit.getId())
|
||||
.addValue("visit_date", visit.getDate())
|
||||
.addValue("description", visit.getDescription())
|
||||
.addValue("pet_id", visit.getPet().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the {@link Visit} data for the supplied {@link Pet}.
|
||||
*/
|
||||
private void loadVisits(JdbcPet pet) {
|
||||
final List<Visit> visits = this.simpleJdbcTemplate.query(
|
||||
"SELECT id, visit_date, description FROM visits WHERE pet_id=?",
|
||||
new ParameterizedRowMapper<Visit>() {
|
||||
public Visit mapRow(ResultSet rs, int row) throws SQLException {
|
||||
Visit visit = new Visit();
|
||||
visit.setId(rs.getInt("id"));
|
||||
visit.setDate(rs.getTimestamp("visit_date"));
|
||||
visit.setDescription(rs.getString("description"));
|
||||
return visit;
|
||||
}
|
||||
},
|
||||
pet.getId().intValue());
|
||||
for (Visit visit : visits) {
|
||||
pet.addVisit(visit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the {@link Pet} and {@link Visit} data for the supplied
|
||||
* {@link Owner}.
|
||||
*/
|
||||
private void loadPetsAndVisits(final Owner owner) {
|
||||
final List<JdbcPet> pets = this.simpleJdbcTemplate.query(
|
||||
"SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE owner_id=?",
|
||||
new JdbcPetRowMapper(),
|
||||
owner.getId().intValue());
|
||||
for (JdbcPet pet : pets) {
|
||||
owner.addPet(pet);
|
||||
pet.setType(EntityUtils.getById(getPetTypes(), PetType.class, pet.getTypeId()));
|
||||
loadVisits(pet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the {@link Pet} and {@link Visit} data for the supplied
|
||||
* {@link List} of {@link Owner Owners}.
|
||||
*
|
||||
* @param owners the list of owners for whom the pet and visit data should be loaded
|
||||
* @see #loadPetsAndVisits(Owner)
|
||||
*/
|
||||
private void loadOwnersPetsAndVisits(List<Owner> owners) {
|
||||
for (Owner owner : owners) {
|
||||
loadPetsAndVisits(owner);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ParameterizedRowMapper} implementation mapping data from a
|
||||
* {@link ResultSet} to the corresponding properties of the {@link JdbcPet} class.
|
||||
*/
|
||||
private class JdbcPetRowMapper implements ParameterizedRowMapper<JdbcPet> {
|
||||
|
||||
public JdbcPet mapRow(ResultSet rs, int rownum) throws SQLException {
|
||||
JdbcPet pet = new JdbcPet();
|
||||
pet.setId(rs.getInt("id"));
|
||||
pet.setName(rs.getString("name"));
|
||||
pet.setBirthDate(rs.getDate("birth_date"));
|
||||
pet.setTypeId(rs.getInt("type_id"));
|
||||
pet.setOwnerId(rs.getInt("owner_id"));
|
||||
return pet;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.springframework.samples.petclinic.jdbc;
|
||||
|
||||
/**
|
||||
* Interface that defines a cache refresh operation.
|
||||
* To be exposed for management via JMX.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @see SimpleJdbcClinic
|
||||
*/
|
||||
public interface SimpleJdbcClinicMBean {
|
||||
|
||||
/**
|
||||
* Refresh the cache of Vets that the Clinic is holding.
|
||||
* @see org.springframework.samples.petclinic.Clinic#getVets()
|
||||
* @see SimpleJdbcClinic#refreshVetsCache()
|
||||
*/
|
||||
void refreshVetsCache();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* The classes in this package represent the JDBC implementation
|
||||
* of PetClinic's persistence layer.
|
||||
*
|
||||
*/
|
||||
package org.springframework.samples.petclinic.jdbc;
|
||||
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
package org.springframework.samples.petclinic.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Owner;
|
||||
import org.springframework.samples.petclinic.Pet;
|
||||
import org.springframework.samples.petclinic.PetType;
|
||||
import org.springframework.samples.petclinic.Vet;
|
||||
import org.springframework.samples.petclinic.Visit;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* JPA implementation of the Clinic interface using EntityManager.
|
||||
*
|
||||
* <p>The mappings are defined in "orm.xml" located in the META-INF directory.
|
||||
*
|
||||
* @author Mike Keith
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @since 22.4.2006
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public class EntityManagerClinic implements Clinic {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<Vet> getVets() {
|
||||
return this.em.createQuery("SELECT vet FROM Vet vet ORDER BY vet.lastName, vet.firstName").getResultList();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<PetType> getPetTypes() {
|
||||
return this.em.createQuery("SELECT ptype FROM PetType ptype ORDER BY ptype.name").getResultList();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<Owner> findOwners(String lastName) {
|
||||
Query query = this.em.createQuery("SELECT owner FROM Owner owner WHERE owner.lastName LIKE :lastName");
|
||||
query.setParameter("lastName", lastName + "%");
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Owner loadOwner(int id) {
|
||||
return this.em.find(Owner.class, id);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Pet loadPet(int id) {
|
||||
return this.em.find(Pet.class, id);
|
||||
}
|
||||
|
||||
public void storeOwner(Owner owner) {
|
||||
// Consider returning the persistent object here, for exposing
|
||||
// a newly assigned id using any persistence provider...
|
||||
Owner merged = this.em.merge(owner);
|
||||
this.em.flush();
|
||||
owner.setId(merged.getId());
|
||||
}
|
||||
|
||||
public void storePet(Pet pet) {
|
||||
// Consider returning the persistent object here, for exposing
|
||||
// a newly assigned id using any persistence provider...
|
||||
Pet merged = this.em.merge(pet);
|
||||
this.em.flush();
|
||||
pet.setId(merged.getId());
|
||||
}
|
||||
|
||||
public void storeVisit(Visit visit) {
|
||||
// Consider returning the persistent object here, for exposing
|
||||
// a newly assigned id using any persistence provider...
|
||||
Visit merged = this.em.merge(visit);
|
||||
this.em.flush();
|
||||
visit.setId(merged.getId());
|
||||
}
|
||||
|
||||
public void deletePet(int id) throws DataAccessException {
|
||||
Pet pet = loadPet(id);
|
||||
this.em.remove(pet);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* The classes in this package represent the JPA implementation
|
||||
* of PetClinic's persistence layer.
|
||||
*
|
||||
*/
|
||||
package org.springframework.samples.petclinic.jpa;
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* The classes in this package represent PetClinic's business layer.
|
||||
*
|
||||
*/
|
||||
package org.springframework.samples.petclinic;
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package org.springframework.samples.petclinic.toplink;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import oracle.toplink.essentials.exceptions.ValidationException;
|
||||
import oracle.toplink.essentials.platform.database.HSQLPlatform;
|
||||
import oracle.toplink.essentials.queryframework.ValueReadQuery;
|
||||
|
||||
/**
|
||||
* Subclass of the TopLink Essentials default HSQLPlatform class, using native
|
||||
* HSQLDB identity columns for id generation.
|
||||
*
|
||||
* <p>Necessary for PetClinic's default data model, which relies on identity
|
||||
* columns: this is uniformly used across all persistence layer implementations
|
||||
* (JDBC, Hibernate, and JPA).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author <a href="mailto:james.x.clark@oracle.com">James Clark</a>
|
||||
* @since 1.2
|
||||
*/
|
||||
public class EssentialsHSQLPlatformWithNativeSequence extends HSQLPlatform {
|
||||
|
||||
private static final long serialVersionUID = -55658009691346735L;
|
||||
|
||||
|
||||
public EssentialsHSQLPlatformWithNativeSequence() {
|
||||
// setUsesNativeSequencing(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNativeSequenceNumbers() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldNativeSequenceAcquireValueAfterInsert() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueReadQuery buildSelectQueryForNativeSequence() {
|
||||
return new ValueReadQuery("CALL IDENTITY()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printFieldIdentityClause(Writer writer) throws ValidationException {
|
||||
try {
|
||||
writer.write(" IDENTITY");
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw ValidationException.fileError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* The classes in this package provide support for using the TopLink
|
||||
* implementation with PetClinic's EntityManagerClinic.
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.springframework.samples.petclinic.toplink;
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
package org.springframework.samples.petclinic.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.BaseEntity;
|
||||
|
||||
/**
|
||||
* Utility methods for handling entities. Separate from the BaseEntity class
|
||||
* mainly because of dependency on the ORM-associated
|
||||
* ObjectRetrievalFailureException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 29.10.2003
|
||||
* @see org.springframework.samples.petclinic.BaseEntity
|
||||
*/
|
||||
public abstract class EntityUtils {
|
||||
|
||||
/**
|
||||
* Look up the entity of the given class with the given id in the given
|
||||
* collection.
|
||||
*
|
||||
* @param entities the collection to search
|
||||
* @param entityClass the entity class to look up
|
||||
* @param entityId the entity id to look up
|
||||
* @return the found entity
|
||||
* @throws ObjectRetrievalFailureException if the entity was not found
|
||||
*/
|
||||
public static <T extends BaseEntity> T getById(Collection<T> entities, Class<T> entityClass, int entityId)
|
||||
throws ObjectRetrievalFailureException {
|
||||
for (T entity : entities) {
|
||||
if (entity.getId().intValue() == entityId && entityClass.isInstance(entity)) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
throw new ObjectRetrievalFailureException(entityClass, new Integer(entityId));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.springframework.samples.petclinic.validation;
|
||||
|
||||
import org.springframework.samples.petclinic.Owner;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.Errors;
|
||||
|
||||
/**
|
||||
* <code>Validator</code> for <code>Owner</code> forms.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class OwnerValidator {
|
||||
|
||||
public void validate(Owner owner, Errors errors) {
|
||||
if (!StringUtils.hasLength(owner.getFirstName())) {
|
||||
errors.rejectValue("firstName", "required", "required");
|
||||
}
|
||||
if (!StringUtils.hasLength(owner.getLastName())) {
|
||||
errors.rejectValue("lastName", "required", "required");
|
||||
}
|
||||
if (!StringUtils.hasLength(owner.getAddress())) {
|
||||
errors.rejectValue("address", "required", "required");
|
||||
}
|
||||
if (!StringUtils.hasLength(owner.getCity())) {
|
||||
errors.rejectValue("city", "required", "required");
|
||||
}
|
||||
|
||||
String telephone = owner.getTelephone();
|
||||
if (!StringUtils.hasLength(telephone)) {
|
||||
errors.rejectValue("telephone", "required", "required");
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < telephone.length(); ++i) {
|
||||
if ((Character.isDigit(telephone.charAt(i))) == false) {
|
||||
errors.rejectValue("telephone", "nonNumeric", "non-numeric");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package org.springframework.samples.petclinic.validation;
|
||||
|
||||
import org.springframework.samples.petclinic.Pet;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.Errors;
|
||||
|
||||
/**
|
||||
* <code>Validator</code> for <code>Pet</code> forms.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class PetValidator {
|
||||
|
||||
public void validate(Pet pet, Errors errors) {
|
||||
String name = pet.getName();
|
||||
if (!StringUtils.hasLength(name)) {
|
||||
errors.rejectValue("name", "required", "required");
|
||||
}
|
||||
else if (pet.isNew() && pet.getOwner().getPet(name, true) != null) {
|
||||
errors.rejectValue("name", "duplicate", "already exists");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package org.springframework.samples.petclinic.validation;
|
||||
|
||||
import org.springframework.samples.petclinic.Visit;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.Errors;
|
||||
|
||||
/**
|
||||
* <code>Validator</code> for <code>Visit</code> forms.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class VisitValidator {
|
||||
|
||||
public void validate(Visit visit, Errors errors) {
|
||||
if (!StringUtils.hasLength(visit.getDescription())) {
|
||||
errors.rejectValue("description", "required", "required");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* The classes in this package represent the set of Validator objects
|
||||
* the Business Layer makes available to the Presentation Layer.
|
||||
*
|
||||
*/
|
||||
package org.springframework.samples.petclinic.validation;
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Owner;
|
||||
import org.springframework.samples.petclinic.validation.OwnerValidator;
|
||||
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.InitBinder;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
|
||||
/**
|
||||
* JavaBean form controller that is used to add a new <code>Owner</code> to the
|
||||
* system.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Ken Krebs
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/owners/new")
|
||||
@SessionAttributes(types = Owner.class)
|
||||
public class AddOwnerForm {
|
||||
|
||||
private final Clinic clinic;
|
||||
|
||||
|
||||
@Autowired
|
||||
public AddOwnerForm(Clinic clinic) {
|
||||
this.clinic = clinic;
|
||||
}
|
||||
|
||||
@InitBinder
|
||||
public void setAllowedFields(WebDataBinder dataBinder) {
|
||||
dataBinder.setDisallowedFields("id");
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public String setupForm(Model model) {
|
||||
Owner owner = new Owner();
|
||||
model.addAttribute(owner);
|
||||
return "owners/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public String processSubmit(@ModelAttribute Owner owner, BindingResult result, SessionStatus status) {
|
||||
new OwnerValidator().validate(owner, result);
|
||||
if (result.hasErrors()) {
|
||||
return "owners/form";
|
||||
}
|
||||
else {
|
||||
this.clinic.storeOwner(owner);
|
||||
status.setComplete();
|
||||
return "redirect:/owners/" + owner.getId();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
|
||||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Owner;
|
||||
import org.springframework.samples.petclinic.Pet;
|
||||
import org.springframework.samples.petclinic.PetType;
|
||||
import org.springframework.samples.petclinic.validation.PetValidator;
|
||||
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.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.SessionAttributes;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
|
||||
/**
|
||||
* JavaBean form controller that is used to add a new <code>Pet</code> to the
|
||||
* system.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Ken Krebs
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/owners/{ownerId}/pets/new")
|
||||
@SessionAttributes("pet")
|
||||
public class AddPetForm {
|
||||
|
||||
private final Clinic clinic;
|
||||
|
||||
|
||||
@Autowired
|
||||
public AddPetForm(Clinic clinic) {
|
||||
this.clinic = clinic;
|
||||
}
|
||||
|
||||
@ModelAttribute("types")
|
||||
public Collection<PetType> populatePetTypes() {
|
||||
return this.clinic.getPetTypes();
|
||||
}
|
||||
|
||||
@InitBinder
|
||||
public void setAllowedFields(WebDataBinder dataBinder) {
|
||||
dataBinder.setDisallowedFields("id");
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public String setupForm(@PathVariable("ownerId") int ownerId, Model model) {
|
||||
Owner owner = this.clinic.loadOwner(ownerId);
|
||||
Pet pet = new Pet();
|
||||
owner.addPet(pet);
|
||||
model.addAttribute("pet", pet);
|
||||
return "pets/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
|
||||
new PetValidator().validate(pet, result);
|
||||
if (result.hasErrors()) {
|
||||
return "pets/form";
|
||||
}
|
||||
else {
|
||||
this.clinic.storePet(pet);
|
||||
status.setComplete();
|
||||
return "redirect:/owners/" + pet.getOwner().getId();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Pet;
|
||||
import org.springframework.samples.petclinic.Visit;
|
||||
import org.springframework.samples.petclinic.validation.VisitValidator;
|
||||
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.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.SessionAttributes;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
|
||||
/**
|
||||
* JavaBean form controller that is used to add a new <code>Visit</code> to the
|
||||
* system.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Ken Krebs
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/owners/*/pets/{petId}/visits/new")
|
||||
@SessionAttributes("visit")
|
||||
public class AddVisitForm {
|
||||
|
||||
private final Clinic clinic;
|
||||
|
||||
|
||||
@Autowired
|
||||
public AddVisitForm(Clinic clinic) {
|
||||
this.clinic = clinic;
|
||||
}
|
||||
|
||||
@InitBinder
|
||||
public void setAllowedFields(WebDataBinder dataBinder) {
|
||||
dataBinder.setDisallowedFields("id");
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public String setupForm(@PathVariable("petId") int petId, Model model) {
|
||||
Pet pet = this.clinic.loadPet(petId);
|
||||
Visit visit = new Visit();
|
||||
pet.addVisit(visit);
|
||||
model.addAttribute("visit", visit);
|
||||
return "pets/visitForm";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public String processSubmit(@ModelAttribute("visit") Visit visit, BindingResult result, SessionStatus status) {
|
||||
new VisitValidator().validate(visit, result);
|
||||
if (result.hasErrors()) {
|
||||
return "pets/visitForm";
|
||||
}
|
||||
else {
|
||||
this.clinic.storeVisit(visit);
|
||||
status.setComplete();
|
||||
return "redirect:/owners/" + visit.getPet().getOwner().getId();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.PetType;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.support.WebBindingInitializer;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
/**
|
||||
* Shared WebBindingInitializer for PetClinic's custom editors.
|
||||
*
|
||||
* <p>Alternatively, such init-binder code may be put into
|
||||
* {@link org.springframework.web.bind.annotation.InitBinder}
|
||||
* annotated methods on the controller classes themselves.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class ClinicBindingInitializer implements WebBindingInitializer {
|
||||
|
||||
@Autowired
|
||||
private Clinic clinic;
|
||||
|
||||
public void initBinder(WebDataBinder binder, WebRequest request) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
dateFormat.setLenient(false);
|
||||
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
|
||||
binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
|
||||
binder.registerCustomEditor(PetType.class, new PetTypeEditor(this.clinic));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Vets;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
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.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Annotation-driven <em>MultiActionController</em> that handles all non-form
|
||||
* URL's.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @author Ken Krebs
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Controller
|
||||
public class ClinicController {
|
||||
|
||||
private final Clinic clinic;
|
||||
|
||||
|
||||
@Autowired
|
||||
public ClinicController(Clinic clinic) {
|
||||
this.clinic = clinic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom handler for the welcome view.
|
||||
* <p>
|
||||
* Note that this handler relies on the RequestToViewNameTranslator to
|
||||
* determine the logical view name based on the request URL: "/welcome.do"
|
||||
* -> "welcome".
|
||||
*/
|
||||
@RequestMapping("/")
|
||||
public String welcomeHandler() {
|
||||
return "welcome";
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom handler for displaying vets.
|
||||
*
|
||||
* <p>Note that this handler returns a plain {@link ModelMap} object instead of
|
||||
* a ModelAndView, thus leveraging convention-based model attribute names.
|
||||
* It relies on the RequestToViewNameTranslator to determine the logical
|
||||
* view name based on the request URL: "/vets.do" -> "vets".
|
||||
*
|
||||
* @return a ModelMap with the model attributes for the view
|
||||
*/
|
||||
@RequestMapping("/vets")
|
||||
public ModelMap vetsHandler() {
|
||||
Vets vets = new Vets();
|
||||
vets.getVetList().addAll(this.clinic.getVets());
|
||||
return new ModelMap(vets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom handler for displaying an owner.
|
||||
*
|
||||
* @param ownerId the ID of the owner to display
|
||||
* @return a ModelMap with the model attributes for the view
|
||||
*/
|
||||
@RequestMapping("/owners/{ownerId}")
|
||||
public ModelAndView ownerHandler(@PathVariable("ownerId") int ownerId) {
|
||||
ModelAndView mav = new ModelAndView("owners/show");
|
||||
mav.addObject(this.clinic.loadOwner(ownerId));
|
||||
return mav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom handler for displaying an list of visits.
|
||||
*
|
||||
* @param petId the ID of the pet whose visits to display
|
||||
* @return a ModelMap with the model attributes for the view
|
||||
*/
|
||||
@RequestMapping(value="/owners/*/pets/{petId}/visits", method=RequestMethod.GET)
|
||||
public ModelAndView visitsHandler(@PathVariable int petId) {
|
||||
ModelAndView mav = new ModelAndView("visits");
|
||||
mav.addObject("visits", this.clinic.loadPet(petId).getVisits());
|
||||
return mav;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Owner;
|
||||
import org.springframework.samples.petclinic.validation.OwnerValidator;
|
||||
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.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.SessionAttributes;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
|
||||
/**
|
||||
* JavaBean Form controller that is used to edit an existing <code>Owner</code>.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Ken Krebs
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/owners/{ownerId}/edit")
|
||||
@SessionAttributes(types = Owner.class)
|
||||
public class EditOwnerForm {
|
||||
|
||||
private final Clinic clinic;
|
||||
|
||||
|
||||
@Autowired
|
||||
public EditOwnerForm(Clinic clinic) {
|
||||
this.clinic = clinic;
|
||||
}
|
||||
|
||||
@InitBinder
|
||||
public void setAllowedFields(WebDataBinder dataBinder) {
|
||||
dataBinder.setDisallowedFields("id");
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public String setupForm(@PathVariable("ownerId") int ownerId, Model model) {
|
||||
Owner owner = this.clinic.loadOwner(ownerId);
|
||||
model.addAttribute(owner);
|
||||
return "owners/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.PUT)
|
||||
public String processSubmit(@ModelAttribute Owner owner, BindingResult result, SessionStatus status) {
|
||||
new OwnerValidator().validate(owner, result);
|
||||
if (result.hasErrors()) {
|
||||
return "owners/form";
|
||||
}
|
||||
else {
|
||||
this.clinic.storeOwner(owner);
|
||||
status.setComplete();
|
||||
return "redirect:/owners/" + owner.getId();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
|
||||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Pet;
|
||||
import org.springframework.samples.petclinic.PetType;
|
||||
import org.springframework.samples.petclinic.validation.PetValidator;
|
||||
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.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.SessionAttributes;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
|
||||
/**
|
||||
* JavaBean Form controller that is used to edit an existing <code>Pet</code>.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Ken Krebs
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/owners/*/pets/{petId}/edit")
|
||||
@SessionAttributes("pet")
|
||||
public class EditPetForm {
|
||||
|
||||
private final Clinic clinic;
|
||||
|
||||
|
||||
@Autowired
|
||||
public EditPetForm(Clinic clinic) {
|
||||
this.clinic = clinic;
|
||||
}
|
||||
|
||||
@ModelAttribute("types")
|
||||
public Collection<PetType> populatePetTypes() {
|
||||
return this.clinic.getPetTypes();
|
||||
}
|
||||
|
||||
@InitBinder
|
||||
public void setAllowedFields(WebDataBinder dataBinder) {
|
||||
dataBinder.setDisallowedFields("id");
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public String setupForm(@PathVariable("petId") int petId, Model model) {
|
||||
Pet pet = this.clinic.loadPet(petId);
|
||||
model.addAttribute("pet", pet);
|
||||
return "pets/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = { RequestMethod.PUT, RequestMethod.POST })
|
||||
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
|
||||
new PetValidator().validate(pet, result);
|
||||
if (result.hasErrors()) {
|
||||
return "pets/form";
|
||||
}
|
||||
else {
|
||||
this.clinic.storePet(pet);
|
||||
status.setComplete();
|
||||
return "redirect:/owners/" + pet.getOwner().getId();
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.DELETE)
|
||||
public String deletePet(@PathVariable int petId) {
|
||||
Pet pet = this.clinic.loadPet(petId);
|
||||
this.clinic.deletePet(petId);
|
||||
return "redirect:/owners/" + pet.getOwner().getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Owner;
|
||||
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.InitBinder;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
/**
|
||||
* JavaBean Form controller that is used to search for <code>Owner</code>s by
|
||||
* last name.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Ken Krebs
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Controller
|
||||
public class FindOwnersForm {
|
||||
|
||||
private final Clinic clinic;
|
||||
|
||||
|
||||
@Autowired
|
||||
public FindOwnersForm(Clinic clinic) {
|
||||
this.clinic = clinic;
|
||||
}
|
||||
|
||||
@InitBinder
|
||||
public void setAllowedFields(WebDataBinder dataBinder) {
|
||||
dataBinder.setDisallowedFields("id");
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/owners/search", method = RequestMethod.GET)
|
||||
public String setupForm(Model model) {
|
||||
model.addAttribute("owner", new Owner());
|
||||
return "owners/search";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/owners", method = RequestMethod.GET)
|
||||
public String processSubmit(Owner owner, BindingResult result, Model model) {
|
||||
|
||||
// allow parameterless GET request for /owners to return all records
|
||||
if (owner.getLastName() == null) {
|
||||
owner.setLastName(""); // empty string signifies broadest possible search
|
||||
}
|
||||
|
||||
// find owners by last name
|
||||
Collection<Owner> results = this.clinic.findOwners(owner.getLastName());
|
||||
if (results.size() < 1) {
|
||||
// no owners found
|
||||
result.rejectValue("lastName", "notFound", "not found");
|
||||
return "owners/search";
|
||||
}
|
||||
if (results.size() > 1) {
|
||||
// multiple owners found
|
||||
model.addAttribute("selections", results);
|
||||
return "owners/list";
|
||||
}
|
||||
else {
|
||||
// 1 owner found
|
||||
owner = results.iterator().next();
|
||||
return "redirect:/owners/" + owner.getId();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.PetType;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class PetTypeEditor extends PropertyEditorSupport {
|
||||
|
||||
private final Clinic clinic;
|
||||
|
||||
|
||||
public PetTypeEditor(Clinic clinic) {
|
||||
this.clinic = clinic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
for (PetType type : this.clinic.getPetTypes()) {
|
||||
if (type.getName().equals(text)) {
|
||||
setValue(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2002-2009 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.web;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.sun.syndication.feed.atom.Content;
|
||||
import com.sun.syndication.feed.atom.Entry;
|
||||
import com.sun.syndication.feed.atom.Feed;
|
||||
|
||||
import org.springframework.samples.petclinic.Visit;
|
||||
import org.springframework.web.servlet.view.feed.AbstractAtomFeedView;
|
||||
|
||||
/**
|
||||
* A view creating a Atom representation from a list of Visit objects.
|
||||
*
|
||||
* @author Alef Arendsen
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class VisitsAtomView extends AbstractAtomFeedView {
|
||||
|
||||
@Override
|
||||
protected void buildFeedMetadata(Map<String, Object> model, Feed feed, HttpServletRequest request) {
|
||||
feed.setId("tag:springsource.com");
|
||||
feed.setTitle("Pet Clinic Visits");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Visit> visits = (List<Visit>) model.get("visits");
|
||||
for (Visit visit : visits) {
|
||||
Date date = visit.getDate();
|
||||
if (feed.getUpdated() == null || date.compareTo(feed.getUpdated()) > 0) {
|
||||
feed.setUpdated(date);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Entry> buildFeedEntries(Map<String, Object> model,
|
||||
HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Visit> visits = (List<Visit>) model.get("visits");
|
||||
List<Entry> entries = new ArrayList<Entry>(visits.size());
|
||||
|
||||
for (Visit visit : visits) {
|
||||
Entry entry = new Entry();
|
||||
String date = String.format("%1$tY-%1$tm-%1$td", visit.getDate());
|
||||
// see http://diveintomark.org/archives/2004/05/28/howto-atom-id#other
|
||||
entry.setId(String.format("tag:springsource.com,%s:%d", date, visit.getId()));
|
||||
entry.setTitle(String.format("%s visit on %s", visit.getPet().getName(), date));
|
||||
entry.setUpdated(visit.getDate());
|
||||
|
||||
Content summary = new Content();
|
||||
summary.setValue(visit.getDescription());
|
||||
entry.setSummary(summary);
|
||||
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
return entries;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* The classes in this package represent PetClinic's web presentation layer.
|
||||
*
|
||||
*/
|
||||
package org.springframework.samples.petclinic.web;
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue