Index: /trunk/grails-app/controllers/AppCoreController.groovy
===================================================================
--- /trunk/grails-app/controllers/AppCoreController.groovy	(revision 257)
+++ /trunk/grails-app/controllers/AppCoreController.groovy	(revision 258)
@@ -7,6 +7,7 @@
 
     def personService
+    def appConfigService
     def createDataService
-    def appConfigService
+    def createBulkDataService
 
     def index = { redirect(action:start,params:params) }
@@ -176,3 +177,19 @@
     }
 
+    /**
+    * Allow admin to create bulk test data.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def createBulkTestData = {
+        if(!createBulkDataService.create()) {
+            flash.message = "Bulk test data could not be created."
+            redirect(action: appAdmin)
+            return
+        }
+
+        // Success.
+        flash.message = "Bulk test data created."
+        redirect(action: appAdmin)
+    }
+
 } // end of class.
Index: /trunk/grails-app/services/CreateBulkDataService.groovy
===================================================================
--- /trunk/grails-app/services/CreateBulkDataService.groovy	(revision 258)
+++ /trunk/grails-app/services/CreateBulkDataService.groovy	(revision 258)
@@ -0,0 +1,235 @@
+import grails.util.GrailsUtil
+
+/**
+* Provides a data service to create a large volume of test data for load testing.
+*/
+class  CreateBulkDataService {
+
+    boolean transactional = false
+
+    def personService
+    def taskService
+    def dateUtilService
+    def appConfigService
+    def assignedGroupService
+    def assignedPersonService
+
+    def sessionFactory
+    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
+
+    def startTime = System.currentTimeMillis()
+    def lastBatchStarted = startTime
+
+/*******************************************
+Start of Group methods.
+Generally use these methods to create data.
+*******************************************/
+
+    /**
+    * Make a run of data creation.
+    */
+    def create() {
+        if(!GrailsUtil.environment == "development") {
+            log.error "Dev environment not detected, will NOT create bulk data."
+            return false
+        }
+
+        log.info "Creating BULK data..."
+
+        // Person and Utils
+        log.info "Creating persons..."
+        createBulkTestPersons()
+
+//         createBulkTestSites()
+//         createBulkTestDepartments()
+//         createBulkTestSuppliers()
+//         createBulkTestManufacturers()
+
+        // Tasks
+        log.info "Creating tasks..."
+        createBulkTestTasks()
+
+//         createBulkTestEntries()
+//         createBulkTestAssignedGroups()
+//         createBulkTestAssignedPersons()
+//         createBulkTestTaskRecurringSchedules()
+
+        // Inventory
+//         createBulkTestInventoryStores()  /// @todo: Perhaps a 'createQuickStartData' method?
+//         createBulkTestInventoryLocations()
+//         createBulkTestInventoryGroups() /// @todo: Perhaps a 'createQuickStartData' method?
+//         createBulkTestInventoryItems()
+
+        // Assets
+//         createBulkTestLifePlan()
+//         createBulkTestTaskProcedure()
+//         createBulkTestMaintenanceActions()
+//         createBulkTestSystemSections()
+//         createBulkTestAssetTypes()
+//         createBulkTestAssemblies()
+//         createBulkTestSubAssemblies()
+//         createBulkTestComponentItems()
+//         createBulkTestAssets()
+//         createBulkTestAssetExtenedAttributes()
+
+        log.info "Creating BULK data...complete."
+        return true
+
+    }
+
+/******************
+Start of Person
+*******************/
+
+    def createBulkTestPersons() {
+        //Person
+        def passClearText = "pass"
+        def passwordEncoded = personService.encodePassword(passClearText)
+        def personInstance
+
+        def range = 1..1000
+
+        def loginName = "BtLoginName"
+        String btLoginName
+        def firstName = "BtFirstName"
+        String btFirstName
+        def lastName = "BtLastName"
+
+        def authority2 = Authority.get(2)
+        def authority3 = Authority.get(3)
+        def personGroup1 = PersonGroup.get(1)
+        def personGroup2 = PersonGroup.get(2)
+        def personGroup3 = PersonGroup.get(3)
+        def personGroup4 = PersonGroup.get(4)
+        def personGroup5 = PersonGroup.get(5)
+
+        range.each() {
+
+            btLoginName = loginName + it
+            btFirstName = firstName + it
+
+            personInstance = new Person(loginName: btLoginName,
+                                        firstName: btFirstName,
+                                        lastName: lastName,
+                                        pass: passClearText,
+                                        password: passwordEncoded,
+                                        email: "bulkTest@example.com")
+            saveAndTest(personInstance)
+            personInstance.addToAuthorities(authority2)
+            personInstance.addToAuthorities(authority3)
+            personInstance.addToPersonGroups(personGroup1)
+            personInstance.addToPersonGroups(personGroup2)
+            personInstance.addToPersonGroups(personGroup3)
+            personInstance.addToPersonGroups(personGroup4)
+            personInstance.addToPersonGroups(personGroup5)
+
+        }
+
+    } // createBulkTestPersons()
+
+/*********************
+START OF TASK
+*********************/
+
+    def createBulkTestTasks() {
+
+        def taskResult
+        def p = [:]
+
+        def range = 0..40000
+
+
+        def taskGroup1 = TaskGroup.get(1)
+        def taskPriority2 = TaskPriority.get(2)
+        def taskType1 = TaskType.get(1)
+        def leadPerson2 = Person.get(2)
+
+        def description = "Bulk test data "
+        String btDescription
+        def comment1 = "Has been noted as problematic, try recalibrating."
+        def today = dateUtilService.today
+
+        range.each() {
+
+            if(it % 1000 == 0) {
+                logStatus("Creating task #" + it)
+                cleanUpGorm()
+            }
+
+            btDescription = description + it
+
+            //Task #1
+            p = [taskGroup: taskGroup1,
+                    taskPriority: taskPriority2,
+                    taskType: taskType1,
+                    leadPerson: leadPerson2,
+                    description: btDescription,
+                    comment: comment1,
+                    targetStartDate: today]
+
+            taskResult = taskService.create(p)
+        }
+
+    }
+
+    def createBulkTestEntries() {
+
+        def entryResult
+        def p = [:]
+
+        def range = 1..10
+        def task1 = Task.get(1)
+        def entryType1 = EntryType.get(1)
+        def comment1 = "This is a bulk test entry."
+        def durationMinute1 = 20
+
+        range.each() {
+
+            p = [task: task1,
+                    entryType: entryType1,
+                    comment: comment1,
+                    durationMinute: durationMinute1]
+
+            entryResult = taskService.createEntry(p)
+
+        }
+
+    } // createBulkTestEntries()
+
+    /**
+    * This cleans up the hibernate session and a grails map.
+    * For more info see: http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/
+    * The hibernate session flush is normal for hibernate.
+    * The map is apparently used by grails for domain object validation errors.
+    * A starting point for clean up is every 100 objects.
+    */
+    def cleanUpGorm() {
+        def session = sessionFactory.currentSession
+        session.flush()
+        session.clear()
+        propertyInstanceMap.get().clear()
+    }
+
+    def logStatus(String message) {
+        def batchEnded = System.currentTimeMillis()
+        def seconds = (batchEnded-lastBatchStarted)/1000
+        def total = (batchEnded-startTime)/1000
+        log.info "${message}, last: ${seconds}s, total: ${total}s"
+        lastBatchStarted = batchEnded
+    }
+
+
+/****************************************
+Call this function instead of .save()
+*****************************************/
+    private boolean saveAndTest(object) {
+        if(!object.save()) {
+//             BulkTestDataSuccessful = false
+            log.error "'${object}' failed to save!"
+            log.error object.errors
+            return false
+        }
+        return true
+    }
+
+} // end class.
Index: /trunk/grails-app/services/CreateDataService.groovy
===================================================================
--- /trunk/grails-app/services/CreateDataService.groovy	(revision 257)
+++ /trunk/grails-app/services/CreateDataService.groovy	(revision 258)
@@ -454,12 +454,15 @@
         def taskGroupInstance
 
+        //TaskGroup #1
         taskGroupInstance = new TaskGroup(name:"Engineering Activites",
                                                                             description:"Engineering daily activities")
         saveAndTest(taskGroupInstance)
 
+        //TaskGroup #2
         taskGroupInstance = new TaskGroup(name:"Production Activites",
                                                                             description:"Production daily activities")
         saveAndTest(taskGroupInstance)
 
+        //TaskGroup #3
         taskGroupInstance = new TaskGroup(name:"New Projects",
                                                                             description:" ")
Index: /trunk/grails-app/views/appCore/appAdmin.gsp
===================================================================
--- /trunk/grails-app/views/appCore/appAdmin.gsp	(revision 257)
+++ /trunk/grails-app/views/appCore/appAdmin.gsp	(revision 258)
@@ -54,4 +54,15 @@
                         </tr>
 
+                        <g:if env="development">
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Test:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:link action="createBulkTestData">Bulk</g:link> - Create a large volume of test data.
+                                </td>
+                            </tr>
+                        </g:if>
+
                     </tbody>
                 </table>
