Benjamin Kovach
Benjamin Kovach

Reputation: 3260

Checking elapsed time in Groovy/Grails

I'm trying to get the duration of a web-based phone call by passing a new Date value to an application at the connection time and exit time of each call.

The code looks a little bit like this:

class Call {
    Date startTime = new Date()
    Date endTime = new Date()
    String callLength = ""
    String Id = UUID.randomUUID()
}
class callController {

    def connected = {
         callInstance = Call.findById(params.Id)

         //Id params are passed through from external voice call 
         Call.executeUpdate("update Call a set a.startTime=? where a.Id='${params.id}'", [new Date()])
    }
    def callEnded = {
        callInstance = Call.findById(params.Id)
        Call.executeUpdate("update Call a set a.endTime=? where a.Id='${params.id}'", [new Date()])
        timeHandler(callInstance.endTime, callInstance.startTime)
    }
    def timeHandler = {end, start->
        TimeDuration duration = TimeCategory.minus(end, start)
        Call.executeUpdate("update Call a set a.callLength='$duration' where a.Id = '${params.id}'")
    }
}

Edit: Code edited slightly to produce a better output.

Edit 2:

I created variables on the Call object for startTime and endTime. But, now I'm having trouble updating the dates-- Grails doesn't like to update dates, I guess? It says it's having trouble passing a new Date to a Date variable. This is the exact error:

java.lang.ClassCastException: [Ljava.util.Date; cannot be cast to java.util.Date

and the Stacktrace points to the line where I try to update the call. Is there a workaround for this?

Thanks again!

Edit 3:

Fixed with correct code.

Thank everyone for your help!

Upvotes: 1

Views: 3584

Answers (3)

GreyBeardedGeek
GreyBeardedGeek

Reputation: 30088

The problem is that controllers are meant to be stateless - so, while I'm not sure that it actually does this, Grails is free to either construct a new controller for each request, or to re-initialize a controller before handling a new request.

If you can guarantee that there will only ever be one client of this controller, you could make startTime a static variable.

Otherwise, you'll have to find some way to hold state between the calls to connected() and callEnded(). In a "normal", user-facing application, this would be done by storing the startTime in the user's session.

Upvotes: 1

tim_yates
tim_yates

Reputation: 171154

So you don't have a Call domain object to store the start and end times of each call?

Controllers are stateless, so you're going to need something like that to store the state of a call.

Or if you don't want to store state, why not just do it all in Javascript?

Upvotes: 1

ataylor
ataylor

Reputation: 66099

You can put the value in the session and it will persist between requests. For example:

def connected = {
    session.startTime = new Date().getTime()
}
def callEnded = {
    def endTime = new Date().getTime()
    timeHandler(endTime, session.startTime)
}
def timeHandler = {end, start->
    return end - start
}

Upvotes: 2

Related Questions