Q:

displaying errors in grails without refreshing the page

I have a page with dynamic list boxes(selecting value from the first list populates the values in the second list box).
The validation errors for the list boxes are working fine, but while displaying the error messages the page is getting refreshed and the selected values are been set to initial status(need to select the values again in the list boxes)
The page is designed to add any number of list boxes using ajax calls, so adding and selecting the values again is going to be a rework.
Could you help me in displaying the validation errors and keeping the selected values as they are(previously I faced a similar situation which was resolved by replacing local variables of preprocess and postprocess with a global variable, this time no luck with that approach)
Any hints/help would be great
static constraints = {
        deviceMapping(
                validator: {val, obj ->
                    Properties dm = (Properties) val;
                    def deviceCheck = [:];
                    if (obj.customErrorMessage == null) {
                        for (def device : dm) {
                            if (device.key == null || "null".equalsIgnoreCase(device.key)) {
                                return ["notSelected"];
                            }
                            deviceCheck.put(device.key, "");
                        }

                        if (deviceCheck.size() != obj.properties["numberOfDevices"]) {
                            return ["multipleDevicesError"];
                        }
                    }
                }
        )
        customErrorMessage (
                validator: {
                    if ("sameDeviceMultipleTimes".equals(it)) {
                        return ['sameDeviceMultipleTimes']
                    }

                }
        )
    }
    public LinkedHashMap<String, Object> preProcess(sessionObject, params, request) {
        Submission submission = (Submission) sessionObject;
        def selectedFileName = sessionObject.fileName;
        logger.debug("submission.deviceMapping :"+submission.deviceMapping)
        try {
            Customer customer = Customer.get(submission.customerId);
            OperatingSystem operatingSystem = OperatingSystem.get(submission.operatingSystemId)
            def ftpClientService = new FtpClientService();
            def files = ftpClientService.listFilesInZip(customer.ftpUser, customer.ftpPassword, customer.ftpHost, customer.ftpToPackageDirectory, selectedFileName, operatingSystem, customer.ftpCustomerTempDirectory);
            def terminalService = new TerminalService();

            OperatingSystem os = OperatingSystem.get(submission.getOperatingSystemId());
            def manufacturers = terminalService.getAllDeviceManufacturersForType(os.getType());
            logger.debug("manufacturers after os type :"+manufacturers)
            logger.debug("files in preprocess :"+files)

            def devicesForFiles = [:]
            files.each { file ->
               def devicesForThisFile = [];
               submission.deviceMapping.each { device ->
                  if (device.value == file.fileName) {
                      String manufacturer = terminalService.getManufacturerFromDevice("${device.key}");
                      def devicesForManufacturer = terminalService.getDevicesForManufacturerAndType(manufacturer, os.getType());

                     devicesForThisFile.push([device:device.key, manufacturer: manufacturer, devicesForManufacturer: devicesForManufacturer]);
                  }
               }
               devicesForFiles.put(file.fileName,devicesForThisFile);
            }
            logger.debug("devicesForFiles :"+devicesForFiles)
            return [command: this, devicesForFiles: devicesForFiles, files: files, manufacturers: manufacturers];
        } catch (Exception e) {
            logger.warn("FTP threw exception");
            logger.error("Exception", e);
            this.errors.reject("mapGameToDeviceCommand.ftp.connectionTimeOut","A temporary FTP error occurred");
            return [command: this];
        }
    }
    public LinkedHashMap<String, Object> postProcess(sessionObject, params, request) {
        Submission submission = (Submission) sessionObject;
        Properties devices = params.devices;
        Properties files = params.files;

        mapping = devices.inject( [:] ) { map, dev ->
          // Get the first part of the version (up to the first dot)
          def v = dev.key.split( /\./ )[ 0 ]
          map << [ (dev.value): files[ v ] ]

        }
        deviceMapping = new Properties();

        params.files.eachWithIndex { file, i ->
            def device = devices["${file.key}"];
            if (deviceMapping.containsKey("${device}")) {
                this.errors.reject("You cannot use the same device more than once");
                return [];
                //customErrorMessage = "sameDeviceMultipleTimes";
            }
            deviceMapping.put("${device}", "${file.value}");
        }

        if (params.devices != null) {
            this.numberOfDevices = params.devices.size(); //Used for the custom validator later on
        } else {
            this.numberOfDevices = 0;
        }
        //logger.debug("device mapping :"+deviceMapping);
        submission.deviceMapping = mapping;

        return [command: this, deviceMapping: mapping, devicesForFiles: devicesForFiles ];
    }
}

A:

The problem is in your gsp page. Be sure that all field are initialised with a value
<g:text value="${objectInstance.fieldname}" ... />

Also the way it is selecting values is through id, so be sure to set it as well:
<g:text value="${objectInstance.fieldname}" id=${device.manufacturer.id} ... />

