Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merges Kevin Burke and tule changes and upgrades cometd dependencies to 2.2.0 #5

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions CometdGrailsPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@
import grails.util.Environment

import org.codehaus.groovy.grails.commons.ConfigurationHolder
import org.codehaus.groovy.grails.commons.ServiceArtefactHandler

import org.cometd.server.BayeuxServerImpl
import org.cometd.server.CometdServlet
import org.cometd.bayeux.server.BayeuxServer
import grails.plugin.cometd.ServiceCometdProcessor

import org.springframework.web.context.support.ServletContextAttributeExporter

import org.apache.commons.logging.LogFactory

class CometdGrailsPlugin {
def version = "0.2.2"
def version = "0.2.5"
def grailsVersion = "1.2.1 > *"
def dependsOn = [:]
def pluginExcludes = [
Expand All @@ -44,9 +48,13 @@ This plugin allows your Grails application to send asynchronous notifications to
CometD and the Bayeux protocol.
'''
def documentation = "http://www.grails.org/plugin/cometd"
def loadAfter = ['services', 'controllers']
def observe = ['services', 'controllers']

def doWithWebDescriptor = { xml ->
def conf = ConfigurationHolder.config.plugins.cometd

LOG.debug("Initializing with continutationFilter: ${!conf.continuationFilter.disable}")
if (!conf.continuationFilter.disable) {
def filters = xml.'filter'
filters[filters.size() - 1] + {
Expand All @@ -70,6 +78,17 @@ CometD and the Bayeux protocol.
servlet {
'servlet-name'('cometd')
'servlet-class'(CometdServlet.class.name)

// Add servlet init params from the config file
if (conf.init?.params) {
LOG.debug("Initializing with init-params: ${conf.init.params}")
conf.init.params.each { key, value ->
'init-param' {
'param-name'(key)
'param-value'(value)
}
}
}
}
}

Expand All @@ -83,7 +102,7 @@ CometD and the Bayeux protocol.
}

def doWithSpring = {
bayeux(BayeuxServerImpl, true) { bean ->
bayeux(BayeuxServerImpl) { bean ->
bean.destroyMethod = 'stop'
}

Expand All @@ -92,4 +111,20 @@ CometD and the Bayeux protocol.
attributes = [(BayeuxServer.ATTRIBUTE): ref('bayeux')]
}
}

def processor = new ServiceCometdProcessor()

def doWithDynamicMethods = { context ->
application.serviceClasses?.each { service ->
processor.process(service.referenceInstance, context)
}
}

def onChange = { event ->
if (application.isServiceClass(event.source)) {
def artefact = application.addArtefact(ServiceArtefactHandler.TYPE, event.source)

processor.process(artefact.referenceInstance, event.ctx)
}
}
}
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Grails Cometd Plugin

[CometD](http://cometd.org) is a scalable HTTP-based event routing bus that uses an Ajax Push technology pattern known as [Comet](http://en.wikipedia.org/wiki/Comet_(programming\)). This plugin allows your Grails application to push asynchronous notifications to HTTP clients using CometD and the [Bayeux](http://cometd.org/documentation/bayeux) protocol.

## Installation
NOTE: Because of a bug this won't work in grails 1.3.2 (fixed in 1.3.3):

grails install-plugin cometd

You can always download the [source](http://github.com/marcusb/grails-cometd) and then from the plugin directory:

grails package-plugin

And then from your application directory:

grails install-plugin /path/to/grails-cometd-plugin-zip-file

## Usage

### CometD Servlet
***

The plugin configures a CometdServlet, mapped to the path cometd relative to your web application's context path.

### Bayeux Service
***

A bean named bayeux is made available to your application. It is an instance of [BayeuxServer](http://download.cometd.org/bayeux-api-2.0.beta0-javadoc/org/cometd/bayeux/server/BayeuxServer.html). This is used to interact with the Comet server.

### Annotations
***

You can annotate your service classes and the plugin will wire everything up for you. This needs a bit of Cometd knowledge, but it's fairly straight forward. In order to register your service as a Cometd service you just have to add a static property to the service, much like the JMS and XFire plugins. (though this might be moving to a class level annotation, we'll see.)

static exposes = ["cometd"]

#### @ChannelInitializer
When you annotate a service method with the @ChannelInitializer annotation, the plugin will register it as a ConfigurableServerChannel.Initializer with the bayeux server. Your service method will be called with one argument, which is the ConfigurableServerChannel instance of the channel. Example:

@ChannelInitializer("/foo/bar")
def configure(channel) {
channel.persistent = true
}

#### @MessageListener
Annotating a service method with the @MessageListener annotation will register the method as a ServerChannel.MessageListener on the provided channel. The functionality is similar to that found with the AbstractService that comes with the Cometd distribution. Depending on the signature of your method, it will be called with different arguments. Possible options include:

def service(session, data) // The "from" Session and Message.data
def service(session, data, id) // The "from" Session, Message.data, and the client id
def service(session, channel, message, id) // The "from" Session, the channel(String), the Message, and the client id

If you were to explicitly define the parameter type for message you will get the actual Message object and not just the data field on the Message:

def service(session, Message message) // The "from" Session and Message

If you return false from the method, the message will not be broadcast. If you return nothing or true, the message will be broadcast. If you return an object or message, that message will be delivered to the client that initialized the service call.

The actual use of this annotation would look thusly:

@MessageListener("/foo/bar")
def onFooBar(session, data) {
// do something with the data

[message: "thanks for the info mr. client"]
}

### Configuration
***

The plugin is configured in Config.groovy, with options prefixed with "plugins.cometd". The following options are defined:

* **plugins.cometd.continuationFilter.disable**: if set, do not install the to [ContinuationFilter](http://download.eclipse.org/jetty/stable-7/apidocs/org/eclipse/jetty/continuation/ContinuationFilter.html)
* **plugins.cometd.init.params**: a map of init-name -> init-value pairs for an init-param element to be applied to the cometd servlet definition. Make sure you read the javadoc for org.cometd.bayeux.server.ServerTransport for how the init params are applied. Some useful settings include:
* **timeout**: In the default long polling http transport is the period of time the server waits before answering to a long poll
* **interval**: In the default long polling http transport is the period of time that the client waits between long polls
* **maxInterval**: In the default long polling http transport is the period of time that must elapse before the server consider the client being lost

## Contributing
Contributions are welcome, preferably by pull request on GitHub

git clone git://github.com/marcusb/grails-cometd.git

## History

### Version 0.2.1
***
* Install the [ContinuationFilter](http://download.eclipse.org/jetty/stable-7/apidocs/org/eclipse/jetty/continuation/ContinuationFilter.html) by default, it is needed for Tomcat 6

### Version 0.2
***
* Rewritten from scratch for CometD 2.0
8 changes: 4 additions & 4 deletions application.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#Grails Metadata file
#Tue Oct 19 04:56:43 GMT+01:00 2010
app.grails.version=1.3.5
#Thu Apr 14 14:23:13 BRT 2011
app.grails.version=1.3.7
app.name=grails-cometd
app.servlet.version=2.4
app.version=0.1
plugins.functional-test=1.2.7
plugins.hibernate=1.3.5
plugins.tomcat=1.3.5
plugins.hibernate=1.3.7
plugins.tomcat=1.3.7
6 changes: 5 additions & 1 deletion grails-app/conf/BuildConfig.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ grails.project.dependency.resolution = {
inherits 'global'
log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
repositories {
grailsPlugins()
grailsHome()
grailsCentral()
mavenLocal()
mavenCentral()
}
dependencies {
def cometdVer = '2.0.0'
def cometdVer = '2.2.0'
compile(group: 'org.cometd.java', name: 'cometd-java-server', version: cometdVer) {
excludes 'servlet-api'
}
Expand Down
41 changes: 0 additions & 41 deletions grails-app/services/grails/plugins/cometd/test/EchoService.groovy

This file was deleted.

Loading