diff --git a/resources/doc.properties b/resources/doc.properties index 35b250cdb6e..9d87a5b0399 100644 --- a/resources/doc.properties +++ b/resources/doc.properties @@ -84,6 +84,7 @@ alias.XML=6.1.7 XML and JSON Responses # javadoc alias used to link to external javadocs in the form [HttpServletRequest|api:javax.servlet.http.HttpServletRequest] api.org.hibernate=http://docs.jboss.org/hibernate/core/3.6/javadocs +api.org.springframework.boot=http://docs.spring.io/spring-boot/docs/current/api api.org.springframework=http://docs.spring.io/spring/docs/4.0.x/javadoc-api api.javax.servlet=http://download.oracle.com/javaee/1.4/api api.java.=http://docs.oracle.com/javase/6/docs/api diff --git a/src/en/guide/plugins/addingDynamicMethodsAtRuntime.gdoc b/src/en/guide/plugins/addingDynamicMethodsAtRuntime.gdoc index 2689d46c600..8616f7330d0 100644 --- a/src/en/guide/plugins/addingDynamicMethodsAtRuntime.gdoc +++ b/src/en/guide/plugins/addingDynamicMethodsAtRuntime.gdoc @@ -1,13 +1,15 @@ h4. The Basics -Grails plugins let you register dynamic methods with any Grails-managed or other class at runtime. This work is done in a @doWithDynamicMethods@ closure. +Grails plugins let you register dynamic methods with any Grails-managed or other class at runtime. This work is done in a @doWithDynamicMethods@ method. -For Grails-managed classes like controllers, tag libraries and so forth you can add methods, constructors etc. using the "ExpandoMetaClass":http://groovy.codehaus.org/ExpandoMetaClass mechanism by accessing each controller's [MetaClass|api:groovy.lang.MetaClass]: +{note} +Note that Grails 3.x features newer features such as traits that are usable from code compiled with @CompileStatic@. It is recommended that dynamic behavior is only added for cases that are not possible with traits. +{note} {code:java} -class ExamplePlugin { - def doWithDynamicMethods = { applicationContext -> - for (controllerClass in application.controllerClasses) { +class ExamplePlugin extends Plugin { + void doWithDynamicMethods() { + for (controllerClass in grailsApplication.controllerClasses) { controllerClass.metaClass.myNewMethod = {-> println "hello world" } } } @@ -19,9 +21,10 @@ In this case we use the implicit application object to get a reference to all of For example we can add a new method @swapCase@ to @java.lang.String@: {code:java} -class ExamplePlugin { +class ExamplePlugin extends Plugin { - def doWithDynamicMethods = { applicationContext -> + @Override + void doWithDynamicMethods() { String.metaClass.swapCase = {-> def sb = new StringBuilder() delegate.each { @@ -44,11 +47,11 @@ The @doWithDynamicMethods@ closure gets passed the Spring @ApplicationContext@ i {code:java} import org.springframework.orm.hibernate3.HibernateTemplate -class ExampleHibernatePlugin { +class ExampleHibernatePlugin extends Plugin{ - def doWithDynamicMethods = { applicationContext -> + void doWithDynamicMethods() { - for (domainClass in application.domainClasses) { + for (domainClass in grailsApplication.domainClasses) { domainClass.metaClass.static.load = { Long id-> def sf = applicationContext.sessionFactory @@ -65,8 +68,8 @@ Also because of the autowiring and dependency injection capability of the Spring {code:java} class MyConstructorPlugin { - def doWithDynamicMethods = { applicationContext -> - for (domainClass in application.domainClasses) { + void doWithDynamicMethods() + for (domainClass in grailsApplication.domainClasses) { domainClass.metaClass.constructor = {-> return applicationContext.getBean(domainClass.name) } diff --git a/src/en/guide/plugins/addingMethodsAtCompileTime.gdoc b/src/en/guide/plugins/addingMethodsAtCompileTime.gdoc new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/en/guide/plugins/evaluatingConventions.gdoc b/src/en/guide/plugins/evaluatingConventions.gdoc index 6677f5b66c3..c02765aff8a 100644 --- a/src/en/guide/plugins/evaluatingConventions.gdoc +++ b/src/en/guide/plugins/evaluatingConventions.gdoc @@ -1,8 +1,8 @@ -Before looking at providing runtime configuration based on conventions you first need to understand how to evaluate those conventions from a plugin. Every plugin has an implicit @application@ variable which is an instance of the [GrailsApplication|api:org.codehaus.groovy.grails.commons.GrailsApplication] interface. +Before looking at providing runtime configuration based on conventions you first need to understand how to evaluate those conventions from a plugin. Every plugin has an implicit @application@ variable which is an instance of the [GrailsApplication|api:grails.core.GrailsApplication] interface. The @GrailsApplication@ interface provides methods to evaluate the conventions within the project and internally stores references to all artifact classes within your application. -Artifacts implement the [GrailsClass|api:org.codehaus.groovy.grails.commons.GrailsClass] interface, which represents a Grails resource such as a controller or a tag library. For example to get all @GrailsClass@ instances you can do: +Artifacts implement the [GrailsClass|api:grails.core.GrailsClass] interface, which represents a Grails resource such as a controller or a tag library. For example to get all @GrailsClass@ instances you can do: {code:java} for (grailsClass in application.allClasses) { @@ -37,4 +37,4 @@ The @GrailsClass@ interface has a number of useful methods that let you further * @getNaturalName@ - Returns the name of the property in natural terms (e.g. 'lastName' becomes 'Last Name') * @getPackageName@ - Returns the package name -For a full reference refer to the [javadoc API|api:org.codehaus.groovy.grails.commons.GrailsClass]. +For a full reference refer to the [javadoc API|api:grails.core.GrailsClass]. diff --git a/src/en/guide/plugins/hookingIntoRuntimeConfiguration.gdoc b/src/en/guide/plugins/hookingIntoRuntimeConfiguration.gdoc index ca1cddefe46..7849f3ea592 100644 --- a/src/en/guide/plugins/hookingIntoRuntimeConfiguration.gdoc +++ b/src/en/guide/plugins/hookingIntoRuntimeConfiguration.gdoc @@ -2,18 +2,19 @@ Grails provides a number of hooks to leverage the different parts of the system h4. Hooking into the Grails Spring configuration -First, you can hook in Grails runtime configuration by providing a property called @doWithSpring@ which is assigned a block of code. For example the following snippet is from one of the core Grails plugins that provides [i18n|guide:i18n] support: +First, you can hook in Grails runtime configuration overriding the @doWithSpring@ method from the [Plugin|api:grails.plugins.Plugin] class and returning a closure that defines additional beans. For example the following snippet is from one of the core Grails plugins that provides [i18n|guide:i18n] support: {code:java} import org.springframework.web.servlet.i18n.CookieLocaleResolver import org.springframework.web.servlet.i18n.LocaleChangeInterceptor import org.springframework.context.support.ReloadableResourceBundleMessageSource +import grails.plugins.* -class I18nGrailsPlugin { +class I18nGrailsPlugin extends Plugin { def version = "0.1" - def doWithSpring = { + Closure doWithSpring() {{-> messageSource(ReloadableResourceBundleMessageSource) { basename = "WEB-INF/grails-app/i18n/messages" } @@ -21,96 +22,75 @@ class I18nGrailsPlugin { paramName = "lang" } localeResolver(CookieLocaleResolver) - } + }} } {code} This plugin configures the Grails @messageSource@ bean and a couple of other beans to manage Locale resolution and switching. It using the [Spring Bean Builder|guide:spring] syntax to do so. -h4. Participating in web.xml Generation - -Grails generates the @WEB-INF/web.xml@ file at load time, and although plugins cannot change this file directly, they can participate in the generation of the file. A plugin can provide a @doWithWebDescriptor@ property that is assigned a block of code that gets passed the @web.xml@ as an @XmlSlurper@ @GPathResult@. +h4. Customizing the Servlet Environment -h5. Add @servlet@ and @servlet-mapping@ +In previous versions of Grails it was possible to dynamically modify the generated @web.xml@. In Grails 3.x there is no @web.xml@ file and it is not possible to programmatically modify the @web.xml@ file anymore. -Consider this example from the @ControllersPlugin@: +However, it is possible to perform the most commons tasks of modifying the Servlet environment in Grails 3.x. -{code:java} -def doWithWebDescriptor = { webXml -> +h4. Adding New Servlets - def mappingElement = webXml.'servlet-mapping' +If you want to add a new Servlet instance the simplest way is simply to define a new Spring bean in the @doWithSpring@ method: - def lastMapping = mappingElement[mappingElement.size() - 1] - lastMapping + { - 'servlet-mapping' { - 'servlet-name'("grails") - 'url-pattern'("*.dispatch") - } - } -} +{code} +Closure doWithSpring() {{-> + myServlet(MyServlet) +}} {code} -Here the plugin gets a reference to the last @@ element and appends Grails' servlet after it using XmlSlurper's ability to programmatically modify XML using closures and blocks. - -h5. Add @filter@ and @filter-mapping@ - -Adding a filter with its mapping works a little differently. The location of the @@ element doesn't matter since order is not important, so it's simplest to insert your custom filter definition immediately after the last @@ element. Order _is_ important for mappings, but the usual approach is to add it immediately after the last @@ element like so: +If you need to customize the servlet you can use Spring Boot's [ServletRegistrationBean|api:org.springframework.boot.context.embedded.ServletRegistrationBean]: -{code:java} -def doWithWebDescriptor = { webXml -> +{code} +Closure doWithSpring() {{-> + myServlet(ServletRegistrationBean, new MyServlet(), "/myServlet/*") { + loadOnStartup = 2 + } +}} +{code} - def contextParam = webXml.'context-param' +h4. Adding New Servlet Filters - contextParam[contextParam.size() - 1] + { - 'filter' { - 'filter-name'('springSecurityFilterChain') - 'filter-class'(DelegatingFilterProxy.name) - } - } +Just like Servlets, the simplest way to configure a new filter is to simply define a Spring bean: - def filter = webXml.'filter' - filter[filter.size() - 1] + { - 'filter-mapping'{ - 'filter-name'('springSecurityFilterChain') - 'url-pattern'('/*') - } - } -} +{code} +Closure doWithSpring() {{-> + myFilter(MyFilter) +}} {code} -In some cases you need to ensure that your filter comes after one of the standard Grails filters, such as the Spring character encoding filter or the SiteMesh filter. Fortunately you can insert filter mappings immediately after the standard ones (more accurately, any that are in the template web.xml file) like so: - -{code:java} -def doWithWebDescriptor = { webXml -> - ... - - // Insert the Spring Security filter after the Spring - // character encoding filter. - def filter = webXml.'filter-mapping'.find { - it.'filter-name'.text() == "charEncodingFilter" - } +However, if you want to control the order of filter registrations you will need to use Spring Boot's [FilterRegistrationBean|api:org.springframework.boot.context.embedded.FilterRegistrationBean]: - filter + { - 'filter-mapping'{ - 'filter-name'('springSecurityFilterChain') - 'url-pattern'('/*') - } - } +{code} +myFilter(FilterRegistrationBean) { + filter = bean(MyFilter) + urlPatterns = ['/*'] + order = Ordered.HIGHEST_PRECEDENCE } {code} +{note} +Grails' internal registered filters (@GrailsWebRequestFilter@, @HiddenHttpMethodFilter@ etc.) are defined by incrementing @HIGHEST_PRECEDENCE@ by 10 thus allowing several filters to be inserted before or between Grails' filters. +{note} + h4. Doing Post Initialisation Configuration Sometimes it is useful to be able do some runtime configuration after the Spring [ApplicationContext|api:org.springframework.context.ApplicationContext] has been built. In this case you can define a @doWithApplicationContext@ closure property. {code:java} -class SimplePlugin { +class SimplePlugin extends Plugin{ def name = "simple" def version = "1.1" - def doWithApplicationContext = { appCtx -> - def sessionFactory = appCtx.sessionFactory + @Override + void doWithApplicationContext() { + def sessionFactory = applicationContext.sessionFactory // do something here with session factory } } diff --git a/src/en/guide/plugins/participatingInAutoReloadEvents.gdoc b/src/en/guide/plugins/participatingInAutoReloadEvents.gdoc index 8760d5b6f09..36015ba00d3 100644 --- a/src/en/guide/plugins/participatingInAutoReloadEvents.gdoc +++ b/src/en/guide/plugins/participatingInAutoReloadEvents.gdoc @@ -3,25 +3,20 @@ h4. Monitoring Resources for Changes Often it is valuable to monitor resources for changes and perform some action when they occur. This is how Grails implements advanced reloading of application state at runtime. For example, consider this simplified snippet from the Grails @ServicesPlugin@: {code:java} -class ServicesGrailsPlugin { +class ServicesGrailsPlugin extends Plugin { ... def watchedResources = "file:./grails-app/services/*Service.groovy" ... - def onChange = { event -> + void onChange( Map event) { if (event.source) { - def serviceClass = application.addServiceClass(event.source) + def serviceClass = grailsApplication.addServiceClass(event.source) def serviceName = "\${serviceClass.propertyName}" - def beans = beans { + beans { "$serviceName"(serviceClass.getClazz()) { bean -> bean.autowire = true } } - if (event.ctx) { - event.ctx.registerBeanDefinition( - serviceName, - beans.getBeanDefinition(serviceName)) - } } } } diff --git a/src/en/guide/plugins/providingBasicArtefacts.gdoc b/src/en/guide/plugins/providingBasicArtefacts.gdoc index 125964a1596..f7d18760084 100644 --- a/src/en/guide/plugins/providingBasicArtefacts.gdoc +++ b/src/en/guide/plugins/providingBasicArtefacts.gdoc @@ -10,18 +10,58 @@ A plugin can add new commands to the Grails 3.0 interactive shell in one of two + etc. {code} +Code generation scripts can be used to create artefacts within the project tree and automate interactions with Gradle. + +If you want to create a new shell command that interacts with a loaded Grails application instance then you should use the @create-command@ command: + +{code} +$ grails create-command MyExampleCommand +{code} + +This will create a file called @grails-app/commands/PACKAGE_PATH/MyExampleCommand.groovy@ that extends [ApplicationCommand|api:grails.dev.commands.ApplicationCommand]: + +{code} +import grails.dev.commands.* + +class MyExampleCommand implements ApplicationCommand { + + boolean handle(ExecutionContext ctx) { + println "Hello World" + return true + } +} +{code} + +An @ApplicationCommand@ has access to the @GrailsApplication@ instance and is subject to autowiring like any other Spring bean. + +For each @ApplicationCommand@ present Grails will create a shell command and a Gradle task to invoke the @ApplicationCommand@. In the above example you can invoke the @MyExampleCommand@ class using either: + +{code} +$ grails my-example +{code} + +Or + +{code} +$ gradle myExample +{code} + +The Grails version is all lower case hyphen separated and excludes the "Command" suffix. + +The main difference between code generation scripts and @ApplicationCommand@ instances is that the latter has full access to the Grails application state and hence can be used to perform tasks that interactive with the database, call into GORM etc. + +In Grails 2.x Gant scripts could be used to perform both these tasks, in Grails 3.x code generation and interacting with runtime application state has been cleanly separated. + h4. Adding a new grails-app artifact (Controller, Tag Library, Service, etc.) -A plugin can add new artifacts by creating the relevant file within the @grails-app@ tree. Note that the plugin is loaded from where it is installed and not copied into the main application tree. +A plugin can add new artifacts by creating the relevant file within the @grails-app@ tree. {code:java} -+ ExamplePlugin.groovy - + scripts - + grails-app - + controllers <-- additional controllers here - + services <-- additional services here - + etc. <-- additional XXX here - + lib + + grails-app + + controllers <-- additional controllers here + + services <-- additional services here + + etc. <-- additional XXX here + {code} h4. Providing Views, Templates and View resolution @@ -42,18 +82,12 @@ h4. Excluded Artefacts By default Grails excludes the following files during the packaging process: -* @grails-app/conf/BootStrap.groovy@ -* @grails-app/conf/BuildConfig.groovy@ (although it is used to generate @dependencies.groovy@) -* @grails-app/conf/Config.groovy@ -* @grails-app/conf/DataSource.groovy@ (and any other @*DataSource.groovy@) -* @grails-app/conf/UrlMappings.groovy@ +* @grails-app/conf/logback.groovy@ +* @grails-app/conf/application.yml@ (renamed to @plugin.yml@) * @grails-app/conf/spring/resources.groovy@ -* Everything within @/web-app/WEB-INF@ -* Everything within @/web-app/plugins/\*\*@ -* Everything within @/test/\*\*@ +* Everything within @/src/test/\*\*@ * SCM management files within @\*\*/.svn/\*\*@ and @\*\*/CVS/\*\*@ -If your plugin requires files under the @web-app/WEB-INF@ directory it is recommended that you modify the plugin's @scripts/_Install.groovy@ Gant script to install these artefacts into the target project's directory tree. In addition, the default @UrlMappings.groovy@ file is excluded to avoid naming conflicts, however you are free to add a UrlMappings definition under a different name which *will* be included. For example a file called @grails-app/conf/BlogUrlMappings.groovy@ is fine. diff --git a/src/en/guide/plugins/understandingPluginStructure.gdoc b/src/en/guide/plugins/understandingPluginStructure.gdoc deleted file mode 100644 index 3ba5a2600c3..00000000000 --- a/src/en/guide/plugins/understandingPluginStructure.gdoc +++ /dev/null @@ -1,31 +0,0 @@ -As as mentioned previously, a plugin is basically a regular Grails application with a plugin descriptor. However when installed, the structure of a plugin differs slightly. For example, take a look at this plugin directory structure: - -{code:java} -+ grails-app - + controllers - + domain - + taglib - etc. - + lib - + src - + java - + groovy - + web-app - + js - + css{code} - -When a plugin is installed the contents of the @grails-app@ directory will go into a directory such as @plugins/example-1.0/grails-app@. They *will not* be copied into the main source tree. A plugin never interferes with a project's primary source tree. - -Dealing with static resources is slightly different. When developing a plugin, just like an application, all static resources go in the @web-app@ directory. You can then link to static resources just like in an application. This example links to a JavaScript source: - -{code:xml} - -{code} - -When you run the plugin in development mode the link to the resource will resolve to something like @/js/mycode.js@. However, when the plugin is installed into an application the path will automatically change to something like @/plugin/example-0.1/js/mycode.js@ and Grails will deal with making sure the resources are in the right place. - -There is a special @pluginContextPath@ variable that can be used whilst both developing the plugin and when in the plugin is installed into the application to find out what the correct path to the plugin is. - -At runtime the @pluginContextPath@ variable will either evaluate to an empty string or @/plugins/example@ depending on whether the plugin is running standalone or has been installed in an application - -Java and Groovy code that the plugin provides within the lib and @src/java@ and @src/groovy@ directories will be compiled into the main project's @web-app/WEB-INF/classes@ directory so that they are made available at runtime. diff --git a/src/en/guide/theWebLayer/ajax.gdoc b/src/en/guide/theWebLayer/ajax.gdoc deleted file mode 100644 index aaa1139c0e9..00000000000 --- a/src/en/guide/theWebLayer/ajax.gdoc +++ /dev/null @@ -1,5 +0,0 @@ -Ajax is the driving force behind the shift to richer web applications. These types of applications in general are better suited to agile, dynamic frameworks written in languages like "Groovy":http://groovy.codehaus.org and "Ruby":http://www.ruby-lang.org/. Grails provides support for building Ajax applications through its Ajax tag library. For a full list of these see the Tag Library Reference. - -{note} -Note: JavaScript examples use the jQuery library. -{note} diff --git a/src/en/guide/theWebLayer/ajax/ajaxOnTheServer.gdoc b/src/en/guide/theWebLayer/ajax/ajaxOnTheServer.gdoc deleted file mode 100644 index 1d75a48156c..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxOnTheServer.gdoc +++ /dev/null @@ -1,126 +0,0 @@ -There are a number of different ways to implement Ajax which are typically broken down into: - -* Content Centric Ajax - Where you just use the HTML result of a remote call to update the page -* Data Centric Ajax - Where you actually send an XML or JSON response from the server and programmatically update the page -* Script Centric Ajax - Where the server sends down a stream of JavaScript to be evaluated on the fly - -Most of the examples in the [Ajax|guide:ajax] section cover Content Centric Ajax where you are updating the page, but you may also want to use Data Centric or Script Centric. This guide covers the different styles of Ajax. - -h4. Content Centric Ajax - -Just to re-cap, content centric Ajax involves sending some HTML back from the server and is typically done by rendering a template with the [render|controllers] method: - -{code:java} -def showBook() { - def b = Book.get(params.id) - - render(template: "bookTemplate", model: [book: b]) -} -{code} - -Calling this on the client involves using the [remoteLink|tags] tag: - -{code:xml} -Update Book - -
- -
-{code} - -h4. Data Centric Ajax with JSON - -Data Centric Ajax typically involves evaluating the response on the client and updating programmatically. For a JSON response with Grails you would typically use Grails' [JSON marshalling|guide:xmlAndJSON] capability: - -{code:java} -import grails.converters.JSON - -def showBook() { - def b = Book.get(params.id) - - render b as JSON -} -{code} - -And then on the client parse the incoming JSON request using an Ajax event handler: - -{code:xml} - -function updateBook(data) { - $("#book" + data.id + "_title").html( data.title ); -} - - - Update Book - -book${book.id} -
-
The Stand
-
-{code} - -h4. Data Centric Ajax with XML - -On the server side using XML is equally simple: - -{code:java} -import grails.converters.XML - -def showBook() { - def b = Book.get(params.id) - - render b as XML -} -{code} - -However, since DOM is involved the client gets more complicated: - -{code:xml} - -function updateBook(data) { - var id = $(data).find("book").attr("id"); - $("#book" + id + "_title").html( $(data).find("title").text() ); -} - - - Update Book - -book${book.id} -
-
The Stand
-
-{code} - -h4. Script Centric Ajax with JavaScript - -Script centric Ajax involves actually sending JavaScript back that gets evaluated on the client. An example of this can be seen below: - -{code:java} -def showBook() { - def b = Book.get(params.id) - - response.contentType = "text/javascript" - String title = b.title.encodeAsJavaScript() - render "\$('#book${b.id}_title').html('${title}');" -} -{code} - -The important thing to remember is to set the @contentType@ to @text/javascript@. If you use Prototype on the client the returned JavaScript will automatically be evaluated due to this @contentType@ setting. - -Obviously in this case it is critical that you have an agreed client-side API as you don't want changes on the client breaking the server. This is one of the reasons Rails has something like RJS. Although Grails does not currently have a feature such as RJS there is a [Dynamic JavaScript Plugin|http://grails.org/plugin/dynamic-javascript] that offers similar capabilities. - -h4. Responding to both Ajax and non-Ajax requests - -It's straightforward to have the same Grails controller action handle both Ajax and non-Ajax requests. Grails adds the @isXhr()@ method to @HttpServletRequest@ which can be used to identify Ajax requests. For example you could render a page fragment using a template for Ajax requests or the full page for regular HTTP requests: - -{code:java} -def listBooks() { - def books = Book.list(params) - if (request.xhr) { - render template: "bookTable", model: [books: books] - } else { - render view: "list", model: [books: books] - } -} -{code} diff --git a/src/en/guide/theWebLayer/ajax/ajaxSupport.gdoc b/src/en/guide/theWebLayer/ajax/ajaxSupport.gdoc deleted file mode 100644 index 99da92fd8d5..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxSupport.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -By default Grails ships with the "jQuery":http://jquery.com/ library, but through the [Plugin system|guide:plugins] provides support for other frameworks such as [Prototype|http://www.prototypejs.org/], [Dojo:http://dojotoolkit.org/], [Yahoo UI:http://developer.yahoo.com/yui/] and the [Google Web Toolkit|http://code.google.com/webtoolkit/]. - -This section covers Grails' support for Ajax in general. To get started, add this line to the @@ tag of your page: - -{code:xml} - -{code} - -You can replace @jQuery@ with any other library supplied by a plugin you have installed. This works because of Grails' support for adaptive tag libraries. Thanks to Grails' plugin system there is support for a number of different Ajax libraries including (but not limited to): - -* jQuery -* Prototype -* Dojo -* YUI -* MooTools diff --git a/src/en/guide/theWebLayer/ajax/ajaxSupport/ajaxEvents.gdoc b/src/en/guide/theWebLayer/ajax/ajaxSupport/ajaxEvents.gdoc deleted file mode 100644 index 617f7c55454..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxSupport/ajaxEvents.gdoc +++ /dev/null @@ -1,33 +0,0 @@ -Specific JavaScript can be called if certain events occur, all the events start with the "on" prefix and let you give feedback to the user where appropriate, or take other action: - -{code:xml} -Show Book 1 -{code} - -The above code will execute the "showProgress()" function which may show a progress bar or whatever is appropriate. Other events include: - -* @onSuccess@ - The JavaScript function to call if successful -* @onFailure@ - The JavaScript function to call if the call failed -* @onERROR_CODE@ - The JavaScript function to call to handle specified error codes (e.g. @on404="alert('not found!')"@) -* @onUninitialized@ - The JavaScript function to call the a Ajax engine failed to initialise -* @onLoading@ - The JavaScript function to call when the remote function is loading the response -* @onLoaded@ - The JavaScript function to call when the remote function is completed loading the response -* @onComplete@ - The JavaScript function to call when the remote function is complete, including any updates - -You can simply refer to the @XMLHttpRequest@ variable to obtain the request: - -{code:xml} - - function fireMe(event) { - alert("XmlHttpRequest = " + event) - } -} - -Ajax Link -{code} diff --git a/src/en/guide/theWebLayer/ajax/ajaxSupport/remoteFormSubmission.gdoc b/src/en/guide/theWebLayer/ajax/ajaxSupport/remoteFormSubmission.gdoc deleted file mode 100644 index 4d64e89bf97..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxSupport/remoteFormSubmission.gdoc +++ /dev/null @@ -1,20 +0,0 @@ -An HTML form can also be submitted asynchronously in one of two ways. Firstly using the [formRemote|tags] tag which expects similar attributes to those for the [remoteLink|tags] tag: - -{code:xml} - - - - -{code} - -Or alternatively you can use the [submitToRemote|tags] tag to create a submit button. This allows some buttons to submit remotely and some not depending on the action: - -{code:xml} -
- - - -{code} - diff --git a/src/en/guide/theWebLayer/ajax/ajaxSupport/remotingLinking.gdoc b/src/en/guide/theWebLayer/ajax/ajaxSupport/remotingLinking.gdoc deleted file mode 100644 index fa1fa0fc293..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxSupport/remotingLinking.gdoc +++ /dev/null @@ -1,7 +0,0 @@ -Remote content can be loaded in a number of ways, the most commons way is through the [remoteLink|tags] tag. This tag allows the creation of HTML anchor tags that perform an asynchronous request and optionally set the response in an element. The simplest way to create a remote link is as follows: - -{code:xml} -Delete Book -{code} - -The above link sends an asynchronous request to the @delete@ action of the current controller with an id of @1@. diff --git a/src/en/guide/theWebLayer/ajax/ajaxSupport/updatingContent.gdoc b/src/en/guide/theWebLayer/ajax/ajaxSupport/updatingContent.gdoc deleted file mode 100644 index 559c93a22d3..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxSupport/updatingContent.gdoc +++ /dev/null @@ -1,31 +0,0 @@ -This is great, but usually you provide feedback to the user about what happened: - -{code:java} -def delete() { - def b = Book.get(params.id) - b.delete() - render "Book ${b.id} was deleted" -} -{code} - -GSP code: - -{code:xml} -
- -Delete Book - -{code} - -The above example will call the action and set the contents of the @message@ @div@ to the response in this case @"Book 1 was deleted"@. This is done by the @update@ attribute on the tag, which can also take a Map to indicate what should be updated on failure: - -{code:xml} -
-
- -Delete Book - -{code} - -Here the @error@ div will be updated if the request failed. diff --git a/src/en/guide/theWebLayer/ajax/ajaxWithDojo.gdoc b/src/en/guide/theWebLayer/ajax/ajaxWithDojo.gdoc deleted file mode 100644 index 0008c23294f..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxWithDojo.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -Grails features an external plugin to add "Dojo":http://dojotoolkit.org/ support to Grails. To install the plugin, list it in BuildConfig.groovy: - -{code:java} -compile "\:dojo\:latest.release" -{code} - -This will download the current supported version of Dojo and install it into your Grails project. With that done you can add the following reference to the top of your page: - -{code:xml} - -{code} - -Now all of Grails tags such as [remoteLink|tags], [formRemote|tags] and [submitToRemote|tags] work with Dojo remoting. diff --git a/src/en/guide/theWebLayer/ajax/ajaxWithGWT.gdoc b/src/en/guide/theWebLayer/ajax/ajaxWithGWT.gdoc deleted file mode 100644 index 8a8ceb75ecb..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxWithGWT.gdoc +++ /dev/null @@ -1 +0,0 @@ -Grails also features support for the "Google Web Toolkit":http://code.google.com/webtoolkit/ through a plugin. There is comprehensive [documentation|http://grails.org/plugin/gwt] available on the Grails wiki. diff --git a/src/en/guide/theWebLayer/ajax/ajaxWithPrototype.gdoc b/src/en/guide/theWebLayer/ajax/ajaxWithPrototype.gdoc deleted file mode 100644 index 9f329068bb8..00000000000 --- a/src/en/guide/theWebLayer/ajax/ajaxWithPrototype.gdoc +++ /dev/null @@ -1,19 +0,0 @@ -Grails features an external plugin to add "Prototype":http://www.prototypejs.org/ support to Grails. To install the plugin, list it in BuildConfig.groovy: - -{code:java} -runtime "\:prototype\:latest.release" -{code} - -This will download the current supported version of the Prototype plugin and install it into your Grails project. With that done you can add the following reference to the top of your page: - -{code:xml} - -{code} - -If you require "Scriptaculous":http://script.aculo.us/ too you can do the following instead: - -{code:xml} - -{code} - -Now all of Grails tags such as [remoteLink|tags], [formRemote|tags] and [submitToRemote|tags] work with Prototype remoting. diff --git a/src/en/guide/theWebLayer/gsp/resources/debugging.gdoc b/src/en/guide/theWebLayer/gsp/resources/debugging.gdoc deleted file mode 100644 index 25cfb26c44c..00000000000 --- a/src/en/guide/theWebLayer/gsp/resources/debugging.gdoc +++ /dev/null @@ -1,23 +0,0 @@ -When your resources are being moved around, renamed and otherwise mutated, it can be hard to debug client-side issues. Modern browsers, especially Safari, Chrome and Firefox have excellent tools that let you view all the resources requested by a page, including the headers and other information about them. - -There are several debugging features built in to the Resources framework. - -h4. X-Grails-Resources-Original-Src Header - -Every resource served in development mode will have the X-Grails-Resources-Original-Src: header added, indicating the original source file(s) that make up the response. - -h4. Adding the debug flag - -If you add a query parameter *_debugResources=y* to your URL and request the page, Resources will bypass any processing so that you can see your original source files. - -This also adds a unique timestamp to all your resource URLs, to defeat any caching that browsers may use. This means that you should always see your very latest code when you reload the page. - -h4. Turning on debug all the time - -You can turn on the aforementioned debug mechanism without requiring a query parameter, but turning it on in Config.groovy: - -{code} -grails.resources.debug = true -{code} - -You can of course set this per-environment. diff --git a/src/en/guide/theWebLayer/gsp/resources/declaringResources.gdoc b/src/en/guide/theWebLayer/gsp/resources/declaringResources.gdoc deleted file mode 100644 index 454c3b41c78..00000000000 --- a/src/en/guide/theWebLayer/gsp/resources/declaringResources.gdoc +++ /dev/null @@ -1,48 +0,0 @@ -A DSL is provided for declaring resources and modules. This can go either in your @Config.groovy@ in the case of application-specific resources, or more commonly in a resources artefact in @grails-app/conf@. - -Note that you do not need to declare all your static resources, especially images. However you must to establish dependencies or other resources-specific attributes. Any resource that is not declared is called "ad-hoc" and will still be processed using defaults for that resource type. - -Consider this example resource configuration file, @grails-app/conf/MyAppResources.groovy@: - -{code:java} -modules = { - core { - dependsOn 'jquery, utils' - - resource url: '/js/core.js', disposition: 'head' - resource url: '/js/ui.js' - resource url: '/css/main.css', - resource url: '/css/branding.css' - resource url: '/css/print.css', attrs: [media: 'print'] - } - - utils { - dependsOn 'jquery' - - resource url: '/js/utils.js' - } - - forms { - dependsOn 'core,utils' - - resource url: '/css/forms.css' - resource url: '/js/forms.js' - } -} -{code} - -This defines three resource modules; 'core', 'utils' and 'forms'. The resources in these modules will be automatically bundled out of the box according to the module name, resulting in fewer files. You can override this with @bundle:'someOtherName'@ on each resource, or call @defaultBundle@ on the module (see [resources plugin documentation|http://grails-plugins.github.com/grails-resources]). - -It declares dependencies between them using @dependsOn@, which controls the load order of the resources. - -When you include an @@ in your GSP, it will pull in all the resources from 'core' and 'utils' as well as 'jquery', all in the correct order. - -You'll also notice the @disposition:'head'@ on the @core.js@ file. This tells Resources that while it can defer all the other JS files to the end of the body, this one must go into the @@. - -The CSS file for print styling adds custom attributes using the @attrs@ map option, and these are passed through to the @r:external@ tag when the engine renders the link to the resource, so you can customize the HTML attributes of the generated link. - -There is no limit to the number of modules or xxxResources.groovy artefacts you can provide, and plugins can supply them to expose modules to applications, which is exactly how the jQuery plugin works. - -To define modules like this in your application's Config.groovy, you simply assign the DSL closure to the @grails.resources.modules@ Config variable. - -For full details of the resource DSL please see the [resources plugin documentation|http://grails-plugins.github.com/grails-resources]. diff --git a/src/en/guide/theWebLayer/gsp/resources/includingResourcesUsingTheResourceTags.gdoc b/src/en/guide/theWebLayer/gsp/resources/includingResourcesUsingTheResourceTags.gdoc deleted file mode 100644 index ab0eba494db..00000000000 --- a/src/en/guide/theWebLayer/gsp/resources/includingResourcesUsingTheResourceTags.gdoc +++ /dev/null @@ -1,134 +0,0 @@ -h4. Pulling in resources with r:require - -To use resources, your GSP page must indicate which resource modules it requires. For example with the [jQuery plugin|http://grails.org/plugin/jquery], which exposes a "jquery" resource module, to use jQuery in any page on your site you simply add: - -{code:xml} - - - - - - - ... - - - -{code} - -This will automatically include all resources needed for jQuery, including them at the correct locations in the page. By default the plugin sets the disposition to be "head", so they load early in the page. - -You can call @r:require@ multiple times in a GSP page, and you use the "modules" attribute to provide a list of modules: - -{code:xml} - - - - - - - ... - - - -{code} - -The above may result in many JavaScript and CSS files being included, in the correct order, with some JavaScript files loading at the end of the body to improve the apparent page load time. - -However you cannot use r:require in isolation - as per the examples you must have the tag to actually perform the render. - -h4. Rendering the links to resources with r:layoutResources - -When you have declared the resource modules that your GSP page requires, the framework needs to render the links to those resources at the correct time. - -To achieve this correctly, you must include the r:layoutResources tag twice in your page, or more commonly, in your GSP layout: - -{code:xml} - - - - - - - - - - -{code} - -This represents the simplest Sitemesh layout you can have that supports Resources. - -The Resources framework has the concept of a "disposition" for every resource. This is an indication of where in the page the resource should be included. - -The default disposition applied depends on the type of resource. All CSS must be rendered in in HTML, so "head" is the default for all CSS, and will be rendered by the first r:layoutResources. Page load times are improved when JavaScript is loaded after the page content, so the default for JavaScript files is "defer", which means it is rendered when the second r:layoutResources is invoked. - -Note that both your GSP page and your Sitemesh layout (as well as any GSP template fragments) can call r:require to depend on resources. The only limitation is that you must call r:require before the r:layoutResources that should render it. - -h4. Adding page-specific JavaScript code with r:script - -Grails has the [javascript|tags] tag which is adapted to defer to Resources plugin if installed, but it is recommended that you call @r:script@ directly when you need to include fragments of JavaScript code. - -This lets you write some "inline" JavaScript which is actually *not* rendered inline, but either in the or at the end of the body, based on the disposition. - -Given a Sitemesh layout like this: - -{code:xml} - - - - - - - - - - -{code} - -...in your GSP you can inject some JavaScript code into the head or deferred regions of the page like this: - -{code:xml} - - - Testing r:script magic! - - - - window.alert('This is at the end of '); - - - window.alert('This is at the end of the body, and the page has loaded.'); - - - -{code} - -The default disposition is "defer", so the disposition in the latter r:script is purely included for demonstration. - -Note that such r:script code fragments *always* load after any modules that you have used, to ensure that any required libraries have loaded. - -h4. Linking to images with r:img - -This tag is used to render @@ markup, using the Resources framework to process the resource on the fly (if configured to do so - e.g. make it eternally cacheable). - -This includes any extra attributes on the @@ tag if the resource has been previously declared in a module. - -With this mechanism you can specify the width, height and any other attributes in the resource declaration in the module, and they will be pulled in as necessary. - -Example: - -{code:xml} - - - Testing r:img - - - - - -{code} - -Note that Grails has a built-in @g:img@ tag as a shortcut for rendering @@ tags that refer to a static resource. The Grails [img|tags] tag is Resources-aware and will delegate to @r:img@ if found. However it is recommended that you use @r:img@ directly if using the Resources plugin. - -Alongside the regular Grails [resource|tags] tag attributes, this also supports the "uri" attribute for increased brevity. - -See [r:resource documentation|http://grails-plugins.github.com/grails-resources] for full details. diff --git a/src/en/guide/theWebLayer/gsp/resources/optimizingYourResources.gdoc b/src/en/guide/theWebLayer/gsp/resources/optimizingYourResources.gdoc deleted file mode 100644 index 6728d661d11..00000000000 --- a/src/en/guide/theWebLayer/gsp/resources/optimizingYourResources.gdoc +++ /dev/null @@ -1,63 +0,0 @@ -The Resources framework uses "mappers" to mutate the resources into the final format served to the user. - -The resource mappers are applied to each static resource once, in a specific order. You can create your own resource mappers, and several plugins provide some already for zipping, caching and minifying. - -Out of the box, the Resources plugin provides bundling of resources into fewer files, which is achieved with a few mappers that also perform CSS re-writing to handle when your CSS files are moved into a bundle. - -h4. Bundling multiple resources into fewer files - -The 'bundle' mapper operates by default on any resource with a "bundle" defined - or inherited from a @defaultBundle@ clause on the module. Modules have an implicit default bundle name the same as the name of the module. - -Files of the same kind will be aggregated into this bundle file. Bundles operate across module boundaries: - -{code:java} -modules = { - core { - dependsOn 'jquery, utils' - defaultBundle 'common' - - resource url: '/js/core.js', disposition: 'head' - resource url: '/js/ui.js', bundle: 'ui' - resource url: '/css/main.css', bundle: 'theme' - resource url: '/css/branding.css' - resource url: '/css/print.css', attrs: [media: 'print'] - } - - utils { - dependsOn 'jquery' - - resource url: '/js/utils.js', bundle: 'common' - } - - forms { - dependsOn 'core,utils' - - resource url: '/css/forms.css', bundle: 'ui' - resource url: '/js/forms.js', bundle: 'ui' - } -} -{code} - -Here you see that resources are grouped into bundles; 'common', 'ui' and 'theme' - across module boundaries. - -Note that auto-bundling by module does *not* occur if there is only one resource in the module. - -h4. Making resources cache "eternally" in the client browser - -Caching resources "eternally" in the client is only viable if the resource has a unique name that changes whenever the contents change, and requires caching headers to be set on the response. - -The [cached-resources|http://grails.org/plugin/cached-resources] plugin provides a mapper that achieves this by hashing your files and renaming them based on this hash. It also sets the caching headers on every response for those resources. To use, simply install the cached-resources plugin. - -Note that the caching headers can only be set if your resources are being served by your application. If you have another server serving the static content from your app (e.g. Apache HTTPD), configure it to send caching headers. Alternatively you can configure it to request and proxy the resources from your container. - -h4. Zipping resources - -Returning gzipped resources is another way to reduce page load times and reduce bandwidth. - -The [zipped-resources|http://grails.org/plugin/zipped-resources] plugin provides a mapper that automatically compresses your content, excluding by default already compressed formats such as gif, jpeg and png. - -Simply install the zipped-resources plugin and it works. - -h4. Minifying - -There are a number of CSS and JavaScript minifiers available to obfuscate and reduce the size of your code. At the time of writing none are publicly released but releases are imminent. diff --git a/src/en/guide/theWebLayer/gsp/resources/otherResourceTags.gdoc b/src/en/guide/theWebLayer/gsp/resources/otherResourceTags.gdoc deleted file mode 100644 index fbfc826a51e..00000000000 --- a/src/en/guide/theWebLayer/gsp/resources/otherResourceTags.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -h4. r:resource - -This is equivalent to the Grails [resource|Tags] tag, returning a link to the processed static resource. Grails' own @g:resource@ tag delegates to this implementation if found, but if your code requires the Resources plugin, you should use @r:resource@ directly. - -Alongside the regular Grails [resource|Tags] tag attributes, this also supports the "uri" attribute for increased brevity. - -See [r:resource documentation|http://grails-plugins.github.com/grails-resources] for full details. - -h4. r:external - -This is a resource-aware version of Grails [external|Tags] tag which renders the HTML markup necessary to include an external file resource such as CSS, JS or a favicon. - -See [r:resource documentation|http://grails-plugins.github.com/grails-resources] for full details. diff --git a/src/en/guide/theWebLayer/gsp/resources/otherResourcesPlugins.gdoc b/src/en/guide/theWebLayer/gsp/resources/otherResourcesPlugins.gdoc deleted file mode 100644 index 6fd07129f90..00000000000 --- a/src/en/guide/theWebLayer/gsp/resources/otherResourcesPlugins.gdoc +++ /dev/null @@ -1,8 +0,0 @@ -At the time of writing, the following plugins include support for the Resources framework: - -* [jquery|http://grails.org/plugin/jquery] -* [jquery-ui|http://grails.org/plugin/jquery-ui] -* [blueprint|http://grails.org/plugin/blueprint] -* [lesscss-resources|http://grails.org/plugin/lesscss-resources] -* [zipped-resources|http://grails.org/plugin/zipped-resources] -* [cached-resources|http://grails.org/plugin/cached-resources] diff --git a/src/en/guide/theWebLayer/gsp/resources/overridingPluginResources.gdoc b/src/en/guide/theWebLayer/gsp/resources/overridingPluginResources.gdoc deleted file mode 100644 index f5ebe5e43d0..00000000000 --- a/src/en/guide/theWebLayer/gsp/resources/overridingPluginResources.gdoc +++ /dev/null @@ -1,47 +0,0 @@ -Because a resource module can define the bundle groupings and other attributes of resources, you may find that the settings provided are not correct for your application. - -For example, you may wish to bundle jQuery and some other libraries all together in one file. There is a load-time and caching trade-off here, but often it is the case that you'd like to override some of these settings. - -To do this, the DSL supports an "overrides" clause, within which you can change the @defaultBundle@ setting for a module, or attributes of individual resources that have been declared with a unique id: - -{code:java} -modules = { - core { - dependsOn 'jquery, utils' - defaultBundle 'monolith' - - resource url: '/js/core.js', disposition: 'head' - resource url: '/js/ui.js' - resource url: '/css/main.css', - resource url: '/css/branding.css' - resource url: '/css/print.css', attrs: [media: 'print'] - } - - utils { - dependsOn 'jquery' - defaultBundle 'monolith' - - resource url: '/js/utils.js' - } - - forms { - dependsOn 'core,utils' - defaultBundle 'monolith' - - resource url: '/css/forms.css' - resource url: '/js/forms.js' - } - - overrides { - jquery { - defaultBundle 'monolith' - } - } -} -{code} - -This will put all code into a single bundle named 'monolith'. Note that this can still result in multiple files, as separate bundles are required for head and defer dispositions, and JavaScript and CSS files are bundled separately. - -Note that overriding individual resources requires the original declaration to have included a unique id for the resource. - -For full details of the resource DSL please see the [resources plugin documentation|http://grails-plugins.github.com/grails-resources]. diff --git a/src/en/guide/theWebLayer/gsp/resources/preventingProcessingOfResources.gdoc b/src/en/guide/theWebLayer/gsp/resources/preventingProcessingOfResources.gdoc deleted file mode 100644 index 48510c2ab76..00000000000 --- a/src/en/guide/theWebLayer/gsp/resources/preventingProcessingOfResources.gdoc +++ /dev/null @@ -1,45 +0,0 @@ -Sometimes you do not want a resource to be processed in a particular way, or even at all. Occasionally you may also want to disable all resource mapping. - -h4. Preventing the application of a specific mapper to an individual resource - -All resource declarations support a convention of noXXXX:true where XXXX is a mapper name. - -So for example to prevent the "hashandcache" mapper from being applied to a resource (which renames and moves it, potentially breaking relative links written in JavaScript code), you would do this: - -{code:java} -modules = { - forms { - resource url: '/css/forms.css', nohashandcache: true - resource url: '/js/forms.js', nohashandcache: true - } -} -{code} - -h4. Excluding/including paths and file types from specific mappers - -Mappers have includes/excludes Ant patterns to control whether they apply to a given resource. Mappers set sensible defaults for these based on their activity, for example the zipped-resources plugin's "zip" mapper is set to exclude images by default. - -You can configure this in your @Config.groovy@ using the mapper name e.g: - -{code:java} -// We wouldn't link to .exe files using Resources but for the sake of example: -grails.resources.zip.excludes = ['**/*.zip', '**/*.exe'] - -// Perhaps for some reason we want to prevent bundling on "less" CSS files: -grails.resources.bundle.excludes = ['**/*.less'] -{code} - -There is also an "includes" inverse. Note that settings these replaces the default includes/excludes for that mapper - it is not additive. - -h4. Controlling what is treated as an "ad-hoc" (legacy) resource - -Ad-hoc resources are those undeclared, but linked to directly in your application *without* using the Grails or Resources linking tags (resource, img or external). - -These may occur with some legacy plugins or code with hardcoded paths in. - -There is a Config.groovy setting *grails.resources.adhoc.patterns* which defines a list of Servlet API compliant filter URI mappings, which the Resources filter will use to detect such "ad-hoc resource" requests. - -By default this is set to: -{code:java} -grails.resources.adhoc.patterns = ['images/*', '*.js', '*.css'] -{code} diff --git a/src/en/guide/toc.yml b/src/en/guide/toc.yml index d9b36c543cf..d8a30db7ebb 100644 --- a/src/en/guide/toc.yml +++ b/src/en/guide/toc.yml @@ -137,16 +137,7 @@ theWebLayer: tagsAsMethodCalls: Tags as Method Calls viewsAndTemplates: Views and Templates layouts: Layouts with Sitemesh - resources: - title: Static Resources - includingResourcesUsingTheResourceTags: Including resources using the resource tags - otherResourceTags: Other resource tags - declaringResources: Declaring resources - overridingPluginResources: Overriding plugin resources - optimizingYourResources: Optimizing your resources - debugging: Debugging - preventingProcessingOfResources: Preventing processing of resources - otherResourcesPlugins: Other Resources-aware plugins + resources: Static Resources sitemeshContentBlocks: Sitemesh Content Blocks makingChangesToADeployedApplication: Making Changes to a Deployed Application GSPDebugging: GSP Debugging @@ -179,18 +170,6 @@ theWebLayer: definingInterceptors: Defining Interceptors interceptorMatching: Matching Requests with Inteceptors interceptorOrdering: Ordering Interceptor Execution - ajax: - title: Ajax - ajaxSupport: - title: Ajax Support - remotingLinking: Remoting Linking - updatingContent: Updating Content - remoteFormSubmission: Remote Form Submission - ajaxEvents: Ajax Events - ajaxWithPrototype: Ajax with Prototype - ajaxWithDojo: Ajax with Dojo - ajaxWithGWT: Ajax with GWT - ajaxOnTheServer: Ajax on the Server contentNegotiation: Content Negotiation webServices: title: Web Services @@ -281,10 +260,10 @@ plugins: title: Plugins creatingAndInstallingPlugins: Creating and Installing Plugins repositories: Plugin Repositories - understandingPluginStructure: Understanding a Plugin's Structure providingBasicArtefacts: Providing Basic Artefacts evaluatingConventions: Evaluating Conventions hookingIntoRuntimeConfiguration: Hooking into Runtime Configuration + addingMethodsAtCompileTime: Adding Methods at Compile Time addingDynamicMethodsAtRuntime: Adding Dynamic Methods at Runtime participatingInAutoReloadEvents: Participating in Auto Reload Events understandingPluginLoadOrder: Understanding Plugin Load Order