diff --git a/src/docs/guide/configuration/accessing_plugin_config.gdoc b/src/docs/guide/configuration/accessing_plugin_config.gdoc index 09425f0..ff41aac 100644 --- a/src/docs/guide/configuration/accessing_plugin_config.gdoc +++ b/src/docs/guide/configuration/accessing_plugin_config.gdoc @@ -6,7 +6,7 @@ your plugin, automatically namespace for your plugin using the @plugin. platformUi { ui.Bootstrap.button.cssClass = 'btn' @@ -21,6 +21,6 @@ def doWithConfig = { config -> grails.x.y = config.p.q == 'something' ? true : false } } -{docx} +{code} See [doWithConfig|pluginConventions] for more details. diff --git a/src/docs/guide/configuration/declaring_configuration_options.gdoc b/src/docs/guide/configuration/declaring_configuration_options.gdoc index 0a6e793..4aaf7bf 100644 --- a/src/docs/guide/configuration/declaring_configuration_options.gdoc +++ b/src/docs/guide/configuration/declaring_configuration_options.gdoc @@ -4,23 +4,23 @@ This allows the platform to warn users when they mistype a config name or supply Do declare the options your plugin supports, add the @doWithConfigOptions@ closure to your plugin descriptor: -{docx} +{code} def doWithConfigOptions = { 'organization.name'(type: String, defaultValue: 'My Corp (set plugin.platformCore.organization.name)') 'site.name'(type: String, defaultValue: 'Our App (set plugin.platformCore.site.name)') } -{docx} +{code} This block, from the platform core, defines two configuration values of type String, with a default value. You can also supply a custom validator: -{docx} +{code} def doWithConfigOptions = { 'concurrentConnections'(type: Integer, defaultValue: 10, validator: { v -> v < 500 ? null : 'concurrent.connections.too.big' } } -{docx} +{code} Behaving just like constraint validators, your validator returns null for "ok" or an i18n message string for the error. diff --git a/src/docs/guide/events.gdoc b/src/docs/guide/events.gdoc index 5d54057..cc33a1b 100644 --- a/src/docs/guide/events.gdoc +++ b/src/docs/guide/events.gdoc @@ -20,7 +20,7 @@ and get maximum flexibility when required : In a nutshell, you will : * Send events : -{docx} +{code} class UserController{ def registration(){ @@ -45,10 +45,10 @@ class UserController{ } } } -{docx} +{code} * Write listeners (or event handler, or event reactor or whatever you call it): -{docx} +{code} class UserService{ //use method name 'mailRegistration' as topic name @@ -72,4 +72,4 @@ class UserService{ } } } -{docx} +{code} diff --git a/src/docs/guide/events/artifact.gdoc b/src/docs/guide/events/artifact.gdoc index ad9eae1..8199979 100644 --- a/src/docs/guide/events/artifact.gdoc +++ b/src/docs/guide/events/artifact.gdoc @@ -37,7 +37,7 @@ timeout | Long | | Default timeout for execution time, throwing a TimeoutExcept \* | \* | | Any attributes can be written to be used by plugins through EventDefinition.othersAttributes {table} -{docx} +{code} events = { //prevents any events in gorm namespace '*' namespace:'gorm', disabled:true @@ -74,8 +74,8 @@ events = { //testTopic9 onError:'anotherTopicErrors', onReply:'anotherTopicReplies' } -{docx} +{code} h3. Reloading in Development mode -It works. \ No newline at end of file +It works. diff --git a/src/docs/guide/events/config.gdoc b/src/docs/guide/events/config.gdoc index 311339e..598a05a 100644 --- a/src/docs/guide/events/config.gdoc +++ b/src/docs/guide/events/config.gdoc @@ -9,7 +9,7 @@ Based on Platform-Core [configuration|guide:configuration] mechanism, the plugin {table} In addition, you can override beans values such as gormTopicSupport -{docx} +{code} beans{ gormTopicSupport { //transform gorm Events Objects types into topics @@ -22,4 +22,4 @@ beans{ ] } } -{docx} +{code} diff --git a/src/docs/guide/events/gorm.gdoc b/src/docs/guide/events/gorm.gdoc index 06c32ba..fba6d07 100644 --- a/src/docs/guide/events/gorm.gdoc +++ b/src/docs/guide/events/gorm.gdoc @@ -19,7 +19,7 @@ Same listeners behaviors apply, e.g. using EventMessage for the argument type, u Because listeners are called if there are *no arguments* or the argument *type is assignable to current event data type*, specifying a domain class is the only required step to filter domains events. -{docx} +{code} class SomeService{ @Listener(namespace = 'gorm') @@ -39,21 +39,21 @@ class SomeService{ } } -{docx} +{code} h3. Filtering with Events Artifact Setting a filter through an Events artifact allows more fined control and efficient selection since it prevents events to be propagated : -{docx} +{code} events = { 'afterInsert' namespace:'gorm', filter:Book 'afterDelete' namespace:'gorm', filter:{it.id > 5} 'afterUpdate' namespace:'gorm', filter:{it in Book || it in Author} 'beforeDelete' namespace:'gorm', disabled:true } -{docx} +{code} {note} GORM may generate tons of events. Consider using it wisely, combine it with routing filtering. @@ -71,7 +71,7 @@ If a listener handles one of the _before\*_ topics and returns a boolean value, * Returning *false* will cancel the current database write * Returning *true* will just let the chain continuing -{docx} +{code} class SomeService{ //veto any Book insert @@ -80,4 +80,4 @@ class SomeService{ false } } -{docx} \ No newline at end of file +{code} diff --git a/src/docs/guide/events/listening.gdoc b/src/docs/guide/events/listening.gdoc index 98fc1be..4d2ed17 100644 --- a/src/docs/guide/events/listening.gdoc +++ b/src/docs/guide/events/listening.gdoc @@ -6,7 +6,7 @@ h3. Defining listeners at compile time Within Grails services you can use the *@Listener* annotation. It takes a *topic* string, but you can omit it and use the *method name* as the topic to listen for: -{docx} +{code} class SomeService{ @grails.events.Listener(topic = 'userLogged') @@ -18,12 +18,12 @@ class SomeService{ def mailSent(){ } } -{docx} +{code} Event methods can define a *single argument*, and the value is the object sent with the event. Usually this is the "subject" of the event. However an event is carried by an enveloppe called EventMessage which contains several useful metadata like additionnal headers, current topic : -{docx} +{code} class SomeService{ @grails.events.Listener(topic = 'userLogged') @@ -33,7 +33,7 @@ class SomeService{ println userMessage.data // displays data } } -{docx} +{code} If a listener argument type is not assignable to an event data type, the event *silently skips the mismatching listener*. If you want to catch every event types, use Object type or if the argument is not necessary, do not declare it. @@ -47,7 +47,7 @@ h3. Namespacing Your declared events belongs to the *app* namespace, unless you tune it using the *namespace* argument or the Events DSL we will introduce later. -{docx} +{code} class SomeService{ @grails.events.Listener(topic = 'userLogged', namespace = 'security') @@ -59,17 +59,17 @@ class SomeService{ def afterInsert(User user){ } } -{docx} +{code} Remember that you will need to specify the scope when triggering events if you customize it with a different value than *app* : -{docx} +{code} class SomeController{ def myAction(){ event for:'security', topic:'userLogged', data:session.user } } -{docx} +{code} {warning} It's mandatory to declare namespace when using events bus from a plugin in order to avoid any conflicts. @@ -79,7 +79,7 @@ h3. Proxy (AOP) support By default, listeners try to call the original method (unproxified bean). Using *proxySupport* you can tweak this setting : -{docx} +{code} class SomeService{ static transactional = true @@ -90,13 +90,13 @@ class SomeService{ } } -{docx} +{code} h3. Dynamic listeners Some edge cases need runtime registration. If you meet this use case, use the injected [on|eventsMethods] method : -{docx} +{code} class SomeController{ def testInlineListener = { @@ -115,13 +115,13 @@ class SomeController{ render "$listener registered" } } -{docx} +{code} h3. Wildcard support Capturing a wider group of events can be useful, specially for monitoring purposes. It's possible to listen for multiple topics/namespaces in a single shot using *wildcard as the last character*. -{docx} +{code} class SomeService{ @grails.events.Listener(namespace='role-*', topic = 'chat-*') @@ -130,7 +130,7 @@ class SomeService{ println userMessage.event } } -{docx} +{code} {note} This feature will probably evolve to a smarter implementation behaving like UrlMappings and authorizing substring captures @@ -147,7 +147,7 @@ The above square brackets determine each optional part of the sequence id thus a This pattern is useful when using *countListeners*, *removeListeners* or *extensions*. For instance, overriding a generated *channel* with *events-si* plugin requires to use @namespace://topic@ if _namespace_ is different from "app". Another example to count listeners: -{docx} +{code} //count every listeners subscribed to 'mytopic' inside TestService countListeners("mytopic:my.TestService") @@ -156,8 +156,8 @@ countListeners("gorm://*") //remove every listeners in TestService removeListeners("*:my.TestService") -{docx} +{code} h3. Reloading in Development mode -It works. \ No newline at end of file +It works. diff --git a/src/docs/guide/events/replying.gdoc b/src/docs/guide/events/replying.gdoc index 02bf832..9e17483 100644 --- a/src/docs/guide/events/replying.gdoc +++ b/src/docs/guide/events/replying.gdoc @@ -6,7 +6,7 @@ h3. Simple reply Replying is a simple matter of returning an object from the listener method : -{docx} +{code} class SomeService{ @Listener def logout(User user){ @@ -17,12 +17,12 @@ class SomeService{ return disconnectDate } } -{docx} +{code} If listeners return non null objects, the caller can access them through the EventReply enveloppe returned immediatly after calling *event* method. The other option is the use of a *reply handler* : -{docx} +{code} class SomeController{ def logout(){ @@ -41,7 +41,7 @@ class SomeController{ render reply_future.get(30, TimeUnit.SECONDS) } } -{docx} +{code} {note} Whenever an event is triggered, a task is submitted into the events bus thread pool and a Future returned, wrapped into EventReply. @@ -55,7 +55,7 @@ Multiple listeners can return values for the same topic/namespace. In this case, Remember that a valid result is a non null value, hence why even if 3 handlers have reacted but only 2 did return something, then you will only see 2 values in the *EventReply.values*. -{docx} +{code} class SomeController{ def logout(){ @@ -68,7 +68,7 @@ class SomeController{ render reply.values } } -{docx} +{code} h3. Exceptions @@ -83,7 +83,7 @@ An *onError* parameter is available and accepts a *Closure{List error Exceptions in multiple listeners scenario don't interrupt the execution flow and leave a chance to others listeners to execute as well. The return value from a failing listener becomes the raised exception. -{docx} +{code} class SomeController{ def logout(){ @@ -111,7 +111,7 @@ class SomeController{ } } -{docx} +{code} h3. Waiting replies @@ -119,7 +119,7 @@ In domains, services and controllers artefacts you can wait for events using "Ev It accepts as many events replies you want and returns the same array for functiunal programming style. EventReply also have a waitFor method for one-line waiting. -{docx} +{code} class SomeController{ def logout(){ @@ -142,4 +142,4 @@ class SomeController{ } } -{docx} \ No newline at end of file +{code} diff --git a/src/docs/guide/events/sending.gdoc b/src/docs/guide/events/sending.gdoc index 2d83fb3..eba06fe 100644 --- a/src/docs/guide/events/sending.gdoc +++ b/src/docs/guide/events/sending.gdoc @@ -42,7 +42,7 @@ Platform-core Events bus provides a non-blocking way to send events by default, Therefore you have the control on the execution flow if you want. Just keep in mind it does not block for processing right after event() call, which seems to be a sensible default for the bus. Eventual *Exceptions* will be raised after using one of the mentioned blocking methods except if *onError* parameter is used. -{docx} +{code} class SomeController{ def logout(){ @@ -59,13 +59,13 @@ class SomeController{ event(topic:"afterAfterLogout", onError:errs) } } -{docx} +{code} h3. Non forked events If you want to reuse the current thread and force synchronous processing, use the fork param. Be aware that each exception will be directly propagated to caller even without using blocking methods except if *onError* parameter is used. -{docx} +{code} class SomeController{ def logout(){ @@ -76,13 +76,13 @@ class SomeController{ render reply.value } } -{docx} +{code} h3. Assigning a namespace All listeners get a property called namespace which prevents topic naming collisions and undesired events. By default, they are all assigned to *app*. This is the same default used when you send an event, but what if you want to reach others namespaced listeners, like 'browser' ones if you use *events-push* plugin ? Simply use *namespace* argument or use *for* if you stick with Map notation. -{docx} +{code} class SomeController{ def logout(){ @@ -90,7 +90,7 @@ All listeners get a property called namespace which prevents topic naming collis event for:'browser', topic:'logout', data:session.user } } -{docx} +{code} {warning} It's mandatory to declare namespace when using events bus from a plugin in order to avoid any conflicts. @@ -99,7 +99,7 @@ It's mandatory to declare namespace when using events bus from a plugin in order h3. Wildcard support It's possible to call multiple topics/namespaces in a single shot using *wildcard as the last character*. -{docx} +{code} class SomeController{ def logout(){ @@ -113,7 +113,7 @@ class SomeController{ event '*' } } -{docx} +{code} {note} This feature will probably evolve to a smarter implementation behaving like UrlMappings and authorizing substring captures diff --git a/src/docs/guide/gettingStarted.gdoc b/src/docs/guide/gettingStarted.gdoc index 8b765b9..730d7d5 100644 --- a/src/docs/guide/gettingStarted.gdoc +++ b/src/docs/guide/gettingStarted.gdoc @@ -2,14 +2,14 @@ To get started you need to install the platform-core plugin. Add the plugin platform as a dependency to your application or plugin, either directly or transitively. To do so directly edit your @BuildConfig.groovy@ to look something like this: -{docx} +{code} grails.project.dependency.resolution = { // inside your plugin dependencies block plugins { compile ':platform-core:1.0.M1' } } -{docx} +{code} You can run your code now and browse to @http://localhost:8080//platform/@, a special page available only in the development environment. From there you can explore some of the plugin platform features in the debug interface. diff --git a/src/docs/guide/nav/menu_navigation.gdoc b/src/docs/guide/nav/menu_navigation.gdoc index 824ebda..b81c323 100644 --- a/src/docs/guide/nav/menu_navigation.gdoc +++ b/src/docs/guide/nav/menu_navigation.gdoc @@ -8,7 +8,7 @@ The main menu would use [primary|navigationTags] & [secondary|navigationTags] ta You would then render the user and footer navigation using the menu tag, and passing the user and footer scopes: -{docx:xml} +{code:xml} @@ -25,7 +25,6 @@ You would then render the user and footer navigation using the menu tag, and pas -{docx} +{code} This results in a page where there are actually for navigation renderings, showing different scopes. - diff --git a/src/docs/guide/nav/navigation_by_convention.gdoc b/src/docs/guide/nav/navigation_by_convention.gdoc index 68acb69..412c976 100644 --- a/src/docs/guide/nav/navigation_by_convention.gdoc +++ b/src/docs/guide/nav/navigation_by_convention.gdoc @@ -2,10 +2,10 @@ To get you started quickly, all your controllers will be automatically registere All the tags default to the "app" scope if you don't supply a scope and the current controller/action are within that scope, so it just works out of the box for the simple cases. So add the following to your sitemesh layout or GSP: -{docx:xml} +{code:xml} -{docx} +{code} This will render one or two