├── application.properties
├── grails-app
└── conf
│ └── BuildConfig.groovy
├── .gitignore
├── .project
├── .classpath
├── src
└── groovy
│ └── com
│ └── netflix
│ └── grails
│ └── contextParam
│ └── ContextParam.groovy
├── README.md
└── ContextParamGrailsPlugin.groovy
/application.properties:
--------------------------------------------------------------------------------
1 | app.grails.version=2.0.4
2 |
--------------------------------------------------------------------------------
/grails-app/conf/BuildConfig.groovy:
--------------------------------------------------------------------------------
1 | grails.project.work.dir = 'target'
2 | grails.project.source.level = 1.6
3 |
4 | grails.project.dependency.resolution = {
5 |
6 | inherits 'global'
7 | log 'warn'
8 |
9 | repositories {
10 | grailsCentral()
11 | mavenLocal()
12 | mavenCentral()
13 | }
14 |
15 | dependencies {}
16 |
17 | plugins {
18 | build(':release:2.0.3', ':rest-client-builder:1.0.2') {
19 | export = false
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # .gitignore for Grails 1.2 and 1.3
2 |
3 | # web application files
4 | /web-app/WEB-INF
5 |
6 | # IDE support files
7 | /.launch
8 | /.settings
9 | /*.launch
10 | /*.tmproj
11 | /ivy*
12 | /eclipse
13 | *.iws
14 |
15 | # default HSQL database files for production mode
16 | /prodDb.*
17 |
18 | # general HSQL database files
19 | *Db.properties
20 | *Db.script
21 |
22 | # logs
23 | *.log
24 | /test/reports
25 | /logs
26 |
27 | # plugin release file and XML metadata
28 | /*.zip
29 | /plugin.xml
30 |
31 | # older plugin install locations
32 | /web-app/plugins
33 | /web-app/WEB-INF/classes
34 |
35 | # "temporary" build files
36 | /target
37 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | grails-context-param
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.common.project.facet.core.builder
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 |
20 | com.springsource.sts.grails.core.nature
21 | org.eclipse.jdt.groovy.core.groovyNature
22 | org.eclipse.jdt.core.javanature
23 | org.eclipse.wst.common.project.facet.core.nature
24 |
25 |
26 |
27 | .link_to_grails_plugins
28 | 2
29 | GRAILS_ROOT/grails-context-param/target/plugins
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/groovy/com/netflix/grails/contextParam/ContextParam.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.grails.contextParam
18 |
19 | import java.lang.annotation.ElementType
20 | import java.lang.annotation.Retention
21 | import java.lang.annotation.RetentionPolicy
22 | import java.lang.annotation.Target
23 |
24 | /**
25 | * The value of this annotation indicates a parameter name that will be automatically sent along to any redirect or
26 | * chain calls to this controller.
27 | */
28 | @Retention(RetentionPolicy.RUNTIME)
29 | @Target(ElementType.TYPE)
30 | @interface ContextParam {
31 | String value()
32 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Grails context param plugin
2 |
3 | In some cases, you may want to ensure a specific context is always passed along to a Grails controllers. For example, you may want to make sure a RESTful url always includes a region for certain controllers. Your URLMappings.groovy will have an entry like:
4 |
5 | `/$region/$controller/$action?/$id?`
6 |
7 | This requires passing the region parameter through every request if you want avoid keeping that state in the session. In practice, this means that all of the redirect and chain blocks will have to repeat appending the same parameters to every call. Your code will have lines like these scattered all over:
8 |
9 | `redirect(action: show, params: [region: region])`
10 |
11 | or
12 |
13 | `chain(action: create, model: [cmd: cmd], params: [region: region])`
14 |
15 | This plugin allows you to annotate controllers with `@ContextParam` annotations to specify these parameters and automatically include them on any redirect or chain calls.
16 |
17 | For example:
18 | ```
19 | @ContextParam('region')
20 | class InstanceController {
21 | ...
22 | ```
23 | will append the `region` param from the current request if `redirect(controller: 'instance')` is called, eliminating the need to append the params to the call.
24 |
25 | In addition, the configuration of context param declarations is available on the `grailsApplication` object in the field `Map> controllerNamesToContextParams`. To check if region is a `@ContextParam` for a particular controller you can call:
26 |
27 | `grailsApplication.controllerNamesToContextParams[(controllerName)].contains('region')`
28 |
29 | This plugin will be used by [Netflix's Asgard project](https://github.com/Netflix/asgard) for it's upgrade to Grails 2.1.
--------------------------------------------------------------------------------
/ContextParamGrailsPlugin.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import com.netflix.grails.contextParam.ContextParam
17 | import org.codehaus.groovy.grails.commons.ControllerArtefactHandler
18 | import org.codehaus.groovy.grails.commons.GrailsControllerClass
19 | import org.springframework.web.context.request.RequestContextHolder
20 |
21 | class ContextParamGrailsPlugin {
22 |
23 | def observe = ["controllers"]
24 |
25 | def version = "1.0"
26 | def grailsVersion = "1.3.7 > *"
27 | def loadAfter = ['controllers']
28 |
29 | def author = "Jason Gritman"
30 | def authorEmail = "jgritman@netflix.com"
31 | def title = "Context param plugin"
32 | def description = 'Automatically adds parameters specified as @ContextParam on a controller to redirect calls.'
33 | def documentation = "https://github.com/Netflix-Skunkworks/grails-context-param#grails-context-param-plugin"
34 |
35 | // License: one of 'APACHE', 'GPL2', 'GPL3'
36 | def license = 'APACHE'
37 |
38 | // Details of company behind the plugin (if there is one)
39 | // def organization = [ name: "My Company", url: "http://www.my-company.com/" ]
40 |
41 | // Any additional developers beyond the author specified above.
42 | // def developers = [ [ name: "Joe Bloggs", email: "joe@bloggs.net" ]]
43 |
44 | // Location of the plugin's issue tracker.
45 | // def issueManagement = [ system: "JIRA", url: "http://jira.grails.org/browse/GPMYPLUGIN" ]
46 |
47 | def scm = [url: 'https://github.com/Netflix-Skunkworks/grails-context-param']
48 |
49 | def doWithDynamicMethods = { ctx ->
50 | Map> controllerNamesToContextParams = [:]
51 | for (GrailsControllerClass controllerClass in application.controllerClasses) {
52 | Collection contextParams = findContextParams(controllerClass)
53 | replaceRedirectMethod(controllerClass, contextParams)
54 | controllerNamesToContextParams[(controllerClass.logicalPropertyName)] = contextParams
55 | }
56 | application.metaClass.getControllerNamesToContextParams = { ->
57 | controllerNamesToContextParams
58 | }
59 | }
60 |
61 | def onChange = { event ->
62 | // Replace the redirect/chain methods again if the controller has changed
63 | if(event.source instanceof Class &&
64 | application.isArtefactOfType(ControllerArtefactHandler.TYPE, event.source)) {
65 | GrailsControllerClass controllerClass = application.getArtefact(ControllerArtefactHandler.TYPE,
66 | event.source.name)
67 | Collection contextParams = findContextParams(controllerClass)
68 | replaceRedirectMethod(controllerClass, contextParams)
69 | application.controllerNamesToContextParams[(controllerClass.logicalPropertyName)] = contextParams
70 | }
71 | }
72 |
73 | /**
74 | * Wraps the chain and redirect methods.
75 | */
76 | private void replaceRedirectMethod(GrailsControllerClass controllerClass, Collection contextParams) {
77 | wrapMethod(controllerClass, contextParams, 'redirect')
78 | wrapMethod(controllerClass, contextParams, 'chain')
79 | }
80 |
81 | /**
82 | * Take a method by name, and add a call to appendContextParams before that method invokation.
83 | */
84 | private void wrapMethod(GrailsControllerClass controllerClass, Collection contextParams, String name) {
85 | def oldMethod = controllerClass.metaClass.pickMethod(name, [Map] as Class[])
86 | controllerClass.metaClass."${name}" = { Map args ->
87 | appendContextParams(contextParams, args)
88 | oldMethod.invoke(delegate, args)
89 | }
90 | }
91 |
92 | /**
93 | * Add any specified context params to the params on the arguments. If there is no params object it will be created.
94 | */
95 | private void appendContextParams(Collection contextParams, Map arguments) {
96 | if (arguments && contextParams ) {
97 | // If redirect was called without a params map object then make an empty params map.
98 | Map params = arguments.params ?: [:]
99 | def request = RequestContextHolder.currentRequestAttributes()
100 | contextParams.each { String contextParam ->
101 | if (!params[(contextParam)]) {
102 | params[(contextParam)] = request.params[(contextParam)]
103 | }
104 | }
105 | arguments.params = params
106 | }
107 | }
108 |
109 | /**
110 | * Find all of the @ContextParam annotions on the controller.
111 | */
112 | private Collection findContextParams(GrailsControllerClass controllerClass) {
113 | controllerClass.clazz.declaredAnnotations.findAll { it instanceof ContextParam }.collect { it.value() }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------