| 1 | ******************************************************************************** |
|---|
| 2 | Copyright 2005-2008 ColdBox Framework by Luis Majano and Ortus Solutions, Corp |
|---|
| 3 | www.coldboxframework.com | www.luismajano.com | www.ortussolutions.com |
|---|
| 4 | ******************************************************************************** |
|---|
| 5 | HONOR GOES TO GOD ABOVE ALL |
|---|
| 6 | ******************************************************************************** |
|---|
| 7 | Because of His grace, this project exits. If you don't like this, then don't read it, its not for you. |
|---|
| 8 | |
|---|
| 9 | "Therefore being justified by faith, we have peace with God through our Lord Jesus Christ: |
|---|
| 10 | By whom also we have access by faith into this grace wherein we stand, and rejoice in hope of the glory of God. |
|---|
| 11 | And not only so, but we glory in tribulations also: knowing that tribulation worketh patience; |
|---|
| 12 | And patience, experience; and experience, hope: |
|---|
| 13 | And hope maketh not ashamed; because the love of God is shed abroad in our hearts by the |
|---|
| 14 | Holy Ghost which is given unto us. ." Romans 5:5 |
|---|
| 15 | |
|---|
| 16 | ******************************************************************************** |
|---|
| 17 | WELCOME TO COLDBOX GROOVY LOADER PLUGIN |
|---|
| 18 | ******************************************************************************** |
|---|
| 19 | The following guide can be read in full splendor here: |
|---|
| 20 | http://ortus.svnrepository.com/coldbox/trac.cgi/wiki/cbGroovyLoader |
|---|
| 21 | |
|---|
| 22 | == Introduction == |
|---|
| 23 | This plugin is thanks to Barney Boisevert for his cfgroovy inspiration. |
|---|
| 24 | |
|---|
| 25 | This plugin dynamically loads a coldbox application with the groovy runtime and |
|---|
| 26 | other java libraries you so desire. You can configure a classpath within your application |
|---|
| 27 | that will act as the root of what you want to execute or you can dynamically use the groovy scripting tags. |
|---|
| 28 | |
|---|
| 29 | The groovy loader plugin also leverages the coldbox cache in order to store the java |
|---|
| 30 | class files the groovyloader creates from script. Internally, the groovy class loader |
|---|
| 31 | also caches the parsed classes so they are not re-parsed at runtime. The plugin includes |
|---|
| 32 | two methods to interact with these caches: |
|---|
| 33 | |
|---|
| 34 | * '''clearClazzCache()''' : Cleans the coldbox cache of loaded groovy scripts |
|---|
| 35 | * '''clearClassLoaderCache()''' : Cleans the actual classloader's cache, use sparingly |
|---|
| 36 | |
|---|
| 37 | Why would I want to clear the class loader cache? You want to do this, whenever |
|---|
| 38 | you make changes to the groovy files on disk. However, be warned that classloading |
|---|
| 39 | is a very tempestous beast and it can lead to memory leaks or JVM permGen errors |
|---|
| 40 | as class definitions do not get garbage collected or disposed of. However, this |
|---|
| 41 | side effect is only visualized on development. |
|---|
| 42 | |
|---|
| 43 | == Release Notes == |
|---|
| 44 | |
|---|
| 45 | === VERSION 2.0 === |
|---|
| 46 | * Added ability to load more than 1 location for groovy scripts |
|---|
| 47 | * Added ability to load more than 1 location for java libraries alongside groovy language |
|---|
| 48 | * Added the !GroovyStarter interceptor for easy loading of the runtime, fully configurable |
|---|
| 49 | |
|---|
| 50 | === VERSION 1.0 === |
|---|
| 51 | * Initial groovy integration |
|---|
| 52 | |
|---|
| 53 | == Installation == |
|---|
| 54 | |
|---|
| 55 | === Requirements: === |
|---|
| 56 | * !ColdFusion 8 and above |
|---|
| 57 | * Railo 3.0 and above |
|---|
| 58 | |
|---|
| 59 | === Install: === |
|---|
| 60 | |
|---|
| 61 | Copy the plugin folder: !GroovyLoader to your custom plugins or bring them in |
|---|
| 62 | via the !MyPluginsLocation or !PluginsExternalLocation setting. |
|---|
| 63 | |
|---|
| 64 | Then either configure the class path and plugin like in the sample application: |
|---|
| 65 | |
|---|
| 66 | {{{ |
|---|
| 67 | <cfset getMyPlugin("GroovyLoader.GroovyLoader").configureClassPath(getSetting("ApplicationPath") & "model/groovy")> |
|---|
| 68 | }}} |
|---|
| 69 | |
|---|
| 70 | Or just use the !GroovyStarter interceptor, way easy: |
|---|
| 71 | |
|---|
| 72 | {{{ |
|---|
| 73 | #!xml |
|---|
| 74 | <!-- Groovy Starter: Creates & configures the GroovyLoader --> |
|---|
| 75 | <Interceptor class="${AppMapping}.plugins.GroovyLoader.GroovyStarter"> |
|---|
| 76 | <!-- Paths that hold groovy libs --> |
|---|
| 77 | <Property name="groovyLibPaths">/${AppMapping}/model/groovy,/${AppMapping}/model/anotherPath</Property> |
|---|
| 78 | <!-- Paths that hold jar's for us to load automagically --> |
|---|
| 79 | <Property name="javalibPaths">/${AppMapping}/model/lib</Property> |
|---|
| 80 | </Interceptor> |
|---|
| 81 | }}} |
|---|
| 82 | |
|---|
| 83 | === Interceptor Properties === |
|---|
| 84 | |
|---|
| 85 | || '''groovyLibPaths''' || A comma-delimitted list of relative/absolute path locations for groovy scripts or classes || |
|---|
| 86 | || '''javaLibPaths''' || A comma-delimitted list of relative/absolute path locations for the java loader to load java libraries alongside the core groovy language || |
|---|
| 87 | || '''pluginClassPath''' || The location of the groovy loader plugin. By Default: !GroovyLoader.!GroovyLoader || |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | == Class Path Usage == |
|---|
| 91 | |
|---|
| 92 | If you will be using a groovy folder for entities or for script executions, then you will have to configure |
|---|
| 93 | the plugin's groovyLibPaths to point to the locations where your groovy scripts/classes are located. The |
|---|
| 94 | Groovy Loader will then let you create scripts and groovy classes at runtime by just using their instantiation name from the root directory downwards. The groovy loader plugin will search in all configured class paths for the scripts/classes, once it locates it it will create it. This way, you can have more than 1 location for the scripts. |
|---|
| 95 | |
|---|
| 96 | Ex: |
|---|
| 97 | {{{ |
|---|
| 98 | /model |
|---|
| 99 | /groovy (is your in your groovyLibPaths) |
|---|
| 100 | - Hello.groovy |
|---|
| 101 | /util |
|---|
| 102 | - DateCompare.groovy |
|---|
| 103 | }}} |
|---|
| 104 | |
|---|
| 105 | To create these classes you would use their dot notation: |
|---|
| 106 | |
|---|
| 107 | {{{ |
|---|
| 108 | #!java |
|---|
| 109 | create("Hello") |
|---|
| 110 | create("util.DateCompare") |
|---|
| 111 | }}} |
|---|
| 112 | |
|---|
| 113 | |
|---|
| 114 | == Loading Groovy Classes == |
|---|
| 115 | |
|---|
| 116 | You can load any class via the ''create(clazz)'' method in the plugin. You can use dot notation to refer |
|---|
| 117 | to packages, starting from the root of your class path as you defined in the section above. |
|---|
| 118 | |
|---|
| 119 | {{{ |
|---|
| 120 | #!java |
|---|
| 121 | rc.oHello = getMyPlugin("GroovyLoader.GroovyLoader").create("Hello"); |
|---|
| 122 | }}} |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | == Executing Groovy File Scripts == |
|---|
| 126 | |
|---|
| 127 | You can also execute groovy as scripts by using the ''runScript()'' method and passing the name of the script |
|---|
| 128 | using the dot-notation path as described above. |
|---|
| 129 | |
|---|
| 130 | {{{ |
|---|
| 131 | #!java |
|---|
| 132 | getMyPlugin("GroovyLoader.GroovyLoader").runScript("This is my script here..."); |
|---|
| 133 | }}} |
|---|
| 134 | |
|---|
| 135 | However, you can pass an optional argument called: '''varCollection'''. This is a structure that the groovy |
|---|
| 136 | script will be binded with at runtime, so you can use it from within your script and basically create a data |
|---|
| 137 | bridge between your app and groovy. |
|---|
| 138 | |
|---|
| 139 | By default, the groovy script will be binded with the following variables/objects: |
|---|
| 140 | |
|---|
| 141 | || '''groovy variable name''' || '''description''' || |
|---|
| 142 | || varCollection || the varCollection argument. || |
|---|
| 143 | || cf_pageContext || the j2ee page context object || |
|---|
| 144 | || cf_application || the application scope || |
|---|
| 145 | || cf_session || if defined, the session scope || |
|---|
| 146 | || cf_server || the server scope || |
|---|
| 147 | || coldbox_rc || the coldbox request collection || |
|---|
| 148 | |
|---|
| 149 | Example: |
|---|
| 150 | {{{ |
|---|
| 151 | #!java |
|---|
| 152 | var varCollection = {name="Luis Majano",age="31"}; |
|---|
| 153 | getMyPlugin("GroovyLoader.GroovyLoader").runScript("Test",varCollection); |
|---|
| 154 | }}} |
|---|
| 155 | |
|---|
| 156 | |
|---|
| 157 | == Executing Groovy Source == |
|---|
| 158 | |
|---|
| 159 | You can execute dynamic groovy source by using two methods below: |
|---|
| 160 | |
|---|
| 161 | 1. executing the ''runSource()'' method |
|---|
| 162 | 1. using the custom tag: ''groovy:script'' |
|---|
| 163 | |
|---|
| 164 | The plugin will also bind the dynamically executed code with the same bindings as described above. The plugin |
|---|
| 165 | will also create a unique hash according to your source in order to keep track of your compiled sources. The |
|---|
| 166 | compiled sources will be stored in the coldbox cache for easy retrieval and usage. Once the script changes, a |
|---|
| 167 | new entry is created in the cache and the groovy class loader will also cache the java representation. |
|---|
| 168 | Again, be careful with permGen problems as object definitions keep increasing in development environments. |
|---|
| 169 | |
|---|
| 170 | {{{ |
|---|
| 171 | #!html |
|---|
| 172 | <div class="mynotes"> |
|---|
| 173 | <Strong>Important Note:</strong> If you get permgen errors, just restart the CF server and you are done. |
|---|
| 174 | </div> |
|---|
| 175 | }}} |
|---|
| 176 | |
|---|
| 177 | To execute on the fly source, just call the '''runSource()''' method on the plugin. You can also pass in the |
|---|
| 178 | optional '''varCollection ''' argument. |
|---|
| 179 | |
|---|
| 180 | {{{ |
|---|
| 181 | #!java |
|---|
| 182 | //Declare the source in CF |
|---|
| 183 | var source = "varCollection.GroovyArray = [1,2,3,4]"; |
|---|
| 184 | //Execute the source |
|---|
| 185 | getMyPlugin("GroovyLoader.GroovyLoader").runSource(source); |
|---|
| 186 | }}} |
|---|
| 187 | |
|---|
| 188 | You can also use the tag import to execute runtime groovy. All you need to do is add the following cfimport |
|---|
| 189 | |
|---|
| 190 | {{{ |
|---|
| 191 | #!xml |
|---|
| 192 | <!--- Import GScript ---> |
|---|
| 193 | <cfimport prefix="groovy" taglib="../plugins/GroovyLoader/tags" /> |
|---|
| 194 | }}} |
|---|
| 195 | |
|---|
| 196 | Then you can script using the following tag '''groovy:script''' |
|---|
| 197 | |
|---|
| 198 | {{{ |
|---|
| 199 | #!xml |
|---|
| 200 | <groovy:script> |
|---|
| 201 | <cfoutput> |
|---|
| 202 | def today = coldbox_rc["today"] |
|---|
| 203 | def SubjectLine = ["Hello","my","name","is","Luis Majano.","Expressed at",today] |
|---|
| 204 | //Place in ColdBox event context |
|---|
| 205 | coldbox_rc["SubjectLine"] = SubjectLine.join("_") |
|---|
| 206 | </cfoutput> |
|---|
| 207 | </groovy:script> |
|---|
| 208 | }}} |
|---|
| 209 | |
|---|
| 210 | You can also add the varCollection optional attribute to the script tag |
|---|
| 211 | |
|---|
| 212 | {{{ |
|---|
| 213 | #!xml |
|---|
| 214 | <groovy:script varCollection="#MyStruct#"> |
|---|
| 215 | </groovy:script> |
|---|
| 216 | }}} |
|---|
| 217 | |
|---|
| 218 | == Conclusion == |
|---|
| 219 | You can now see the power of both Java and !ColdFusion. !ColdBox's !GroovyLoader really makes it easy |
|---|
| 220 | to integrate groovy in any !ColdBox application. So now you can get Groovy with !ColdBox! |
|---|
| 221 | |
|---|