Skip to content
This repository was archived by the owner on Sep 26, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ plugin.xml
.DS_Store
.idea/
*.iml
CodeNarcReport.html
.*.swp
46 changes: 41 additions & 5 deletions SpringcacheGrailsPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
Expand All @@ -23,11 +23,14 @@ import org.springframework.web.filter.DelegatingFilterProxy
import grails.plugin.springcache.aop.*
import grails.plugin.springcache.web.*
import org.springframework.cache.ehcache.*
import java.lang.management.ManagementFactory
import net.sf.ehcache.management.ManagementService
import org.springframework.context.ApplicationContext

class SpringcacheGrailsPlugin {

def version = "1.4"
def grailsVersion = "1.2.0 > *"
def version = "1.4.1"
def grailsVersion = "2.0.0 > *"
def dependsOn = [:]
def pluginExcludes = [
"grails-app/views/**",
Expand Down Expand Up @@ -79,7 +82,7 @@ class SpringcacheGrailsPlugin {
def doWithSpring = {
if (!isEnabled(application)) {
log.warn "Springcache plugin is disabled"
springcacheFilter(NoOpFilter)
springcacheFilter(NoOpFilter)
} else {
if (application.config.grails.spring.disable.aspectj.autoweaving) {
log.warn "Service method caching is not compatible with the config setting 'grails.spring.disable.aspectj.autoweaving = false'"
Expand Down Expand Up @@ -127,23 +130,56 @@ class SpringcacheGrailsPlugin {

def doWithDynamicMethods = {ctx ->
PageInfo.metaClass.mixin(HeadersCategory)
attachGetCached(applicationContext)
}

def doWithApplicationContext = { applicationContext ->
def decorator = new CachingTagLibDecorator(applicationContext.springcacheService)
for (tagLibClass in application.tagLibClasses) {
decorator.decorate(tagLibClass, applicationContext."${tagLibClass.fullName}")
}

def jmxConfig = application.config.springcache.jmx
if (jmxConfig) {
def springcacheCacheManager = applicationContext.getBean("springcacheCacheManager")
ManagementService.registerMBeans(springcacheCacheManager, ManagementFactory.platformMBeanServer,
jmxConfig.cacheManager,
jmxConfig.cache,
jmxConfig.cacheConfiguration,
jmxConfig.cacheStatistics
)
}

}

def onChange = { event ->
ApplicationContext ctx = event.ctx
GrailsApplication application = event.application

if (application.isTagLibClass(event.source)) {
def tagLibClass = application.getTagLibClass(event.source.name)
def instance = event.ctx."${event.source.name}"
def instance = ctx."${event.source.name}"
def decorator = new CachingTagLibDecorator(event.ctx.springcacheService)

decorator.decorate(tagLibClass, instance)
}

attachGetCached(ctx)
}

def attachGetCached(ApplicationContext ctx) {
ctx.beanDefinitionNames.each { beanName ->
def mc
if(ctx.isSingleton(beanName)) {
mc = ctx.getBean(beanName).getMetaClass()
} else {
mc = ctx.getType(beanName).getMetaClass()
}

mc.getCached = { ->
ctx.getBean(beanName)
}
}
}

def getWebXmlFilterOrder() {
Expand Down
3 changes: 1 addition & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
## General

* convert annotation classes to Groovy so they can use null defaults
* expose caching statistics (JMX?)
* support reloading via onChange and onConfigChange [GRAILSPLUGINS-1825][1825]

## Controller caching
Expand All @@ -27,4 +26,4 @@

* cacheable version of g:render?

[1825]:http://jira.codehaus.org/browse/GRAILSPLUGINS-1825
[1825]:http://jira.codehaus.org/browse/GRAILSPLUGINS-1825
1 change: 1 addition & 0 deletions grails-app/conf/BuildConfig.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ grails.project.test.reports.dir = "target/test-reports"

grails.project.dependency.resolution = {
inherits "global"

log "warn"
repositories {
grailsHome()
Expand Down
4 changes: 2 additions & 2 deletions src/docs/guide/1. Introduction.gdoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ The plugin depends on the "EhCache":http://ehcache.org/ and "EhCache-Web":http:/

h3. Contact

The plugin code is hosted on [GitHub|http://github.com/robfletcher/grails-springcache]. Please feel free to fork the plugin and contribute patches.
The plugin code is hosted on [GitHub|https://github.com/gpc/grails-springcache]. Please feel free to fork the plugin and contribute patches.

Please raise defects or enhancements against the Grails Springcache plugin component on the [Codehaus JIRA|http://jira.codehaus.org/browse/GRAILSPLUGINS/component/14010].
Please raise defects or enhancements against the Grails Springcache plugin component on the [Codehaus JIRA|http://jira.grails.org/browse/GPSPRINGCACHE].

Questions, comments? [rob@energizedwork.com|mailto:rob@energizedwork.com] or better still contact me via the [Grails User mailing list|http://grails.org/Mailing+lists].
4 changes: 2 additions & 2 deletions src/docs/guide/1.1. Known Issues.gdoc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
* "GRAILSPLUGINS-2553":http://jira.codehaus.org/browse/GRAILSPLUGINS-2553 Cached methods with default arguments are not intercepted unless all the arguments are specified. Therefore the cache is completely bypassed (neither hit or missed).
* "GRAILSPLUGINS-2544":http://jira.codehaus.org/browse/GRAILSPLUGINS-2544 Due to a bug with Grails itself query string parameters are not included in the generated cache key. This can be a serious issue if you are using pagination for example as query string parameters such as @offset@ will be ignored resulting in the same cached content being served for every page. This *only* affects Grails version 1.3.4.
* "GPSPRINGCACHE-11":http://jira.grails.org/browse/GPSPRINGCACHE-11 Cached methods with default arguments are not intercepted unless all the arguments are specified. Therefore the cache is completely bypassed (neither hit or missed).
* "GPSPRINGCACHE-14G":http://jira.grails.org/browse/GPSPRINGCACHE-14 Due to a bug with Grails itself query string parameters are not included in the generated cache key. This can be a serious issue if you are using pagination for example as query string parameters such as @offset@ will be ignored resulting in the same cached content being served for every page. This *only* affects Grails version 1.3.4.
4 changes: 4 additions & 0 deletions src/docs/guide/1.2. Release Notes.gdoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
h4. 1.3.2

* exposing ehcache to JMX

h4. 1.3.1

* Fixes compilation problem on recent Groovy versions "GRAILSPLUGINS-2820":http://jira.codehaus.org/browse/GRAILSPLUGINS-2820
Expand Down
4 changes: 2 additions & 2 deletions src/docs/guide/3.2 Calling Cached Methods Internally.gdoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ExampleService {
def grailsApplication

def nonCachedMethod() {
grailsApplication.mainContext.exampleService.cachedMethod()
cached.cachedMethod()
}

@Cacheable('cachedMethodCache')
Expand All @@ -38,4 +38,4 @@ class ExampleService {
}
{code}

Instead of calling the method on @this@, we obtain the proxy via the application context (i.e. @grailsApplication.mainContext.exampleService@) and call the method on that. This way we go through the caching mechanism.
Instead of calling the method on @this@, we obtain the proxy via the injected @cached@ property, and call the method on that. This way we go through the caching mechanism.
18 changes: 18 additions & 0 deletions src/docs/guide/7. Cache Configuration.gdoc
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,21 @@ springcache {
Under the hood this is simply setting up @EhCacheFactoryBean@ instances in the Spring context, so it is up to you whether you prefer to use @resources.groovy@ or @Config.groovy@ there is not much difference.

The properties shown are just examples, see the "EhCacheFactoryBean":http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/cache/ehcache/EhCacheFactoryBean.html documentation for full details of all the properties you can set.


h3. exposing ehcache to JMX

Ehcache is already prepared to expose itself to JMX. To enable this use the following snippet in @grails-app/conf/Config.groovy@:

{code}
springcache {
jmx {
cacheManager = true
cache = true
cacheConfiguration = true
cacheStatistics = true
}
}
{code}

For details, see [Ehcache's JMX manual|http://ehcache.org/documentation/operations/jmx].
20 changes: 20 additions & 0 deletions src/docs/ref/Tag Lib/getCacheDirectives.gdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

h1. getCacheDirectives

h2. Purpose



h2. Examples

{code:java}
foo.getCacheDirectives()
{code}

h2. Description



Arguments:

[]
21 changes: 21 additions & 0 deletions src/docs/ref/Tag Lib/getDateHeader.gdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

h1. getDateHeader

h2. Purpose



h2. Examples

{code:java}
foo.getDateHeader(string)
{code}

h2. Description



Arguments:

[* @string@
]
21 changes: 21 additions & 0 deletions src/docs/ref/Tag Lib/getHeader.gdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

h1. getHeader

h2. Purpose



h2. Examples

{code:java}
foo.getHeader(string)
{code}

h2. Description



Arguments:

[* @string@
]
21 changes: 21 additions & 0 deletions src/docs/ref/Tag Lib/isMatch.gdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

h1. isMatch

h2. Purpose



h2. Examples

{code:java}
foo.isMatch(httpServletRequest)
{code}

h2. Description



Arguments:

[* @httpServletRequest@
]
21 changes: 21 additions & 0 deletions src/docs/ref/Tag Lib/isModified.gdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

h1. isModified

h2. Purpose



h2. Examples

{code:java}
foo.isModified(httpServletRequest)
{code}

h2. Description



Arguments:

[* @httpServletRequest@
]
20 changes: 20 additions & 0 deletions src/docs/ref/Tag Lib/toString.gdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

h1. toString

h2. Purpose



h2. Examples

{code:java}
foo.toString()
{code}

h2. Description



Arguments:

[]
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ class GrailsFragmentCachingFilter extends PageFragmentCachingFilter {
SpringcacheService springcacheService
CacheManager cacheManager

private final ThreadLocal<FilterContext> contextHolder = new ThreadLocal<FilterContext>()
private final ThreadLocal<Stack<FilterContext>> contextHolder = new ThreadLocal<Stack<FilterContext>>() {
@Override
protected Stack<FilterContext> initialValue() {
new Stack<FilterContext>()
}
}
static final String X_SPRINGCACHE_CACHED = "X-Springcache-Cached"

/**
Expand Down Expand Up @@ -249,15 +254,20 @@ class GrailsFragmentCachingFilter extends PageFragmentCachingFilter {
}

private void initContext() {
contextHolder.set(new FilterContext())
contextStack.push(new FilterContext())
}

private FilterContext getContext() {
contextHolder.get()
contextStack.peek()
}

private void destroyContext() {
contextHolder.remove()
contextStack.pop()
if (contextStack.empty()) contextHolder.remove()
}

private Stack<FilterContext> getContextStack() {
contextHolder.get()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ grails.project.class.dir = "target/classes"
grails.project.test.class.dir = "target/test-classes"
grails.project.test.reports.dir = "target/test-reports"
grails.project.dependency.resolution = {
inherits "global"
inherits("global") {
excludes "xml-apis"
}
log "warn"
repositories {
grailsPlugins()
Expand Down Expand Up @@ -39,5 +41,17 @@ grails.project.dependency.resolution = {
compile ":resources:1.1.6"
runtime ":jquery:1.7.1"
}
plugins {
build ":tomcat:$grailsVersion"
compile ":bean-fields:0.5"
compile ":cache-headers:1.1.2"
compile ":rateable:0.6.2"
compile ":shiro:1.1.1"
compile ":yui:2.7.0.1"
runtime ":hibernate:$grailsVersion"
test ":build-test-data:1.1.1"
test ":geb:0.5.1"
test ":spock:0.5-groovy-1.7"
}
}
grails.plugin.location.springcache = "../../.."
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ springcache {
userControllerCache
latestControllerCache
popularControllerCache
forwardingControllerCache
layoutsCache
configuredCache {
timeToLive = 86400
Expand Down
Loading