Index: branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureDetailedController.groovy	(revision 773)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureDetailedController.groovy	(revision 774)
@@ -6,4 +6,5 @@
     def filterService
     def authService
+    def taskProcedureService
 
     def index = { redirect(action:list,params:params) }
@@ -99,56 +100,22 @@
 
     def update = {
-        def taskProcedureInstance = TaskProcedure.get( params.id )
-        if(taskProcedureInstance) {
-            if(params.version) {
-                def version = params.version.toLong()
-                if(taskProcedureInstance.version > version) {
+        def result = taskProcedureService.update(params)
 
-                    taskProcedureInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
-                    render(view:'edit',model:[taskProcedureInstance:taskProcedureInstance])
-                    return
-                }
-            }
-            taskProcedureInstance.properties = params
-            taskProcedureInstance.lastUpdatedBy = authService.currentUser
-            taskProcedureInstance.lastUpdated = new Date() // Required to trigger version increment.
+        if(!result.error) {
+            flash.message = g.message(code: "default.update.success", args: ["TaskProcedure", params.id])
+            redirect(controller:'taskDetailed',
+                            action:'show',
+                            id:result.taskProcedureInstance.linkedTask.id,
+                            params:[showTab:"showProcedureTab"])
+            return
+        }
 
-            // Gaps in the html index's can be created by adding 2 items and removing the first one.
-            // This creates a gap at the missing index where LazyList will return a null.
-            def nullMaintenanceActions = taskProcedureInstance.maintenanceActions.findAll {!it}
-            if (nullMaintenanceActions) {
-                taskProcedureInstance.maintenanceActions.removeAll(nullMaintenanceActions)
-            }
+        if(result.error.code == "default.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(action:list)
+            return
+        }
 
-            // Save for restoration if validation fails.
-            def savedMaintenanceActions = new ArrayList(taskProcedureInstance.maintenanceActions)
-
-            // Remove toBeDeleted before validation.
-            def toBeDeleted = taskProcedureInstance.maintenanceActions.findAll {it.toBeDeleted}
-            if (toBeDeleted) {
-                taskProcedureInstance.maintenanceActions.removeAll(toBeDeleted)
-            }
-
-            if(!taskProcedureInstance.hasErrors() && taskProcedureInstance.save(flush: true)) {
-                flash.message = "TaskProcedure ${params.id} updated"
-                redirect(controller:'taskDetailed',
-                                action:'show',
-                                id:taskProcedureInstance.linkedTask.id,
-                                params:[showTab:"showProcedureTab"])
-            }
-            else {
-                // Restore the saved items, some of which contain toBeDeleted flags but
-                // have not been deleted yet since validation failed.
-                // The toBeDeleted items are hidden in the view.
-                taskProcedureInstance.maintenanceActions = savedMaintenanceActions
-                // Populate maintenanceAction errors for display.
-                taskProcedureInstance.maintenanceActions.each { it.validate() }
-                render(view:'edit',model:[taskProcedureInstance:taskProcedureInstance])
-            }
-        }
-        else {
-            flash.message = "TaskProcedure not found with id ${params.id}"
-            redirect(action:list)
-        }
+        render(view:'edit', model:[taskProcedureInstance: result.taskProcedureInstance])
     }
 
Index: branches/features/taskProcedureRework/grails-app/services/TaskProcedureService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/TaskProcedureService.groovy	(revision 774)
+++ branches/features/taskProcedureRework/grails-app/services/TaskProcedureService.groovy	(revision 774)
@@ -0,0 +1,77 @@
+/**
+* Provides a service class for the TaskProcedure domain class.
+*/
+class TaskProcedureService {
+
+    boolean transactional = false
+
+    def authService
+
+    /**
+    * Updates an existing taskProcedure.
+    * @param params The params to update for taskProcedure with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskProcedureInstance (if available).
+    */
+    def update(params) {
+        TaskProcedure.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskProcedureInstance && m.field)
+                    result.taskProcedureInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["TaskProcedure", params.id] ]
+                return result
+            }
+
+            result.taskProcedureInstance = TaskProcedure.get(params.id)
+
+            if(!result.taskProcedureInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskProcedureInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            result.taskProcedureInstance.properties = params
+            result.taskProcedureInstance.lastUpdatedBy = authService.currentUser
+            result.taskProcedureInstance.lastUpdated = new Date() // Required to trigger version increment.
+
+            // Gaps in the html index's can be created by adding 2 items and removing the first one.
+            // This creates a gap at the missing index where LazyList will return a null.
+            def nullMaintenanceActions = result.taskProcedureInstance.maintenanceActions.findAll {!it}
+            if (nullMaintenanceActions) {
+                result.taskProcedureInstance.maintenanceActions.removeAll(nullMaintenanceActions)
+            }
+
+            // Save for restoration if validation fails.
+            def savedMaintenanceActions = new ArrayList(result.taskProcedureInstance.maintenanceActions)
+
+            // Remove toBeDeleted before validation.
+            def toBeDeleted = result.taskProcedureInstance.maintenanceActions.findAll {it.toBeDeleted}
+            if (toBeDeleted) {
+                result.taskProcedureInstance.maintenanceActions.removeAll(toBeDeleted)
+            }
+
+            if(result.taskProcedureInstance.hasErrors() || !result.taskProcedureInstance.save()) {
+                // Restore the saved items, some of which contain toBeDeleted flags but
+                // have not been deleted yet since validation failed.
+                // The toBeDeleted items are hidden in the view.
+                result.taskProcedureInstance.maintenanceActions = savedMaintenanceActions
+                // Populate maintenanceAction errors for display.
+                result.taskProcedureInstance.maintenanceActions.each { it.validate() }
+                // Fetch to prevent lazy initialization error.
+                result.taskProcedureInstance.linkedTask.primaryAsset
+                result.taskProcedureInstance.createdBy
+                return fail(code:"default.update.failure")
+            }
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end update()
+
+} // end class
