Added petclinic sample
This commit is contained in:
		
							parent
							
								
									68dfd9efe8
								
							
						
					
					
						commit
						9d3cb3a47e
					
				|  | @ -0,0 +1,5 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project name="org.springframework.samples.petclinic"> | ||||||
|  | 	<property file="${basedir}/../build.properties"/> | ||||||
|  | 	<import file="${basedir}/../spring-build/war/default.xml"/> | ||||||
|  | </project> | ||||||
|  | @ -0,0 +1,42 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?> | ||||||
|  | <ivy-module | ||||||
|  | 		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 		xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd" | ||||||
|  | 		version="1.3"> | ||||||
|  | 
 | ||||||
|  | 	<info organisation="org.springframework" module="${ant.project.name}"> | ||||||
|  | 		<license name="Apache 2.0" url="http://www.apache.org/licenses/LICENSE-2.0"/> | ||||||
|  | 	</info> | ||||||
|  | 
 | ||||||
|  | 	<configurations> | ||||||
|  | 		<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/> | ||||||
|  | 		<conf name="hibernate" extends="runtime" description="JARs needed to use Hibernate"/> | ||||||
|  | 		<conf name="jpa" extends="runtime" description="JARs needed to develop JPA beans"/> | ||||||
|  | 		<conf name="toplink-essentials" extends="jpa" description="JARs needed to use TopLink Essentials JPA"/> | ||||||
|  | 	</configurations> | ||||||
|  | 
 | ||||||
|  | 	<publications> | ||||||
|  | 		<artifact name="${ant.project.name}" type="war" ext="war"/> | ||||||
|  | 		<artifact name="${ant.project.name}-sources" type="src" ext="jar"/> | ||||||
|  | 	</publications> | ||||||
|  | 
 | ||||||
|  | 	<dependencies> | ||||||
|  | 		<dependency org="com.oracle.toplink.essentials" name="com.springsource.oracle.toplink.essentials" rev="2.0.0.b41-beta2" conf="optional, toplink-essentials->compile"/> | ||||||
|  | 		<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="provided, jpa->compile"/> | ||||||
|  | 		<dependency org="javax.servlet" name="com.springsource.javax.servlet" rev="2.4.0" conf="compile->compile"/> | ||||||
|  | 		<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->compile"/> | ||||||
|  | 		<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="compile->compile"/> | ||||||
|  | 		<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="1.5.4" conf="compile->compile"/> | ||||||
|  | 		<dependency org="org.hibernate" name="com.springsource.org.hibernate" rev="3.2.6.ga" conf="optional, hibernate->compile"/> | ||||||
|  | 		<dependency org="org.springframework" name="org.springframework.orm" rev="latest.integration" conf="compile->compile"/> | ||||||
|  | 		<dependency org="org.springframework" name="org.springframework.web.servlet" rev="latest.integration" conf="compile->compile"/> | ||||||
|  | 		<!-- test dependencies --> | ||||||
|  | 		<dependency org="org.junit" name="com.springsource.org.junit" rev="4.4.0" conf="test->runtime" /> | ||||||
|  | 		<dependency org="org.springframework" name="org.springframework.test" rev="latest.integration" conf="test->compile"/> | ||||||
|  | 		<dependency org="org.objectweb.asm" name="com.springsource.org.objectweb.asm" rev="2.2.3" conf="test->compile" /> | ||||||
|  | 		<dependency org="org.objectweb.asm" name="com.springsource.org.objectweb.asm.commons" rev="2.2.3" conf="test->compile" /> | ||||||
|  | 
 | ||||||
|  | 	</dependencies> | ||||||
|  | 
 | ||||||
|  | </ivy-module> | ||||||
|  | @ -0,0 +1,141 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <module relativePaths="true" type="JAVA_MODULE" version="4"> | ||||||
|  |   <component name="FacetManager"> | ||||||
|  |     <facet type="web" name="Web"> | ||||||
|  |       <configuration> | ||||||
|  |         <descriptors> | ||||||
|  |           <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/web/WEB-INF/web.xml" optional="false" version="2.5" /> | ||||||
|  |         </descriptors> | ||||||
|  |         <webroots> | ||||||
|  |           <root url="file://$MODULE_DIR$/web" relative="/" /> | ||||||
|  |         </webroots> | ||||||
|  |         <building> | ||||||
|  |           <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../out/exploded/petclinicWeb" /> | ||||||
|  |           <setting name="EXPLODED_ENABLED" value="true" /> | ||||||
|  |           <setting name="JAR_URL" value="file://" /> | ||||||
|  |           <setting name="JAR_ENABLED" value="false" /> | ||||||
|  |           <setting name="EXCLUDE_EXPLODED_DIRECTORY" value="true" /> | ||||||
|  |         </building> | ||||||
|  |         <packaging> | ||||||
|  |           <containerElement type="module" name="petclinic"> | ||||||
|  |             <attribute name="method" value="1" /> | ||||||
|  |             <attribute name="URI" value="/WEB-INF/classes" /> | ||||||
|  |           </containerElement> | ||||||
|  |         </packaging> | ||||||
|  |       </configuration> | ||||||
|  |     </facet> | ||||||
|  |     <facet type="web" name="Web2"> | ||||||
|  |       <configuration> | ||||||
|  |         <descriptors> | ||||||
|  |           <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml" optional="false" version="2.5" /> | ||||||
|  |         </descriptors> | ||||||
|  |         <webroots> | ||||||
|  |           <root url="file://$MODULE_DIR$/src/main/webapp" relative="/" /> | ||||||
|  |         </webroots> | ||||||
|  |         <building> | ||||||
|  |           <setting name="EXPLODED_URL" value="file://" /> | ||||||
|  |           <setting name="EXPLODED_ENABLED" value="false" /> | ||||||
|  |           <setting name="JAR_URL" value="file://" /> | ||||||
|  |           <setting name="JAR_ENABLED" value="false" /> | ||||||
|  |           <setting name="EXCLUDE_EXPLODED_DIRECTORY" value="true" /> | ||||||
|  |         </building> | ||||||
|  |         <packaging> | ||||||
|  |           <containerElement type="module" name="petclinic"> | ||||||
|  |             <attribute name="method" value="1" /> | ||||||
|  |             <attribute name="URI" value="/WEB-INF/classes" /> | ||||||
|  |           </containerElement> | ||||||
|  |         </packaging> | ||||||
|  |       </configuration> | ||||||
|  |     </facet> | ||||||
|  |     <facet type="jpa" name="JPA"> | ||||||
|  |       <configuration> | ||||||
|  |         <setting name="validation-enabled" value="true" /> | ||||||
|  |         <setting name="provider-name" value="" /> | ||||||
|  |         <setting name="targe-facet" value="" /> | ||||||
|  |         <datasource-mapping /> | ||||||
|  |         <deploymentDescriptor name="persistence.xml" url="file://$MODULE_DIR$/src/main/resources/META-INF/persistence.xml" optional="false" version="1.0" /> | ||||||
|  |       </configuration> | ||||||
|  |     </facet> | ||||||
|  |   </component> | ||||||
|  |   <component name="NewModuleRootManager" inherit-compiler-output="true"> | ||||||
|  |     <exclude-output /> | ||||||
|  |     <content url="file://$MODULE_DIR$"> | ||||||
|  |       <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> | ||||||
|  |       <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="false" /> | ||||||
|  |     </content> | ||||||
|  |     <orderEntry type="inheritedJdk" /> | ||||||
|  |     <orderEntry type="sourceFolder" forTests="false" /> | ||||||
|  |     <orderEntry type="module-library"> | ||||||
|  |       <library> | ||||||
|  |         <CLASSES> | ||||||
|  |           <root url="jar://$APPLICATION_HOME_DIR$/lib/javaee.jar!/" /> | ||||||
|  |         </CLASSES> | ||||||
|  |         <JAVADOC /> | ||||||
|  |         <SOURCES /> | ||||||
|  |       </library> | ||||||
|  |     </orderEntry> | ||||||
|  |     <orderEntry type="module" module-name="web-servlet" /> | ||||||
|  |     <orderEntry type="module" module-name="web" /> | ||||||
|  |     <orderEntry type="module" module-name="beans" /> | ||||||
|  |     <orderEntry type="module" module-name="transaction" /> | ||||||
|  |     <orderEntry type="module" module-name="core" /> | ||||||
|  |     <orderEntry type="module" module-name="context" /> | ||||||
|  |     <orderEntry type="module" module-name="jdbc" /> | ||||||
|  |     <orderEntry type="module" module-name="test" /> | ||||||
|  |     <orderEntry type="module-library"> | ||||||
|  |       <library> | ||||||
|  |         <CLASSES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/org.junit/com.springsource.org.junit/4.4.0/com.springsource.org.junit-4.4.0.jar!/" /> | ||||||
|  |         </CLASSES> | ||||||
|  |         <JAVADOC /> | ||||||
|  |         <SOURCES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/org.junit/com.springsource.org.junit/4.4.0/com.springsource.org.junit-sources-4.4.0.jar!/" /> | ||||||
|  |         </SOURCES> | ||||||
|  |       </library> | ||||||
|  |     </orderEntry> | ||||||
|  |     <orderEntry type="module-library"> | ||||||
|  |       <library> | ||||||
|  |         <CLASSES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar!/" /> | ||||||
|  |         </CLASSES> | ||||||
|  |         <JAVADOC /> | ||||||
|  |         <SOURCES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar!/" /> | ||||||
|  |         </SOURCES> | ||||||
|  |       </library> | ||||||
|  |     </orderEntry> | ||||||
|  |     <orderEntry type="module" module-name="orm" /> | ||||||
|  |     <orderEntry type="module-library"> | ||||||
|  |       <library> | ||||||
|  |         <CLASSES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/org.aspectj/com.springsource.org.aspectj.weaver/1.5.4/com.springsource.org.aspectj.weaver-1.5.4.jar!/" /> | ||||||
|  |         </CLASSES> | ||||||
|  |         <JAVADOC /> | ||||||
|  |         <SOURCES /> | ||||||
|  |       </library> | ||||||
|  |     </orderEntry> | ||||||
|  |     <orderEntry type="module-library"> | ||||||
|  |       <library> | ||||||
|  |         <CLASSES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/com.oracle.toplink.essentials/com.springsource.oracle.toplink.essentials/2.0.0.b41-beta2/com.springsource.oracle.toplink.essentials-2.0.0.b41-beta2.jar!/" /> | ||||||
|  |         </CLASSES> | ||||||
|  |         <JAVADOC /> | ||||||
|  |         <SOURCES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/com.oracle.toplink.essentials/com.springsource.oracle.toplink.essentials/2.0.0.b41-beta2/com.springsource.oracle.toplink.essentials-sources-2.0.0.b41-beta2.jar!/" /> | ||||||
|  |         </SOURCES> | ||||||
|  |       </library> | ||||||
|  |     </orderEntry> | ||||||
|  |     <orderEntry type="module-library"> | ||||||
|  |       <library> | ||||||
|  |         <CLASSES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/org.hibernate/com.springsource.org.hibernate/3.2.6.ga/com.springsource.org.hibernate-3.2.6.ga.jar!/" /> | ||||||
|  |         </CLASSES> | ||||||
|  |         <JAVADOC /> | ||||||
|  |         <SOURCES> | ||||||
|  |           <root url="jar://$IVY_CACHE$/org.hibernate/com.springsource.org.hibernate/3.2.6.ga/com.springsource.org.hibernate-sources-3.2.6.ga.jar!/" /> | ||||||
|  |         </SOURCES> | ||||||
|  |       </library> | ||||||
|  |     </orderEntry> | ||||||
|  |   </component> | ||||||
|  | </module> | ||||||
|  | 
 | ||||||
|  | @ -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,77 @@ | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -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(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -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; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -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 { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,49 @@ | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Simple JavaBean domain object representing a veterinarian. | ||||||
|  |  * | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Sam Brannen | ||||||
|  |  */ | ||||||
|  | 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; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	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,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. | ||||||
|  | 	 */ | ||||||
|  | 	protected 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,89 @@ | ||||||
|  | package org.springframework.samples.petclinic.hibernate; | ||||||
|  | 
 | ||||||
|  | import java.util.Collection; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.SessionFactory; | ||||||
|  | 
 | ||||||
|  | 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.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 { | ||||||
|  | 
 | ||||||
|  | 	@Autowired | ||||||
|  | 	private 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); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | The classes in this package represent the Hibernate implementation | ||||||
|  | of PetClinic's persistence layer. | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -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,338 @@ | ||||||
|  | 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"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// 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,8 @@ | ||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | The classes in this package represent the JDBC implementation | ||||||
|  | of PetClinic's persistence layer. | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,90 @@ | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 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()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | The classes in this package represent the JPA implementation | ||||||
|  | of PetClinic's persistence layer. | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | The classes in this package represent PetClinic's business layer. | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -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,8 @@ | ||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | The classes in this package provide support for using the TopLink | ||||||
|  | implementation with PetClinic's EntityManagerClinic. | ||||||
|  |   | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -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,8 @@ | ||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | The classes in this package represent the set of Validator objects  | ||||||
|  | the Business Layer makes available to the Presentation Layer. | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,62 @@ | ||||||
|  | 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.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.annotation.InitBinder; | ||||||
|  | import org.springframework.web.bind.support.SessionStatus; | ||||||
|  | import org.springframework.web.bind.WebDataBinder; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * JavaBean form controller that is used to add a new <code>Owner</code> to | ||||||
|  |  * the system. | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  */ | ||||||
|  | @Controller | ||||||
|  | @RequestMapping("/addOwner.do") | ||||||
|  | @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(new String[] {"id"}); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @RequestMapping(method = RequestMethod.GET) | ||||||
|  | 	public String setupForm(Model model) { | ||||||
|  | 		Owner owner = new Owner(); | ||||||
|  | 		model.addAttribute(owner); | ||||||
|  | 		return "ownerForm"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.POST) | ||||||
|  | 	public String processSubmit(@ModelAttribute Owner owner, BindingResult result, SessionStatus status) { | ||||||
|  | 		new OwnerValidator().validate(owner, result); | ||||||
|  | 		if (result.hasErrors()) { | ||||||
|  | 			return "ownerForm"; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			this.clinic.storeOwner(owner); | ||||||
|  | 			status.setComplete(); | ||||||
|  | 			return "redirect:owner.do?ownerId=" + owner.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.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.annotation.ModelAttribute; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMethod; | ||||||
|  | import org.springframework.web.bind.annotation.RequestParam; | ||||||
|  | import org.springframework.web.bind.annotation.SessionAttributes; | ||||||
|  | import org.springframework.web.bind.annotation.InitBinder; | ||||||
|  | import org.springframework.web.bind.support.SessionStatus; | ||||||
|  | import org.springframework.web.bind.WebDataBinder; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * JavaBean form controller that is used to add a new <code>Pet</code> to the | ||||||
|  |  * system. | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  */ | ||||||
|  | @Controller | ||||||
|  | @RequestMapping("/addPet.do") | ||||||
|  | @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(new String[] {"id"}); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @RequestMapping(method = RequestMethod.GET) | ||||||
|  | 	public String setupForm(@RequestParam("ownerId") int ownerId, Model model) { | ||||||
|  | 		Owner owner = this.clinic.loadOwner(ownerId); | ||||||
|  | 		Pet pet = new Pet(); | ||||||
|  | 		owner.addPet(pet); | ||||||
|  | 		model.addAttribute("pet", pet); | ||||||
|  | 		return "petForm"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.POST) | ||||||
|  | 	public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) { | ||||||
|  | 		new PetValidator().validate(pet, result); | ||||||
|  | 		if (result.hasErrors()) { | ||||||
|  | 			return "petForm"; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			this.clinic.storePet(pet); | ||||||
|  | 			status.setComplete(); | ||||||
|  | 			return "redirect:owner.do?ownerId=" + pet.getOwner().getId(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,66 @@ | ||||||
|  | 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.annotation.ModelAttribute; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMethod; | ||||||
|  | import org.springframework.web.bind.annotation.RequestParam; | ||||||
|  | import org.springframework.web.bind.annotation.SessionAttributes; | ||||||
|  | import org.springframework.web.bind.annotation.InitBinder; | ||||||
|  | import org.springframework.web.bind.support.SessionStatus; | ||||||
|  | import org.springframework.web.bind.WebDataBinder; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * JavaBean form controller that is used to add a new <code>Visit</code> to | ||||||
|  |  * the system. | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  */ | ||||||
|  | @Controller | ||||||
|  | @RequestMapping("/addVisit.do") | ||||||
|  | @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(new String[] {"id"}); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.GET) | ||||||
|  | 	public String setupForm(@RequestParam("petId") int petId, Model model) { | ||||||
|  | 		Pet pet = this.clinic.loadPet(petId); | ||||||
|  | 		Visit visit = new Visit(); | ||||||
|  | 		pet.addVisit(visit); | ||||||
|  | 		model.addAttribute("visit", visit); | ||||||
|  | 		return "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 "visitForm"; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			this.clinic.storeVisit(visit); | ||||||
|  | 			status.setComplete(); | ||||||
|  | 			return "redirect:owner.do?ownerId=" + 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,72 @@ | ||||||
|  | 
 | ||||||
|  | package org.springframework.samples.petclinic.web; | ||||||
|  | 
 | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.samples.petclinic.Clinic; | ||||||
|  | import org.springframework.stereotype.Controller; | ||||||
|  | import org.springframework.ui.ModelMap; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestParam; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Annotation-driven <em>MultiActionController</em> that handles all non-form | ||||||
|  |  * URL's. | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Mark Fisher | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  */ | ||||||
|  | @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("/welcome.do") | ||||||
|  | 	public void welcomeHandler() { | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * 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.do") | ||||||
|  | 	public ModelMap vetsHandler() { | ||||||
|  | 		return new ModelMap(this.clinic.getVets()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Custom handler for displaying an owner. | ||||||
|  | 	 * <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: "/owner.do" -> "owner". | ||||||
|  | 	 * | ||||||
|  | 	 * @param ownerId the ID of the owner to display | ||||||
|  | 	 * @return a ModelMap with the model attributes for the view | ||||||
|  | 	 */ | ||||||
|  | 	@RequestMapping("/owner.do") | ||||||
|  | 	public ModelMap ownerHandler(@RequestParam("ownerId") int ownerId) { | ||||||
|  | 		return new ModelMap(this.clinic.loadOwner(ownerId)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,62 @@ | ||||||
|  | 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.annotation.ModelAttribute; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMethod; | ||||||
|  | import org.springframework.web.bind.annotation.RequestParam; | ||||||
|  | import org.springframework.web.bind.annotation.SessionAttributes; | ||||||
|  | import org.springframework.web.bind.annotation.InitBinder; | ||||||
|  | import org.springframework.web.bind.support.SessionStatus; | ||||||
|  | import org.springframework.web.bind.WebDataBinder; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * JavaBean Form controller that is used to edit an existing <code>Owner</code>. | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  */ | ||||||
|  | @Controller | ||||||
|  | @RequestMapping("/editOwner.do") | ||||||
|  | @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(new String[] {"id"}); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.GET) | ||||||
|  | 	public String setupForm(@RequestParam("ownerId") int ownerId, Model model) { | ||||||
|  | 		Owner owner = this.clinic.loadOwner(ownerId); | ||||||
|  | 		model.addAttribute(owner); | ||||||
|  | 		return "ownerForm"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.POST) | ||||||
|  | 	public String processSubmit(@ModelAttribute Owner owner, BindingResult result, SessionStatus status) { | ||||||
|  | 		new OwnerValidator().validate(owner, result); | ||||||
|  | 		if (result.hasErrors()) { | ||||||
|  | 			return "ownerForm"; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			this.clinic.storeOwner(owner); | ||||||
|  | 			status.setComplete(); | ||||||
|  | 			return "redirect:owner.do?ownerId=" + owner.getId(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,70 @@ | ||||||
|  | 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.annotation.ModelAttribute; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMethod; | ||||||
|  | import org.springframework.web.bind.annotation.RequestParam; | ||||||
|  | import org.springframework.web.bind.annotation.SessionAttributes; | ||||||
|  | import org.springframework.web.bind.annotation.InitBinder; | ||||||
|  | import org.springframework.web.bind.support.SessionStatus; | ||||||
|  | import org.springframework.web.bind.WebDataBinder; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * JavaBean Form controller that is used to edit an existing <code>Pet</code>. | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  */ | ||||||
|  | @Controller | ||||||
|  | @RequestMapping("/editPet.do") | ||||||
|  | @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(new String[] {"id"}); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.GET) | ||||||
|  | 	public String setupForm(@RequestParam("petId") int petId, Model model) { | ||||||
|  | 		Pet pet = this.clinic.loadPet(petId); | ||||||
|  | 		model.addAttribute("pet", pet); | ||||||
|  | 		return "petForm"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.POST) | ||||||
|  | 	public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) { | ||||||
|  | 		new PetValidator().validate(pet, result); | ||||||
|  | 		if (result.hasErrors()) { | ||||||
|  | 			return "petForm"; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			this.clinic.storePet(pet); | ||||||
|  | 			status.setComplete(); | ||||||
|  | 			return "redirect:owner.do?ownerId=" + pet.getOwner().getId(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,66 @@ | ||||||
|  | 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.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMethod; | ||||||
|  | import org.springframework.web.bind.annotation.InitBinder; | ||||||
|  | import org.springframework.web.bind.WebDataBinder; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * JavaBean Form controller that is used to search for <code>Owner</code>s by | ||||||
|  |  * last name. | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  */ | ||||||
|  | @Controller | ||||||
|  | @RequestMapping("/findOwners.do") | ||||||
|  | public class FindOwnersForm { | ||||||
|  | 
 | ||||||
|  | 	private final Clinic clinic; | ||||||
|  | 
 | ||||||
|  | 	@Autowired | ||||||
|  | 	public FindOwnersForm(Clinic clinic) { | ||||||
|  | 		this.clinic = clinic; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  |     @InitBinder | ||||||
|  |     public void setAllowedFields(WebDataBinder dataBinder) { | ||||||
|  |         dataBinder.setDisallowedFields(new String[] {"id"}); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.GET) | ||||||
|  | 	public  String setupForm(Model model) { | ||||||
|  | 		model.addAttribute("owner", new Owner()); | ||||||
|  | 		return "findOwners"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@RequestMapping(method = RequestMethod.POST) | ||||||
|  | 	public  String processSubmit(Owner owner, BindingResult result, Model model) { | ||||||
|  | 		// 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 "findOwners"; | ||||||
|  | 		} | ||||||
|  | 		if (results.size() > 1) { | ||||||
|  | 			// multiple owners found | ||||||
|  | 			model.addAttribute("selections", results); | ||||||
|  | 			return "owners"; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			// 1 owner found | ||||||
|  | 			owner = results.iterator().next(); | ||||||
|  | 			return "redirect:owner.do?ownerId=" + 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,7 @@ | ||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | The classes in this package represent PetClinic's web presentation layer. | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | <p> | ||||||
|  | The Spring Data Binding framework, an internal library used by Spring Web Flow. | ||||||
|  | </p> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | <?xml version="1.0"?> | ||||||
|  | 
 | ||||||
|  | <!-- Custom aspects for the PetClinic sample application --> | ||||||
|  | <aspectj> | ||||||
|  | 
 | ||||||
|  | 	<weaver> | ||||||
|  | 		<include within="org.springframework.samples.petclinic..*"/> | ||||||
|  | 	</weaver> | ||||||
|  | 
 | ||||||
|  | 	<aspects> | ||||||
|  | 		<aspect name="org.springframework.samples.petclinic.aspects.UsageLogAspect"/> | ||||||
|  | 		<concrete-aspect name="org.springframework.samples.petclinic.aspects.ApplicationTraceAspect" | ||||||
|  | 				extends="org.springframework.samples.petclinic.aspects.AbstractTraceAspect"> | ||||||
|  | 			<pointcut name="traced" expression="execution(* org.springframework.samples..*.*(..))"/> | ||||||
|  | 		</concrete-aspect> | ||||||
|  | 	</aspects> | ||||||
|  | 
 | ||||||
|  | </aspectj> | ||||||
|  | @ -0,0 +1,122 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" | ||||||
|  | 		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 		xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" | ||||||
|  | 		version="1.0"> | ||||||
|  | 
 | ||||||
|  | 	<persistence-unit-metadata> | ||||||
|  | 		<xml-mapping-metadata-complete/> | ||||||
|  | 		<persistence-unit-defaults> | ||||||
|  | 			<access>PROPERTY</access> | ||||||
|  | 		</persistence-unit-defaults> | ||||||
|  | 	</persistence-unit-metadata> | ||||||
|  | 
 | ||||||
|  | 	<package>org.springframework.samples.petclinic</package> | ||||||
|  | 
 | ||||||
|  | 	<mapped-superclass class="BaseEntity"> | ||||||
|  | 		<attributes> | ||||||
|  | 			<id name="id"> | ||||||
|  | 				<generated-value strategy="IDENTITY"/> | ||||||
|  | 			</id> | ||||||
|  | 			<transient name="new"/> | ||||||
|  | 		</attributes> | ||||||
|  | 	</mapped-superclass> | ||||||
|  | 
 | ||||||
|  | 	<mapped-superclass class="NamedEntity"> | ||||||
|  | 		<attributes> | ||||||
|  | 			<basic name="name"> | ||||||
|  | 				<column name="NAME"/> | ||||||
|  | 			</basic> | ||||||
|  | 		</attributes> | ||||||
|  | 	</mapped-superclass> | ||||||
|  | 
 | ||||||
|  | 	<mapped-superclass class="Person"> | ||||||
|  | 		<attributes> | ||||||
|  | 			<basic name="firstName"> | ||||||
|  | 				<column name="FIRST_NAME"/> | ||||||
|  | 			</basic> | ||||||
|  | 			<basic name="lastName"> | ||||||
|  | 				<column name="LAST_NAME"/> | ||||||
|  | 			</basic> | ||||||
|  | 		</attributes> | ||||||
|  | 	</mapped-superclass> | ||||||
|  | 
 | ||||||
|  | 	<entity class="Vet"> | ||||||
|  | 		<table name="VETS"/> | ||||||
|  | 		<attributes> | ||||||
|  | 			<many-to-many name="specialtiesInternal" target-entity="Specialty" fetch="EAGER"> | ||||||
|  | 				<join-table name="VET_SPECIALTIES"> | ||||||
|  | 					<join-column name="VET_ID"/> | ||||||
|  | 					<inverse-join-column name="SPECIALTY_ID"/> | ||||||
|  | 				</join-table> | ||||||
|  | 			</many-to-many> | ||||||
|  | 			<transient name="specialties"/> | ||||||
|  | 			<transient name="nrOfSpecialties"/> | ||||||
|  | 		</attributes> | ||||||
|  | 	</entity> | ||||||
|  | 
 | ||||||
|  | 	<entity class="Specialty"> | ||||||
|  | 		<table name="SPECIALTIES"/> | ||||||
|  | 	</entity> | ||||||
|  | 
 | ||||||
|  | 	<entity class="Owner"> | ||||||
|  | 		<table name="OWNERS"/> | ||||||
|  | 		<attributes> | ||||||
|  | 			<basic name="address"/> | ||||||
|  | 			<basic name="city"/> | ||||||
|  | 			<basic name="telephone"/> | ||||||
|  | 			<one-to-many name="petsInternal" target-entity="Pet" mapped-by="owner" fetch="EAGER"> | ||||||
|  | 				<cascade> | ||||||
|  | 					<cascade-all/> | ||||||
|  | 				</cascade> | ||||||
|  | 			</one-to-many> | ||||||
|  | 			<transient name="pets"/> | ||||||
|  | 		</attributes> | ||||||
|  | 	</entity> | ||||||
|  | 
 | ||||||
|  | 	<entity class="Pet"> | ||||||
|  | 		<table name="PETS"/> | ||||||
|  | 		<attributes> | ||||||
|  | 			<basic name="birthDate"> | ||||||
|  | 				<column name="BIRTH_DATE"/> | ||||||
|  | 				<temporal>DATE</temporal> | ||||||
|  | 			</basic> | ||||||
|  | 			<many-to-one name="owner" fetch="EAGER"> | ||||||
|  | 				<cascade> | ||||||
|  | 					<cascade-all/> | ||||||
|  | 				</cascade> | ||||||
|  | 			</many-to-one> | ||||||
|  | 			<many-to-one name="type" fetch="EAGER"> | ||||||
|  | 				<cascade> | ||||||
|  | 					<cascade-all/> | ||||||
|  | 				</cascade> | ||||||
|  | 			</many-to-one> | ||||||
|  | 			<one-to-many name="visitsInternal" target-entity="Visit" mapped-by="pet" fetch="EAGER"> | ||||||
|  | 				<cascade> | ||||||
|  | 					<cascade-all/> | ||||||
|  | 				</cascade> | ||||||
|  | 			</one-to-many> | ||||||
|  | 			<transient name="visits"/> | ||||||
|  | 		</attributes> | ||||||
|  | 	</entity> | ||||||
|  | 
 | ||||||
|  | 	<entity class="PetType"> | ||||||
|  | 		<table name="TYPES"/> | ||||||
|  | 	</entity> | ||||||
|  | 
 | ||||||
|  | 	<entity class="Visit"> | ||||||
|  | 		<table name="VISITS"/> | ||||||
|  | 		<attributes> | ||||||
|  | 			<basic name="date"> | ||||||
|  | 				<column name="VISIT_DATE"/> | ||||||
|  | 				<temporal>DATE</temporal> | ||||||
|  | 			</basic> | ||||||
|  | 			<many-to-one name="pet" fetch="EAGER"> | ||||||
|  | 				<cascade> | ||||||
|  | 					<cascade-all/> | ||||||
|  | 				</cascade> | ||||||
|  | 			</many-to-one> | ||||||
|  | 		</attributes> | ||||||
|  | 	</entity> | ||||||
|  | 
 | ||||||
|  | </entity-mappings> | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | <persistence xmlns="http://java.sun.com/xml/ns/persistence" | ||||||
|  | 		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 		xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" | ||||||
|  | 		version="1.0"> | ||||||
|  | 
 | ||||||
|  | 	<persistence-unit name="PetClinic" transaction-type="RESOURCE_LOCAL"> | ||||||
|  | 
 | ||||||
|  | 		<!-- Explicitly define mapping file path, else Hibernate won't find the default --> | ||||||
|  | 		<mapping-file>META-INF/orm.xml</mapping-file> | ||||||
|  | 
 | ||||||
|  | 		<!-- Prevent annotation scanning. In this app we are purely driven by orm.xml --> | ||||||
|  | 		<exclude-unlisted-classes>true</exclude-unlisted-classes> | ||||||
|  | 
 | ||||||
|  | 	</persistence-unit> | ||||||
|  | 
 | ||||||
|  | </persistence> | ||||||
|  | @ -0,0 +1,48 @@ | ||||||
|  | # Properties file with JDBC and JPA settings. | ||||||
|  | # | ||||||
|  | # Applied by <context:property-placeholder location="jdbc.properties"/> from | ||||||
|  | # various application context XML files (e.g., "applicationContext-*.xml"). | ||||||
|  | # Targeted at system administrators, to avoid touching the context XML files. | ||||||
|  | 
 | ||||||
|  | #------------------------------------------------------------------------------- | ||||||
|  | # Common Settings | ||||||
|  | 
 | ||||||
|  | hibernate.generate_statistics=true | ||||||
|  | hibernate.show_sql=true | ||||||
|  | jpa.showSql=true | ||||||
|  | 
 | ||||||
|  | #------------------------------------------------------------------------------- | ||||||
|  | # HSQL Settings | ||||||
|  | 
 | ||||||
|  | jdbc.driverClassName=org.hsqldb.jdbcDriver | ||||||
|  | jdbc.url=jdbc:hsqldb:hsql://localhost:9001 | ||||||
|  | jdbc.username=sa | ||||||
|  | jdbc.password= | ||||||
|  | 
 | ||||||
|  | # Property that determines which Hibernate dialect to use | ||||||
|  | # (only applied with "applicationContext-hibernate.xml") | ||||||
|  | hibernate.dialect=org.hibernate.dialect.HSQLDialect | ||||||
|  | 
 | ||||||
|  | # Property that determines which JPA DatabasePlatform to use with TopLink Essentials | ||||||
|  | jpa.databasePlatform=org.springframework.samples.petclinic.toplink.EssentialsHSQLPlatformWithNativeSequence | ||||||
|  | 
 | ||||||
|  | # Property that determines which database to use with an AbstractJpaVendorAdapter | ||||||
|  | jpa.database=HSQL | ||||||
|  | 
 | ||||||
|  | #------------------------------------------------------------------------------- | ||||||
|  | # MySQL Settings | ||||||
|  | 
 | ||||||
|  | #jdbc.driverClassName=com.mysql.jdbc.Driver | ||||||
|  | #jdbc.url=jdbc:mysql://localhost:3306/petclinic | ||||||
|  | #jdbc.username=pc | ||||||
|  | #jdbc.password=pc | ||||||
|  | 
 | ||||||
|  | # Property that determines which Hibernate dialect to use | ||||||
|  | # (only applied with "applicationContext-hibernate.xml") | ||||||
|  | #hibernate.dialect=org.hibernate.dialect.MySQLDialect | ||||||
|  | 
 | ||||||
|  | # Property that determines which JPA DatabasePlatform to use with TopLink Essentials | ||||||
|  | #jpa.databasePlatform=oracle.toplink.essentials.platform.database.MySQL4Platform | ||||||
|  | 
 | ||||||
|  | # Property that determines which database to use with an AbstractJpaVendorAdapter | ||||||
|  | #jpa.database=MYSQL | ||||||
|  | @ -0,0 +1,74 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" | ||||||
|  | 		"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> | ||||||
|  | 
 | ||||||
|  | <!-- | ||||||
|  |   - Mapping file for the Hibernate implementation of the Clinic interface. | ||||||
|  | 	--> | ||||||
|  | <hibernate-mapping auto-import="true" default-lazy="false"> | ||||||
|  | 
 | ||||||
|  | 	<class name="org.springframework.samples.petclinic.Vet" table="vets"> | ||||||
|  | 		<id name="id" column="id"> | ||||||
|  | 			<generator class="identity"/> | ||||||
|  | 		</id> | ||||||
|  | 		<property name="firstName" column="first_name"/> | ||||||
|  | 		<property name="lastName" column="last_name"/> | ||||||
|  | 		<set name="specialtiesInternal" table="vet_specialties"> | ||||||
|  | 			<key column="vet_id"/> | ||||||
|  | 			<many-to-many column="specialty_id" class="org.springframework.samples.petclinic.Specialty"/> | ||||||
|  | 		</set> | ||||||
|  | 	</class> | ||||||
|  | 
 | ||||||
|  | 	<class name="org.springframework.samples.petclinic.Specialty" table="specialties"> | ||||||
|  | 		<id name="id" column="id"> | ||||||
|  | 			<generator class="identity"/> | ||||||
|  | 		</id> | ||||||
|  | 		<property name="name" column="name"/> | ||||||
|  | 	</class> | ||||||
|  | 
 | ||||||
|  | 	<class name="org.springframework.samples.petclinic.Owner" table="owners"> | ||||||
|  | 		<id name="id" column="id"> | ||||||
|  | 			<generator class="identity"/> | ||||||
|  | 		</id> | ||||||
|  | 		<property name="firstName" column="first_name"/> | ||||||
|  | 		<property name="lastName" column="last_name"/> | ||||||
|  | 		<property name="address" column="address"/> | ||||||
|  | 		<property name="city" column="city"/> | ||||||
|  | 		<property name="telephone" column="telephone"/> | ||||||
|  | 		<set name="petsInternal" inverse="true" cascade="all"> | ||||||
|  | 			<key column="owner_id"/> | ||||||
|  | 			<one-to-many class="org.springframework.samples.petclinic.Pet"/> | ||||||
|  | 		</set> | ||||||
|  | 	</class> | ||||||
|  | 
 | ||||||
|  | 	<class name="org.springframework.samples.petclinic.Pet" table="pets"> | ||||||
|  | 		<id name="id" column="id"> | ||||||
|  | 			<generator class="identity"/> | ||||||
|  | 		</id> | ||||||
|  | 		<property name="name" column="name"/> | ||||||
|  | 		<property name="birthDate" column="birth_date" type="date"/> | ||||||
|  | 		<many-to-one name="owner" column="owner_id" class="org.springframework.samples.petclinic.Owner"/> | ||||||
|  | 		<many-to-one name="type" column="type_id" class="org.springframework.samples.petclinic.PetType"/> | ||||||
|  | 		<set name="visitsInternal" inverse="true" cascade="all"> | ||||||
|  | 			<key column="pet_id"/> | ||||||
|  | 			<one-to-many class="org.springframework.samples.petclinic.Visit"/> | ||||||
|  | 		</set> | ||||||
|  | 	</class> | ||||||
|  | 
 | ||||||
|  | 	<class name="org.springframework.samples.petclinic.PetType" table="types"> | ||||||
|  | 		<id name="id" column="id"> | ||||||
|  | 			<generator class="identity"/> | ||||||
|  | 		</id> | ||||||
|  | 		<property name="name" column="name"/> | ||||||
|  | 	</class> | ||||||
|  | 
 | ||||||
|  | 	<class name="org.springframework.samples.petclinic.Visit" table="visits"> | ||||||
|  | 		<id name="id" column="id"> | ||||||
|  | 			<generator class="identity"/> | ||||||
|  | 		</id> | ||||||
|  | 		<property name="date" column="visit_date" type="date"/> | ||||||
|  | 		<property name="description" column="description"/> | ||||||
|  | 		<many-to-one name="pet" column="pet_id" class="org.springframework.samples.petclinic.Pet"/> | ||||||
|  | 	</class> | ||||||
|  | 
 | ||||||
|  | </hibernate-mapping> | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | <!-- Tomcat context descriptor used for specifying a custom ClassLoader --> | ||||||
|  | <Context path="/petclinic" reloadable="false"> | ||||||
|  | 	<!-- please note that useSystemClassLoaderAsParent is available since Tomcat 5.5.20 / remove if previous versions are being used --> | ||||||
|  | 	<!--   | ||||||
|  | 	<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader" useSystemClassLoaderAsParent="false"/> | ||||||
|  | 	--> | ||||||
|  | </Context> | ||||||
|  | @ -0,0 +1,89 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!-- | ||||||
|  | 	Application context definition for PetClinic on Hibernate. | ||||||
|  | --> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 		xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" | ||||||
|  | 		xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" | ||||||
|  | 		xsi:schemaLocation=" | ||||||
|  | 			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<!-- ========================= RESOURCE DEFINITIONS ========================= --> | ||||||
|  | 
 | ||||||
|  | 	<!-- Configurer that replaces ${...} placeholders with values from a properties file --> | ||||||
|  | 	<!-- (in this case, JDBC-related settings for the dataSource definition below) --> | ||||||
|  | 	<context:property-placeholder location="classpath:jdbc.properties"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Uses Apache Commons DBCP for connection pooling. See Commons DBCP documentation | ||||||
|  | 		for the required JAR files. Alternatively you can use another connection pool | ||||||
|  | 		such as C3P0, similarly configured using Spring. | ||||||
|  | 	--> | ||||||
|  | 	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" | ||||||
|  | 			p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" | ||||||
|  | 			p:password="${jdbc.password}"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- JNDI DataSource for JEE environments --> | ||||||
|  | 	<!-- | ||||||
|  | 		<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/petclinic"/> | ||||||
|  | 	--> | ||||||
|  | 
 | ||||||
|  | 	<!-- Hibernate SessionFactory --> | ||||||
|  | 	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" | ||||||
|  | 			p:dataSource-ref="dataSource" p:mappingResources="petclinic.hbm.xml"> | ||||||
|  | 		<property name="hibernateProperties"> | ||||||
|  | 			<props> | ||||||
|  | 				<prop key="hibernate.dialect">${hibernate.dialect}</prop> | ||||||
|  | 				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop> | ||||||
|  | 				<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop> | ||||||
|  | 			</props> | ||||||
|  | 		</property> | ||||||
|  | 		<property name="eventListeners"> | ||||||
|  | 			<map> | ||||||
|  | 				<entry key="merge"> | ||||||
|  | 					<bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/> | ||||||
|  | 				</entry> | ||||||
|  | 			</map> | ||||||
|  | 		</property> | ||||||
|  | 	</bean> | ||||||
|  | 
 | ||||||
|  | 	<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --> | ||||||
|  | 	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" | ||||||
|  | 			p:sessionFactory-ref="sessionFactory"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- Transaction manager that delegates to JTA (for a transactional JNDI DataSource) --> | ||||||
|  | 	<!-- | ||||||
|  | 	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> | ||||||
|  | 	--> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	<!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= --> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Activates various annotations to be detected in bean classes: | ||||||
|  | 		Spring's @Required and @Autowired, as well as JSR 250's @Resource. | ||||||
|  | 	--> | ||||||
|  | 	<context:annotation-config/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Instruct Spring to perform declarative transaction management | ||||||
|  | 		automatically on annotated classes. | ||||||
|  | 	--> | ||||||
|  | 	<tx:annotation-driven/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Exporter that exposes the Hibernate statistics service via JMX. Autodetects the | ||||||
|  | 		service MBean, using its bean name as JMX object name. | ||||||
|  | 	--> | ||||||
|  | 	<context:mbean-export/> | ||||||
|  | 
 | ||||||
|  | 	<!-- PetClinic's central data access object: Hibernate implementation --> | ||||||
|  | 	<bean id="clinic" class="org.springframework.samples.petclinic.hibernate.HibernateClinic"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- Hibernate's JMX statistics service --> | ||||||
|  | 	<bean name="petclinic:type=HibernateStatistics" class="org.hibernate.jmx.StatisticsService" autowire="byName"/> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,81 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!-- | ||||||
|  | 	Application context definition for PetClinic on JDBC. | ||||||
|  | --> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 		xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" | ||||||
|  | 		xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" | ||||||
|  | 		xmlns:tx="http://www.springframework.org/schema/tx" | ||||||
|  | 		xsi:schemaLocation=" | ||||||
|  | 			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<!-- ========================= RESOURCE DEFINITIONS ========================= --> | ||||||
|  | 
 | ||||||
|  | 	<!-- Configurer that replaces ${...} placeholders with values from a properties file --> | ||||||
|  | 	<!-- (in this case, JDBC-related settings for the dataSource definition below) --> | ||||||
|  | 	<context:property-placeholder location="classpath:jdbc.properties"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Uses Apache Commons DBCP for connection pooling. See Commons DBCP documentation | ||||||
|  | 		for the required JAR files. Alternatively you can use another connection pool | ||||||
|  | 		such as C3P0, similarly configured using Spring. | ||||||
|  | 	--> | ||||||
|  | 	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" | ||||||
|  | 			p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" | ||||||
|  | 			p:password="${jdbc.password}"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- JNDI DataSource for JEE environments --> | ||||||
|  | 	<!-- | ||||||
|  | 	<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/petclinic"/> | ||||||
|  | 	--> | ||||||
|  | 
 | ||||||
|  | 	<!-- Transaction manager for a single JDBC DataSource (alternative to JTA) --> | ||||||
|  | 	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" | ||||||
|  | 			p:dataSource-ref="dataSource"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- Transaction manager that delegates to JTA (for a transactional JNDI DataSource) --> | ||||||
|  | 	<!-- | ||||||
|  | 	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> | ||||||
|  | 	--> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	<!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= --> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Activates various annotations to be detected in bean classes: Spring's | ||||||
|  | 		@Required and @Autowired, as well as JSR 250's @PostConstruct, | ||||||
|  | 		@PreDestroy and @Resource (if available) and JPA's @PersistenceContext | ||||||
|  | 		and @PersistenceUnit (if available). | ||||||
|  | 	--> | ||||||
|  | 	<context:annotation-config/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Instruct Spring to retrieve and apply @AspectJ aspects which are defined | ||||||
|  | 		as beans in this context (such as the CallMonitoringAspect below). | ||||||
|  | 	--> | ||||||
|  | 	<aop:aspectj-autoproxy/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Instruct Spring to perform automatic transaction management on annotated classes. | ||||||
|  | 		The SimpleJdbcClinic implementation declares @Transactional annotations. | ||||||
|  | 		"proxy-target-class" is set because of SimpleJdbcClinic's @ManagedOperation usage. | ||||||
|  | 	--> | ||||||
|  | 	<tx:annotation-driven/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Exporter that exposes the Clinic DAO and the CallMonitoringAspect via JMX, | ||||||
|  | 		based on the @ManagedResource, @ManagedAttribute, and @ManagedOperation annotations. | ||||||
|  | 	--> | ||||||
|  | 	<context:mbean-export/> | ||||||
|  | 
 | ||||||
|  | 	<!-- PetClinic's central data access object using Spring's SimpleJdbcTemplate --> | ||||||
|  | 	<bean id="clinic" class="org.springframework.samples.petclinic.jdbc.SimpleJdbcClinic"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- Call monitoring aspect that monitors call count and call invocation time --> | ||||||
|  | 	<bean id="callMonitor" class="org.springframework.samples.petclinic.aspects.CallMonitoringAspect"/> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,101 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!-- | ||||||
|  | 	Application context definition for PetClinic on JPA. | ||||||
|  | --> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 		xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" | ||||||
|  | 		xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" | ||||||
|  | 		xmlns:tx="http://www.springframework.org/schema/tx" | ||||||
|  | 		xsi:schemaLocation=" | ||||||
|  | 			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd | ||||||
|  | 			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<!-- ========================= RESOURCE DEFINITIONS ========================= --> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Activates a load-time weaver for the context. Any bean within the context that | ||||||
|  | 		implements LoadTimeWeaverAware (such as LocalContainerEntityManagerFactoryBean) | ||||||
|  | 		will receive a reference to the autodetected load-time weaver. | ||||||
|  | 	--> | ||||||
|  | 	<context:load-time-weaver/> | ||||||
|  | 
 | ||||||
|  | 	<!-- Configurer that replaces ${...} placeholders with values from a properties file --> | ||||||
|  | 	<!-- (in this case, JDBC-related settings for the dataSource definition below) --> | ||||||
|  | 	<context:property-placeholder location="classpath:jdbc.properties"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Uses Apache Commons DBCP for connection pooling. See Commons DBCP documentation | ||||||
|  | 		for the required JAR files. Alternatively you can use another connection pool | ||||||
|  | 		such as C3P0, similarly configured using Spring. | ||||||
|  | 	--> | ||||||
|  | 	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" | ||||||
|  | 			p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" | ||||||
|  | 			p:password="${jdbc.password}"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- JNDI DataSource for JEE environments --> | ||||||
|  | 	<!-- | ||||||
|  | 	<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/petclinic"/> | ||||||
|  | 	--> | ||||||
|  | 
 | ||||||
|  | 	<!-- JPA EntityManagerFactory --> | ||||||
|  | 	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" | ||||||
|  | 			p:dataSource-ref="dataSource"> | ||||||
|  | 		<property name="jpaVendorAdapter"> | ||||||
|  | 			<bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter" | ||||||
|  | 					p:databasePlatform="${jpa.databasePlatform}" p:showSql="${jpa.showSql}"/> | ||||||
|  | 			<!-- | ||||||
|  | 			<bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter" | ||||||
|  | 					p:database="${jpa.database}" p:showSql="${jpa.showSql}"/> | ||||||
|  | 			--> | ||||||
|  | 			<!-- | ||||||
|  | 			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" | ||||||
|  | 					p:database="${jpa.database}" p:showSql="${jpa.showSql}"/> | ||||||
|  | 			--> | ||||||
|  | 		</property> | ||||||
|  | 	</bean> | ||||||
|  | 
 | ||||||
|  | 	<!-- Transaction manager for a single JPA EntityManagerFactory (alternative to JTA) --> | ||||||
|  | 	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" | ||||||
|  | 			p:entityManagerFactory-ref="entityManagerFactory"/> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	<!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= --> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Activates various annotations to be detected in bean classes: Spring's | ||||||
|  | 		@Required and @Autowired, as well as JSR 250's @PostConstruct, | ||||||
|  | 		@PreDestroy and @Resource (if available) and JPA's @PersistenceContext | ||||||
|  | 		and @PersistenceUnit (if available). | ||||||
|  | 	--> | ||||||
|  | 	<context:annotation-config/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Instruct Spring to perform declarative transaction management | ||||||
|  | 		automatically on annotated classes. | ||||||
|  | 	--> | ||||||
|  | 	<tx:annotation-driven mode="aspectj"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Simply defining this bean will cause requests to owner names to be saved. | ||||||
|  | 		This aspect is defined in petclinic.jar's META-INF/aop.xml file. | ||||||
|  | 		Note that we can dependency inject this bean like any other bean. | ||||||
|  | 	--> | ||||||
|  | 	<bean class="org.springframework.samples.petclinic.aspects.UsageLogAspect" p:historySize="300"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Post-processor to perform exception translation on @Repository classes (from native | ||||||
|  | 		exceptions such as JPA PersistenceExceptions to Spring's DataAccessException hierarchy). | ||||||
|  | 	--> | ||||||
|  | 	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Will automatically be transactional due to @Transactional. | ||||||
|  | 		EntityManager will be auto-injected due to @PersistenceContext. | ||||||
|  | 		PersistenceExceptions will be auto-translated due to @Repository. | ||||||
|  | 	--> | ||||||
|  | 	<bean id="clinic" class="org.springframework.samples.petclinic.jpa.EntityManagerClinic"/> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | # For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml! | ||||||
|  | # For all other servers: Comment out the Log4J listener in web.xml to activate Log4J. | ||||||
|  | log4j.rootLogger=INFO, stdout, logfile | ||||||
|  | 
 | ||||||
|  | log4j.appender.stdout=org.apache.log4j.ConsoleAppender | ||||||
|  | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout | ||||||
|  | log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n | ||||||
|  | 
 | ||||||
|  | log4j.appender.logfile=org.apache.log4j.RollingFileAppender | ||||||
|  | log4j.appender.logfile.File=${petclinic.root}/WEB-INF/petclinic.log | ||||||
|  | log4j.appender.logfile.MaxFileSize=512KB | ||||||
|  | # Keep three backup files. | ||||||
|  | log4j.appender.logfile.MaxBackupIndex=3 | ||||||
|  | # Pattern to output: date priority [category] - message | ||||||
|  | log4j.appender.logfile.layout=org.apache.log4j.PatternLayout | ||||||
|  | log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n | ||||||
|  | 
 | ||||||
|  | log4j.logger.org.springframework.samples.petclinic.aspects=DEBUG | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | welcome=Welcome | ||||||
|  | required=is required | ||||||
|  | notFound=has not been found | ||||||
|  | duplicate=is already in use | ||||||
|  | nonNumeric=must be all numeric | ||||||
|  | duplicateFormSubmission=Duplicate form submission is not allowed | ||||||
|  | typeMismatch.date=invalid date | ||||||
|  | typeMismatch.birthDate=invalid date | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | welcome=Willkommen | ||||||
|  | required=muss angegeben werden | ||||||
|  | notFound=wurde nicht gefunden | ||||||
|  | duplicate=ist bereits vergeben | ||||||
|  | nonNumeric=darf nur numerisch sein | ||||||
|  | duplicateFormSubmission=Wiederholtes Absenden des Formulars ist nicht erlaubt | ||||||
|  | typeMismatch.date=ungültiges Datum | ||||||
|  | typeMismatch.birthDate=ungültiges Datum | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | # This file is intentionally empty. Message look-ups will fall back to the default "messages.properties" file. | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.0" | ||||||
|  | 		 configId="org/springframework/samples/petclinic"> | ||||||
|  | 	<context-root>/petclinic</context-root> | ||||||
|  | 	<context-priority-classloader>true</context-priority-classloader> | ||||||
|  | </web-app> | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <% | ||||||
|  | Exception ex = (Exception) request.getAttribute("exception"); | ||||||
|  | %> | ||||||
|  | 
 | ||||||
|  | <h2>Data access failure: <%= ex.getMessage() %></h2> | ||||||
|  | <p/> | ||||||
|  | 
 | ||||||
|  | <% | ||||||
|  | ex.printStackTrace(new java.io.PrintWriter(out)); | ||||||
|  | %> | ||||||
|  | 
 | ||||||
|  | <p/> | ||||||
|  | <br/> | ||||||
|  | <a href="<c:url value="/welcome.do"/>">Home</a> | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <h2>Find Owners:</h2> | ||||||
|  | 
 | ||||||
|  | <form:form modelAttribute="owner"> | ||||||
|  |   <table> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         Last Name: <form:errors path="*" cssClass="errors"/> | ||||||
|  |         <br/>  | ||||||
|  |         <form:input path="lastName" size="30" maxlength="80"/> | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <td><p class="submit"><input type="submit" value="Find Owners"/></p></td> | ||||||
|  |     </tr> | ||||||
|  |   </table> | ||||||
|  | </form:form> | ||||||
|  | 
 | ||||||
|  | <br/> | ||||||
|  | <a href="<c:url value="/addOwner.do"/>">Add Owner</a> | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | 
 | ||||||
|  |   <table class="footer"> | ||||||
|  |     <tr> | ||||||
|  |       <td><a href="<c:url value="/welcome.do"/>">Home</a></td> | ||||||
|  |       <td align="right"><img src="<c:url value="/images/springsource-logo.png"/>"/></td> | ||||||
|  |     </tr> | ||||||
|  |   </table> | ||||||
|  | 
 | ||||||
|  |   </div> | ||||||
|  | </body> | ||||||
|  | 
 | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | <!-- | ||||||
|  | 	PetClinic :: a Spring Framework demonstration | ||||||
|  | --> | ||||||
|  | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | ||||||
|  | 
 | ||||||
|  | <head> | ||||||
|  |   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||||||
|  |   <link rel="stylesheet" href="<c:url value="/styles/petclinic.css"/>" type="text/css"/> | ||||||
|  |   <title>PetClinic :: a Spring Framework demonstration</title>	 | ||||||
|  | </head> | ||||||
|  | 
 | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  |   <div id="main"> | ||||||
|  | @ -0,0 +1,4 @@ | ||||||
|  | <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> | ||||||
|  | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> | ||||||
|  | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> | ||||||
|  | <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> | ||||||
|  | @ -0,0 +1,98 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <h2>Owner Information</h2> | ||||||
|  | 
 | ||||||
|  |   <table> | ||||||
|  |     <tr> | ||||||
|  |       <th>Name</th> | ||||||
|  |       <td><b>${owner.firstName} ${owner.lastName}</b></td> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th>Address</th> | ||||||
|  |       <td>${owner.address}</td> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th>City</th> | ||||||
|  |       <td>${owner.city}</td> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th>Telephone </th> | ||||||
|  |       <td>${owner.telephone}</td> | ||||||
|  |     </tr> | ||||||
|  |   </table> | ||||||
|  |   <table class="table-buttons"> | ||||||
|  |     <tr> | ||||||
|  |       <td colspan="2" align="center"> | ||||||
|  |         <form method="GET" action="<c:url value="/editOwner.do"/>"> | ||||||
|  |           <input type="hidden" name="ownerId" value="${owner.id}"/> | ||||||
|  |           <p class="submit"><input type="submit" value="Edit Owner"/></p> | ||||||
|  |         </form> | ||||||
|  |       </td> | ||||||
|  |       <td> | ||||||
|  |         <form method="GET" action="<c:url value="/addPet.do"/>" name="formAddPet"> | ||||||
|  |           <input type="hidden" name="ownerId" value="${owner.id}"/> | ||||||
|  |           <p class="submit"><input type="submit" value="Add New Pet"/></p> | ||||||
|  |         </form> | ||||||
|  |       </td> | ||||||
|  |     </tr> | ||||||
|  |   </table> | ||||||
|  | 
 | ||||||
|  |   <h2>Pets and Visits</h2> | ||||||
|  | 
 | ||||||
|  |   <c:forEach var="pet" items="${owner.pets}"> | ||||||
|  |     <table width="94%"> | ||||||
|  |       <tr> | ||||||
|  |         <td valign="top"> | ||||||
|  |           <table> | ||||||
|  |             <tr> | ||||||
|  |               <th>Name</th> | ||||||
|  |               <td><b>${pet.name}</b></td> | ||||||
|  |             </tr> | ||||||
|  |             <tr> | ||||||
|  |               <th>Birth Date</th> | ||||||
|  |               <td><fmt:formatDate value="${pet.birthDate}" pattern="yyyy-MM-dd"/></td> | ||||||
|  |             </tr> | ||||||
|  |             <tr> | ||||||
|  |               <th>Type</th> | ||||||
|  |               <td>${pet.type.name}</td> | ||||||
|  |             </tr> | ||||||
|  |           </table> | ||||||
|  |         </td> | ||||||
|  |         <td valign="top"> | ||||||
|  |           <table> | ||||||
|  |             <tr> | ||||||
|  |             <thead> | ||||||
|  |               <th>Visit Date</th> | ||||||
|  |               <th>Description</th> | ||||||
|  |             </thead> | ||||||
|  |             </tr> | ||||||
|  |             <c:forEach var="visit" items="${pet.visits}"> | ||||||
|  |               <tr> | ||||||
|  |                 <td><fmt:formatDate value="${visit.date}" pattern="yyyy-MM-dd"/></td> | ||||||
|  |                 <td>${visit.description}</td> | ||||||
|  |               </tr> | ||||||
|  |             </c:forEach> | ||||||
|  |           </table> | ||||||
|  |         </td> | ||||||
|  |       </tr> | ||||||
|  |     </table> | ||||||
|  |     <table class="table-buttons"> | ||||||
|  |       <tr> | ||||||
|  |         <td> | ||||||
|  |           <form method="GET" action="<c:url value="/editPet.do"/>" name="formEditPet${pet.id}"> | ||||||
|  |             <input type="hidden" name="petId" value="${pet.id}"/> | ||||||
|  |             <p class="submit"><input type="submit" value="Edit Pet"/></p> | ||||||
|  |           </form> | ||||||
|  |         </td> | ||||||
|  |         <td> | ||||||
|  |           <form method="GET" action="<c:url value="/addVisit.do"/>" name="formVisitPet${pet.id}"> | ||||||
|  |             <input type="hidden" name="petId" value="${pet.id}"/> | ||||||
|  |             <p class="submit"><input type="submit" value="Add Visit"/></p> | ||||||
|  |           </form> | ||||||
|  |         </td> | ||||||
|  |       </tr> | ||||||
|  |     </table> | ||||||
|  |   </c:forEach> | ||||||
|  |    | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,58 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <h2><c:if test="${owner.new}">New </c:if>Owner:</h2> | ||||||
|  | 
 | ||||||
|  | <form:form modelAttribute="owner"> | ||||||
|  |   <table> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         First Name: <form:errors path="firstName" cssClass="errors"/> | ||||||
|  |         <br/> | ||||||
|  |         <form:input path="firstName" size="30" maxlength="80"/> | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         Last Name: <form:errors path="lastName" cssClass="errors"/> | ||||||
|  |         <br/> | ||||||
|  |         <form:input path="lastName" size="30" maxlength="80"/> | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         Address: <form:errors path="address" cssClass="errors"/> | ||||||
|  |         <br/> | ||||||
|  |         <form:input path="address" size="30" maxlength="80"/> | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         City: <form:errors path="city" cssClass="errors"/> | ||||||
|  |         <br/> | ||||||
|  |         <form:input path="city" size="30" maxlength="80"/> | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         Telephone: <form:errors path="telephone" cssClass="errors"/> | ||||||
|  |         <br/> | ||||||
|  |         <form:input path="telephone" size="20" maxlength="20"/> | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <td> | ||||||
|  |         <c:choose> | ||||||
|  |           <c:when test="${owner.new}"> | ||||||
|  |             <p class="submit"><input type="submit" value="Add Owner"/></p> | ||||||
|  |           </c:when> | ||||||
|  |           <c:otherwise> | ||||||
|  |             <p class="submit"><input type="submit" value="Update Owner"/></p> | ||||||
|  |           </c:otherwise> | ||||||
|  |         </c:choose> | ||||||
|  |       </td> | ||||||
|  |     </tr> | ||||||
|  |   </table> | ||||||
|  | </form:form> | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <h2>Owners:</h2> | ||||||
|  | 
 | ||||||
|  | <table> | ||||||
|  |   <tr> | ||||||
|  |   <thead> | ||||||
|  |     <th>Name</th> | ||||||
|  |     <th>Address</th> | ||||||
|  |     <th>City</th> | ||||||
|  |     <th>Telephone</th> | ||||||
|  |     <th>Pets</th> | ||||||
|  |   </thead> | ||||||
|  |   </tr> | ||||||
|  |   <c:forEach var="owner" items="${selections}"> | ||||||
|  |     <tr> | ||||||
|  |       <td> | ||||||
|  |           <a href="owner.do?ownerId=${owner.id}">${owner.firstName} ${owner.lastName}</a> | ||||||
|  |       </td> | ||||||
|  |       <td>${owner.address}</td> | ||||||
|  |       <td>${owner.city}</td> | ||||||
|  |       <td>${owner.telephone}</td> | ||||||
|  |       <td> | ||||||
|  |         <c:forEach var="pet" items="${owner.pets}"> | ||||||
|  |           ${pet.name}   | ||||||
|  |         </c:forEach> | ||||||
|  |       </td> | ||||||
|  |     </tr> | ||||||
|  |   </c:forEach> | ||||||
|  | </table> | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,47 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <h2><c:if test="${pet.new}">New </c:if>Pet</h2> | ||||||
|  | 
 | ||||||
|  | <b>Owner:</b> ${pet.owner.firstName} ${pet.owner.lastName} | ||||||
|  | <br/> | ||||||
|  | 
 | ||||||
|  | <form:form modelAttribute="pet"> | ||||||
|  |   <table> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         Name: <form:errors path="name" cssClass="errors"/> | ||||||
|  |         <br/> | ||||||
|  |         <form:input path="name" size="30" maxlength="30"/> | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         Birth Date: <form:errors path="birthDate" cssClass="errors"/> | ||||||
|  |         <br/> | ||||||
|  |         <form:input path="birthDate" size="10" maxlength="10"/> (yyyy-mm-dd) | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         Type: <form:errors path="type" cssClass="errors"/> | ||||||
|  |         <br/> | ||||||
|  |         <form:select path="type" items="${types}"/> | ||||||
|  |       </th> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <td> | ||||||
|  |         <c:choose> | ||||||
|  |           <c:when test="${pet.new}"> | ||||||
|  |             <p class="submit"><input type="submit" value="Add Pet"/></p> | ||||||
|  |           </c:when> | ||||||
|  |           <c:otherwise> | ||||||
|  |             <p class="submit"><input type="submit" value="Update Pet"/></p> | ||||||
|  |           </c:otherwise> | ||||||
|  |         </c:choose> | ||||||
|  |       </td> | ||||||
|  |     </tr> | ||||||
|  |   </table> | ||||||
|  | </form:form> | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,49 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <h2/>Internal error</h2> | ||||||
|  | <p/> | ||||||
|  | 
 | ||||||
|  | <%  | ||||||
|  | try { | ||||||
|  | 	// The Servlet spec guarantees this attribute will be available | ||||||
|  | 	Throwable exception = (Throwable) request.getAttribute("javax.servlet.error.exception");  | ||||||
|  | 
 | ||||||
|  | 	if (exception != null) { | ||||||
|  | 		if (exception instanceof ServletException) { | ||||||
|  | 			// It's a ServletException: we should extract the root cause | ||||||
|  | 			ServletException sex = (ServletException) exception; | ||||||
|  | 			Throwable rootCause = sex.getRootCause(); | ||||||
|  | 			if (rootCause == null) | ||||||
|  | 				rootCause = sex; | ||||||
|  | 			out.println("** Root cause is: "+ rootCause.getMessage()); | ||||||
|  | 			rootCause.printStackTrace(new java.io.PrintWriter(out));  | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			// It's not a ServletException, so we'll just show it | ||||||
|  | 			exception.printStackTrace(new java.io.PrintWriter(out));  | ||||||
|  | 		} | ||||||
|  | 	}  | ||||||
|  | 	else  { | ||||||
|  |     	out.println("No error information available"); | ||||||
|  | 	}  | ||||||
|  | 
 | ||||||
|  | 	// Display cookies | ||||||
|  | 	out.println("\nCookies:\n"); | ||||||
|  | 	Cookie[] cookies = request.getCookies(); | ||||||
|  | 	if (cookies != null) { | ||||||
|  |     	for (int i = 0; i < cookies.length; i++) { | ||||||
|  |       		out.println(cookies[i].getName() + "=[" + cookies[i].getValue() + "]"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	     | ||||||
|  | } catch (Exception ex) {  | ||||||
|  | 	ex.printStackTrace(new java.io.PrintWriter(out)); | ||||||
|  | } | ||||||
|  | %> | ||||||
|  | 
 | ||||||
|  | <p/> | ||||||
|  | <br/> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <h2>Veterinarians:</h2> | ||||||
|  | 
 | ||||||
|  | <table> | ||||||
|  |   <tr> | ||||||
|  |   <thead> | ||||||
|  |     <th>Name</th> | ||||||
|  |     <th>Specialties</th> | ||||||
|  |   </thead> | ||||||
|  |   </tr> | ||||||
|  |   <c:forEach var="vet" items="${vetList}"> | ||||||
|  |     <tr> | ||||||
|  |       <td>${vet.firstName} ${vet.lastName}</td> | ||||||
|  |       <td> | ||||||
|  | 	    <c:forEach var="specialty" items="${vet.specialties}"> | ||||||
|  |           ${specialty.name} | ||||||
|  |         </c:forEach> | ||||||
|  |         <c:if test="${vet.nrOfSpecialties == 0}">none</c:if> | ||||||
|  |       </td> | ||||||
|  |     </tr> | ||||||
|  |   </c:forEach> | ||||||
|  | </table> | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,70 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <h2><c:if test="${visit.new}">New </c:if>Visit:</h2> | ||||||
|  | 
 | ||||||
|  | <form:form modelAttribute="visit"> | ||||||
|  |   <b>Pet:</b> | ||||||
|  |   <table width="333"> | ||||||
|  |     <tr> | ||||||
|  |     <thead> | ||||||
|  |       <th>Name</th> | ||||||
|  |       <th>Birth Date</th> | ||||||
|  |       <th>Type</th> | ||||||
|  |       <th>Owner</th> | ||||||
|  |     </thead> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <td>${visit.pet.name}</td> | ||||||
|  |       <td><fmt:formatDate value="${visit.pet.birthDate}" pattern="yyyy-MM-dd"/></td> | ||||||
|  |       <td>${visit.pet.type.name}</td> | ||||||
|  |       <td>${visit.pet.owner.firstName} ${visit.pet.owner.lastName}</td> | ||||||
|  |     </tr> | ||||||
|  |   </table> | ||||||
|  | 
 | ||||||
|  |   <table width="333"> | ||||||
|  |     <tr> | ||||||
|  |       <th> | ||||||
|  |         Date: | ||||||
|  |         <br/><form:errors path="date" cssClass="errors"/> | ||||||
|  |       </th> | ||||||
|  |       <td> | ||||||
|  |         <form:input path="date" size="10" maxlength="10"/> (yyyy-mm-dd) | ||||||
|  |       </td> | ||||||
|  |     <tr/> | ||||||
|  |     <tr> | ||||||
|  |       <th valign="top"> | ||||||
|  |         Description: | ||||||
|  |         <br/><form:errors path="description" cssClass="errors"/> | ||||||
|  |       </th> | ||||||
|  |       <td> | ||||||
|  |         <form:textarea path="description" rows="10" cols="25"/> | ||||||
|  |       </td> | ||||||
|  |     </tr> | ||||||
|  |     <tr> | ||||||
|  |       <td colspan="2"> | ||||||
|  |         <input type="hidden" name="petId" value="${visit.pet.id}"/> | ||||||
|  |         <p class="submit"><input type="submit" value="Add Visit"/></p> | ||||||
|  |       </td> | ||||||
|  |     </tr> | ||||||
|  |   </table> | ||||||
|  | </form:form> | ||||||
|  | 
 | ||||||
|  | <br/> | ||||||
|  | <b>Previous Visits:</b> | ||||||
|  | <table width="333"> | ||||||
|  |   <tr> | ||||||
|  |     <th>Date</th> | ||||||
|  |     <th>Description</th> | ||||||
|  |   </tr> | ||||||
|  |   <c:forEach var="visit" items="${visit.pet.visits}"> | ||||||
|  |     <c:if test="${!visit.new}"> | ||||||
|  |       <tr> | ||||||
|  |         <td><fmt:formatDate value="${visit.date}" pattern="yyyy-MM-dd"/></td> | ||||||
|  |         <td>${visit.description}</td> | ||||||
|  |       </tr> | ||||||
|  |     </c:if> | ||||||
|  |   </c:forEach> | ||||||
|  | </table> | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | <%@ include file="/WEB-INF/jsp/header.jsp" %> | ||||||
|  | 
 | ||||||
|  | <img src="images/pets.png" align="right" style="position:relative;right:30px;"> | ||||||
|  | <h2><fmt:message key="welcome"/></h2> | ||||||
|  | 
 | ||||||
|  | <ul> | ||||||
|  |   <li><a href="<c:url value="/findOwners.do"/>">Find owner</a></li> | ||||||
|  |   <li><a href="<c:url value="/vets.do"/>">Display all veterinarians</a></li> | ||||||
|  |   <li><a href="<c:url value="/html/petclinic.html"/>">Tutorial</a></li> | ||||||
|  |   <li><a href="<c:url value="/docs/index.html"/>">Documentation</a></li> | ||||||
|  | </ul> | ||||||
|  | 
 | ||||||
|  | <p> </p> | ||||||
|  | 
 | ||||||
|  | <%@ include file="/WEB-INF/jsp/footer.jsp" %> | ||||||
|  | @ -0,0 +1,68 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!-- | ||||||
|  | 	- DispatcherServlet application context for PetClinic's web tier. | ||||||
|  | --> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 		xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" | ||||||
|  | 		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd | ||||||
|  | 				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- The controllers are autodetected POJOs labeled with the @Controller annotation. | ||||||
|  | 	--> | ||||||
|  | 	<context:component-scan base-package="org.springframework.samples.petclinic.web"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- The form-based controllers within this application provide @RequestMapping  | ||||||
|  | 		- annotations at the type level for path mapping URLs and @RequestMapping  | ||||||
|  | 		- at the method level for request type mappings (e.g., GET and POST).  | ||||||
|  | 		- In contrast, ClinicController - which is not form-based - provides  | ||||||
|  | 		- @RequestMapping only at the method level for path mapping URLs. | ||||||
|  | 		- | ||||||
|  | 		- DefaultAnnotationHandlerMapping is driven by these annotations and is  | ||||||
|  | 		- enabled by default with Java 5+. | ||||||
|  | 	--> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- This bean processes annotated handler methods, applying PetClinic-specific PropertyEditors | ||||||
|  | 		- for request parameter binding. It overrides the default AnnotationMethodHandlerAdapter. | ||||||
|  | 	--> | ||||||
|  | 	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> | ||||||
|  | 		<property name="webBindingInitializer"> | ||||||
|  | 			<bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer"/> | ||||||
|  | 		</property> | ||||||
|  | 	</bean> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- This bean resolves specific types of exceptions to corresponding logical  | ||||||
|  | 		- view names for error views. The default behaviour of DispatcherServlet  | ||||||
|  | 		- is to propagate all exceptions to the servlet container: this will happen  | ||||||
|  | 		- here with all other types of exceptions. | ||||||
|  | 	--> | ||||||
|  | 	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> | ||||||
|  | 		<property name="exceptionMappings"> | ||||||
|  | 			<props> | ||||||
|  | 				<prop key="org.springframework.dao.DataAccessException">dataAccessFailure</prop> | ||||||
|  | 				<prop key="org.springframework.transaction.TransactionException">dataAccessFailure</prop> | ||||||
|  | 			</props> | ||||||
|  | 		</property> | ||||||
|  | 	</bean> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- This bean configures the 'prefix' and 'suffix' properties of  | ||||||
|  | 		- InternalResourceViewResolver, which resolves logical view names  | ||||||
|  | 		- returned by Controllers. For example, a logical view name of "vets"  | ||||||
|  | 		- will be mapped to "/WEB-INF/jsp/vets.jsp". | ||||||
|  | 	--> | ||||||
|  | 	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" | ||||||
|  | 			p:suffix=".jsp"/> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- Message source for this context, loaded from localized "messages_xx" files. | ||||||
|  | 		- Could also reside in the root application context, as it is generic, | ||||||
|  | 		- but is currently just used within PetClinic's web tier. | ||||||
|  | 	--> | ||||||
|  | 	<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" | ||||||
|  | 			p:basename="messages"/> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,143 @@ | ||||||
|  | <?xml version="1.0" encoding="ISO-8859-1"?> | ||||||
|  | <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 		xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<display-name>Spring PetClinic</display-name> | ||||||
|  | 
 | ||||||
|  | 	<description>Spring PetClinic sample application</description> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Key of the system property that should specify the root directory of this | ||||||
|  | 		web app. Applied by WebAppRootListener or Log4jConfigListener. | ||||||
|  | 	--> | ||||||
|  | 	<context-param> | ||||||
|  | 		<param-name>webAppRootKey</param-name> | ||||||
|  | 		<param-value>petclinic.root</param-value> | ||||||
|  | 	</context-param> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		Location of the Log4J config file, for initialization and refresh checks. | ||||||
|  | 		Applied by Log4jConfigListener. | ||||||
|  | 	--> | ||||||
|  | 	<context-param> | ||||||
|  | 		<param-name>log4jConfigLocation</param-name> | ||||||
|  | 		<param-value>/WEB-INF/classes/log4j.properties</param-value> | ||||||
|  | 	</context-param> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- Location of the XML file that defines the root application context. | ||||||
|  | 		- Applied by ContextLoaderServlet. | ||||||
|  | 		- | ||||||
|  | 		- Can be set to: | ||||||
|  | 		- "/WEB-INF/applicationContext-hibernate.xml" for the Hibernate implementation, | ||||||
|  | 		- "/WEB-INF/applicationContext-jpa.xml" for the JPA one, or | ||||||
|  | 		- "/WEB-INF/applicationContext-jdbc.xml" for the JDBC one. | ||||||
|  | 	--> | ||||||
|  | 	<context-param> | ||||||
|  | 		<param-name>contextConfigLocation</param-name> | ||||||
|  | 
 | ||||||
|  | 		<param-value>/WEB-INF/applicationContext-jdbc.xml</param-value> | ||||||
|  | 		<!-- | ||||||
|  | 		<param-value>/WEB-INF/applicationContext-hibernate.xml</param-value> | ||||||
|  | 		<param-value>/WEB-INF/applicationContext-jpa.xml</param-value> | ||||||
|  | 		--> | ||||||
|  | 
 | ||||||
|  | 		<!-- | ||||||
|  | 			To use the JPA variant above, you will need to enable Spring load-time | ||||||
|  | 			weaving in your server environment. See PetClinic's readme and/or | ||||||
|  | 			Spring's JPA documentation for information on how to do this. | ||||||
|  | 		--> | ||||||
|  | 	</context-param> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- Configures Log4J for this web app. | ||||||
|  | 		- As this context specifies a context-param "log4jConfigLocation", its file path | ||||||
|  | 		- is used to load the Log4J configuration, including periodic refresh checks. | ||||||
|  | 		- | ||||||
|  | 		- Would fall back to default Log4J initialization (non-refreshing) if no special | ||||||
|  | 		- context-params are given. | ||||||
|  | 		- | ||||||
|  | 		- Exports a "web app root key", i.e. a system property that specifies the root | ||||||
|  | 		- directory of this web app, for usage in log file paths. | ||||||
|  | 		- This web app specifies "petclinic.root" (see log4j.properties file). | ||||||
|  | 	--> | ||||||
|  | 	<!-- Leave the listener commented-out if using JBoss --> | ||||||
|  | 	<!-- | ||||||
|  | 	<listener> | ||||||
|  | 		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> | ||||||
|  | 	</listener> | ||||||
|  | 	--> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- Loads the root application context of this web app at startup, | ||||||
|  | 		- by default from "/WEB-INF/applicationContext.xml". | ||||||
|  | 		- Note that you need to fall back to Spring's ContextLoaderServlet for | ||||||
|  | 		- J2EE servers that do not follow the Servlet 2.4 initialization order. | ||||||
|  | 		- | ||||||
|  | 		- Use WebApplicationContextUtils.getWebApplicationContext(servletContext) | ||||||
|  | 		- to access it anywhere in the web application, outside of the framework. | ||||||
|  | 		- | ||||||
|  | 		- The root context is the parent of all servlet-specific contexts. | ||||||
|  | 		- This means that its beans are automatically available in these child contexts, | ||||||
|  | 		- both for getBean(name) calls and (external) bean references. | ||||||
|  | 	--> | ||||||
|  | 	<listener> | ||||||
|  | 		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> | ||||||
|  | 	</listener> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- Servlet that dispatches request to registered handlers (Controller implementations). | ||||||
|  | 		- Has its own application context, by default defined in "{servlet-name}-servlet.xml", | ||||||
|  | 		- i.e. "petclinic-servlet.xml". | ||||||
|  | 		- | ||||||
|  | 		- A web app can contain any number of such servlets. | ||||||
|  | 		- Note that this web app has a shared root application context, serving as parent | ||||||
|  | 		- of all DispatcherServlet contexts. | ||||||
|  | 	--> | ||||||
|  | 	<servlet> | ||||||
|  | 		<servlet-name>petclinic</servlet-name> | ||||||
|  | 		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> | ||||||
|  | 		<load-on-startup>2</load-on-startup> | ||||||
|  | 	</servlet> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- Maps the petclinic dispatcher to "*.do". All handler mappings in | ||||||
|  | 		- petclinic-servlet.xml will by default be applied to this subpath. | ||||||
|  | 		- If a mapping isn't a /* subpath, the handler mappings are considered | ||||||
|  | 		- relative to the web app root. | ||||||
|  | 		- | ||||||
|  | 		- NOTE: A single dispatcher can be mapped to multiple paths, like any servlet. | ||||||
|  | 	--> | ||||||
|  | 	<servlet-mapping> | ||||||
|  | 		<servlet-name>petclinic</servlet-name> | ||||||
|  | 		<url-pattern>*.do</url-pattern> | ||||||
|  | 	</servlet-mapping> | ||||||
|  | 
 | ||||||
|  | 	<session-config> | ||||||
|  | 		<session-timeout>10</session-timeout> | ||||||
|  | 	</session-config> | ||||||
|  | 
 | ||||||
|  | 	<welcome-file-list> | ||||||
|  | 		<!-- Redirects to "welcome.htm" for dispatcher handling --> | ||||||
|  | 		<welcome-file>index.jsp</welcome-file> | ||||||
|  | 	</welcome-file-list> | ||||||
|  | 
 | ||||||
|  | 	<error-page> | ||||||
|  | 		<exception-type>java.lang.Exception</exception-type> | ||||||
|  | 		<!-- Displays a stack trace --> | ||||||
|  | 		<location>/WEB-INF/jsp/uncaughtException.jsp</location> | ||||||
|  | 	</error-page> | ||||||
|  | 
 | ||||||
|  | 	<!-- | ||||||
|  | 		- Reference to PetClinic database. | ||||||
|  | 		- Only needed if not using a local DataSource but a JNDI one instead. | ||||||
|  | 	--> | ||||||
|  | 	<!-- | ||||||
|  | 	<resource-ref> | ||||||
|  | 		<res-ref-name>jdbc/petclinic</res-ref-name> | ||||||
|  | 		<res-type>javax.sql.DataSource</res-type> | ||||||
|  | 		<res-auth>Container</res-auth> | ||||||
|  | 	</resource-ref> | ||||||
|  | 	--> | ||||||
|  | 
 | ||||||
|  | </web-app> | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 14 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.9 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 54 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.9 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.8 KiB | 
|  | @ -0,0 +1,5 @@ | ||||||
|  | <%@ include file="/WEB-INF/jsp/includes.jsp" %> | ||||||
|  | 
 | ||||||
|  | <%-- Redirected because we can't set the welcome page to a virtual URL. --%> | ||||||
|  | <c:redirect url="/welcome.do"/> | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,234 @@ | ||||||
|  | /* main elements */ | ||||||
|  | 
 | ||||||
|  | body,div,td { | ||||||
|  | 	font-family: Arial, Helvetica, sans-serif; | ||||||
|  | 	font-size: 12px; | ||||||
|  | 	color: #666; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | body { | ||||||
|  | 	background-color: #fff; | ||||||
|  | 	background-image: url(../images/banner-graphic.png); | ||||||
|  | 	background-position: top center; | ||||||
|  | 	background-repeat: no-repeat; | ||||||
|  | 	text-align: center; | ||||||
|  | 	min-width: 600px; | ||||||
|  | 	margin-top: 60px; | ||||||
|  | 	margin-left: auto; | ||||||
|  | 	margin-right: auto; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div { | ||||||
|  | 	margin: 5px 25px 5px 25px; | ||||||
|  | 	text-align: left; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* header and footer elements */ | ||||||
|  | 
 | ||||||
|  | #main { | ||||||
|  |   	margin:0 auto; | ||||||
|  |   	position:relative; | ||||||
|  |   	top: 35px; | ||||||
|  |   	left:0px; | ||||||
|  |   	width:560px; | ||||||
|  |   	text-align:left; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .footer { | ||||||
|  | 	background:#fff; | ||||||
|  | 	border:none; | ||||||
|  | 	margin-top:20px; | ||||||
|  | 	border-top:1px solid #999999; | ||||||
|  | 	width:100%; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .footer td {color:#999999;} | ||||||
|  | 
 | ||||||
|  | .footer a:link {color: #7db223;} | ||||||
|  | 
 | ||||||
|  | 	 | ||||||
|  | /* text styles */ | ||||||
|  | 
 | ||||||
|  | h1,h2,h3 { | ||||||
|  | 	font-family: Helvetica, sans-serif; | ||||||
|  | 	color: #7db223; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | h1 { | ||||||
|  | 	font-size: 20px; | ||||||
|  | 	line-height: 26px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | h2 { | ||||||
|  | 	font-size: 18px; | ||||||
|  | 	line-height: 24px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | h3 { | ||||||
|  | 	font-size: 15px; | ||||||
|  | 	line-height: 21px; | ||||||
|  | 	color:#555; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | h4 { | ||||||
|  | 	font-size: 14px; | ||||||
|  | 	line-height: 20px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .errors { | ||||||
|  | 	color: red; | ||||||
|  | 	font-weight: bold; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | a { | ||||||
|  | 	text-decoration: underline; | ||||||
|  | 	font-size: 13px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | a:link { | ||||||
|  | 	color: #7db223; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | a:hover { | ||||||
|  | 	color: #456314; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | a:active { | ||||||
|  | 	color: #7db223; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | a:visited { | ||||||
|  | 	color: #7db223; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ul { | ||||||
|  | 	list-style: disc url(../images/bullet-arrow.png); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | li { | ||||||
|  | 	padding-top: 5px; | ||||||
|  | 	text-align: left; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | li ul { | ||||||
|  | 	list-style: square url(images/sub-bullet.gif); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | li ul li ul { | ||||||
|  | 	list-style: circle none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* table elements */ | ||||||
|  | 
 | ||||||
|  | table { | ||||||
|  | 	background: #d6e2c3; | ||||||
|  | 	margin: 3px 0 0 0; | ||||||
|  | 	border: 4px solid #d6e2c3; | ||||||
|  | 	border-collapse: collapse; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | table table { | ||||||
|  | 	margin: -5px 0; | ||||||
|  | 	border: 0px solid #e0e7d3; | ||||||
|  | 	width: 100%; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | table td,table th { | ||||||
|  | 	padding: 8px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | table th { | ||||||
|  | 	font-size: 12px; | ||||||
|  | 	text-align: left; | ||||||
|  | 	font-weight: bold; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | table thead { | ||||||
|  | 	font-weight: bold; | ||||||
|  | 	font-style: italic; | ||||||
|  | 	background-color: #c2ceaf; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | table a:link {color: #303030;} | ||||||
|  | 
 | ||||||
|  | caption { | ||||||
|  | 	caption-side: top; | ||||||
|  | 	width: auto; | ||||||
|  | 	text-align: left; | ||||||
|  | 	font-size: 12px; | ||||||
|  | 	color: #848f73; | ||||||
|  | 	padding-bottom: 4px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fieldset { | ||||||
|  | 	background: #e0e7d3; | ||||||
|  | 	padding: 8px; | ||||||
|  | 	padding-bottom: 22px; | ||||||
|  | 	border: none; | ||||||
|  | 	width: 560px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fieldset label { | ||||||
|  | 	width: 70px; | ||||||
|  | 	float: left; | ||||||
|  | 	margin-top: 1.7em; | ||||||
|  | 	margin-left: 20px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fieldset textfield { | ||||||
|  | 	margin: 3px; | ||||||
|  | 	height: 20px; | ||||||
|  | 	background: #e0e7d3; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fieldset textarea { | ||||||
|  | 	margin: 3px; | ||||||
|  | 	height: 165px; | ||||||
|  | 	background: #e0e7d3; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fieldset input { | ||||||
|  | 	margin: 3px; | ||||||
|  | 	height: 20px; | ||||||
|  | 	background: #e0e7d3; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fieldset table { | ||||||
|  | 	width: 100%; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fieldset th { | ||||||
|  | 	padding-left: 25px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .table-buttons { | ||||||
|  | 	background-color:#fff; | ||||||
|  | 	border:none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .table-buttons td { | ||||||
|  | 	border:none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .submit input { | ||||||
|  | 	background:url(../images/submit-bg.png) repeat-x; | ||||||
|  |     border: 2px outset #d7b9c9; | ||||||
|  | 	color:#383838; | ||||||
|  | 	padding:2px 10px; | ||||||
|  | 	font-size:11px; | ||||||
|  | 	text-transform:uppercase; | ||||||
|  | 	font-weight:bold; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .updated { | ||||||
|  | 	background:#ecf1e5; | ||||||
|  | 	font-size:11px; | ||||||
|  | 	margin-left:2px; | ||||||
|  | 	border:4px solid #ecf1e5; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .updated td { | ||||||
|  | 	padding:2px 8px; | ||||||
|  | 	font-size:11px; | ||||||
|  | 	color:#888888; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" | ||||||
|  | 	xmlns:tx="http://www.springframework.org/schema/tx" | ||||||
|  | 	xsi:schemaLocation=" | ||||||
|  | 		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd | ||||||
|  | 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd | ||||||
|  | 		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<context:property-placeholder location="classpath:jdbc.properties"/> | ||||||
|  | 
 | ||||||
|  | 	<context:annotation-config/> | ||||||
|  | 
 | ||||||
|  | 	<tx:annotation-driven/> | ||||||
|  | 
 | ||||||
|  | 	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" | ||||||
|  | 			p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" | ||||||
|  | 			p:username="${jdbc.username}" p:password="${jdbc.password}" /> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,224 @@ | ||||||
|  | package org.springframework.samples.petclinic; | ||||||
|  | 
 | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.Date; | ||||||
|  | 
 | ||||||
|  | import static org.junit.Assert.assertEquals; | ||||||
|  | import static org.junit.Assert.assertTrue; | ||||||
|  | import org.junit.Test; | ||||||
|  | 
 | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.samples.petclinic.util.EntityUtils; | ||||||
|  | import org.springframework.test.context.ContextConfiguration; | ||||||
|  | import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * <p> | ||||||
|  |  * Base class for {@link Clinic} integration tests. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * "AbstractClinicTests-context.xml" declares a common | ||||||
|  |  * {@link javax.sql.DataSource DataSource}. Subclasses should specify | ||||||
|  |  * additional context locations which declare a | ||||||
|  |  * {@link org.springframework.transaction.PlatformTransactionManager PlatformTransactionManager} | ||||||
|  |  * and a concrete implementation of {@link Clinic}. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * This class extends {@link AbstractTransactionalJUnit4SpringContextTests}, | ||||||
|  |  * one of the valuable testing support classes provided by the | ||||||
|  |  * <em>Spring TestContext Framework</em> found in the | ||||||
|  |  * <code>org.springframework.test.context</code> package. The | ||||||
|  |  * annotation-driven configuration used here represents best practice for | ||||||
|  |  * integration tests with Spring. Note, however, that | ||||||
|  |  * AbstractTransactionalJUnit4SpringContextTests serves only as a convenience | ||||||
|  |  * for extension. For example, if you do not wish for your test classes to be | ||||||
|  |  * tied to a Spring-specific class hierarchy, you may configure your tests with | ||||||
|  |  * annotations such as {@link ContextConfiguration @ContextConfiguration}, | ||||||
|  |  * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}, | ||||||
|  |  * {@link org.springframework.transaction.annotation.Transactional @Transactional}, | ||||||
|  |  * etc. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * AbstractClinicTests and its subclasses benefit from the following services | ||||||
|  |  * provided by the Spring TestContext Framework: | ||||||
|  |  * </p> | ||||||
|  |  * <ul> | ||||||
|  |  * <li><strong>Spring IoC container caching</strong> which spares us | ||||||
|  |  * unnecessary set up time between test execution.</li> | ||||||
|  |  * <li><strong>Dependency Injection</strong> of test fixture instances, | ||||||
|  |  * meaning that we don't need to perform application context lookups. See the | ||||||
|  |  * use of {@link Autowired @Autowired} on the <code>clinic</code> instance | ||||||
|  |  * variable, which uses autowiring <em>by type</em>. As an alternative, we | ||||||
|  |  * could annotate <code>clinic</code> with | ||||||
|  |  * {@link javax.annotation.Resource @Resource} to achieve dependency injection | ||||||
|  |  * <em>by name</em>. | ||||||
|  |  * <em>(see: {@link ContextConfiguration @ContextConfiguration}, | ||||||
|  |  * {@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener DependencyInjectionTestExecutionListener})</em></li> | ||||||
|  |  * <li><strong>Transaction management</strong>, meaning each test method is | ||||||
|  |  * executed in its own transaction, which is automatically rolled back by | ||||||
|  |  * default. Thus, even if tests insert or otherwise change database state, there | ||||||
|  |  * is no need for a teardown or cleanup script. | ||||||
|  |  * <em>(see: {@link org.springframework.test.context.transaction.TransactionConfiguration @TransactionConfiguration}, | ||||||
|  |  * {@link org.springframework.transaction.annotation.Transactional @Transactional}, | ||||||
|  |  * {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener TransactionalTestExecutionListener})</em></li> | ||||||
|  |  * <li><strong>Useful inherited protected fields</strong>, such as a | ||||||
|  |  * {@link org.springframework.jdbc.core.simple.SimpleJdbcTemplate SimpleJdbcTemplate} | ||||||
|  |  * that can be used to verify database state after test operations or to verify | ||||||
|  |  * the results of queries performed by application code. An | ||||||
|  |  * {@link org.springframework.context.ApplicationContext ApplicationContext} is | ||||||
|  |  * also inherited and can be used for explicit bean lookup if necessary. | ||||||
|  |  * <em>(see: {@link org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests AbstractJUnit4SpringContextTests}, | ||||||
|  |  * {@link AbstractTransactionalJUnit4SpringContextTests})</em></li> | ||||||
|  |  * </ul> | ||||||
|  |  * <p> | ||||||
|  |  * The Spring TestContext Framework and related unit and integration testing | ||||||
|  |  * support classes are shipped in <code>spring-test.jar</code>. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  * @author Rod Johnson | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Sam Brannen | ||||||
|  |  */ | ||||||
|  | @ContextConfiguration | ||||||
|  | public abstract class AbstractClinicTests extends AbstractTransactionalJUnit4SpringContextTests { | ||||||
|  | 
 | ||||||
|  | 	@Autowired | ||||||
|  | 	protected Clinic clinic; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void getVets() { | ||||||
|  | 		Collection<Vet> vets = this.clinic.getVets(); | ||||||
|  | 		// Use the inherited countRowsInTable() convenience method (from | ||||||
|  | 		// AbstractTransactionalJUnit4SpringContextTests) to verify the results. | ||||||
|  | 		assertEquals("JDBC query must show the same number of vets", super.countRowsInTable("VETS"), vets.size()); | ||||||
|  | 		Vet v1 = EntityUtils.getById(vets, Vet.class, 2); | ||||||
|  | 		assertEquals("Leary", v1.getLastName()); | ||||||
|  | 		assertEquals(1, v1.getNrOfSpecialties()); | ||||||
|  | 		assertEquals("radiology", (v1.getSpecialties().get(0)).getName()); | ||||||
|  | 		Vet v2 = EntityUtils.getById(vets, Vet.class, 3); | ||||||
|  | 		assertEquals("Douglas", v2.getLastName()); | ||||||
|  | 		assertEquals(2, v2.getNrOfSpecialties()); | ||||||
|  | 		assertEquals("dentistry", (v2.getSpecialties().get(0)).getName()); | ||||||
|  | 		assertEquals("surgery", (v2.getSpecialties().get(1)).getName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void getPetTypes() { | ||||||
|  | 		Collection<PetType> petTypes = this.clinic.getPetTypes(); | ||||||
|  | 		assertEquals("JDBC query must show the same number of pet types", super.countRowsInTable("TYPES"), | ||||||
|  | 				petTypes.size()); | ||||||
|  | 		PetType t1 = EntityUtils.getById(petTypes, PetType.class, 1); | ||||||
|  | 		assertEquals("cat", t1.getName()); | ||||||
|  | 		PetType t4 = EntityUtils.getById(petTypes, PetType.class, 4); | ||||||
|  | 		assertEquals("snake", t4.getName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void findOwners() { | ||||||
|  | 		Collection<Owner> owners = this.clinic.findOwners("Davis"); | ||||||
|  | 		assertEquals(2, owners.size()); | ||||||
|  | 		owners = this.clinic.findOwners("Daviss"); | ||||||
|  | 		assertEquals(0, owners.size()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void loadOwner() { | ||||||
|  | 		Owner o1 = this.clinic.loadOwner(1); | ||||||
|  | 		assertTrue(o1.getLastName().startsWith("Franklin")); | ||||||
|  | 		Owner o10 = this.clinic.loadOwner(10); | ||||||
|  | 		assertEquals("Carlos", o10.getFirstName()); | ||||||
|  | 
 | ||||||
|  | 		// XXX: Add programmatic support for ending transactions with the | ||||||
|  | 		// TestContext Framework. | ||||||
|  | 
 | ||||||
|  | 		// Check lazy loading, by ending the transaction: | ||||||
|  | 		// endTransaction(); | ||||||
|  | 
 | ||||||
|  | 		// Now Owners are "disconnected" from the data store. | ||||||
|  | 		// We might need to touch this collection if we switched to lazy loading | ||||||
|  | 		// in mapping files, but this test would pick this up. | ||||||
|  | 		o1.getPets(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void insertOwner() { | ||||||
|  | 		Collection<Owner> owners = this.clinic.findOwners("Schultz"); | ||||||
|  | 		int found = owners.size(); | ||||||
|  | 		Owner owner = new Owner(); | ||||||
|  | 		owner.setLastName("Schultz"); | ||||||
|  | 		this.clinic.storeOwner(owner); | ||||||
|  | 		// assertTrue(!owner.isNew()); -- NOT TRUE FOR TOPLINK (before commit) | ||||||
|  | 		owners = this.clinic.findOwners("Schultz"); | ||||||
|  | 		assertEquals("Verifying number of owners after inserting a new one.", found + 1, owners.size()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void updateOwner() throws Exception { | ||||||
|  | 		Owner o1 = this.clinic.loadOwner(1); | ||||||
|  | 		String old = o1.getLastName(); | ||||||
|  | 		o1.setLastName(old + "X"); | ||||||
|  | 		this.clinic.storeOwner(o1); | ||||||
|  | 		o1 = this.clinic.loadOwner(1); | ||||||
|  | 		assertEquals(old + "X", o1.getLastName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void loadPet() { | ||||||
|  | 		Collection<PetType> types = this.clinic.getPetTypes(); | ||||||
|  | 		Pet p7 = this.clinic.loadPet(7); | ||||||
|  | 		assertTrue(p7.getName().startsWith("Samantha")); | ||||||
|  | 		assertEquals(EntityUtils.getById(types, PetType.class, 1).getId(), p7.getType().getId()); | ||||||
|  | 		assertEquals("Jean", p7.getOwner().getFirstName()); | ||||||
|  | 		Pet p6 = this.clinic.loadPet(6); | ||||||
|  | 		assertEquals("George", p6.getName()); | ||||||
|  | 		assertEquals(EntityUtils.getById(types, PetType.class, 4).getId(), p6.getType().getId()); | ||||||
|  | 		assertEquals("Peter", p6.getOwner().getFirstName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void insertPet() { | ||||||
|  | 		Owner o6 = this.clinic.loadOwner(6); | ||||||
|  | 		int found = o6.getPets().size(); | ||||||
|  | 		Pet pet = new Pet(); | ||||||
|  | 		pet.setName("bowser"); | ||||||
|  | 		Collection<PetType> types = this.clinic.getPetTypes(); | ||||||
|  | 		pet.setType(EntityUtils.getById(types, PetType.class, 2)); | ||||||
|  | 		pet.setBirthDate(new Date()); | ||||||
|  | 		o6.addPet(pet); | ||||||
|  | 		assertEquals(found + 1, o6.getPets().size()); | ||||||
|  | 		// both storePet and storeOwner are necessary to cover all ORM tools | ||||||
|  | 		this.clinic.storePet(pet); | ||||||
|  | 		this.clinic.storeOwner(o6); | ||||||
|  | 		// assertTrue(!pet.isNew()); -- NOT TRUE FOR TOPLINK (before commit) | ||||||
|  | 		o6 = this.clinic.loadOwner(6); | ||||||
|  | 		assertEquals(found + 1, o6.getPets().size()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void updatePet() throws Exception { | ||||||
|  | 		Pet p7 = this.clinic.loadPet(7); | ||||||
|  | 		String old = p7.getName(); | ||||||
|  | 		p7.setName(old + "X"); | ||||||
|  | 		this.clinic.storePet(p7); | ||||||
|  | 		p7 = this.clinic.loadPet(7); | ||||||
|  | 		assertEquals(old + "X", p7.getName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void insertVisit() { | ||||||
|  | 		Pet p7 = this.clinic.loadPet(7); | ||||||
|  | 		int found = p7.getVisits().size(); | ||||||
|  | 		Visit visit = new Visit(); | ||||||
|  | 		p7.addVisit(visit); | ||||||
|  | 		visit.setDescription("test"); | ||||||
|  | 		// both storeVisit and storePet are necessary to cover all ORM tools | ||||||
|  | 		this.clinic.storeVisit(visit); | ||||||
|  | 		this.clinic.storePet(p7); | ||||||
|  | 		// assertTrue(!visit.isNew()); -- NOT TRUE FOR TOPLINK (before commit) | ||||||
|  | 		p7 = this.clinic.loadPet(7); | ||||||
|  | 		assertEquals(found + 1, p7.getVisits().size()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | package org.springframework.samples.petclinic; | ||||||
|  | 
 | ||||||
|  | import static org.junit.Assert.assertEquals; | ||||||
|  | import static org.junit.Assert.assertNull; | ||||||
|  | 
 | ||||||
|  | import org.junit.Test; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * JUnit test for the {@link Owner} class. | ||||||
|  |  * | ||||||
|  |  * @author Ken Krebs | ||||||
|  |  */ | ||||||
|  | public class OwnerTests { | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void testHasPet() { | ||||||
|  | 		Owner owner = new Owner(); | ||||||
|  | 		Pet fido = new Pet(); | ||||||
|  | 		fido.setName("Fido"); | ||||||
|  | 		assertNull(owner.getPet("Fido")); | ||||||
|  | 		assertNull(owner.getPet("fido")); | ||||||
|  | 		owner.addPet(fido); | ||||||
|  | 		assertEquals(fido, owner.getPet("Fido")); | ||||||
|  | 		assertEquals(fido, owner.getPet("fido")); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | package org.springframework.samples.petclinic; | ||||||
|  | 
 | ||||||
|  | import org.junit.runner.RunWith; | ||||||
|  | import org.junit.runners.Suite; | ||||||
|  | import org.junit.runners.Suite.SuiteClasses; | ||||||
|  | 
 | ||||||
|  | import org.springframework.samples.petclinic.hibernate.HibernateClinicTests; | ||||||
|  | import org.springframework.samples.petclinic.jdbc.SimpleJdbcClinicTests; | ||||||
|  | import org.springframework.samples.petclinic.jpa.EntityManagerClinicTests; | ||||||
|  | import org.springframework.samples.petclinic.jpa.HibernateEntityManagerClinicTests; | ||||||
|  | import org.springframework.samples.petclinic.jpa.OpenJpaEntityManagerClinicTests; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * JUnit 4 based test suite for all PetClinic tests. | ||||||
|  |  * | ||||||
|  |  * @author Sam Brannen | ||||||
|  |  */ | ||||||
|  | @RunWith(Suite.class) | ||||||
|  | @SuiteClasses({ | ||||||
|  | 		OwnerTests.class, | ||||||
|  | 		SimpleJdbcClinicTests.class, | ||||||
|  | 		HibernateClinicTests.class, | ||||||
|  | 		EntityManagerClinicTests.class, | ||||||
|  | 		HibernateEntityManagerClinicTests.class, | ||||||
|  | 		OpenJpaEntityManagerClinicTests.class | ||||||
|  | }) | ||||||
|  | public class PetClinicSuiteTests { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xmlns:p="http://www.springframework.org/schema/p" | ||||||
|  | 	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<bean class="org.springframework.samples.petclinic.hibernate.HibernateClinic" /> | ||||||
|  | 
 | ||||||
|  | 	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" | ||||||
|  | 		p:dataSource-ref="dataSource" p:mappingResources="petclinic.hbm.xml"> | ||||||
|  | 		<property name="hibernateProperties"> | ||||||
|  | 			<props> | ||||||
|  | 				<prop key="hibernate.dialect">${hibernate.dialect}</prop> | ||||||
|  | 				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop> | ||||||
|  | 			</props> | ||||||
|  | 		</property> | ||||||
|  | 		<property name="eventListeners"> | ||||||
|  | 			<map> | ||||||
|  | 				<entry key="merge"> | ||||||
|  | 					<bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener" /> | ||||||
|  | 				</entry> | ||||||
|  | 			</map> | ||||||
|  | 		</property> | ||||||
|  | 	</bean> | ||||||
|  | 
 | ||||||
|  | 	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" | ||||||
|  | 		p:sessionFactory-ref="sessionFactory" /> | ||||||
|  | 
 | ||||||
|  | 	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | package org.springframework.samples.petclinic.hibernate; | ||||||
|  | 
 | ||||||
|  | import org.springframework.samples.petclinic.AbstractClinicTests; | ||||||
|  | import org.springframework.test.context.ContextConfiguration; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * <p> | ||||||
|  |  * Integration tests for the {@link HibernateClinic} implementation. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * "HibernateClinicTests-context.xml" determines the actual beans to test. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  * @author Sam Brannen | ||||||
|  |  */ | ||||||
|  | @ContextConfiguration | ||||||
|  | public class HibernateClinicTests extends AbstractClinicTests { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xmlns:p="http://www.springframework.org/schema/p" | ||||||
|  | 	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" | ||||||
|  | 		p:dataSource-ref="dataSource" /> | ||||||
|  | 
 | ||||||
|  | 	<bean class="org.springframework.samples.petclinic.jdbc.SimpleJdbcClinic" /> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | package org.springframework.samples.petclinic.jdbc; | ||||||
|  | 
 | ||||||
|  | import org.springframework.samples.petclinic.AbstractClinicTests; | ||||||
|  | import org.springframework.test.context.ContextConfiguration; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * <p> | ||||||
|  |  * Integration tests for the {@link SimpleJdbcClinic} implementation. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * "SimpleJdbcClinicTests-context.xml" determines the actual beans to test. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Thomas Risberg | ||||||
|  |  */ | ||||||
|  | @ContextConfiguration | ||||||
|  | public class SimpleJdbcClinicTests extends AbstractClinicTests { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,199 @@ | ||||||
|  | 
 | ||||||
|  | package org.springframework.samples.petclinic.jpa; | ||||||
|  | 
 | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.Date; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | 
 | ||||||
|  | import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; | ||||||
|  | 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.samples.petclinic.util.EntityUtils; | ||||||
|  | import org.springframework.test.annotation.ExpectedException; | ||||||
|  | import org.springframework.test.jpa.AbstractJpaTests; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * <p> | ||||||
|  |  * This class extends {@link AbstractJpaTests}, one of the valuable test | ||||||
|  |  * superclasses provided in the <code>org.springframework.test</code> package. | ||||||
|  |  * This represents best practice for integration tests with Spring for JPA based | ||||||
|  |  * tests which require <em>shadow class loading</em>. For all other types of | ||||||
|  |  * integration testing, the <em>Spring TestContext Framework</em> is | ||||||
|  |  * preferred. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * AbstractJpaTests and its superclasses provide the following services: | ||||||
|  |  * <ul> | ||||||
|  |  * <li>Injects test dependencies, meaning that we don't need to perform | ||||||
|  |  * application context lookups. See the setClinic() method. Injection uses | ||||||
|  |  * autowiring by type.</li> | ||||||
|  |  * <li>Executes each test method in its own transaction, which is automatically | ||||||
|  |  * rolled back by default. This means that even if tests insert or otherwise | ||||||
|  |  * change database state, there is no need for a teardown or cleanup script.</li> | ||||||
|  |  * <li>Provides useful inherited protected fields, such as a | ||||||
|  |  * {@link SimpleJdbcTemplate} that can be used to verify database state after | ||||||
|  |  * test operations, or verify the results of queries performed by application | ||||||
|  |  * code. Alternatively, you can use protected convenience methods such as | ||||||
|  |  * {@link #countRowsInTable(String)}, {@link #deleteFromTables(String[])}, | ||||||
|  |  * etc. An ApplicationContext is also inherited, and can be used for explicit | ||||||
|  |  * lookup if necessary.</li> | ||||||
|  |  * </ul> | ||||||
|  |  * <p> | ||||||
|  |  * {@link AbstractJpaTests} and related classes are shipped in | ||||||
|  |  * <code>spring-test.jar</code>. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Rod Johnson | ||||||
|  |  * @author Sam Brannen | ||||||
|  |  * @see AbstractJpaTests | ||||||
|  |  */ | ||||||
|  | public abstract class AbstractJpaClinicTests extends AbstractJpaTests { | ||||||
|  | 
 | ||||||
|  | 	protected Clinic clinic; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * This method is provided to set the Clinic instance being tested by the | ||||||
|  | 	 * Dependency Injection injection behaviour of the superclass from the | ||||||
|  | 	 * <code>org.springframework.test</code> package. | ||||||
|  | 	 * | ||||||
|  | 	 * @param clinic clinic to test | ||||||
|  | 	 */ | ||||||
|  | 	public void setClinic(Clinic clinic) { | ||||||
|  | 		this.clinic = clinic; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@ExpectedException(IllegalArgumentException.class) | ||||||
|  | 	public void testBogusJpql() { | ||||||
|  | 		this.sharedEntityManager.createQuery("SELECT RUBBISH FROM RUBBISH HEAP").executeUpdate(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testApplicationManaged() { | ||||||
|  | 		EntityManager appManaged = this.entityManagerFactory.createEntityManager(); | ||||||
|  | 		appManaged.joinTransaction(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testGetVets() { | ||||||
|  | 		Collection<Vet> vets = this.clinic.getVets(); | ||||||
|  | 		// Use the inherited countRowsInTable() convenience method (from | ||||||
|  | 		// AbstractTransactionalDataSourceSpringContextTests) to verify the | ||||||
|  | 		// results. | ||||||
|  | 		assertEquals("JDBC query must show the same number of vets", super.countRowsInTable("VETS"), vets.size()); | ||||||
|  | 		Vet v1 = EntityUtils.getById(vets, Vet.class, 2); | ||||||
|  | 		assertEquals("Leary", v1.getLastName()); | ||||||
|  | 		assertEquals(1, v1.getNrOfSpecialties()); | ||||||
|  | 		assertEquals("radiology", (v1.getSpecialties().get(0)).getName()); | ||||||
|  | 		Vet v2 = EntityUtils.getById(vets, Vet.class, 3); | ||||||
|  | 		assertEquals("Douglas", v2.getLastName()); | ||||||
|  | 		assertEquals(2, v2.getNrOfSpecialties()); | ||||||
|  | 		assertEquals("dentistry", (v2.getSpecialties().get(0)).getName()); | ||||||
|  | 		assertEquals("surgery", (v2.getSpecialties().get(1)).getName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testGetPetTypes() { | ||||||
|  | 		Collection<PetType> petTypes = this.clinic.getPetTypes(); | ||||||
|  | 		assertEquals("JDBC query must show the same number of pet types", super.countRowsInTable("TYPES"), | ||||||
|  | 				petTypes.size()); | ||||||
|  | 		PetType t1 = EntityUtils.getById(petTypes, PetType.class, 1); | ||||||
|  | 		assertEquals("cat", t1.getName()); | ||||||
|  | 		PetType t4 = EntityUtils.getById(petTypes, PetType.class, 4); | ||||||
|  | 		assertEquals("snake", t4.getName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testFindOwners() { | ||||||
|  | 		Collection<Owner> owners = this.clinic.findOwners("Davis"); | ||||||
|  | 		assertEquals(2, owners.size()); | ||||||
|  | 		owners = this.clinic.findOwners("Daviss"); | ||||||
|  | 		assertEquals(0, owners.size()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testLoadOwner() { | ||||||
|  | 		Owner o1 = this.clinic.loadOwner(1); | ||||||
|  | 		assertTrue(o1.getLastName().startsWith("Franklin")); | ||||||
|  | 		Owner o10 = this.clinic.loadOwner(10); | ||||||
|  | 		assertEquals("Carlos", o10.getFirstName()); | ||||||
|  | 
 | ||||||
|  | 		// Check lazy loading, by ending the transaction | ||||||
|  | 		endTransaction(); | ||||||
|  | 
 | ||||||
|  | 		// Now Owners are "disconnected" from the data store. | ||||||
|  | 		// We might need to touch this collection if we switched to lazy loading | ||||||
|  | 		// in mapping files, but this test would pick this up. | ||||||
|  | 		o1.getPets(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testInsertOwner() { | ||||||
|  | 		Collection<Owner> owners = this.clinic.findOwners("Schultz"); | ||||||
|  | 		int found = owners.size(); | ||||||
|  | 		Owner owner = new Owner(); | ||||||
|  | 		owner.setLastName("Schultz"); | ||||||
|  | 		this.clinic.storeOwner(owner); | ||||||
|  | 		// assertTrue(!owner.isNew()); -- NOT TRUE FOR TOPLINK (before commit) | ||||||
|  | 		owners = this.clinic.findOwners("Schultz"); | ||||||
|  | 		assertEquals(found + 1, owners.size()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testUpdateOwner() throws Exception { | ||||||
|  | 		Owner o1 = this.clinic.loadOwner(1); | ||||||
|  | 		String old = o1.getLastName(); | ||||||
|  | 		o1.setLastName(old + "X"); | ||||||
|  | 		this.clinic.storeOwner(o1); | ||||||
|  | 		o1 = this.clinic.loadOwner(1); | ||||||
|  | 		assertEquals(old + "X", o1.getLastName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testLoadPet() { | ||||||
|  | 		Collection<PetType> types = this.clinic.getPetTypes(); | ||||||
|  | 		Pet p7 = this.clinic.loadPet(7); | ||||||
|  | 		assertTrue(p7.getName().startsWith("Samantha")); | ||||||
|  | 		assertEquals(EntityUtils.getById(types, PetType.class, 1).getId(), p7.getType().getId()); | ||||||
|  | 		assertEquals("Jean", p7.getOwner().getFirstName()); | ||||||
|  | 		Pet p6 = this.clinic.loadPet(6); | ||||||
|  | 		assertEquals("George", p6.getName()); | ||||||
|  | 		assertEquals(EntityUtils.getById(types, PetType.class, 4).getId(), p6.getType().getId()); | ||||||
|  | 		assertEquals("Peter", p6.getOwner().getFirstName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testInsertPet() { | ||||||
|  | 		Owner o6 = this.clinic.loadOwner(6); | ||||||
|  | 		int found = o6.getPets().size(); | ||||||
|  | 		Pet pet = new Pet(); | ||||||
|  | 		pet.setName("bowser"); | ||||||
|  | 		Collection<PetType> types = this.clinic.getPetTypes(); | ||||||
|  | 		pet.setType(EntityUtils.getById(types, PetType.class, 2)); | ||||||
|  | 		pet.setBirthDate(new Date()); | ||||||
|  | 		o6.addPet(pet); | ||||||
|  | 		assertEquals(found + 1, o6.getPets().size()); | ||||||
|  | 		this.clinic.storeOwner(o6); | ||||||
|  | 		// assertTrue(!pet.isNew()); -- NOT TRUE FOR TOPLINK (before commit) | ||||||
|  | 		o6 = this.clinic.loadOwner(6); | ||||||
|  | 		assertEquals(found + 1, o6.getPets().size()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testUpdatePet() throws Exception { | ||||||
|  | 		Pet p7 = this.clinic.loadPet(7); | ||||||
|  | 		String old = p7.getName(); | ||||||
|  | 		p7.setName(old + "X"); | ||||||
|  | 		this.clinic.storePet(p7); | ||||||
|  | 		p7 = this.clinic.loadPet(7); | ||||||
|  | 		assertEquals(old + "X", p7.getName()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testInsertVisit() { | ||||||
|  | 		Pet p7 = this.clinic.loadPet(7); | ||||||
|  | 		int found = p7.getVisits().size(); | ||||||
|  | 		Visit visit = new Visit(); | ||||||
|  | 		p7.addVisit(visit); | ||||||
|  | 		visit.setDescription("test"); | ||||||
|  | 		this.clinic.storePet(p7); | ||||||
|  | 		// assertTrue(!visit.isNew()); -- NOT TRUE FOR TOPLINK (before commit) | ||||||
|  | 		p7 = this.clinic.loadPet(7); | ||||||
|  | 		assertEquals(found + 1, p7.getVisits().size()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,51 @@ | ||||||
|  | package org.springframework.samples.petclinic.jpa; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.springframework.samples.petclinic.aspects.UsageLogAspect; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * <p> | ||||||
|  |  * Tests for the DAO variant based on the shared EntityManager approach. Uses | ||||||
|  |  * TopLink Essentials (the reference implementation) for testing. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * Specifically tests usage of an <code>orm.xml</code> file, loaded by the | ||||||
|  |  * persistence provider through the Spring-provided persistence unit root URL. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Rod Johnson | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  */ | ||||||
|  | public class EntityManagerClinicTests extends AbstractJpaClinicTests { | ||||||
|  | 
 | ||||||
|  | 	private UsageLogAspect usageLogAspect; | ||||||
|  | 
 | ||||||
|  | 	public void setUsageLogAspect(UsageLogAspect usageLogAspect) { | ||||||
|  | 		this.usageLogAspect = usageLogAspect; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	protected String[] getConfigPaths() { | ||||||
|  | 		return new String[] { | ||||||
|  | 			"applicationContext-jpaCommon.xml", | ||||||
|  | 			"applicationContext-toplinkAdapter.xml", | ||||||
|  | 			"applicationContext-entityManager.xml" | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void testUsageLogAspectIsInvoked() { | ||||||
|  | 		String name1 = "Schuurman"; | ||||||
|  | 		String name2 = "Greenwood"; | ||||||
|  | 		String name3 = "Leau"; | ||||||
|  | 
 | ||||||
|  | 		assertTrue(this.clinic.findOwners(name1).isEmpty()); | ||||||
|  | 		assertTrue(this.clinic.findOwners(name2).isEmpty()); | ||||||
|  | 
 | ||||||
|  | 		List<String> namesRequested = this.usageLogAspect.getNamesRequested(); | ||||||
|  | 		assertTrue(namesRequested.contains(name1)); | ||||||
|  | 		assertTrue(namesRequested.contains(name2)); | ||||||
|  | 		assertFalse(namesRequested.contains(name3)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | package org.springframework.samples.petclinic.jpa; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * <p> | ||||||
|  |  * Tests for the DAO variant based on the shared EntityManager approach, using | ||||||
|  |  * Hibernate EntityManager for testing instead of the reference implementation. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * Specifically tests usage of an <code>orm.xml</code> file, loaded by the | ||||||
|  |  * persistence provider through the Spring-provided persistence unit root URL. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  */ | ||||||
|  | public class HibernateEntityManagerClinicTests extends EntityManagerClinicTests { | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	protected String[] getConfigPaths() { | ||||||
|  | 		return new String[] { | ||||||
|  | 			"applicationContext-jpaCommon.xml", | ||||||
|  | 			"applicationContext-hibernateAdapter.xml", | ||||||
|  | 			"applicationContext-entityManager.xml" | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | 
 | ||||||
|  | package org.springframework.samples.petclinic.jpa; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * <p> | ||||||
|  |  * Tests for the DAO variant based on the shared EntityManager approach, using | ||||||
|  |  * Apache OpenJPA for testing instead of the reference implementation. | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * Specifically tests usage of an <code>orm.xml</code> file, loaded by the | ||||||
|  |  * persistence provider through the Spring-provided persistence unit root URL. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Juergen Hoeller | ||||||
|  |  */ | ||||||
|  | public class OpenJpaEntityManagerClinicTests extends EntityManagerClinicTests { | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	protected String[] getConfigPaths() { | ||||||
|  | 		return new String[] { | ||||||
|  | 			"applicationContext-jpaCommon.xml", | ||||||
|  | 			"applicationContext-openJpaAdapter.xml", | ||||||
|  | 			"applicationContext-entityManager.xml" | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" | ||||||
|  | 	xsi:schemaLocation=" | ||||||
|  | 		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd | ||||||
|  | 		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<aop:aspectj-autoproxy /> | ||||||
|  | 
 | ||||||
|  | 	<bean class="org.springframework.samples.petclinic.aspects.UsageLogAspect" p:historySize="300" /> | ||||||
|  | 
 | ||||||
|  | 	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> | ||||||
|  | 
 | ||||||
|  | 	<bean id="clinic" class="org.springframework.samples.petclinic.jpa.EntityManagerClinic" /> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xmlns:p="http://www.springframework.org/schema/p" | ||||||
|  | 	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" | ||||||
|  | 		p:database="${jpa.database}" p:showSql="${jpa.showSql}" /> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" | ||||||
|  | 	xmlns:tx="http://www.springframework.org/schema/tx" | ||||||
|  | 	xsi:schemaLocation=" | ||||||
|  | 		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd | ||||||
|  | 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd | ||||||
|  | 		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<context:property-placeholder location="classpath:jdbc.properties" /> | ||||||
|  | 
 | ||||||
|  | 	<tx:annotation-driven /> | ||||||
|  | 
 | ||||||
|  | 	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" | ||||||
|  | 		p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" | ||||||
|  | 		p:password="${jdbc.password}" /> | ||||||
|  | 
 | ||||||
|  | 	<!-- Note: the specific "jpaAdapter" bean sits in adapter context file --> | ||||||
|  | 	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" | ||||||
|  | 		p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter"> | ||||||
|  | 		<property name="loadTimeWeaver"> | ||||||
|  | 			<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> | ||||||
|  | 		</property> | ||||||
|  | 	</bean> | ||||||
|  | 
 | ||||||
|  | 	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" | ||||||
|  | 		p:entityManagerFactory-ref="entityManagerFactory" /> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xmlns:p="http://www.springframework.org/schema/p" | ||||||
|  | 	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter" p:database="${jpa.database}" | ||||||
|  | 		p:showSql="${jpa.showSql}" /> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xmlns:p="http://www.springframework.org/schema/p" | ||||||
|  | 	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> | ||||||
|  | 
 | ||||||
|  | 	<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter" | ||||||
|  | 		p:databasePlatform="${jpa.databasePlatform}" p:showSql="${jpa.showSql}" /> | ||||||
|  | 
 | ||||||
|  | </beans> | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> | ||||||
|  | 
 | ||||||
|  | <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> | ||||||
|  | 
 | ||||||
|  | 	<!-- Appenders --> | ||||||
|  | 	<appender name="console" class="org.apache.log4j.ConsoleAppender"> | ||||||
|  | 		<param name="Target" value="System.out" /> | ||||||
|  | 		<layout class="org.apache.log4j.PatternLayout"> | ||||||
|  | 			<param name="ConversionPattern" value="%-5p: %c - %m%n" /> | ||||||
|  | 		</layout> | ||||||
|  | 	</appender> | ||||||
|  | 
 | ||||||
|  | 	<logger name="org.springframework.beans"> | ||||||
|  | 		<level value="warn" /> | ||||||
|  | 	</logger> | ||||||
|  | 
 | ||||||
|  | 	<logger name="org.springframework.binding"> | ||||||
|  | 		<level value="debug" /> | ||||||
|  | 	</logger> | ||||||
|  | 
 | ||||||
|  | 	<!-- Root Logger --> | ||||||
|  | 	<root> | ||||||
|  | 		<priority value="warn" /> | ||||||
|  | 		<appender-ref ref="console" /> | ||||||
|  | 	</root> | ||||||
|  | 	 | ||||||
|  | </log4j:configuration> | ||||||
		Loading…
	
		Reference in New Issue