diff --git a/.springBeans b/.springBeans index 2f9dc4c20f8b7a40de4883d0d8b863abe632c3e6..1dea402645c5b0b56863f212d3f225def2fcb4fc 100644 --- a/.springBeans +++ b/.springBeans @@ -11,6 +11,7 @@ <config>src/main/webapp/WEB-INF/mvc-view-config.xml</config> <config>src/main/resources/spring/dao-config.xml</config> <config>src/main/resources/spring/datasource-config.xml</config> + <config>src/main/resources/spring/tools-config.xml</config> </configs> <configSets> <configSet> @@ -22,7 +23,7 @@ <config>src/main/webapp/WEB-INF/mvc-view-config.xml</config> <config>src/main/resources/spring/dao-config.xml</config> <config>src/main/resources/spring/datasource-config.xml</config> - <config>src/main/resources/spring/jmx-aop-config.xml</config> + <config>src/main/resources/spring/tools-config.xml</config> </configs> <profiles> </profiles> diff --git a/pom.xml b/pom.xml index 82da93b2f18a26412a121efb8d9bba6a267a4c0f..a6d787106d6d539b81639b622211f762a33848e6 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,11 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context-support</artifactId> + <version>${spring.version}</version> + </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> @@ -204,6 +209,13 @@ <scope>test</scope> </dependency> + <dependency> + <groupId>net.sf.ehcache</groupId> + <artifactId>ehcache</artifactId> + <version>2.5.2</version> + <type>pom</type> + </dependency> + <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java index d97f4846546cad85c5c66a0748ec87dc2228eb8d..79b3e5a0b309162afcb8a9be90b673b61386ec84 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java @@ -6,14 +6,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper; import org.springframework.jdbc.core.simple.ParameterizedRowMapper; -import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.samples.petclinic.model.Specialty; import org.springframework.samples.petclinic.model.Vet; import org.springframework.samples.petclinic.repository.VetRepository; @@ -28,16 +26,13 @@ import org.springframework.stereotype.Repository; * @author Sam Brannen * @author Thomas Risberg * @author Mark Fisher + * @author Michael Isvy */ @Repository public class JdbcVetRepositoryImpl implements VetRepository { - private final Logger logger = LoggerFactory.getLogger(getClass()); - private JdbcTemplate jdbcTemplate; - private final List<Vet> vets = new ArrayList<Vet>(); - @Autowired public JdbcVetRepositoryImpl(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; @@ -47,14 +42,11 @@ public class JdbcVetRepositoryImpl implements VetRepository { * Refresh the cache of Vets that the ClinicService is holding. * @see org.springframework.samples.petclinic.model.service.ClinicService#findVets() */ - @ManagedOperation - 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.jdbcTemplate.query( + @Cacheable(value="vets") + public Collection<Vet> findAll() throws DataAccessException { + List<Vet> vets = new ArrayList<Vet>(); + // Retrieve the list of all vets. + vets.addAll(this.jdbcTemplate.query( "SELECT id, first_name, last_name FROM vets ORDER BY last_name,first_name", ParameterizedBeanPropertyRowMapper.newInstance(Vet.class))); @@ -64,7 +56,7 @@ public class JdbcVetRepositoryImpl implements VetRepository { ParameterizedBeanPropertyRowMapper.newInstance(Specialty.class)); // Build each vet's list of specialties. - for (Vet vet : this.vets) { + for (Vet vet : vets) { final List<Integer> vetSpecialtiesIds = this.jdbcTemplate.query( "SELECT specialty_id FROM vet_specialties WHERE vet_id=?", new ParameterizedRowMapper<Integer>() { @@ -77,17 +69,6 @@ public class JdbcVetRepositoryImpl implements VetRepository { vet.addSpecialty(specialty); } } + return vets; } - } - - public Collection<Vet> findAll() throws DataAccessException { - synchronized (this.vets) { - if (this.vets.isEmpty()) { - refreshVetsCache(); - } - return this.vets; - } - } - - } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaVetRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaVetRepositoryImpl.java index 63a4e729c9afdbd34016060087fec3c1281944fc..82bfb7e9863dde244753c7efca8ec54c0d289f98 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaVetRepositoryImpl.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaVetRepositoryImpl.java @@ -5,6 +5,7 @@ import java.util.Collection; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; +import org.springframework.cache.annotation.Cacheable; import org.springframework.samples.petclinic.model.Vet; import org.springframework.samples.petclinic.repository.VetRepository; import org.springframework.stereotype.Repository; @@ -27,6 +28,7 @@ public class JpaVetRepositoryImpl implements VetRepository { private EntityManager em; + @Cacheable(value="vets") @SuppressWarnings("unchecked") public Collection<Vet> findAll() { return this.em.createQuery("SELECT vet FROM Vet vet join fetch vet.specialties ORDER BY vet.lastName, vet.firstName").getResultList(); diff --git a/src/main/resources/ehcache.xml b/src/main/resources/ehcache.xml new file mode 100644 index 0000000000000000000000000000000000000000..8167066b136a779deebee14bccbe691337f0d40d --- /dev/null +++ b/src/main/resources/ehcache.xml @@ -0,0 +1,17 @@ +<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="ehcache.xsd" + updateCheck="false"> + <diskStore path="java.io.tmpdir"/> + + <!-- objects are evicted from the cache every 60 seconds --> + <cache name="vets" + timeToLiveSeconds="60" + maxElementsInMemory="100" + eternal="false" + overflowToDisk="false" + maxElementsOnDisk="10000000" + diskPersistent="false" + diskExpiryThreadIntervalSeconds="1" + memoryStoreEvictionPolicy="LRU" /> + +</ehcache> diff --git a/src/main/resources/ehcache.xsd b/src/main/resources/ehcache.xsd new file mode 100644 index 0000000000000000000000000000000000000000..2a539199fed4c3b0951b686afd5fa5ac6f989450 --- /dev/null +++ b/src/main/resources/ehcache.xsd @@ -0,0 +1,418 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="1.7"> + + <xs:element name="ehcache"> + <xs:complexType> + <xs:sequence> + <xs:element maxOccurs="1" minOccurs="0" ref="managementRESTService"/> + <xs:element maxOccurs="1" minOccurs="0" ref="diskStore"/> + <xs:element maxOccurs="1" minOccurs="0" ref="sizeOfPolicy"/> + <xs:element maxOccurs="1" minOccurs="0" ref="transactionManagerLookup"/> + <xs:element maxOccurs="1" minOccurs="0" ref="cacheManagerEventListenerFactory"/> + <xs:element maxOccurs="unbounded" minOccurs="0" ref="cacheManagerPeerProviderFactory"/> + <xs:element maxOccurs="unbounded" minOccurs="0" ref="cacheManagerPeerListenerFactory"/> + <xs:element maxOccurs="1" minOccurs="0" ref="terracottaConfig"/> + <xs:element maxOccurs="1" minOccurs="0" ref="defaultCache"/> + <xs:element maxOccurs="unbounded" minOccurs="0" ref="cache"/> + </xs:sequence> + <xs:attribute name="name" use="optional"/> + <xs:attribute default="true" name="updateCheck" type="xs:boolean" use="optional"/> + <xs:attribute default="autodetect" name="monitoring" type="monitoringType" use="optional"/> + <xs:attribute default="true" name="dynamicConfig" type="xs:boolean" use="optional"/> + <xs:attribute default="15" name="defaultTransactionTimeoutInSeconds" type="xs:integer" use="optional"/> + <xs:attribute default="0" name="maxBytesLocalHeap" type="memoryUnitOrPercentage" use="optional"/> + <xs:attribute default="0" name="maxBytesLocalOffHeap" type="memoryUnit" use="optional"/> + <xs:attribute default="0" name="maxBytesLocalDisk" type="memoryUnit" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="managementRESTService"> + <xs:complexType> + <xs:attribute name="enabled" type="xs:boolean" use="optional"/> + <xs:attribute name="bind" use="optional"/> + <xs:attribute name="securityServiceLocation" use="optional"/> + <xs:attribute name="securityServiceTimeout" use="optional" type="xs:integer"/> + <xs:attribute name="sslEnabled" use="optional" type="xs:boolean"/> + <xs:attribute name="needClientAuth" use="optional" type="xs:boolean"/> + <xs:attribute name="sampleHistorySize" use="optional" type="xs:integer"/> + <xs:attribute name="sampleIntervalSeconds" use="optional" type="xs:integer"/> + <xs:attribute name="sampleSearchIntervalSeconds" use="optional" type="xs:integer"/> + </xs:complexType> + </xs:element> + <xs:element name="diskStore"> + <xs:complexType> + <xs:attribute name="path" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="transactionManagerLookup"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cacheManagerEventListenerFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cacheManagerPeerProviderFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cacheManagerPeerListenerFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="terracottaConfig"> + <xs:complexType> + <xs:sequence> + <xs:element maxOccurs="1" minOccurs="0" name="tc-config"> + <xs:complexType> + <xs:sequence> + <xs:any maxOccurs="unbounded" minOccurs="0" processContents="skip"/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:attribute default="localhost:9510" name="url" use="optional"/> + <xs:attribute name="rejoin" type="xs:boolean" use="optional" default="false"/> + </xs:complexType> + </xs:element> + <!-- add clone support for addition of cacheExceptionHandler. Important! --> + <xs:element name="defaultCache"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheLoaderFactory"/> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheDecoratorFactory"/> + <xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/> + <xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/> + <xs:element minOccurs="0" maxOccurs="1" ref="pinning"/> + <xs:element minOccurs="0" maxOccurs="1" ref="terracotta"/> + <xs:element minOccurs="0" maxOccurs="1" ref="cacheWriter"/> + <xs:element minOccurs="0" maxOccurs="1" ref="copyStrategy"/> + <xs:element minOccurs="0" maxOccurs="1" ref="elementValueComparator"/> + <xs:element minOccurs="0" maxOccurs="1" ref="sizeOfPolicy"/> + <xs:element minOccurs="0" maxOccurs="1" ref="persistence"/> + </xs:sequence> + <xs:attribute name="diskExpiryThreadIntervalSeconds" type="xs:integer" use="optional"/> + <xs:attribute name="diskSpoolBufferSizeMB" type="xs:integer" use="optional"/> + <xs:attribute name="diskPersistent" type="xs:boolean" use="optional"/> + <xs:attribute name="diskAccessStripes" type="xs:integer" use="optional" default="1"/> + <xs:attribute name="eternal" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="maxElementsInMemory" type="xs:integer" use="optional"/> + <xs:attribute name="maxEntriesLocalHeap" type="xs:integer" use="optional"/> + <xs:attribute name="clearOnFlush" type="xs:boolean" use="optional"/> + <xs:attribute name="memoryStoreEvictionPolicy" type="xs:string" use="optional"/> + <xs:attribute name="overflowToDisk" type="xs:boolean" use="optional"/> + <xs:attribute name="timeToIdleSeconds" type="xs:integer" use="optional"/> + <xs:attribute name="timeToLiveSeconds" type="xs:integer" use="optional"/> + <xs:attribute name="maxElementsOnDisk" type="xs:integer" use="optional"/> + <xs:attribute name="maxEntriesLocalDisk" type="xs:integer" use="optional"/> + <xs:attribute name="transactionalMode" type="transactionalMode" use="optional" default="off"/> + <xs:attribute name="statistics" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="copyOnRead" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="copyOnWrite" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="cacheLoaderTimeoutMillis" type="xs:integer" use="optional" default="0"/> + <xs:attribute name="overflowToOffHeap" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="maxMemoryOffHeap" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cache"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheLoaderFactory"/> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheDecoratorFactory"/> + <xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/> + <xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/> + <xs:element minOccurs="0" maxOccurs="1" ref="pinning"/> + <xs:element minOccurs="0" maxOccurs="1" ref="terracotta"/> + <xs:element minOccurs="0" maxOccurs="1" ref="cacheWriter"/> + <xs:element minOccurs="0" maxOccurs="1" ref="copyStrategy"/> + <xs:element minOccurs="0" maxOccurs="1" ref="searchable"/> + <xs:element minOccurs="0" maxOccurs="1" ref="elementValueComparator"/> + <xs:element minOccurs="0" maxOccurs="1" ref="sizeOfPolicy"/> + <xs:element minOccurs="0" maxOccurs="1" ref="persistence"/> + </xs:sequence> + <xs:attribute name="diskExpiryThreadIntervalSeconds" type="xs:integer" use="optional"/> + <xs:attribute name="diskSpoolBufferSizeMB" type="xs:integer" use="optional"/> + <xs:attribute name="diskPersistent" type="xs:boolean" use="optional"/> + <xs:attribute name="diskAccessStripes" type="xs:integer" use="optional" default="1"/> + <xs:attribute name="eternal" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="maxElementsInMemory" type="xs:integer" use="optional"/> + <xs:attribute name="maxEntriesLocalHeap" type="xs:integer" use="optional"/> + <xs:attribute name="memoryStoreEvictionPolicy" type="xs:string" use="optional"/> + <xs:attribute name="clearOnFlush" type="xs:boolean" use="optional"/> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="overflowToDisk" type="xs:boolean" use="optional"/> + <xs:attribute name="timeToIdleSeconds" type="xs:integer" use="optional"/> + <xs:attribute name="timeToLiveSeconds" type="xs:integer" use="optional"/> + <xs:attribute name="maxElementsOnDisk" type="xs:integer" use="optional"/> + <xs:attribute name="maxEntriesLocalDisk" type="xs:integer" use="optional"/> + <xs:attribute name="transactionalMode" type="transactionalMode" use="optional" default="off"/> + <xs:attribute name="statistics" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="copyOnRead" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="copyOnWrite" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="logging" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="cacheLoaderTimeoutMillis" type="xs:integer" use="optional" default="0"/> + <xs:attribute name="overflowToOffHeap" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="maxMemoryOffHeap" type="xs:string" use="optional"/> + <xs:attribute default="0" name="maxBytesLocalHeap" type="memoryUnitOrPercentage" use="optional"/> + <xs:attribute default="0" name="maxBytesLocalOffHeap" type="memoryUnitOrPercentage" use="optional"/> + <xs:attribute default="0" name="maxBytesLocalDisk" type="memoryUnitOrPercentage" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cacheEventListenerFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + <xs:attribute name="listenFor" use="optional" type="notificationScope" default="all"/> + </xs:complexType> + </xs:element> + <xs:element name="bootstrapCacheLoaderFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cacheExtensionFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cacheExceptionHandlerFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cacheLoaderFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="cacheDecoratorFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="searchAttribute"> + <xs:complexType> + <xs:attribute name="name" use="required" type="xs:string"/> + <xs:attribute name="expression" type="xs:string"/> + <xs:attribute name="class" type="xs:string"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + + <xs:element name="searchable"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="searchAttribute"/> + </xs:sequence> + <xs:attribute name="keys" use="optional" type="xs:boolean" default="true"/> + <xs:attribute name="values" use="optional" type="xs:boolean" default="true"/> + </xs:complexType> + </xs:element> + + <xs:element name="pinning"> + <xs:complexType> + <xs:attribute name="store" use="required" type="pinningStoreType"/> + </xs:complexType> + </xs:element> + + <xs:element name="terracotta"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="nonstop"/> + </xs:sequence> + <xs:attribute name="clustered" use="optional" type="xs:boolean" default="true"/> + <xs:attribute name="valueMode" use="optional" type="terracottaCacheValueType" default="serialization"/> + <xs:attribute name="coherentReads" use="optional" type="xs:boolean" default="true"/> + <xs:attribute name="localKeyCache" use="optional" type="xs:boolean" default="false"/> + <xs:attribute name="localKeyCacheSize" use="optional" type="xs:positiveInteger" default="300000"/> + <xs:attribute name="orphanEviction" use="optional" type="xs:boolean" default="true"/> + <xs:attribute name="orphanEvictionPeriod" use="optional" type="xs:positiveInteger" default="4"/> + <xs:attribute name="copyOnRead" use="optional" type="xs:boolean" default="false"/> + <xs:attribute name="coherent" use="optional" type="xs:boolean" default="false"/> + <xs:attribute name="consistency" use="optional" type="consistencyType" default="eventual"/> + <xs:attribute name="synchronousWrites" use="optional" type="xs:boolean" default="false"/> + <xs:attribute name="concurrency" use="optional" type="xs:nonNegativeInteger" default="0"/> + <xs:attribute name="localCacheEnabled" use="optional" type="xs:boolean" default="true"/> + <xs:attribute name="compressionEnabled" use="optional" type="xs:boolean" default="false"/> + </xs:complexType> + </xs:element> + <xs:simpleType name="consistencyType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="strong"/> + <xs:enumeration value="eventual"/> + </xs:restriction> + </xs:simpleType> + <xs:element name="nonstop"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="timeoutBehavior"/> + </xs:sequence> + <xs:attribute name="enabled" use="optional" type="xs:boolean" default="true"/> + <xs:attribute name="immediateTimeout" use="optional" type="xs:boolean" default="false"/> + <xs:attribute name="timeoutMillis" use="optional" type="xs:positiveInteger" default="30000"/> + </xs:complexType> + </xs:element> + <xs:element name="timeoutBehavior"> + <xs:complexType> + <xs:attribute name="type" use="optional" type="timeoutBehaviorType" default="exception"/> + <xs:attribute name="properties" use="optional" default=""/> + <xs:attribute name="propertySeparator" use="optional" default=","/> + </xs:complexType> + </xs:element> + <xs:simpleType name="timeoutBehaviorType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="noop"/> + <xs:enumeration value="exception"/> + <xs:enumeration value="localReads"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="monitoringType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="autodetect"/> + <xs:enumeration value="on"/> + <xs:enumeration value="off"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="pinningStoreType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="localHeap"/> + <xs:enumeration value="localMemory"/> + <xs:enumeration value="inCache"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="terracottaCacheValueType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="serialization"/> + <xs:enumeration value="identity"/> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="transactionalMode"> + <xs:restriction base="xs:string"> + <xs:enumeration value="off"/> + <xs:enumeration value="xa_strict"/> + <xs:enumeration value="xa"/> + <xs:enumeration value="local"/> + </xs:restriction> + </xs:simpleType> + + <xs:element name="cacheWriter"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="cacheWriterFactory"/> + </xs:sequence> + <xs:attribute name="writeMode" use="optional" type="writeModeType" default="write-through"/> + <xs:attribute name="notifyListenersOnException" use="optional" type="xs:boolean" default="false"/> + <xs:attribute name="minWriteDelay" use="optional" type="xs:nonNegativeInteger" default="1"/> + <xs:attribute name="maxWriteDelay" use="optional" type="xs:nonNegativeInteger" default="1"/> + <xs:attribute name="rateLimitPerSecond" use="optional" type="xs:nonNegativeInteger" default="0"/> + <xs:attribute name="writeCoalescing" use="optional" type="xs:boolean" default="false"/> + <xs:attribute name="writeBatching" use="optional" type="xs:boolean" default="false"/> + <xs:attribute name="writeBatchSize" use="optional" type="xs:positiveInteger" default="1"/> + <xs:attribute name="retryAttempts" use="optional" type="xs:nonNegativeInteger" default="0"/> + <xs:attribute name="retryAttemptDelaySeconds" use="optional" type="xs:nonNegativeInteger" default="1"/> + <xs:attribute name="writeBehindConcurrency" use="optional" type="xs:nonNegativeInteger" default="1"/> + <xs:attribute name="writeBehindMaxQueueSize" use="optional" type="xs:nonNegativeInteger" default="0"/> + </xs:complexType> + </xs:element> + <xs:simpleType name="writeModeType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="write-through"/> + <xs:enumeration value="write-behind"/> + </xs:restriction> + </xs:simpleType> + <xs:element name="cacheWriterFactory"> + <xs:complexType> + <xs:attribute name="class" use="required"/> + <xs:attribute name="properties" use="optional"/> + <xs:attribute name="propertySeparator" use="optional"/> + </xs:complexType> + </xs:element> + + <xs:element name="copyStrategy"> + <xs:complexType> + <xs:attribute name="class" use="required" type="xs:string"/> + </xs:complexType> + </xs:element> + + <xs:element name="elementValueComparator"> + <xs:complexType> + <xs:attribute name="class" use="required" type="xs:string"/> + </xs:complexType> + </xs:element> + + <xs:element name="sizeOfPolicy"> + <xs:complexType> + <xs:attribute name="maxDepth" use="required" type="xs:integer"/> + <xs:attribute name="maxDepthExceededBehavior" use="optional" default="continue" type="maxDepthExceededBehavior"/> + </xs:complexType> + </xs:element> + + <xs:element name="persistence"> + <xs:complexType> + <xs:attribute name="strategy" use="required" type="persistenceStrategy"/> + <xs:attribute name="synchronousWrites" use="optional" default="false" type="xs:boolean"/> + </xs:complexType> + </xs:element> + + <xs:simpleType name="persistenceStrategy"> + <xs:restriction base="xs:string"> + <xs:enumeration value="localTempSwap"/> + <xs:enumeration value="localRestartable"/> + <xs:enumeration value="none"/> + <xs:enumeration value="distributed"/> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="maxDepthExceededBehavior"> + <xs:restriction base="xs:string"> + <xs:enumeration value="continue"/> + <xs:enumeration value="abort"/> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="notificationScope"> + <xs:restriction base="xs:string"> + <xs:enumeration value="local"/> + <xs:enumeration value="remote"/> + <xs:enumeration value="all"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="memoryUnit"> + <xs:restriction base="xs:token"> + <xs:pattern value="[0-9]+[bBkKmMgG]?"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="memoryUnitOrPercentage"> + <xs:restriction base="xs:token"> + <xs:pattern value="([0-9]+[bBkKmMgG]?|100%|[0-9]{1,2}%)"/> + </xs:restriction> + </xs:simpleType> +</xs:schema> \ No newline at end of file diff --git a/src/main/resources/log4j.dtd b/src/main/resources/log4j.dtd old mode 100755 new mode 100644 diff --git a/src/main/resources/log4j.xml b/src/main/resources/log4j.xml index c39d78d7427d81538f11d4d08f748c9bdbba1c4f..f865a8473768bf93f24215566b65bf4739530bb4 100755 --- a/src/main/resources/log4j.xml +++ b/src/main/resources/log4j.xml @@ -10,7 +10,6 @@ <param name="ConversionPattern" value="%-5p: %c - %m%n" /> </layout> </appender> - <!-- Root Logger --> <root> diff --git a/src/main/resources/spring/jmx-aop-config.xml b/src/main/resources/spring/tools-config.xml similarity index 66% rename from src/main/resources/spring/jmx-aop-config.xml rename to src/main/resources/spring/tools-config.xml index 5b2cfb9b16813c4203398d1eef1dabc8499f17c0..cf204ba2a08335740578b49de5abf37ccc695102 100644 --- a/src/main/resources/spring/jmx-aop-config.xml +++ b/src/main/resources/spring/tools-config.xml @@ -4,8 +4,10 @@ --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" + xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- @@ -18,12 +20,26 @@ </aop:aspectj-autoproxy> <!-- Call monitoring aspect that monitors call count and call invocation time --> - <bean id="callMonitor" class="org.springframework.samples.petclinic.util.CallMonitoringAspect"/> + <bean id="callMonitor" class="org.springframework.samples.petclinic.util.CallMonitoringAspect"/> <!-- Exporter that exposes the CallMonitoringAspect via JMX, based on the @ManagedResource, @ManagedAttribute, and @ManagedOperation annotations. --> - <context:mbean-export /> + <context:mbean-export /> + + <!-- enables scanning for @Cacheable annotation --> + <cache:annotation-driven /> + + <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> + <property name="cacheManager" ref="ehcache"/> + </bean> + + <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> + <property name="configLocation" value="classpath:ehcache.xml"/> + </bean> + + + </beans> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index aa7171e44f5f1ef2567b399beb076c579c883fb1..2817b8996a3f9a289789595cf813bd029149a527 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -23,7 +23,7 @@ id="WebApp_ID" version="2.5"> --> <context-param> <param-name>contextConfigLocation</param-name> - <param-value>classpath:spring/dao-config.xml, classpath:spring/jmx-aop-config.xml</param-value> + <param-value>classpath:spring/dao-config.xml, classpath:spring/tools-config.xml</param-value> </context-param> <listener>