Git Product home page Git Product logo

grails-executor's Introduction

Summary

This grails plugin incorporates the java concurrency Executor Framework into a plugin so your grails app can take advantage of asynchronous (background thread / concurrent) processing. The main need for this as opposed to just using an ExecutorService from Executors is that we need to wrap the calls so there is a Hibernate or other Data provider session bound to the thread. This uses the following pattern to wrap Runnable/Closures so they get a session for whatever Gorm you are using. Hibernate being the default but this is also tested with Mongo (no heavily) See the info on the PersistenceContextInterceptor grails bean for more info

//injected spring bean
PersistenceContextInterceptor persistenceInterceptor

protected wrap(Closure wrapped) {
	persistenceInterceptor.init()
	try {
		wrapped()
	} finally {
		persistenceInterceptor.flush()
		persistenceInterceptor.destroy()
	}
}

Here are a couple of links to get give you some background information.

http://www.ibm.com/developerworks/java/library/j-jtp1126.html
http://www.vogella.de/articles/JavaConcurrency/article.html

and here are few good write up on groovy concurrency
http://groovy.codehaus.org/Concurrency+with+Groovy
and a slide show
http://www.slideshare.net/paulk_asert/groovy-and-concurrency-paul-king

Setup

The plugin sets up a Grails service bean called executorService so you need do nothing really. It delegates to an implementation of an Java ExecutorService (not to be confused with a Grails Service) interface so read up on that for more info on what you can do with the executorService. It basically wraps another thread pool ExecutorService. By default it uses the java Executors utility class to setup the injected thread pool ExecutorService implementation. The default Grails executorService config looks like this

executorService( grails.plugin.executor.PersistenceContextExecutorWrapper ) { bean->
	bean.destroyMethod = 'destroy'
	persistenceInterceptor = ref("persistenceInterceptor")
	executor = Executors.newCachedThreadPool()
}

You can override it and inject your own special thread pool executor using Executors by overriding the bean in conf/spring/resources.groovy or the doWithSpring closure in your plugin.

executorService(  grails.plugin.executor.PersistenceContextExecutorWrapper ) { bean->
	bean.destroyMethod = 'destroy' //keep this destroy method so it can try and clean up nicely
	persistenceInterceptor = ref("persistenceInterceptor")
	//this can be whatever from Executors (don't write your own and pre-optimize)
	executor = Executors.newCachedThreadPool(new YourSpecialThreadFactory()) 
}

Usage

You can inject the executorService into any bean. Its a PersistenceContextExecutorWrapper that delegates any calls to a concrete ExecutorService implementation so, again, see the api for more on what you can do. Remember that a Closure is a Runnable so you can pass it to any of the methods that accept a runnable. A great example exists here on the groovy site

The plugin adds shortcut methods to any service/controller/domain artifacts.

  • runAsync closure - takes any closure and passes it through to the executorService.execute
  • callAsync closure - takes any closure that returns a value and passes it through to the executorService.submit . You will get a Future back that you can work with. This will not bind a session in java 1.5 and only works on 1.6 or later

NOTE ON TRANSACTIONS: keep in mind that this is spinning off a new thread and that any call will be outside of the transaction you are in. Use .withTransaction inside your closure, runnable or callable to make your process run in a transaction that is not calling a transactional service method (such as when using this in a controller).

Examples

in a service/domain/controller just pass a Closure or Runnable to runAsync

class someService {

	def myMethod(){
		..do some stuff
		runAsync {
			//this will be in its own trasaction 
			//since each of these service methods are Transactional
			calcAging() 
		}
		.. do some other stuff while aging is calced in background
	}

	def calcAging(){
		...do long process
	}
}

or inject the executorService

class someService {
	def executorService

	def myMethod(){
		....do stuff
		def future = executorService.submit({
			return calcAging() //you can of course leave out the "return" here
		} as Callable)
		.. do some other stuff while its processing
		//now block and wait with get()
		def aging = future.get()
		..do something
	}

	def calcAging(){
		...do long process
		return agingCalcObject
	}

}

or during a domain event

class Book {
	def myNotifyService
	
	String name
	
	def afterInsert(){
		runAsync {
			myNotifyService.informLibraryOfCongress(this)
		}
	}
}

the callAsync allows you to spin of a process and calls the underlying executorService submit

class someService {
	def myMethod(){
		....do stuff
		def future = callAsync {
			return calcAging() //you can of course leave out the "return" here
		}
		.. do some other stuff while its processing
		//now block and wait with get()
		def aging = future.get()
		..do something with the aging
	}

	def calcAging(){
		...do stuff
		return agingCalcObject
	}
}

GOTCHAS and TODOs

grails-executor's People

Contributors

basejump avatar boatmeme avatar ldaley avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.