Permalink
Browse files

initial commit

  • Loading branch information...
Joshua Burnett Joshua Burnett
Joshua Burnett authored and Joshua Burnett committed Dec 15, 2011
0 parents commit 102ca7c48fc6b4d619a37cf02c3aa510988bebe8
Showing with 18,213 additions and 0 deletions.
  1. +11 −0 .gitignore
  2. +105 −0 Quartz2GrailsPlugin.groovy
  3. +199 −0 README.md
  4. +6 −0 application.properties
  5. +26 −0 grails-app/conf/BuildConfig.groovy
  6. +25 −0 grails-app/conf/Config.groovy
  7. +32 −0 grails-app/conf/DataSource.groovy
  8. +25 −0 grails-app/conf/Quartz2DefaultConfig.groovy
  9. +131 −0 quartz2.tmproj
  10. +10 −0 scripts/_Install.groovy
  11. +5 −0 scripts/_Uninstall.groovy
  12. +10 −0 scripts/_Upgrade.groovy
  13. +77 −0 src/groovy/grails/plugin/quartz2/ClosureJob.groovy
  14. +97 −0 src/groovy/grails/plugin/quartz2/InvokeMethodJob.groovy
  15. +38 −0 src/groovy/grails/plugin/quartz2/JobErrorLoggerListener.groovy
  16. +58 −0 src/groovy/grails/plugin/quartz2/PersistenceContextJobListener.groovy
  17. +180 −0 src/groovy/grails/plugin/quartz2/QuartzFactoryBean.groovy
  18. +44 −0 src/groovy/grails/plugin/quartz2/QuartzHelper.groovy
  19. +223 −0 src/groovy/grails/plugin/quartz2/SimpleJobDetail.groovy
  20. +132 −0 test/projects/qkiss/app-qkiss-quartz.groovy
  21. +8 −0 test/projects/qkiss/application.properties
  22. +38 −0 test/projects/qkiss/grails-app/conf/BootStrap.groovy
  23. +32 −0 test/projects/qkiss/grails-app/conf/BuildConfig.groovy
  24. +60 −0 test/projects/qkiss/grails-app/conf/Config.groovy
  25. +32 −0 test/projects/qkiss/grails-app/conf/DataSource.groovy
  26. +13 −0 test/projects/qkiss/grails-app/conf/UrlMappings.groovy
  27. +3 −0 test/projects/qkiss/grails-app/conf/spring/resources.groovy
  28. +9 −0 test/projects/qkiss/grails-app/domain/qkiss/Org.groovy
  29. +55 −0 test/projects/qkiss/grails-app/i18n/messages.properties
  30. +56 −0 test/projects/qkiss/grails-app/i18n/messages_da.properties
  31. +55 −0 test/projects/qkiss/grails-app/i18n/messages_de.properties
  32. +30 −0 test/projects/qkiss/grails-app/i18n/messages_es.properties
  33. +19 −0 test/projects/qkiss/grails-app/i18n/messages_fr.properties
  34. +19 −0 test/projects/qkiss/grails-app/i18n/messages_it.properties
  35. +19 −0 test/projects/qkiss/grails-app/i18n/messages_ja.properties
  36. +55 −0 test/projects/qkiss/grails-app/i18n/messages_nl.properties
  37. +34 −0 test/projects/qkiss/grails-app/i18n/messages_pt_BR.properties
  38. +34 −0 test/projects/qkiss/grails-app/i18n/messages_pt_PT.properties
  39. +31 −0 test/projects/qkiss/grails-app/i18n/messages_ru.properties
  40. +35 −0 test/projects/qkiss/grails-app/i18n/messages_th.properties
  41. +18 −0 test/projects/qkiss/grails-app/i18n/messages_zh_CN.properties
  42. +27 −0 test/projects/qkiss/grails-app/services/qkiss/HunterService.groovy
  43. +54 −0 test/projects/qkiss/grails-app/views/error.gsp
  44. +100 −0 test/projects/qkiss/grails-app/views/index.gsp
  45. +17 −0 test/projects/qkiss/grails-app/views/layouts/main.gsp
  46. +36 −0 test/projects/qkiss/src/groovy/qkiss/HelloFromExternalConfigJob.groovy
  47. +35 −0 test/projects/qkiss/src/groovy/qkiss/HelloJob.groovy
  48. +33 −0 test/projects/qkiss/test/integration/qkiss/BuilderConfigTests.groovy
  49. +73 −0 test/projects/qkiss/test/integration/qkiss/ClosureJobTests.groovy
  50. +55 −0 test/projects/qkiss/test/integration/qkiss/JobLookupTests.groovy
  51. +17 −0 test/projects/qkiss/test/unit/qkiss/JobRunnerServiceTests.groovy
  52. +17 −0 test/projects/qkiss/test/unit/qkiss/OrgTests.groovy
  53. +42 −0 test/projects/qkiss/web-app/WEB-INF/applicationContext.xml
  54. +14 −0 test/projects/qkiss/web-app/WEB-INF/sitemesh.xml
  55. +563 −0 test/projects/qkiss/web-app/WEB-INF/tld/c.tld
  56. +671 −0 test/projects/qkiss/web-app/WEB-INF/tld/fmt.tld
  57. +550 −0 test/projects/qkiss/web-app/WEB-INF/tld/grails.tld
  58. +311 −0 test/projects/qkiss/web-app/WEB-INF/tld/spring.tld
  59. +273 −0 test/projects/qkiss/web-app/css/main.css
  60. BIN test/projects/qkiss/web-app/images/favicon.ico
  61. BIN test/projects/qkiss/web-app/images/grails_logo.jpg
  62. BIN test/projects/qkiss/web-app/images/grails_logo.png
  63. BIN test/projects/qkiss/web-app/images/leftnav_btm.png
  64. BIN test/projects/qkiss/web-app/images/leftnav_midstretch.png
  65. BIN test/projects/qkiss/web-app/images/leftnav_top.png
  66. BIN test/projects/qkiss/web-app/images/skin/database_add.png
  67. BIN test/projects/qkiss/web-app/images/skin/database_delete.png
  68. BIN test/projects/qkiss/web-app/images/skin/database_edit.png
  69. BIN test/projects/qkiss/web-app/images/skin/database_save.png
  70. BIN test/projects/qkiss/web-app/images/skin/database_table.png
  71. BIN test/projects/qkiss/web-app/images/skin/exclamation.png
  72. BIN test/projects/qkiss/web-app/images/skin/house.png
  73. BIN test/projects/qkiss/web-app/images/skin/information.png
  74. BIN test/projects/qkiss/web-app/images/skin/shadow.jpg
  75. BIN test/projects/qkiss/web-app/images/skin/sorted_asc.gif
  76. BIN test/projects/qkiss/web-app/images/skin/sorted_desc.gif
  77. BIN test/projects/qkiss/web-app/images/spinner.gif
  78. BIN test/projects/qkiss/web-app/images/springsource.png
  79. +13 −0 test/projects/qkiss/web-app/js/application.js
  80. +7 −0 test/projects/qkiss/web-app/js/prototype/animation.js
  81. +136 −0 test/projects/qkiss/web-app/js/prototype/builder.js
  82. +965 −0 test/projects/qkiss/web-app/js/prototype/controls.js
  83. +974 −0 test/projects/qkiss/web-app/js/prototype/dragdrop.js
  84. +1,123 −0 test/projects/qkiss/web-app/js/prototype/effects.js
  85. +4,874 −0 test/projects/qkiss/web-app/js/prototype/prototype.js
  86. +2,691 −0 test/projects/qkiss/web-app/js/prototype/rico.js
  87. +68 −0 test/projects/qkiss/web-app/js/prototype/scriptaculous.js
  88. +275 −0 test/projects/qkiss/web-app/js/prototype/slider.js
  89. +59 −0 test/projects/qkiss/web-app/js/prototype/sound.js
  90. +568 −0 test/projects/qkiss/web-app/js/prototype/unittest.js
  91. +84 −0 test/unit/grails/plugin/quartz2/ClosureJobTests.groovy
  92. +65 −0 test/unit/grails/plugin/quartz2/InvokeMethodJobTests.groovy
  93. +44 −0 test/unit/grails/plugin/quartz2/SimpleJobDetailTests.groovy
  94. +42 −0 web-app/WEB-INF/applicationContext.xml
  95. +14 −0 web-app/WEB-INF/sitemesh.xml
  96. +563 −0 web-app/WEB-INF/tld/c.tld
  97. +671 −0 web-app/WEB-INF/tld/fmt.tld
@@ -0,0 +1,11 @@
+target/
+stacktrace.log
+
+# Eclipse Project files
+.classpath
+.project
+.settings/
+
+# OS X generated files
+.DS_Store
+
@@ -0,0 +1,105 @@
+import grails.plugin.quartz2.*
+
+class Quartz2GrailsPlugin {
+ // the plugin version
+ def version = "0.2.1"
+ // the version or versions of Grails the plugin is designed for
+ def grailsVersion = "1.3.1 > *"
+ // the other plugins this plugin depends on
+ def dependsOn = [:]
+ // resources that are excluded from plugin packaging
+ def pluginExcludes = [
+ "grails-app/views/error.gsp"
+ ]
+
+ // TODO Fill in these fields
+ def author = "Joshua Burentt"
+ def authorEmail = "Joshua@greenbill.com"
+ def title = "Quartz 2.1 Scheduler"
+ def description = '''\\
+Uses the new Quartz 2.1 framework from quartz-scheduler.org.
+The goal is to keep it as simple as possible while making it friendly for Groovy/Grails.
+'''
+
+ // URL to the plugin's documentation
+ def documentation = "http://grails.org/plugin/quartz2"
+
+ def doWithWebDescriptor = { xml ->
+ // TODO Implement additions to web.xml (optional), this event occurs before
+ }
+
+ def doWithSpring = {
+ def mcfg = application.mergedConfig
+ def quartzProps = loadQuartzConfig(mcfg)
+
+ persistenceContextJobListener(PersistenceContextJobListener){
+ persistenceInterceptor = ref("persistenceInterceptor")
+ }
+
+ jobErrorLoggerListener(JobErrorLoggerListener)
+
+ quartzScheduler(QuartzFactoryBean) {
+ grailsApplication = ref('grailsApplication')
+ quartzProperties = quartzProps
+ // delay scheduler startup to after-bootstrap stage
+ autoStartup = mcfg.grails.plugins.quartz2.autoStartup
+ globalJobListeners = [ref('jobErrorLoggerListener'),ref('persistenceContextJobListener')]
+ }
+
+ /* for future reloading
+ scheduledExecutorForReloading(org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean){
+ continueScheduledExecutionAfterException=true
+ waitForTasksToCompleteOnShutdown=true
+ scheduledExecutorTasks = [ref('scheduledExecutorTaskForReloading')]
+ }
+ scheduledExecutorTaskForReloading(org.springframework.scheduling.concurrent.ScheduledExecutorTask){
+ runnable = ref('configReloadingTask')
+ delay=5000 //5 seconds
+ period=5000 //5 seconds
+ }
+
+ configReloadingTask(ConfigReloadingTask)
+ */
+
+ }
+
+ def doWithDynamicMethods = { ctx ->
+ // TODO Implement registering dynamic methods to classes (optional)
+ }
+
+ def doWithApplicationContext = { ctx ->
+ if(application.mergedConfig.grails.plugins.quartz2.autoStartup){
+ def builders = application.mergedConfig.grails.plugin.quartz2.jobSetup.flatten()
+ if(builders?.keySet()){
+ builders.each{key,clos->
+ clos(ctx.quartzScheduler,ctx)
+ }
+ }
+ }
+ // TODO Implement post initialization spring config (optional)
+ }
+
+ def onChange = { event ->
+ // TODO Implement code that is executed when any artefact that this plugin is
+ // watching is modified and reloaded. The event contains: event.source,
+ // event.application, event.manager, event.ctx, and event.plugin.
+ }
+
+ def onConfigChange = { event ->
+ // TODO Implement code that is executed when the project configuration changes.
+ // The event is the same as for 'onChange'.
+ }
+
+ //private ConfigObject loadQuartzConfig(config) {
+ Properties loadQuartzConfig(config) {
+ def properties = new Properties()
+ if (config.org.containsKey('quartz')) {
+ properties << config.org.quartz.toProperties('org.quartz')
+ }
+
+ //config.quartz._properties = properties
+
+ return properties
+ }
+
+}
199 README.md
@@ -0,0 +1,199 @@
+# A simple plugin for Quartz 2+ #
+
+Uses the new [Quartz][] 2.1 framework from quartz-scheduler.org. The goal is to keep it as simple as possible while making it friendly for Groovy/Grails.
+
+## What this plugin adds to be friendly with Grails
+
+* Uses a factory to creates a single bean called quartzScheduler which is a standard Quartz [Scheduler][] and starts it. Its does not start it by default in test. You can inject and use the quartzScheduler bean like any normal Grails/Spring bean.
+* All quartz settings can be done in Config.groovy, thus eliminating the need for a quartz.properties
+* Sets up a PersistenceContextJobListener, makes it a bean and adds it to the scheduler. This wraps all the jobs to make sure they have a hibernate session bound to the thread or if using another (nosql) engine then this should work for other non-hibernate gorm engines too as it uses the "persistenceInterceptor" bean to init(). If you don't need gorm persistence in your job then you can avoid the overhead and turn it of by assigning a "gorm:false" property in the the JobDataMap when setting up a [JobDetail][] or Trigger. Note:
+* adds a general InvokeMethodJob class that can be used to setup a [JobDetail][] to calls a service bean method or any static or local method on a passed in object
+* support for assigning a builder closures in Config.groovy (or an externalized config) that will get called on application startup to setup your scheduler
+* Adds a SimpleJobDetail - an implementation of the JobDetail that makes it easier to setDisallowConcurrentExecution with the need to put the annotaion on the Job class. Also makes it much easier to add JobDataMap properties by simply passing a map into the constructor
+* ClosureJob - implements the Quartz [Job][] interface and is a utility class to allow you pass in configuration and a closure to be called when the Job executes.
+
+## Why we chose not to use or modify the quartz-plugin
+
+* the changes in [Quartz][] 2 made for many incompatibilities with older 1.8. I think it will be difficult to have 1 plugin support both versions but it may be possible with some work. Spring 3.1 seemed to pull it off but with a considerable amount of ugly gyrations
+* This plugin does not rely on the Spring support classes for quartz which the existing quartz-plugin makes heavy use of. Spring added support for [Quartz][] 2 in their upcoming 3.1 which will come with Grails 2. However we need and wanted Quartz 2 support now for our 1.3.x Grails apps
+* We wanted something dirt simple and light weight but got the job done to integrate with Grails
+
+[Quartz][] 2 has a fairly simple way to build schedules so we just stick with the out of the box stuff. The [documentation and quick start][] are a fairly easy read.
+
+## Docs and Examples ##
+
+clone this and look at the example test project under tests/projects/qkiss for examples on how its being used. Look at Config.groovy, the externalized app-qkiss-config.groovy on the root, and the integration tests. To get a schedule going in your app follow the examples in the [documentation and quick start][] and either set a grails.plugin.quartz2.jobSetup closure in config as in the example below or just inject the quartzScheduler([Scheduler][]) into BuildConfig and call quartzScheduler.scheduleJob once you have a JobDetail and Trigger setup.
+
+### Config.groovy closure
+
+You can externalize the config (see the grails docs on externalizing the config) and this allows us to configure and setup new jobs without recompiling the app. For example you could add something like grails.config.locations = [ "file:Quartz-config.groovy"] in your config.groovy and then follow the example below.
+
+#### Example Quartz-config.groovy
+
+ import static org.quartz.JobBuilder.*;
+ import static org.quartz.SimpleScheduleBuilder.*;
+ import static org.quartz.TriggerBuilder.*;
+ import grails.plugin.quartz2.InvokeMethodJob
+
+ grails.plugins.quartz.autoStartup = true
+
+ org{
+ quartz{
+ //anything here will get merged into the quartz.properties so you don't need another file
+ scheduler.instanceName = 'MyAppScheduler'
+ threadPool.class = 'org.quartz.simpl.SimpleThreadPool'
+ threadPool.threadCount = 20
+ threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
+ jobStore.class = 'org.quartz.simpl.RAMJobStore'
+ }
+ }
+
+ /you can drive the setup. just give them a unique key like "buyTheTicket" below.
+ //the quartzScheduler bean and application context are passed to your closure
+ grails.plugin.quartz2.jobSetup.buyTheTicket = { quartzScheduler, ctx ->
+ //how it should look
+ def jobDetail = ClosureJob.createJob { jobCtx , appCtx->
+ appCtx.hunterService.takeTheRide(true)
+ }
+
+ def trigger1 = new SimpleTriggerImpl(name:"trig1", startTime:new Date(),repeatInterval:1000,repeatCount:-1)
+
+ quartzScheduler.scheduleJob(jobDetail, trigger1)
+ }
+
+ grails.plugin.quartz2.jobSetup.buyTicket2 = { quartzScheduler, ctx ->
+
+ //example a service call using the InvokeMethodJob and quartz's new builder syntax
+ def props = new JobDataMap([targetObject:ctx.hunterService,targetMethod:'takeTheRide',arguments:[true]])
+ JobDetail jobDetail = newJob(InvokeMethodJob.class) //use the static helper newJob from org.quartz.JobBuilder
+ .withIdentity("take the ride")
+ .usingJobData(props)
+ .build()
+
+ Trigger trigger = newTrigger().withIdentity("hunter trigger")
+ .withSchedule(
+ simpleSchedule().withIntervalInSeconds(1).repeatForever()
+ )
+ .startNow().build()
+
+ quartzScheduler.scheduleJob(jobDetail, trigger)
+ }
+
+
+### SimpleJobDetail ###
+
+SimpleJobDetail is an implementation of the Quartz [JobDetail][] interface.
+Its primary purpose was to make it easier to set make a Job or JobDetail single threaded and not need to
+name and jobClass are the only required fields
+
+- **name** * - the jobKey name for this
+- **group** - the jobKey group name
+- **key** - set your own JobKey instead of constructing from a map
+- **description** - description
+- **jobClass** * - the Job class that will be instantiated and run via the exceute method
+- **jobDataMap** - a JobDataMap with any data that will be set to the JobExecutionContext
+- **jobData** - a convenience setter to allow a normal Map to be set into the JobDataMap
+- **concurrent** - setting this to false will make it so only 1 trigger at a time can run. isConcurrentExectionDisallowed will return true.
+- **durability** - if this be stored even if no trigers
+- **persistJobDataAfterExecution**
+
+#### examples
+
+ def sd = new SimpleJobDetail("test",TestJob.class, [prop:'xyz'] )
+ ...
+ //gorm:false will turn off the session init for gorm
+ def map = [name:"test",jobClass:TestJob.class, concurrent:false, jobData:[fly:'free',gorm:false] ]
+ def sd = new SimpleJobDetail(map)
+ assert sd.isConcurrentExectionDisallowed() == false
+ assert sd.jobDataMap.fly=='free'
+
+### ClosureJob ###
+
+ClosureJob implements the Quartz [Job][] interface and is a utility class to allow you pass in configuration and a closure to be called when the JOb executes.
+the easiest way is to use the static method **createJob** which will return a **SimpleJobDetail**.
+You can pass in a map of parameters to construct the SimpleJobDetail and then a closure that takes optional args for [JobExecutionContext][] and the spring application context .
+To pass in values for the JobDataMap then just pass in a map of values to the jobData property such as
+
+#### examples
+
+ //import the static as in previous examples
+ def dataMap
+
+ def jobDetail = ClosureJob.createJob(name:"test_quarts_builder",durability:true,concurrent:false){ jobCtx , appCtx->
+ println "************* it ran ***********"
+ //do something
+ }
+ jobDetail.jobData = [gorm:false]
+
+ def trigger = TriggerBuilder.newTrigger().withIdentity("closureJobTrigger")
+ .withSchedule(
+ simpleSchedule()
+ .withIntervalInMilliseconds(10)
+ .withRepeatCount(2)
+ ).startNow().build()
+
+ quartzScheduler.scheduleJob(jobDetail, trigger)
+
+### InvokeMethodJob ###
+
+InvokeMethodJob implements the Quartz [Job][] interface and facilitates calls to groovy's object.invokeMethod( targetMethod, args) or the metaClass.invokeStaticMethod.
+It is configured by setting up the JobDataMap with the following keys
+
+- **targetObject** - the object to call the method on.
+- **targetClass** - set this instead of targetObject if targetMethod is a static
+- **targetMethod** - the method to call on the object, or static method to call on the targetClass
+- **arguments** - list or array of arguments that you want passed to your method.
+
+#### InvokeMethodJob examples
+
+ import static org.quartz.JobBuilder.*
+ import static org.quartz.SimpleScheduleBuilder.*
+ import static org.quartz.TriggerBuilder.*
+ import static org.quartz.DateBuilder.*
+ import grails.plugin.quartz2.InvokeMethodJob
+ ...
+ def jobDataMap = new JobDataMap([targetObject:ctx.hunterService,targetMethod:'takeTheRide',arguments:[true]])
+ JobDetail job2 = newJob(InvokeMethodJob.class).withIdentity("take the ride")
+ .usingJobData(jobDataMap)
+ .build()
+
+ Trigger trigger2 = newTrigger().withIdentity("hunter trigger2")
+ .withSchedule(simpleSchedule().withIntervalInSeconds(4).repeatForever())
+ .startNow()
+ .build()
+
+ quartzScheduler.scheduleJob(job2, trigger2)
+
+### Setting up your own job class ###
+
+the plugin will set's the grailsAppication and appCtx (applicationContext) into "global" property into the schedules context.
+Quartz, by default , uses the PropertySettingJobFactory which will attempt to inject the properties by keyName that exists in the schedule;s context, jobs context or triggers context into the Job when it creates it. So that mean if you setup your own Job and need the appCtx or grailsApplication just declare a field and it will get set.
+
+Example:
+
+ public class HelloJob implements Job {
+
+ def grailsApplication
+
+ /**
+ * Quartz requires a public empty constructor so that the
+ * scheduler can instantiate the class whenever it needs.
+ */
+ public HelloJob() {}
+
+ void execute(JobExecutionContext jobCtx) {
+ def someConfigProp = grailsApplication.config.my.prop.here
+ //or get a service with grailsApplication.mainContext.someService
+ // Say Hello to the World and display the date/time
+ println ("Hello from - ${jobCtx.jobDetail.key.name} - $someConfigProp" )
+ }
+
+ }
+
+
+[documentation and quick start]: http://www.quartz-scheduler.org/documentation/quartz-2.1.x/quick-start
+[Quartz]: http://www.quartz-scheduler.org
+[Job]: http://www.quartz-scheduler.org/api/2.1.0/org/quartz/Job.html
+[JobDetail]: http://www.quartz-scheduler.org/api/2.1.0/org/quartz/JobDetail.html
+[JobExecutionContext]: http://www.quartz-scheduler.org/api/2.1.0/org/quartz/JobExecutionContext.html
+[Scheduler]: http://www.quartz-scheduler.org/api/2.1.0/org/quartz/impl/StdScheduler.html
@@ -0,0 +1,6 @@
+#Grails Metadata file
+#Wed Oct 05 15:46:15 CDT 2011
+app.grails.version=1.3.7
+app.name=quartz2
+plugins.hibernate=1.3.7
+plugins.tomcat=1.3.7
@@ -0,0 +1,26 @@
+grails.project.class.dir = "target/classes"
+grails.project.test.class.dir = "target/test-classes"
+grails.project.test.reports.dir = "target/test-reports"
+//grails.project.war.file = "target/${appName}-${appVersion}.war"
+grails.project.dependency.resolution = {
+ // inherit Grails' default dependencies
+ inherits("global") {
+ // uncomment to disable ehcache
+ // excludes 'ehcache'
+ }
+ log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
+ repositories {
+ grailsPlugins()
+ grailsHome()
+ grailsCentral()
+ mavenCentral()
+ }
+ dependencies {
+ // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
+ compile 'org.quartz-scheduler:quartz:2.1.0'
+ // runtime 'mysql:mysql-connector-java:5.1.13'
+ }
+ plugins {
+ compile ':plugin-config:0.1.5'
+ }
+}
@@ -0,0 +1,25 @@
+// configuration for plugin testing - will not be included in the plugin zip
+
+log4j = {
+ // Example of changing the log pattern for the default console
+ // appender:
+ //
+ root { info() }
+ appenders {
+ console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
+ }
+
+ error 'org.codehaus.groovy.grails.web.servlet', // controllers
+ 'org.codehaus.groovy.grails.web.pages', // GSP
+ 'org.codehaus.groovy.grails.web.sitemesh', // layouts
+ 'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
+ 'org.codehaus.groovy.grails.web.mapping', // URL mapping
+ 'org.codehaus.groovy.grails.commons', // core / classloading
+ 'org.codehaus.groovy.grails.plugins', // plugins
+ 'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
+ 'org.springframework',
+ 'org.hibernate',
+ 'net.sf.ehcache.hibernate'
+
+ warn 'org.mortbay.log'
+}
Oops, something went wrong.

0 comments on commit 102ca7c

Please sign in to comment.