Question

I'm new in Grails and I'm creating my first app and I'm having a little trouble finding where things happen, so, I have an object "cicle" that has many "measurements" and gets created by the measurement controller each time I create a new "measurement" that a different machine, this happens for the same machine, some properties of cicle change, so, I execute a method in cicle called updateCalculations that needs the data of the newly created measurement.

So in the measurementController I´m trying to perform some operations using measurements from cycle but I get a null pointer exception, I guessed cicle wasn't created so I moved the operation to the method afterInsert in Measurement object a place I thougth was better for this method to be invoqued, but I'm getting the same problem there, I even think cicle is created buy measurements some how isn't initialized, I don't know really whats happening, so can you help me?

this is my code:

Measurement.groovy

class Measurement{

String machine
int time1
int time2
int time3
int cicleValue

static belongsTo = [cicle: Cicle]

static constraints = {
    machine blank:false 
    time1 nullable:false 
    time1 min:0 
    time2 nullable:false
    time2 min:0
    time3 nullable:false
    time3 min:0
    cicleValue nullable:false
    cicleValue min:0  
}

def afterInsert(){
    this.cicle.updateCalculations()
}

public void updateCicleValue(){
    double avgTime = (time1 + time2 + time3)/3
    cicleValue = 30 * 24 * 60 * 60 / avgTime
}
}

Cicle.groovy

class Cicle {

String machine
int cicleValue

static hasMany = [measurements:Measurement]

static constraints = {
    machine blank:false 
    cicleValue nullable:false 
}

public void updateCalculations(){

    int sumCicles = 0

    measurements.each{ measurement ->
        sumCicles += measurement.cicleValue
    }

    cicleValue = sumCicles / measurements.size()
    this.save(failOnError: true) 
}
}

MeasurementController.groovy

@Transactional(readOnly = true)
class MeasurementController {

static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]

def create() {
    respond new Measurement(params)
}

@Transactional
def save(Measurement measurementInstance) {
if (measurementInstance == null) {
        notFound()
        return
    }

measurementInstance.updateCicleValue()

    Cicle cicle = Cicle.findByMachine(measurementInstance.machine)

    if(cicle == null){
        cicle = new Cicle(machine: measurementInstance.machine, cicleValue: measurementInstance.cicleValue)
        cicle.save flush: true
    } 

    measurementInstance.cicle = cicle

    measurementInstance.validate()

    if (measurementInstance.hasErrors()) {
        respond measurementInstance.errors, view:'create'
        return
    }

    measurementInstance.save flush:true
    cicle.measurements << measurementInstance
    cicle.save flush: true

    request.withFormat {
        form multipartForm {
            flash.message = message(code: 'default.created.message', args: [message(code: 'measurementInstance.label', default: 'Measurement'), measurementInstance.id])
            redirect measurementInstance
        }
        '*' { respond measurementInstance, [status: CREATED] }
    }
}

protected void notFound() {
    request.withFormat {
        form multipartForm {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'measurementInstance.label', default: 'Measurement'), params.id])
            redirect action: "index", method: "GET"
        }
        '*'{ render status: NOT_FOUND }
    }
}
}

Here is the stack-trace from the console:

|Loading Grails 2.3.7
|Configuring classpath
.
|Environment set to development
.................................
|Packaging Grails application
...........
|Compiling 1 source files
...............................
|Running Grails application
|Server running. Browse to http://localhost:8080/mock-app
....Error 
|
2014-04-24 21:51:34,719 [http-bio-8080-exec-3] ERROR errors.GrailsExceptionResolver  - NullPointerException occurred when processing request: [POST] /mock-app/measurement/save - parameters:
time3: 20
time2: 20
time1: 20
machine: 2-12
create: Crear
Cannot invoke method size() on null object. Stacktrace follows:
Message: Cannot invoke method size() on null object
    Line | Method
->>   23 | updateCalculations in com.rpc.mock.app.Cicle
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     26 | afterInsert        in com.rpc.mock.app.Measurement
|    153 | call . . . . . . . in org.grails.datastore.gorm.support.EventTriggerCaller$MethodCaller
|     96 | call               in org.grails.datastore.gorm.support.EventTriggerCaller
|     47 | onApplicationEvent in org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
|     51 | $tt__save          in com.rpc.mock.app.MeasurementController
|    200 | doFilter . . . . . in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter           in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker . . . .  in java.util.concurrent.ThreadPoolExecutor
|    615 | run                in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run . . . . . . .  in java.lang.Thread

it stops in the afterUpdate method telling measurements its null

Any help would be great

Thanks

Was it helpful?

Solution

This is beacause you forgot to add measurementInstance to the cicle.measurements. Have a try and add it when saving cicle instance here:

 if(cicle == null){
        cicle = new Cicle(machine: measurementInstance.machine, cicleValue: measurementInstance.cicleValue)
        cicle.addToMeasurements(measurementInstance)    //add to collection
        cicle.save flush: true
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top