Permalink
Browse files

Initial version with domain and service

  • Loading branch information...
Michael J Salera
Michael J Salera committed Dec 3, 2012
0 parents commit 49ba22f262bba45c539a437304b2ac906813dfe1
@@ -0,0 +1,14 @@
+<classpath>
+ <classpathentry kind="src" path="src/java"/>
+ <classpathentry kind="src" path="src/groovy"/>
+ <classpathentry kind="src" path="grails-app/conf"/>
+ <classpathentry kind="src" path="grails-app/controllers"/>
+ <classpathentry kind="src" path="grails-app/domain"/>
+ <classpathentry kind="src" path="grails-app/services"/>
+ <classpathentry kind="src" path="grails-app/taglib"/>
+ <classpathentry kind="src" path="test/integration"/>
+ <classpathentry kind="src" path="test/unit"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="com.springsource.sts.grails.core.CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="web-app/WEB-INF/classes"/>
+</classpath>
@@ -0,0 +1,45 @@
+# Mac OS X Finder and whatnot
+.DS_Store
+
+
+# Sparkle distribution Private Key (Don't check me in!)
+dsa_priv.pem
+
+
+# XCode (and ancestors) per-user config (very noisy, and not relevant)
+*.mode1
+*.mode1v3
+*.mode2v3
+*.perspective
+*.perspectivev3
+*.pbxuser
+
+
+# Generated files
+VersionX-revision.h
+
+
+# build products
+build/
+target/
+*.[oa]
+
+
+# Other source repository archive directories (protects when importing)
+.hg
+.svn
+CVS
+
+
+# automatic backup files
+*~.nib
+*.swp
+*~
+*.groovy~
+*(Autosaved).rtfd/
+Backup[ ]of[ ]*.pages/
+Backup[ ]of[ ]*.key/
+Backup[ ]of[ ]*.numbers/
+web-app/WEB-INF/tld/c.tld
+web-app/WEB-INF/tld/fmt.tld
+stacktrace.log
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bates</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.springsource.sts.grails.core.nature</nature>
+ <nature>org.eclipse.jdt.groovy.core.groovyNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
@@ -0,0 +1,3 @@
+#Created by grails
+eclipse.preferences.version=1
+groovy.dont.generate.class.files=true
@@ -0,0 +1,89 @@
+class BatesGrailsPlugin {
+ // the plugin version
+ def version = "0.8"
+
+ // the version or versions of Grails the plugin is designed for
+ def grailsVersion = "2.1 > *"
+
+ // the other plugins this plugin depends on
+ def dependsOn = [mongodbMorphia: "0.8.2"]
+// executor: "0.3"]
+
+ // resources that are excluded from plugin packaging
+ def pluginExcludes = [
+ "grails-app/views/error.gsp"
+ ]
+
+ // TODO Fill in these fields
+ def title = "Business Audit Trail Events System (BATES) Plugin" // Headline display name of the plugin
+ def author = "Michael Salera"
+ def authorEmail = "mikesalera@mac.com"
+ def description = '''\
+Business Audit Trail Events System (BATES) is designed to take the load off the primary relational database (GORM dataSource) and allow fine-grained log events,
+that is, changes to the records or documents themselves, and create these logs in MongoDB. It is intended to be used across the enterprise, esp. if your
+Mongo cluster is setup supporting sharding by Department or Application area/domain.
+
+Primary reason for writing Bates was not only to use the MongoDB backend, but also to provide similar features to Shawn Hartsock's excellent audit-logging plug-in,
+which was not upgraded to work with Grails 2.0 or above. Though this may be done in a future release....
+
+Bates's job is to make audit trail simple, unobtrusive, yet powerful enough to be able to reconstruct should things go awry or front-end developers would like to
+build an Admin style front end to view and filter thru all log documents, for example.
+
+(c) 2012 Mike Salera / FRC
+'''
+
+ // URL to the plugin's documentation
+ def documentation = "http://grails.org/plugin/bates"
+
+ // Extra (optional) plugin metadata
+
+ // License: one of 'APACHE', 'GPL2', 'GPL3'
+ def license = "APACHE"
+
+ // Details of company behind the plugin (if there is one)
+ def organization = [ name: "Free Range Consultants", url: "http://www.freerangeconsultants.com/" ]
+
+ // Any additional developers beyond the author specified above.
+// def developers = [ [ name: "Johanan Lancaon", email: "javageek@gmail.com" ]]
+
+ // Location of the plugin's issue tracker.
+// def issueManagement = [ system: "JIRA", url: "http://jira.grails.org/browse/GPMYPLUGIN" ]
+
+ // Online location of the plugin's browseable source code.
+// def scm = [ url: "http://svn.codehaus.org/grails-plugins/" ]
+
+
+//METHODS
+ def doWithWebDescriptor = { xml ->
+ // TODO Implement additions to web.xml (optional), this event occurs before
+ }
+
+ def doWithSpring = {
+ businessAuditLogService(com.freerangeconsultants.plugins.bates.core.BusinessAuditLogService)
+ }
+
+ def doWithDynamicMethods = { ctx ->
+ // TODO Implement registering dynamic methods to classes (optional)
+ }
+
+ def doWithApplicationContext = { applicationContext ->
+ application.mainContext.eventTriggeringInterceptor.datastores.each { k, datastore ->
+ applicationContext.addApplicationListener(new com.freerangeconsultants.plugins.bates.listeners.BusinessAuditLogListener(datastore))
+ }
+ }
+
+ 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'.
+ }
+
+ def onShutdown = { event ->
+ // TODO Implement code that is executed when the application shuts down (optional)
+ }
+}
@@ -0,0 +1,5 @@
+#Grails Metadata file
+#Sun Dec 02 18:43:39 PST 2012
+app.grails.version=2.1.1
+app.name=bates
+plugins.mongodb-morphia=0.8.2
@@ -0,0 +1,38 @@
+grails.project.class.dir = "target/classes"
+grails.project.test.class.dir = "target/test-classes"
+grails.project.test.reports.dir = "target/test-reports"
+
+grails.project.dependency.resolution = {
+ // inherit Grails' default dependencies
+ inherits("global") {
+ // uncomment to disable ehcache
+ // excludes 'ehcache'
+ }
+
+ log "info" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
+
+ repositories {
+ grailsCentral()
+ // uncomment the below to enable remote dependency resolution
+ // from public Maven repositories
+ //mavenLocal()
+ //mavenCentral()
+ //mavenRepo "http://snapshots.repository.codehaus.org"
+ //mavenRepo "http://repository.codehaus.org"
+ //mavenRepo "http://download.java.net/maven/2/"
+ //mavenRepo "http://repository.jboss.com/maven2/"
+ }
+
+ dependencies {
+ // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
+ build "org.codehaus.gpars:gpars:1.0-beta-3"
+ }
+
+ plugins {
+ build(":tomcat:$grailsVersion",
+ ":release:2.0.3",
+ ":rest-client-builder:1.0.2") {
+ export = false
+ }
+ }
+}
@@ -0,0 +1,24 @@
+// configuration for plugin testing - will not be included in the plugin zip
+
+log4j = {
+ // Example of changing the log pattern for the default console
+ // appender:
+ //
+ //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'
+}
@@ -0,0 +1,49 @@
+dataSource {
+ pooled = true
+ driverClassName = "org.h2.Driver"
+ username = "sa"
+ password = ""
+}
+hibernate {
+ cache.use_second_level_cache = true
+ cache.use_query_cache = false
+ cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
+}
+// environment specific settings
+environments {
+ development {
+ dataSource {
+ dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
+ url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
+ }
+ }
+ test {
+ dataSource {
+ dbCreate = "update"
+ url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
+ }
+ }
+ production {
+ dataSource {
+ dbCreate = "update"
+ url = "jdbc:h2:prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
+ pooled = true
+ properties {
+ maxActive = -1
+ minEvictableIdleTimeMillis=1800000
+ timeBetweenEvictionRunsMillis=1800000
+ numTestsPerEvictionRun=3
+ testOnBorrow=true
+ testWhileIdle=true
+ testOnReturn=true
+ validationQuery="SELECT 1"
+ }
+ }
+ }
+}
+
+mongodb {
+ host = 'localhost'
+ port = 27017
+ databaseName = 'auditDb'
+}
@@ -0,0 +1,13 @@
+class UrlMappings {
+
+ static mappings = {
+ "/$controller/$action?/$id?"{
+ constraints {
+ // apply constraints here
+ }
+ }
+
+ "/"(view:"/index")
+ "500"(view:'/error')
+ }
+}
@@ -0,0 +1,40 @@
+package com.freerangeconsultants.plugins.bates.domain
+
+import groovy.transform.ToString
+
+/**
+ * Audit Log Event
+ * One of these documents is stored in MongoDB shard for each record-level change detected
+ * these can be from PostInsert, PostUpdate, or PostDelete Grails system events.
+ *
+ * Developed custom for the B.A.T.E.S. business audit trail plugin for Grails 2.1.x or above
+ * @version 1.0
+ * @author Mike Salera
+ */
+
+@ToString
+class AuditLogEvent implements Serializable, Comparable {
+
+ String eventName
+ String className
+ String persistedObjectId
+ Map<String, String> oldState
+ Map<String, String> newState
+ Date dateCreated = new Date()
+
+
+ //METHODS
+ def getDiffMap() {
+ def ignoreList = ['version', 'lastUpdated']
+ StringBuilder sb = new StringBuilder();
+ if (newState && oldState) {
+ newState.each { key, value ->
+ if (value && value != oldState[key] && !(key in ignoreList))
+ sb.append("${key} = ${value}, was, ${key} = ${oldState[key]} ")
+ }
+ }
+ sb.toString()
+ }
+
+ int compareTo(java.lang.Object anObject) { return id.compareTo(anObject.id) }
+}
Oops, something went wrong.

0 comments on commit 49ba22f

Please sign in to comment.