98 changed files with 5693 additions and 0 deletions
@ -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
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
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