├── .gitignore ├── LICENSE.txt ├── README.md ├── RemoteControlGrailsPlugin.groovy ├── application.properties ├── grails-app ├── conf │ ├── BuildConfig.groovy │ ├── Config.groovy │ ├── DataSource.groovy │ └── UrlMappings.groovy ├── domain │ └── Person.groovy ├── services │ └── TheService.groovy └── views │ └── error.gsp ├── scripts └── _Events.groovy ├── src └── groovy │ └── grails │ └── plugin │ └── remotecontrol │ ├── RemoteControl.groovy │ └── RemoteControlServlet.groovy ├── test └── functional │ └── SmokeTests.groovy └── web-app └── WEB-INF ├── applicationContext.xml ├── sitemesh.xml └── tld ├── c.tld ├── fmt.tld ├── grails.tld └── spring.tld /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .classpath 3 | .settings 4 | .project 5 | .DS_Store 6 | *.log 7 | *.zip 8 | *.xml -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The Grails remote-control plugin allows you to execute code inside a remote Grails application. The typical use case for this is for functional testing where you are testing an application inside a separate JVM and therefore do not have easy access to the application runtime. If you can access the application runtime environment then you can do things like change service parameter values, create and delete domain data and so forth. 2 | 3 | The plugin uses the [Groovy Remote Control](http://groovy.codehaus.org/modules/remote/ "Groovy Remote Control") library. 4 | 5 | **This plugin requires Grails 2.0.0 and will not work on earlier versions** 6 | 7 | ## An Example 8 | 9 | ### The Test 10 | 11 | We have written an application and now want to write some functional tests. In these tests we need to create some test data. This might look something like… 12 | ```groovy 13 | class MyFunctionalTest extends GroovyTestCase { 14 | 15 | def testIt() { 16 | def person = new Person(name: "Me") 17 | person.save(flush: true) 18 | 19 | // Somehow make some HTTP request and test that person is in the DB 20 | 21 | person.delete(flush: true) 22 | } 23 | 24 | } 25 | ``` 26 | That will work if we are running our tests in the same JVM as the running application, which is the default behaviour… 27 | ```sh 28 | grails test-app functional: 29 | ``` 30 | However, it won't work if your tests ARE NOT in the same JVM, as is the case with testing against a WAR deployment… 31 | ```sh 32 | grails test-app functional: -war 33 | ``` 34 | This is going to fail because in the JVM that is running the tests there is no Grails application (the WAR is run in a forked JVM to be closer to a production like environment). 35 | 36 | ### Existing Solutions 37 | 38 | The most common existing workaround for this problem is to write a special controller that you call via HTTP in your functional tests to do the setup/teardown. This will work, but requires effort and is inherently fragile. 39 | 40 | ### Using a remote control 41 | 42 | The remote control plugin solves this problem by allowing you to define closures to be executed in the application you are testing. This is best illustrated by rewriting the above test… 43 | ```groovy 44 | import grails.plugin.remotecontrol.RemoteControl 45 | 46 | class MyFunctionalTest extends GroovyTestCase { 47 | 48 | def remote = new RemoteControl() 49 | 50 | def testIt() { 51 | def id = remote { 52 | def person = new Person(name: "Me") 53 | person.save() 54 | person.id 55 | } 56 | 57 | // Somehow make some HTTP request and test that person is in the DB 58 | 59 | remote { 60 | Person.get(id).delete() 61 | } 62 | } 63 | } 64 | ``` 65 | This test will now working when testing agains a WAR or a local version. The closures passed to `remote` are sent over HTTP to the running application and executed there, so it doesn't matter where the application is. 66 | 67 | #### Chaining 68 | 69 | Closures can be *chained*, with the return value of the previous closure being passed as an argument to the next closure in the chain. This is done on the server side, so it's ok for a closure to return a non serialisable value to be given to the next one. An example use for this would be reusing a closure to fetch some value, and then using another closure to process it. 70 | ```groovy 71 | import grails.plugin.remotecontrol.RemoteControl 72 | 73 | class MyFunctionalTest extends GroovyTestCase { 74 | 75 | def remote = new RemoteControl() 76 | 77 | def getPerson = { id -> Person.get(id) } 78 | 79 | def modifyPerson(id, Closure modifications) { 80 | // pass the result of the getPerson command to the 81 | // given modifications command 82 | remote.exec(getPerson.curry(id), modifications) 83 | } 84 | 85 | def testIt() { 86 | def id = remote { 87 | def person = new Person(name: "Me") 88 | person.save() 89 | person.id 90 | } 91 | 92 | // Somehow make some HTTP request and test that person is in the DB 93 | 94 | // Change the name 95 | modifyPerson(id) { 96 | it.setName("New Name") 97 | it.save(flush: true) 98 | null // return must be serialisable 99 | } 100 | 101 | // Somehow make some HTTP request and test that the person's name has changed 102 | 103 | // Cleanup 104 | modifyPerson(id) { 105 | it.delete() 106 | } 107 | } 108 | } 109 | ``` 110 | A more concise example of how values are passed to the next command in the chain would be… 111 | ```groovy 112 | assert remote.exec({ 1 }, { it + 1 }, { it + 1 }) == 3 113 | ``` 114 | 115 | #### Context 116 | 117 | The Groovy Remote Control library establishes a [command context](http://groovy.codehaus.org/modules/remote/manual/latest/contexts.html "Groovy Remote Control - Command Context") that is shared for all commands in a given chain. 118 | 119 | This plugin prepoluates the context with two variables: 120 | 121 | * `ctx` - The main application context 122 | * `app` - The grails application object 123 | 124 | This allows you to access beans (such as services) from commands… 125 | ```groovy 126 | remote.exec { ctx.someService.doSomeServiceStuff() } 127 | ``` 128 | 129 | ##### Populating The Context 130 | 131 | You can also set values in the context. This is sometimes useful when using a command chain where an initial command sets up some context. 132 | ```groovy 133 | def getPersonWithId = { person = Person.get(it) } 134 | def doubleAge = { person.age *= 2 } 135 | def savePerson = { person.save(flush: true) } 136 | 137 | def doubleAgeOfPersonWithId(id) { 138 | remote.exec(getPersonWithId.curry(id), doubleAge, savePerson) 139 | } 140 | 141 | doubleAgeOfPersonWithId(10) 142 | ``` 143 | 144 | #### More Examples 145 | 146 | To see some more usage examples of a remote control, see the [demonstration test case](http://github.com/alkemist/grails-remote-control/blob/master/test/functional/SmokeTests.groovy) in the project. 147 | 148 | ### Testing Remote Apps 149 | 150 | Let's say that we want to functionally test our application on different flavours of application server and we have our app deployed on three different app servers at the following URLs: 151 | 152 | * http://appsrv1.test.my.org/myapp 153 | * http://appsrv2.test.my.org/myapp 154 | * http://appsrv3.test.my.org/myapp 155 | 156 | If we have the remote-control plugin installed and have written our tests to use it, we could simply run: 157 | ```sh 158 | grails test-app functional: -baseUrl=http://appsrv1.test.my.org/myapp 159 | grails test-app functional: -baseUrl=http://appsrv2.test.my.org/myapp 160 | grails test-app functional: -baseUrl=http://appsrv3.test.my.org/myapp 161 | ``` 162 | 163 | Which will execute the tests against that remote instance. 164 | 165 | ### Security 166 | 167 | By default, the servlet that accepts remote commands is only configured when the application is started in the **test** environment. This means that it is not possible to use a remote with a production application out of the box. 168 | 169 | However, if you do want to enable the remote control servlet that accepts commands in an environment other than production you can set `remoteControl.enabled` to `true` in the application config for that environment. 170 | 171 | ### Testing applications with catch-all URL Mappings 172 | 173 | Your remote control will not work if you have a catch-all URL mapping, e.g. 174 | 175 | class UrlMappings { 176 | static mappings = { 177 | "/**"(controller:'boss') 178 | } 179 | } 180 | 181 | You will see `groovyx.remote.RemoteControlException: Error sending command chain`. The fix is to add the following line to URL Mappings: 182 | 183 | static excludes = ['/grails-remote-control'] 184 | 185 | Your URL mappings should now look like: 186 | 187 | class UrlMappings { 188 | static excludes = ['/grails-remote-control'] 189 | static mappings = { 190 | "/**"(controller:'boss') 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /RemoteControlGrailsPlugin.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Luke Daley 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 | class RemoteControlGrailsPlugin { 18 | 19 | def version = "2.0" 20 | def grailsVersion = "2.0.0 > *" 21 | def dependsOn = [:] 22 | def pluginExcludes = ["grails-app/**/*", "scripts/**/*"] 23 | 24 | def author = "Luke Daley" 25 | def authorEmail = "ld@ldaley.com" 26 | def title = "Remote Control" 27 | def description = "Remotely control a Grails application (for functional testing)" 28 | def documentation = "http://grails.org/plugin/remote-control" 29 | 30 | def doWithWebDescriptor = { webXml -> 31 | def remoteControlClass = getClass().classLoader.loadClass('grails.plugin.remotecontrol.RemoteControl') 32 | 33 | def servlets = webXml.servlet 34 | def lastServlet = servlets[servlets.size() - 1] 35 | lastServlet + { 36 | servlet { 37 | 'servlet-name'('grails-remote-control') 38 | 'servlet-class'('grails.plugin.remotecontrol.RemoteControlServlet') 39 | 'load-on-startup'(1) 40 | } 41 | } 42 | def mappings = webXml.'servlet-mapping' 43 | def lastMapping = mappings[mappings.size() - 1] 44 | lastMapping + { 45 | 'servlet-mapping' { 46 | 'servlet-name'('grails-remote-control') 47 | 'url-pattern'("/${remoteControlClass.RECEIVER_PATH}") 48 | } 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /application.properties: -------------------------------------------------------------------------------- 1 | #Grails Metadata file 2 | #Tue Oct 02 16:56:40 MSK 2012 3 | app.grails.version=2.0.0 4 | app.name=grails-remote-control 5 | plugins.rest-client-builder=1.0.2 6 | -------------------------------------------------------------------------------- /grails-app/conf/BuildConfig.groovy: -------------------------------------------------------------------------------- 1 | grails.project.class.dir = "target/classes" 2 | grails.project.test.class.dir = "target/test-classes" 3 | grails.project.test.reports.dir = "target/test-reports" 4 | grails.project.target.level = 1.6 5 | grails.project.source.level = 1.6 6 | grails.project.dependency.resolution = { 7 | inherits( "global" ) 8 | log "warn" 9 | repositories { 10 | grailsCentral() 11 | grailsHome() 12 | mavenLocal() 13 | mavenCentral() 14 | mavenRepo "http://dl.bintray.com/alkemist/maven" 15 | } 16 | dependencies { 17 | compile "io.remotecontrol:remote-core:0.7" 18 | compile "io.remotecontrol:remote-transport-http:0.7", { 19 | excludes "servlet-api" 20 | } 21 | } 22 | plugins { 23 | compile ( 24 | ":tomcat:$grailsVersion", 25 | ":hibernate:$grailsVersion", 26 | ":spock:0.6" 27 | ) { 28 | export = false 29 | } 30 | 31 | build(":release:2.0.4") { 32 | export = false 33 | } 34 | } 35 | } 36 | 37 | grails.release.scm.enabled = false 38 | -------------------------------------------------------------------------------- /grails-app/conf/Config.groovy: -------------------------------------------------------------------------------- 1 | // remoteControl.enabled = false 2 | grails.views.default.codec="none" // none, html, base64 3 | grails.views.gsp.encoding="UTF-8" 4 | -------------------------------------------------------------------------------- /grails-app/conf/DataSource.groovy: -------------------------------------------------------------------------------- 1 | dataSource { 2 | pooled = true 3 | driverClassName = "org.h2.Driver" 4 | username = "sa" 5 | password = "" 6 | } 7 | hibernate { 8 | cache.use_second_level_cache=true 9 | cache.use_query_cache=true 10 | cache.provider_class='net.sf.ehcache.hibernate.EhCacheProvider' 11 | } 12 | // environment specific settings 13 | environments { 14 | development { 15 | dataSource { 16 | dbCreate = "create-drop" // one of 'create', 'create-drop','update' 17 | url = "jdbc:h2:mem:devDB" 18 | } 19 | } 20 | test { 21 | dataSource { 22 | dbCreate = "update" 23 | url = "jdbc:h2:mem:testDb" 24 | } 25 | } 26 | production { 27 | dataSource { 28 | dbCreate = "update" 29 | url = "jdbc:h2:file:prodDb;shutdown=true" 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /grails-app/conf/UrlMappings.groovy: -------------------------------------------------------------------------------- 1 | class UrlMappings { 2 | static mappings = { 3 | "/$controller/$action?/$id?"{ 4 | constraints { 5 | // apply constraints here 6 | } 7 | } 8 | "/"(view:"/index") 9 | "500"(view:'/error') 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /grails-app/domain/Person.groovy: -------------------------------------------------------------------------------- 1 | class Person { 2 | 3 | String name 4 | 5 | } -------------------------------------------------------------------------------- /grails-app/services/TheService.groovy: -------------------------------------------------------------------------------- 1 | class TheService { 2 | 3 | def value 4 | 5 | } -------------------------------------------------------------------------------- /grails-app/views/error.gsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | Grails Runtime Exception 4 | 24 | 25 | 26 | 27 |

Grails Runtime Exception

28 |

Error Details

29 | 30 |
31 | Error ${request.'javax.servlet.error.status_code'}: ${request.'javax.servlet.error.message'.encodeAsHTML()}
32 | Servlet: ${request.'javax.servlet.error.servlet_name'}
33 | URI: ${request.'javax.servlet.error.request_uri'}
34 | 35 | Exception Message: ${exception.message?.encodeAsHTML()}
36 | Caused by: ${exception.cause?.message?.encodeAsHTML()}
37 | Class: ${exception.className}
38 | At Line: [${exception.lineNumber}]
39 | Code Snippet:
40 |
41 | 42 | ${cs?.encodeAsHTML()}
43 |
44 |
45 |
46 |
47 | 48 |

Stack Trace

49 |
50 |
${it.encodeAsHTML()}
51 |
52 |
53 | 54 | -------------------------------------------------------------------------------- /scripts/_Events.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Luke Daley 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 | eventAllTestsStart = { 17 | if (grailsAppName == "grails-remote-control") { 18 | functionalTests << "functional" 19 | } 20 | } -------------------------------------------------------------------------------- /src/groovy/grails/plugin/remotecontrol/RemoteControl.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Luke Daley 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 | package grails.plugin.remotecontrol 17 | 18 | import grails.util.BuildSettingsHolder 19 | import io.remotecontrol.transport.http.HttpTransport 20 | 21 | /** 22 | * Adds grails specific convenient no arg constructor 23 | */ 24 | class RemoteControl extends io.remotecontrol.groovy.client.RemoteControl { 25 | 26 | static public final RECEIVER_PATH = "grails-remote-control" 27 | 28 | static defaultReceiverAddress 29 | 30 | RemoteControl() { 31 | super(new HttpTransport(getFunctionalTestReceiverAddress(), Thread.currentThread().contextClassLoader), Thread.currentThread().contextClassLoader) 32 | } 33 | 34 | private static getFunctionalTestReceiverAddress() { 35 | def base = getFunctionalTestBaseUrl() 36 | if (!base) { 37 | throw new IllegalStateException("Cannot get receiver address for functional testing as functional test base URL is not set. Are you calling this from a functional test?") 38 | } 39 | 40 | base.endsWith("/") ? base + RECEIVER_PATH : base + "/" + RECEIVER_PATH 41 | } 42 | 43 | private static getFunctionalTestBaseUrl() { 44 | BuildSettingsHolder.settings?.functionalTestBaseUrl 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/groovy/grails/plugin/remotecontrol/RemoteControlServlet.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Luke Daley 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 | package grails.plugin.remotecontrol 17 | 18 | import javax.servlet.* 19 | import javax.servlet.http.* 20 | import io.remotecontrol.server.Receiver 21 | import io.remotecontrol.groovy.server.ClosureReceiver 22 | import grails.util.Holders 23 | import grails.util.Environment 24 | 25 | class RemoteControlServlet extends io.remotecontrol.transport.http.RemoteControlServlet { 26 | 27 | void doExecute(InputStream input, OutputStream output) { 28 | def persistenceInterceptor = grailsApplication?.mainContext?.persistenceInterceptor 29 | persistenceInterceptor?.init() 30 | try { 31 | super.doExecute(input, output) 32 | } finally { 33 | persistenceInterceptor?.flush() 34 | persistenceInterceptor?.destroy() 35 | } 36 | } 37 | 38 | protected boolean validateRequest(HttpServletRequest request, HttpServletResponse response) { 39 | if (!isEnabled()) { 40 | response.sendError(404, "Remote control disabled") 41 | return false 42 | } 43 | 44 | return super.validateRequest(request, response) 45 | } 46 | 47 | def getGrailsApplication() { 48 | Holders.grailsApplication 49 | } 50 | 51 | protected Receiver createReceiver() { 52 | new ClosureReceiver(grailsApplication.classLoader, [app: grailsApplication, ctx: grailsApplication.mainContext]) 53 | } 54 | 55 | boolean isEnabled() { 56 | def configValue = grailsApplication.config.remoteControl.enabled 57 | if (configValue instanceof ConfigObject) { 58 | getDefaultIsEnabledForEnvironment() 59 | } else { 60 | configValue 61 | } 62 | } 63 | 64 | boolean getDefaultIsEnabledForEnvironment() { 65 | if (Environment.current == Environment.TEST) { 66 | true 67 | } else { 68 | false 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /test/functional/SmokeTests.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Luke Daley 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 grails.plugin.remotecontrol.RemoteControl 17 | import io.remotecontrol.client.RemoteException 18 | import io.remotecontrol.client.UnserializableReturnException 19 | import io.remotecontrol.UnserializableCommandException 20 | 21 | /** 22 | * This test case shows how to use the remote control and some of it's limitations 23 | * with regard to serialisation and scope. 24 | * 25 | * The remote control object has an exec(Closure) method, and an alias for that as call(Closure). 26 | * The call(Closure) variant allows the use of the Groovy language feature where you can essentially 27 | * treat an object like a method, which is how “remote { … }” works below (i.e. it's really “remote.call { … }). 28 | * This doesn't always work though as you will see (due to Groovy), so sometimes you need to use .exec(). 29 | * 30 | * Where we are passing a closure to the remote control object, that closure gets executed INSIDE the 31 | * application we are functionally testing, which may be in a different JVM on a completely different machine. 32 | * This works by sending the closure over HTTP to the application (which must have the remote-control plugin installed). 33 | * 34 | * An example use for this would be creating/deleting domain data inside your remote application for testing purposes. 35 | */ 36 | class SmokeTests extends GroovyTestCase { 37 | 38 | def remote = new RemoteControl() 39 | 40 | // Used in a later test 41 | def anIvar = 2 42 | 43 | /** 44 | * The result of the command run on the server is sent back and is returned 45 | */ 46 | void testReturingValues() { 47 | assert remote { 1 + 1 } == 2 48 | } 49 | 50 | /** 51 | * The delegate of the command contains the app context under 'ctx', 52 | * so we can access any beans defined there 53 | */ 54 | void testAccessTheAppContext() { 55 | def name = remote { 56 | ctx.grailsApplication.metadata['app.name'] 57 | } 58 | 59 | assert name == "grails-remote-control" 60 | } 61 | 62 | /** 63 | * We can create and manipulate domain data. Each command operates in a 64 | * hibernate session that is flushed at the end of the command. 65 | */ 66 | void testWorkingWithDomain() { 67 | def id = remote { 68 | def person = new Person(name: "Me") 69 | person.save() 70 | person.id 71 | } 72 | 73 | assert remote { Person.countByName("Me") } == 1 74 | 75 | remote { 76 | Person.get(id).delete() 77 | } 78 | 79 | assert remote { Person.countByName("Me") } == 0 80 | } 81 | 82 | /** 83 | * Commands can contain other closures 84 | */ 85 | void testWithInnerClosures() { 86 | assert [2,3,4] == remote { 87 | [1,2,3].collect { it + 1 } 88 | } 89 | } 90 | 91 | /** 92 | * If the command throwns an exception, we throw a RemoteException 93 | * client side with the actual exception instance that was thrown server 94 | * side as the cause 95 | */ 96 | void testThrowingException() { 97 | def thrown = null 98 | try { 99 | remote { throw new Exception("bang!") } 100 | } catch (RemoteException e) { 101 | thrown = e.cause 102 | assert thrown.class == Exception 103 | assert thrown.message == "bang!" 104 | } 105 | 106 | assert thrown 107 | } 108 | 109 | /** 110 | * If the command returns something that is unserialisable, we thrown an UnserializableReturnException 111 | */ 112 | void testUnserialisableReturn() { 113 | shouldFail(UnserializableReturnException) { 114 | remote.exec { System.out } 115 | } 116 | } 117 | 118 | /** 119 | * If the command returns an exception but does not throw it, we just return the exception 120 | */ 121 | void testReturningException() { 122 | assert (remote { new Exception() }) instanceof Exception 123 | } 124 | 125 | /** 126 | * We can access lexical scope (within limits) 127 | */ 128 | void testAccessingLexicalScope() { 129 | def a = 1 130 | assert remote { a + 1 } == 2 131 | } 132 | 133 | /** 134 | * Anything in lexical scope we access must be serialisable 135 | */ 136 | void testAccessingNonSerializableLexicalScope() { 137 | def a = System.out 138 | shouldFail(UnserializableCommandException) { 139 | remote.exec { a } 140 | } 141 | } 142 | 143 | /** 144 | * Owner ivars can't be accessed because they aren't really lexical 145 | * so get treated as bean names from the app context 146 | */ 147 | void testAccessingIvar() { 148 | def thrown 149 | try { 150 | remote { anIvar * 2 } 151 | } catch (RemoteException e) { 152 | thrown = e.cause 153 | assert thrown instanceof MissingPropertyException 154 | } 155 | 156 | assert thrown 157 | } 158 | 159 | /** 160 | * We can pass curried commands 161 | */ 162 | void testCurryingCommands() { 163 | def command = { it + 2 } 164 | assert remote.exec(command.curry(2)) == 4 165 | } 166 | 167 | /** 168 | * We can curry a command as many times as we need to 169 | */ 170 | void testCurryingCommandsMoreThanOnce() { 171 | def command = { a, b -> a + b } 172 | def curry1 = command.curry(1) 173 | def curry2 = curry1.curry(1) 174 | 175 | assert remote.exec(curry2) == 2 176 | } 177 | 178 | /** 179 | * Like everything else, currying args must be serialisable 180 | */ 181 | void testCurryingArgsMustBeSerializable() { 182 | shouldFail(UnserializableCommandException) { 183 | remote.exec({ it }.curry(System.out)) 184 | } 185 | } 186 | 187 | /** 188 | * Any classes referenced have to be available in the remote app, 189 | * and any classes defined in tests ARE NOT. 190 | */ 191 | void testCannotReferToClassesNotInTheApp() { 192 | def a = new SmokeTestsLocal() 193 | shouldFailWithCause(ClassNotFoundException) { 194 | remote.exec { a } 195 | } 196 | } 197 | 198 | /** 199 | * Variation of above, but yields a different error. 200 | */ 201 | void testCannotInstantiateClassesNotInTheApp() { 202 | shouldFailWithCause(NoClassDefFoundError) { 203 | remote.exec { new SmokeTestsLocal() } 204 | } 205 | } 206 | 207 | /** 208 | * Multiple commands can be sent, the return value of the previous 209 | * command is passed to the next command as it's single argument 210 | */ 211 | void testCommandChaining() { 212 | remote.exec({ 1 }, { it + 1 }, { it + 1 }) == 3 213 | } 214 | 215 | /** 216 | * The delegate of commands is like a map and can store properties. 217 | */ 218 | void testCanUseDelegateStorageAlongChain() { 219 | remote.exec({ num = 1 }, { num = num + 1 }, { num + 1 }) == 3 220 | } 221 | 222 | /** 223 | * Trying to access a property that is not existing in the delegate 224 | * causes a MissingPropertyException 225 | */ 226 | void testAccessingNonExistantPropertyFromDelegateCausesMPE() { 227 | shouldFailWithCause(MissingPropertyException) { 228 | remote.exec { iDontExist == true } 229 | } 230 | } 231 | 232 | void testCanSetProperties() { 233 | remote.exec { ctx.theService.value = 1 } 234 | remote.exec { ctx.theService.setValue(1) } 235 | remote.exec { ctx.theService.setProperty('value', 1) } 236 | } 237 | 238 | void testCanCallMethodsDynamicaly() { 239 | def methodName = "setValue" 240 | remote.exec { ctx.theService."$methodName"(1) } 241 | remote.exec { ctx.theService.invokeMethod(methodName, 1) } 242 | } 243 | 244 | } 245 | 246 | 247 | class SmokeTestsLocal implements Serializable {} 248 | -------------------------------------------------------------------------------- /web-app/WEB-INF/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | Grails application factory bean 9 | 10 | 11 | 12 | 13 | 14 | A bean that manages Grails plugins 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | utf-8 31 | 32 | 33 | -------------------------------------------------------------------------------- /web-app/WEB-INF/sitemesh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /web-app/WEB-INF/tld/c.tld: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | JSTL 1.2 core library 9 | JSTL core 10 | 1.2 11 | c 12 | http://java.sun.com/jsp/jstl/core 13 | 14 | 15 | 16 | Provides core validation features for JSTL tags. 17 | 18 | 19 | org.apache.taglibs.standard.tlv.JstlCoreTLV 20 | 21 | 22 | 23 | 24 | 25 | Catches any Throwable that occurs in its body and optionally 26 | exposes it. 27 | 28 | catch 29 | org.apache.taglibs.standard.tag.common.core.CatchTag 30 | JSP 31 | 32 | 33 | Name of the exported scoped variable for the 34 | exception thrown from a nested action. The type of the 35 | scoped variable is the type of the exception thrown. 36 | 37 | var 38 | false 39 | false 40 | 41 | 42 | 43 | 44 | 45 | Simple conditional tag that establishes a context for 46 | mutually exclusive conditional operations, marked by 47 | <when> and <otherwise> 48 | 49 | choose 50 | org.apache.taglibs.standard.tag.common.core.ChooseTag 51 | JSP 52 | 53 | 54 | 55 | 56 | Simple conditional tag, which evalutes its body if the 57 | supplied condition is true and optionally exposes a Boolean 58 | scripting variable representing the evaluation of this condition 59 | 60 | if 61 | org.apache.taglibs.standard.tag.rt.core.IfTag 62 | JSP 63 | 64 | 65 | The test condition that determines whether or 66 | not the body content should be processed. 67 | 68 | test 69 | true 70 | true 71 | boolean 72 | 73 | 74 | 75 | Name of the exported scoped variable for the 76 | resulting value of the test condition. The type 77 | of the scoped variable is Boolean. 78 | 79 | var 80 | false 81 | false 82 | 83 | 84 | 85 | Scope for var. 86 | 87 | scope 88 | false 89 | false 90 | 91 | 92 | 93 | 94 | 95 | Retrieves an absolute or relative URL and exposes its contents 96 | to either the page, a String in 'var', or a Reader in 'varReader'. 97 | 98 | import 99 | org.apache.taglibs.standard.tag.rt.core.ImportTag 100 | org.apache.taglibs.standard.tei.ImportTEI 101 | JSP 102 | 103 | 104 | The URL of the resource to import. 105 | 106 | url 107 | true 108 | true 109 | 110 | 111 | 112 | Name of the exported scoped variable for the 113 | resource's content. The type of the scoped 114 | variable is String. 115 | 116 | var 117 | false 118 | false 119 | 120 | 121 | 122 | Scope for var. 123 | 124 | scope 125 | false 126 | false 127 | 128 | 129 | 130 | Name of the exported scoped variable for the 131 | resource's content. The type of the scoped 132 | variable is Reader. 133 | 134 | varReader 135 | false 136 | false 137 | 138 | 139 | 140 | Name of the context when accessing a relative 141 | URL resource that belongs to a foreign 142 | context. 143 | 144 | context 145 | false 146 | true 147 | 148 | 149 | 150 | Character encoding of the content at the input 151 | resource. 152 | 153 | charEncoding 154 | false 155 | true 156 | 157 | 158 | 159 | 160 | 161 | The basic iteration tag, accepting many different 162 | collection types and supporting subsetting and other 163 | functionality 164 | 165 | forEach 166 | org.apache.taglibs.standard.tag.rt.core.ForEachTag 167 | org.apache.taglibs.standard.tei.ForEachTEI 168 | JSP 169 | 170 | 171 | Collection of items to iterate over. 172 | 173 | items 174 | false 175 | true 176 | java.lang.Object 177 | 178 | java.lang.Object 179 | 180 | 181 | 182 | 183 | If items specified: 184 | Iteration begins at the item located at the 185 | specified index. First item of the collection has 186 | index 0. 187 | If items not specified: 188 | Iteration begins with index set at the value 189 | specified. 190 | 191 | begin 192 | false 193 | true 194 | int 195 | 196 | 197 | 198 | If items specified: 199 | Iteration ends at the item located at the 200 | specified index (inclusive). 201 | If items not specified: 202 | Iteration ends when index reaches the value 203 | specified. 204 | 205 | end 206 | false 207 | true 208 | int 209 | 210 | 211 | 212 | Iteration will only process every step items of 213 | the collection, starting with the first one. 214 | 215 | step 216 | false 217 | true 218 | int 219 | 220 | 221 | 222 | Name of the exported scoped variable for the 223 | current item of the iteration. This scoped 224 | variable has nested visibility. Its type depends 225 | on the object of the underlying collection. 226 | 227 | var 228 | false 229 | false 230 | 231 | 232 | 233 | Name of the exported scoped variable for the 234 | status of the iteration. Object exported is of type 235 | javax.servlet.jsp.jstl.core.LoopTagStatus. This scoped variable has nested 236 | visibility. 237 | 238 | varStatus 239 | false 240 | false 241 | 242 | 243 | 244 | 245 | 246 | Iterates over tokens, separated by the supplied delimeters 247 | 248 | forTokens 249 | org.apache.taglibs.standard.tag.rt.core.ForTokensTag 250 | JSP 251 | 252 | 253 | String of tokens to iterate over. 254 | 255 | items 256 | true 257 | true 258 | java.lang.String 259 | 260 | java.lang.String 261 | 262 | 263 | 264 | 265 | The set of delimiters (the characters that 266 | separate the tokens in the string). 267 | 268 | delims 269 | true 270 | true 271 | java.lang.String 272 | 273 | 274 | 275 | Iteration begins at the token located at the 276 | specified index. First token has index 0. 277 | 278 | begin 279 | false 280 | true 281 | int 282 | 283 | 284 | 285 | Iteration ends at the token located at the 286 | specified index (inclusive). 287 | 288 | end 289 | false 290 | true 291 | int 292 | 293 | 294 | 295 | Iteration will only process every step tokens 296 | of the string, starting with the first one. 297 | 298 | step 299 | false 300 | true 301 | int 302 | 303 | 304 | 305 | Name of the exported scoped variable for the 306 | current item of the iteration. This scoped 307 | variable has nested visibility. 308 | 309 | var 310 | false 311 | false 312 | 313 | 314 | 315 | Name of the exported scoped variable for the 316 | status of the iteration. Object exported is of 317 | type 318 | javax.servlet.jsp.jstl.core.LoopTag 319 | Status. This scoped variable has nested 320 | visibility. 321 | 322 | varStatus 323 | false 324 | false 325 | 326 | 327 | 328 | 329 | 330 | Like <%= ... >, but for expressions. 331 | 332 | out 333 | org.apache.taglibs.standard.tag.rt.core.OutTag 334 | JSP 335 | 336 | 337 | Expression to be evaluated. 338 | 339 | value 340 | true 341 | true 342 | 343 | 344 | 345 | Default value if the resulting value is null. 346 | 347 | default 348 | false 349 | true 350 | 351 | 352 | 353 | Determines whether characters <,>,&,'," in the 354 | resulting string should be converted to their 355 | corresponding character entity codes. Default value is 356 | true. 357 | 358 | escapeXml 359 | false 360 | true 361 | 362 | 363 | 364 | 365 | 366 | 367 | Subtag of <choose> that follows <when> tags 368 | and runs only if all of the prior conditions evaluated to 369 | 'false' 370 | 371 | otherwise 372 | org.apache.taglibs.standard.tag.common.core.OtherwiseTag 373 | JSP 374 | 375 | 376 | 377 | 378 | Adds a parameter to a containing 'import' tag's URL. 379 | 380 | param 381 | org.apache.taglibs.standard.tag.rt.core.ParamTag 382 | JSP 383 | 384 | 385 | Name of the query string parameter. 386 | 387 | name 388 | true 389 | true 390 | 391 | 392 | 393 | Value of the parameter. 394 | 395 | value 396 | false 397 | true 398 | 399 | 400 | 401 | 402 | 403 | Redirects to a new URL. 404 | 405 | redirect 406 | org.apache.taglibs.standard.tag.rt.core.RedirectTag 407 | JSP 408 | 409 | 410 | The URL of the resource to redirect to. 411 | 412 | url 413 | false 414 | true 415 | 416 | 417 | 418 | Name of the context when redirecting to a relative URL 419 | resource that belongs to a foreign context. 420 | 421 | context 422 | false 423 | true 424 | 425 | 426 | 427 | 428 | 429 | Removes a scoped variable (from a particular scope, if specified). 430 | 431 | remove 432 | org.apache.taglibs.standard.tag.common.core.RemoveTag 433 | empty 434 | 435 | 436 | Name of the scoped variable to be removed. 437 | 438 | var 439 | true 440 | false 441 | 442 | 443 | 444 | Scope for var. 445 | 446 | scope 447 | false 448 | false 449 | 450 | 451 | 452 | 453 | 454 | Sets the result of an expression evaluation in a 'scope' 455 | 456 | set 457 | org.apache.taglibs.standard.tag.rt.core.SetTag 458 | JSP 459 | 460 | 461 | Name of the exported scoped variable to hold the value 462 | specified in the action. The type of the scoped variable is 463 | whatever type the value expression evaluates to. 464 | 465 | var 466 | false 467 | false 468 | 469 | 470 | 471 | Expression to be evaluated. 472 | 473 | value 474 | false 475 | true 476 | 477 | java.lang.Object 478 | 479 | 480 | 481 | 482 | Target object whose property will be set. Must evaluate to 483 | a JavaBeans object with setter property property, or to a 484 | java.util.Map object. 485 | 486 | target 487 | false 488 | true 489 | 490 | 491 | 492 | Name of the property to be set in the target object. 493 | 494 | property 495 | false 496 | true 497 | 498 | 499 | 500 | Scope for var. 501 | 502 | scope 503 | false 504 | false 505 | 506 | 507 | 508 | 509 | 510 | Creates a URL with optional query parameters. 511 | 512 | url 513 | org.apache.taglibs.standard.tag.rt.core.UrlTag 514 | JSP 515 | 516 | 517 | Name of the exported scoped variable for the 518 | processed url. The type of the scoped variable is 519 | String. 520 | 521 | var 522 | false 523 | false 524 | 525 | 526 | 527 | Scope for var. 528 | 529 | scope 530 | false 531 | false 532 | 533 | 534 | 535 | URL to be processed. 536 | 537 | value 538 | false 539 | true 540 | 541 | 542 | 543 | Name of the context when specifying a relative URL 544 | resource that belongs to a foreign context. 545 | 546 | context 547 | false 548 | true 549 | 550 | 551 | 552 | 553 | 554 | Subtag of <choose> that includes its body if its 555 | condition evalutes to 'true' 556 | 557 | when 558 | org.apache.taglibs.standard.tag.rt.core.WhenTag 559 | JSP 560 | 561 | 562 | The test condition that determines whether or not the 563 | body content should be processed. 564 | 565 | test 566 | true 567 | true 568 | boolean 569 | 570 | 571 | 572 | 573 | -------------------------------------------------------------------------------- /web-app/WEB-INF/tld/fmt.tld: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | JSTL 1.2 i18n-capable formatting library 9 | JSTL fmt 10 | 1.2 11 | fmt 12 | http://java.sun.com/jsp/jstl/fmt 13 | 14 | 15 | 16 | Provides core validation features for JSTL tags. 17 | 18 | 19 | org.apache.taglibs.standard.tlv.JstlFmtTLV 20 | 21 | 22 | 23 | 24 | 25 | Sets the request character encoding 26 | 27 | requestEncoding 28 | org.apache.taglibs.standard.tag.rt.fmt.RequestEncodingTag 29 | empty 30 | 31 | 32 | Name of character encoding to be applied when 33 | decoding request parameters. 34 | 35 | value 36 | false 37 | true 38 | 39 | 40 | 41 | 42 | 43 | Stores the given locale in the locale configuration variable 44 | 45 | setLocale 46 | org.apache.taglibs.standard.tag.rt.fmt.SetLocaleTag 47 | empty 48 | 49 | 50 | A String value is interpreted as the 51 | printable representation of a locale, which 52 | must contain a two-letter (lower-case) 53 | language code (as defined by ISO-639), 54 | and may contain a two-letter (upper-case) 55 | country code (as defined by ISO-3166). 56 | Language and country codes must be 57 | separated by hyphen (-) or underscore 58 | (_). 59 | 60 | value 61 | true 62 | true 63 | 64 | 65 | 66 | Vendor- or browser-specific variant. 67 | See the java.util.Locale javadocs for 68 | more information on variants. 69 | 70 | variant 71 | false 72 | true 73 | 74 | 75 | 76 | Scope of the locale configuration variable. 77 | 78 | scope 79 | false 80 | false 81 | 82 | 83 | 84 | 85 | 86 | Specifies the time zone for any time formatting or parsing actions 87 | nested in its body 88 | 89 | timeZone 90 | org.apache.taglibs.standard.tag.rt.fmt.TimeZoneTag 91 | JSP 92 | 93 | 94 | The time zone. A String value is interpreted as 95 | a time zone ID. This may be one of the time zone 96 | IDs supported by the Java platform (such as 97 | "America/Los_Angeles") or a custom time zone 98 | ID (such as "GMT-8"). See 99 | java.util.TimeZone for more information on 100 | supported time zone formats. 101 | 102 | value 103 | true 104 | true 105 | 106 | 107 | 108 | 109 | 110 | Stores the given time zone in the time zone configuration variable 111 | 112 | setTimeZone 113 | org.apache.taglibs.standard.tag.rt.fmt.SetTimeZoneTag 114 | empty 115 | 116 | 117 | The time zone. A String value is interpreted as 118 | a time zone ID. This may be one of the time zone 119 | IDs supported by the Java platform (such as 120 | "America/Los_Angeles") or a custom time zone 121 | ID (such as "GMT-8"). See java.util.TimeZone for 122 | more information on supported time zone 123 | formats. 124 | 125 | value 126 | true 127 | true 128 | 129 | 130 | 131 | Name of the exported scoped variable which 132 | stores the time zone of type 133 | java.util.TimeZone. 134 | 135 | var 136 | false 137 | false 138 | 139 | 140 | 141 | Scope of var or the time zone configuration 142 | variable. 143 | 144 | scope 145 | false 146 | false 147 | 148 | 149 | 150 | 151 | 152 | Loads a resource bundle to be used by its tag body 153 | 154 | bundle 155 | org.apache.taglibs.standard.tag.rt.fmt.BundleTag 156 | JSP 157 | 158 | 159 | Resource bundle base name. This is the bundle's 160 | fully-qualified resource name, which has the same 161 | form as a fully-qualified class name, that is, it uses 162 | "." as the package component separator and does not 163 | have any file type (such as ".class" or ".properties") 164 | suffix. 165 | 166 | basename 167 | true 168 | true 169 | 170 | 171 | 172 | Prefix to be prepended to the value of the message 173 | key of any nested <fmt:message> action. 174 | 175 | prefix 176 | false 177 | true 178 | 179 | 180 | 181 | 182 | 183 | Loads a resource bundle and stores it in the named scoped variable or 184 | the bundle configuration variable 185 | 186 | setBundle 187 | org.apache.taglibs.standard.tag.rt.fmt.SetBundleTag 188 | empty 189 | 190 | 191 | Resource bundle base name. This is the bundle's 192 | fully-qualified resource name, which has the same 193 | form as a fully-qualified class name, that is, it uses 194 | "." as the package component separator and does not 195 | have any file type (such as ".class" or ".properties") 196 | suffix. 197 | 198 | basename 199 | true 200 | true 201 | 202 | 203 | 204 | Name of the exported scoped variable which stores 205 | the i18n localization context of type 206 | javax.servlet.jsp.jstl.fmt.LocalizationC 207 | ontext. 208 | 209 | var 210 | false 211 | false 212 | 213 | 214 | 215 | Scope of var or the localization context 216 | configuration variable. 217 | 218 | scope 219 | false 220 | false 221 | 222 | 223 | 224 | 225 | 226 | Maps key to localized message and performs parametric replacement 227 | 228 | message 229 | org.apache.taglibs.standard.tag.rt.fmt.MessageTag 230 | JSP 231 | 232 | 233 | Message key to be looked up. 234 | 235 | key 236 | false 237 | true 238 | 239 | 240 | 241 | Localization context in whose resource 242 | bundle the message key is looked up. 243 | 244 | bundle 245 | false 246 | true 247 | 248 | 249 | 250 | Name of the exported scoped variable 251 | which stores the localized message. 252 | 253 | var 254 | false 255 | false 256 | 257 | 258 | 259 | Scope of var. 260 | 261 | scope 262 | false 263 | false 264 | 265 | 266 | 267 | 268 | 269 | Supplies an argument for parametric replacement to a containing 270 | <message> tag 271 | 272 | param 273 | org.apache.taglibs.standard.tag.rt.fmt.ParamTag 274 | JSP 275 | 276 | 277 | Argument used for parametric replacement. 278 | 279 | value 280 | false 281 | true 282 | 283 | 284 | 285 | 286 | 287 | Formats a numeric value as a number, currency, or percentage 288 | 289 | formatNumber 290 | org.apache.taglibs.standard.tag.rt.fmt.FormatNumberTag 291 | JSP 292 | 293 | 294 | Numeric value to be formatted. 295 | 296 | value 297 | false 298 | true 299 | 300 | 301 | 302 | Specifies whether the value is to be 303 | formatted as number, currency, or 304 | percentage. 305 | 306 | type 307 | false 308 | true 309 | 310 | 311 | 312 | Custom formatting pattern. 313 | 314 | pattern 315 | false 316 | true 317 | 318 | 319 | 320 | ISO 4217 currency code. Applied only 321 | when formatting currencies (i.e. if type is 322 | equal to "currency"); ignored otherwise. 323 | 324 | currencyCode 325 | false 326 | true 327 | 328 | 329 | 330 | Currency symbol. Applied only when 331 | formatting currencies (i.e. if type is equal 332 | to "currency"); ignored otherwise. 333 | 334 | currencySymbol 335 | false 336 | true 337 | 338 | 339 | 340 | Specifies whether the formatted output 341 | will contain any grouping separators. 342 | 343 | groupingUsed 344 | false 345 | true 346 | 347 | 348 | 349 | Maximum number of digits in the integer 350 | portion of the formatted output. 351 | 352 | maxIntegerDigits 353 | false 354 | true 355 | 356 | 357 | 358 | Minimum number of digits in the integer 359 | portion of the formatted output. 360 | 361 | minIntegerDigits 362 | false 363 | true 364 | 365 | 366 | 367 | Maximum number of digits in the 368 | fractional portion of the formatted output. 369 | 370 | maxFractionDigits 371 | false 372 | true 373 | 374 | 375 | 376 | Minimum number of digits in the 377 | fractional portion of the formatted output. 378 | 379 | minFractionDigits 380 | false 381 | true 382 | 383 | 384 | 385 | Name of the exported scoped variable 386 | which stores the formatted result as a 387 | String. 388 | 389 | var 390 | false 391 | false 392 | 393 | 394 | 395 | Scope of var. 396 | 397 | scope 398 | false 399 | false 400 | 401 | 402 | 403 | 404 | 405 | Parses the string representation of a number, currency, or percentage 406 | 407 | parseNumber 408 | org.apache.taglibs.standard.tag.rt.fmt.ParseNumberTag 409 | JSP 410 | 411 | 412 | String to be parsed. 413 | 414 | value 415 | false 416 | true 417 | 418 | 419 | 420 | Specifies whether the string in the value 421 | attribute should be parsed as a number, 422 | currency, or percentage. 423 | 424 | type 425 | false 426 | true 427 | 428 | 429 | 430 | Custom formatting pattern that determines 431 | how the string in the value attribute is to be 432 | parsed. 433 | 434 | pattern 435 | false 436 | true 437 | 438 | 439 | 440 | Locale whose default formatting pattern (for 441 | numbers, currencies, or percentages, 442 | respectively) is to be used during the parse 443 | operation, or to which the pattern specified 444 | via the pattern attribute (if present) is 445 | applied. 446 | 447 | parseLocale 448 | false 449 | true 450 | 451 | 452 | 453 | Specifies whether just the integer portion of 454 | the given value should be parsed. 455 | 456 | integerOnly 457 | false 458 | true 459 | 460 | 461 | 462 | Name of the exported scoped variable which 463 | stores the parsed result (of type 464 | java.lang.Number). 465 | 466 | var 467 | false 468 | false 469 | 470 | 471 | 472 | Scope of var. 473 | 474 | scope 475 | false 476 | false 477 | 478 | 479 | 480 | 481 | 482 | Formats a date and/or time using the supplied styles and pattern 483 | 484 | formatDate 485 | org.apache.taglibs.standard.tag.rt.fmt.FormatDateTag 486 | empty 487 | 488 | 489 | Date and/or time to be formatted. 490 | 491 | value 492 | true 493 | true 494 | 495 | 496 | 497 | Specifies whether the time, the date, or both 498 | the time and date components of the given 499 | date are to be formatted. 500 | 501 | type 502 | false 503 | true 504 | 505 | 506 | 507 | Predefined formatting style for dates. Follows 508 | the semantics defined in class 509 | java.text.DateFormat. Applied only 510 | when formatting a date or both a date and 511 | time (i.e. if type is missing or is equal to 512 | "date" or "both"); ignored otherwise. 513 | 514 | dateStyle 515 | false 516 | true 517 | 518 | 519 | 520 | Predefined formatting style for times. Follows 521 | the semantics defined in class 522 | java.text.DateFormat. Applied only 523 | when formatting a time or both a date and 524 | time (i.e. if type is equal to "time" or "both"); 525 | ignored otherwise. 526 | 527 | timeStyle 528 | false 529 | true 530 | 531 | 532 | 533 | Custom formatting style for dates and times. 534 | 535 | pattern 536 | false 537 | true 538 | 539 | 540 | 541 | Time zone in which to represent the formatted 542 | time. 543 | 544 | timeZone 545 | false 546 | true 547 | 548 | 549 | 550 | Name of the exported scoped variable which 551 | stores the formatted result as a String. 552 | 553 | var 554 | false 555 | false 556 | 557 | 558 | 559 | Scope of var. 560 | 561 | scope 562 | false 563 | false 564 | 565 | 566 | 567 | 568 | 569 | Parses the string representation of a date and/or time 570 | 571 | parseDate 572 | org.apache.taglibs.standard.tag.rt.fmt.ParseDateTag 573 | JSP 574 | 575 | 576 | Date string to be parsed. 577 | 578 | value 579 | false 580 | true 581 | 582 | 583 | 584 | Specifies whether the date string in the 585 | value attribute is supposed to contain a 586 | time, a date, or both. 587 | 588 | type 589 | false 590 | true 591 | 592 | 593 | 594 | Predefined formatting style for days 595 | which determines how the date 596 | component of the date string is to be 597 | parsed. Applied only when formatting a 598 | date or both a date and time (i.e. if type 599 | is missing or is equal to "date" or "both"); 600 | ignored otherwise. 601 | 602 | dateStyle 603 | false 604 | true 605 | 606 | 607 | 608 | Predefined formatting styles for times 609 | which determines how the time 610 | component in the date string is to be 611 | parsed. Applied only when formatting a 612 | time or both a date and time (i.e. if type 613 | is equal to "time" or "both"); ignored 614 | otherwise. 615 | 616 | timeStyle 617 | false 618 | true 619 | 620 | 621 | 622 | Custom formatting pattern which 623 | determines how the date string is to be 624 | parsed. 625 | 626 | pattern 627 | false 628 | true 629 | 630 | 631 | 632 | Time zone in which to interpret any time 633 | information in the date string. 634 | 635 | timeZone 636 | false 637 | true 638 | 639 | 640 | 641 | Locale whose predefined formatting styles 642 | for dates and times are to be used during 643 | the parse operation, or to which the 644 | pattern specified via the pattern 645 | attribute (if present) is applied. 646 | 647 | parseLocale 648 | false 649 | true 650 | 651 | 652 | 653 | Name of the exported scoped variable in 654 | which the parsing result (of type 655 | java.util.Date) is stored. 656 | 657 | var 658 | false 659 | false 660 | 661 | 662 | 663 | Scope of var. 664 | 665 | scope 666 | false 667 | false 668 | 669 | 670 | 671 | 672 | -------------------------------------------------------------------------------- /web-app/WEB-INF/tld/grails.tld: -------------------------------------------------------------------------------- 1 | 2 | 7 | The Grails custom tag library 8 | 0.2 9 | grails 10 | http://grails.codehaus.org/tags 11 | 12 | 13 | link 14 | org.codehaus.groovy.grails.web.taglib.jsp.JspLinkTag 15 | JSP 16 | 17 | action 18 | false 19 | true 20 | 21 | 22 | controller 23 | false 24 | true 25 | 26 | 27 | id 28 | false 29 | true 30 | 31 | 32 | url 33 | false 34 | true 35 | 36 | 37 | params 38 | false 39 | true 40 | 41 | true 42 | 43 | 44 | form 45 | org.codehaus.groovy.grails.web.taglib.jsp.JspFormTag 46 | JSP 47 | 48 | action 49 | false 50 | true 51 | 52 | 53 | controller 54 | false 55 | true 56 | 57 | 58 | id 59 | false 60 | true 61 | 62 | 63 | url 64 | false 65 | true 66 | 67 | 68 | method 69 | true 70 | true 71 | 72 | true 73 | 74 | 75 | select 76 | org.codehaus.groovy.grails.web.taglib.jsp.JspSelectTag 77 | JSP 78 | 79 | name 80 | true 81 | true 82 | 83 | 84 | value 85 | false 86 | true 87 | 88 | 89 | optionKey 90 | false 91 | true 92 | 93 | 94 | optionValue 95 | false 96 | true 97 | 98 | true 99 | 100 | 101 | datePicker 102 | org.codehaus.groovy.grails.web.taglib.jsp.JspDatePickerTag 103 | empty 104 | 105 | name 106 | true 107 | true 108 | 109 | 110 | value 111 | false 112 | true 113 | 114 | 115 | precision 116 | false 117 | true 118 | 119 | false 120 | 121 | 122 | currencySelect 123 | org.codehaus.groovy.grails.web.taglib.jsp.JspCurrencySelectTag 124 | empty 125 | 126 | name 127 | true 128 | true 129 | 130 | 131 | value 132 | false 133 | true 134 | 135 | true 136 | 137 | 138 | localeSelect 139 | org.codehaus.groovy.grails.web.taglib.jsp.JspLocaleSelectTag 140 | empty 141 | 142 | name 143 | true 144 | true 145 | 146 | 147 | value 148 | false 149 | true 150 | 151 | true 152 | 153 | 154 | timeZoneSelect 155 | org.codehaus.groovy.grails.web.taglib.jsp.JspTimeZoneSelectTag 156 | empty 157 | 158 | name 159 | true 160 | true 161 | 162 | 163 | value 164 | false 165 | true 166 | 167 | true 168 | 169 | 170 | checkBox 171 | org.codehaus.groovy.grails.web.taglib.jsp.JspCheckboxTag 172 | empty 173 | 174 | name 175 | true 176 | true 177 | 178 | 179 | value 180 | true 181 | true 182 | 183 | true 184 | 185 | 186 | hasErrors 187 | org.codehaus.groovy.grails.web.taglib.jsp.JspHasErrorsTag 188 | JSP 189 | 190 | model 191 | false 192 | true 193 | 194 | 195 | bean 196 | false 197 | true 198 | 199 | 200 | field 201 | false 202 | true 203 | 204 | false 205 | 206 | 207 | eachError 208 | org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag 209 | JSP 210 | 211 | model 212 | false 213 | true 214 | 215 | 216 | bean 217 | false 218 | true 219 | 220 | 221 | field 222 | false 223 | true 224 | 225 | false 226 | 227 | 228 | renderErrors 229 | org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag 230 | JSP 231 | 232 | model 233 | false 234 | true 235 | 236 | 237 | bean 238 | false 239 | true 240 | 241 | 242 | field 243 | false 244 | true 245 | 246 | 247 | as 248 | true 249 | true 250 | 251 | false 252 | 253 | 254 | message 255 | org.codehaus.groovy.grails.web.taglib.jsp.JspMessageTag 256 | JSP 257 | 258 | code 259 | false 260 | true 261 | 262 | 263 | error 264 | false 265 | true 266 | 267 | 268 | default 269 | false 270 | true 271 | 272 | false 273 | 274 | 275 | remoteFunction 276 | org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteFunctionTag 277 | empty 278 | 279 | before 280 | false 281 | true 282 | 283 | 284 | after 285 | false 286 | true 287 | 288 | 289 | action 290 | false 291 | true 292 | 293 | 294 | controller 295 | false 296 | true 297 | 298 | 299 | id 300 | false 301 | true 302 | 303 | 304 | url 305 | false 306 | true 307 | 308 | 309 | params 310 | false 311 | true 312 | 313 | 314 | asynchronous 315 | false 316 | true 317 | 318 | 319 | method 320 | false 321 | true 322 | 323 | 324 | update 325 | false 326 | true 327 | 328 | 329 | onSuccess 330 | false 331 | true 332 | 333 | 334 | onFailure 335 | false 336 | true 337 | 338 | 339 | onComplete 340 | false 341 | true 342 | 343 | 344 | onLoading 345 | false 346 | true 347 | 348 | 349 | onLoaded 350 | false 351 | true 352 | 353 | 354 | onInteractive 355 | false 356 | true 357 | 358 | true 359 | 360 | 361 | remoteLink 362 | org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteLinkTag 363 | JSP 364 | 365 | before 366 | false 367 | true 368 | 369 | 370 | after 371 | false 372 | true 373 | 374 | 375 | action 376 | false 377 | true 378 | 379 | 380 | controller 381 | false 382 | true 383 | 384 | 385 | id 386 | false 387 | true 388 | 389 | 390 | url 391 | false 392 | true 393 | 394 | 395 | params 396 | false 397 | true 398 | 399 | 400 | asynchronous 401 | false 402 | true 403 | 404 | 405 | method 406 | false 407 | true 408 | 409 | 410 | update 411 | false 412 | true 413 | 414 | 415 | onSuccess 416 | false 417 | true 418 | 419 | 420 | onFailure 421 | false 422 | true 423 | 424 | 425 | onComplete 426 | false 427 | true 428 | 429 | 430 | onLoading 431 | false 432 | true 433 | 434 | 435 | onLoaded 436 | false 437 | true 438 | 439 | 440 | onInteractive 441 | false 442 | true 443 | 444 | true 445 | 446 | 447 | formRemote 448 | org.codehaus.groovy.grails.web.taglib.jsp.JspFormRemoteTag 449 | JSP 450 | 451 | before 452 | false 453 | true 454 | 455 | 456 | after 457 | false 458 | true 459 | 460 | 461 | action 462 | false 463 | true 464 | 465 | 466 | controller 467 | false 468 | true 469 | 470 | 471 | id 472 | false 473 | true 474 | 475 | 476 | url 477 | false 478 | true 479 | 480 | 481 | params 482 | false 483 | true 484 | 485 | 486 | asynchronous 487 | false 488 | true 489 | 490 | 491 | method 492 | false 493 | true 494 | 495 | 496 | update 497 | false 498 | true 499 | 500 | 501 | onSuccess 502 | false 503 | true 504 | 505 | 506 | onFailure 507 | false 508 | true 509 | 510 | 511 | onComplete 512 | false 513 | true 514 | 515 | 516 | onLoading 517 | false 518 | true 519 | 520 | 521 | onLoaded 522 | false 523 | true 524 | 525 | 526 | onInteractive 527 | false 528 | true 529 | 530 | true 531 | 532 | 533 | invokeTag 534 | org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag 535 | JSP 536 | 537 | it 538 | java.lang.Object 539 | true 540 | NESTED 541 | 542 | 543 | tagName 544 | true 545 | true 546 | 547 | true 548 | 549 | 550 | 551 | -------------------------------------------------------------------------------- /web-app/WEB-INF/tld/spring.tld: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 1.1.1 7 | 8 | 1.2 9 | 10 | Spring 11 | 12 | http://www.springframework.org/tags 13 | 14 | Spring Framework JSP Tag Library. Authors: Rod Johnson, Juergen Hoeller 15 | 16 | 17 | 18 | 19 | htmlEscape 20 | org.springframework.web.servlet.tags.HtmlEscapeTag 21 | JSP 22 | 23 | 24 | Sets default HTML escape value for the current page. 25 | Overrides a "defaultHtmlEscape" context-param in web.xml, if any. 26 | 27 | 28 | 29 | defaultHtmlEscape 30 | true 31 | true 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | escapeBody 40 | org.springframework.web.servlet.tags.EscapeBodyTag 41 | JSP 42 | 43 | 44 | Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping. 45 | The HTML escaping flag participates in a page-wide or application-wide setting 46 | (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). 47 | 48 | 49 | 50 | htmlEscape 51 | false 52 | true 53 | 54 | 55 | 56 | javaScriptEscape 57 | false 58 | true 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | message 67 | org.springframework.web.servlet.tags.MessageTag 68 | JSP 69 | 70 | 71 | Retrieves the message with the given code, or text if code isn't resolvable. 72 | The HTML escaping flag participates in a page-wide or application-wide setting 73 | (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). 74 | 75 | 76 | 77 | code 78 | false 79 | true 80 | 81 | 82 | 83 | arguments 84 | false 85 | true 86 | 87 | 88 | 89 | text 90 | false 91 | true 92 | 93 | 94 | 95 | var 96 | false 97 | true 98 | 99 | 100 | 101 | scope 102 | false 103 | true 104 | 105 | 106 | 107 | htmlEscape 108 | false 109 | true 110 | 111 | 112 | 113 | javaScriptEscape 114 | false 115 | true 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | theme 124 | org.springframework.web.servlet.tags.ThemeTag 125 | JSP 126 | 127 | 128 | Retrieves the theme message with the given code, or text if code isn't resolvable. 129 | The HTML escaping flag participates in a page-wide or application-wide setting 130 | (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). 131 | 132 | 133 | 134 | code 135 | false 136 | true 137 | 138 | 139 | 140 | arguments 141 | false 142 | true 143 | 144 | 145 | 146 | text 147 | false 148 | true 149 | 150 | 151 | 152 | var 153 | false 154 | true 155 | 156 | 157 | 158 | scope 159 | false 160 | true 161 | 162 | 163 | 164 | htmlEscape 165 | false 166 | true 167 | 168 | 169 | 170 | javaScriptEscape 171 | false 172 | true 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | hasBindErrors 181 | org.springframework.web.servlet.tags.BindErrorsTag 182 | JSP 183 | 184 | 185 | Provides Errors instance in case of bind errors. 186 | The HTML escaping flag participates in a page-wide or application-wide setting 187 | (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). 188 | 189 | 190 | 191 | errors 192 | org.springframework.validation.Errors 193 | 194 | 195 | 196 | name 197 | true 198 | true 199 | 200 | 201 | 202 | htmlEscape 203 | false 204 | true 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | nestedPath 213 | org.springframework.web.servlet.tags.NestedPathTag 214 | JSP 215 | 216 | 217 | Sets a nested path to be used by the bind tag's path. 218 | 219 | 220 | 221 | nestedPath 222 | java.lang.String 223 | 224 | 225 | 226 | path 227 | true 228 | true 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | bind 237 | org.springframework.web.servlet.tags.BindTag 238 | JSP 239 | 240 | 241 | Provides BindStatus object for the given bind path. 242 | The HTML escaping flag participates in a page-wide or application-wide setting 243 | (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). 244 | 245 | 246 | 247 | status 248 | org.springframework.web.servlet.support.BindStatus 249 | 250 | 251 | 252 | path 253 | true 254 | true 255 | 256 | 257 | 258 | ignoreNestedPath 259 | false 260 | true 261 | 262 | 263 | 264 | htmlEscape 265 | false 266 | true 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | transform 275 | org.springframework.web.servlet.tags.TransformTag 276 | JSP 277 | 278 | 279 | Provides transformation of variables to Strings, using an appropriate 280 | custom PropertyEditor from BindTag (can only be used inside BindTag). 281 | The HTML escaping flag participates in a page-wide or application-wide setting 282 | (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). 283 | 284 | 285 | 286 | value 287 | true 288 | true 289 | 290 | 291 | 292 | var 293 | false 294 | true 295 | 296 | 297 | 298 | scope 299 | false 300 | true 301 | 302 | 303 | 304 | htmlEscape 305 | false 306 | true 307 | 308 | 309 | 310 | 311 | 312 | --------------------------------------------------------------------------------