Search code examples
grailsgroovygrails-orm

Multiple GORM ValidationException after import from excel file


I work on a bug. I have a excel file that is imported into the application. The file contains information for the core domain object (Zoo, see below). Every row has two cells, string value for the name and int value for the number of animals.

If i have an invalid field inside this excel file, it will show an error msg like "Error on column X on cell Y. Value is "someValue" invalid". Let's assume we have an excel file with 250 rows. If we have an invalid field error on row 200, every row that comes after it will throw the following error

Validation error whilst flushing entity [com.rolotec.ost.Zoo]:
- Field error in object 'com.rolotec.ost.Zoo' on field 'ceo': rejected value [null]

If i look in the DB the object isn't null on ceo field.

Here the domain objects.

class Zoo{   
  String name;
  int animalsInTheZoo;
  CEO ceo;
  hasMany=[ zooEnclosures : ZooEnclosures]
  constraints=[//some constraints]   
}

class CEO{
  Date ceoTillDate;
  Person person;
  constraints=[//some constraints]    
}

class Person{    
  String name;
  int age;
  constraints=[//some constraints]  
}

Here is the service for the import

class ImportService{

importExcel(){

    String errorMsg="";

    Zoo.withTransaction { status->   
        try{

            //some other operations 
            for(int rowNum = excelFile.firstRow; rowNum<=excelFile.lastRow; rowNum++) {  
            try {
                importRow(row);
            } catch (Exception e) {
                //doSomething
            }
           } //end for-loop
            if (errorMsg != "") {
                status.setRollback();
            }     
        } catch(Exception e){
            //doSomething with e
            status.setRollback();               
        }

    }           
}

importRow(Row row){    
    String name = row.getCell(1).stringCellValue;
    Zoo.findAllByName(name).each{    
        try{    
            //reads every cell in Excel data and validates the field
            it.save() //error occures here in the validation    
        } catch(Exception e){
            //doSomething with e
        }
    }
}

If i inspect the object, it will have a value for it.ceo.name but the rest will be null inside it.ceo. Also will be the it.ceo.person = null. In the DB there are all values for the attributes.

EDIT: If there are no invalid fields inside the excel file, there are no ValidationException. Everything will be imported fine.

EDIT 2: Added the for-loop inside the importExcel() method.


Solution

  • The problem was, that inside the Zoo.withTransaction closure was a for-loop which looped through all the rows inside the excel file. For the solution, we moved the .withTransaction inside the for-loop and the problem was gone.

    Code in ImportService looks now like this:

      importExcel(){
    
       String errorMsg="";
       //some operations
       for(int rowNum = excelFile.firstRow; rowNum<=excelFile.lastRow; rowNum++){
          Zoo.withTransaction{status -> 
           //some operations
           try{
            importRow(row)
           } 
          catch(Exception e){
              //do something with exception
              status.setRollbackOnly()
           }
          }
         }
    
       }