1

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!

Benjamin Kovach
  • 3,190
  • 1
  • 24
  • 38
  • 1
    Re: Edit 2 try `executeUpdate(query, [new Date()])`, with the arguments in a list. But rather than `executeUpdate`, is there reason not to just update the domain object and save? – ataylor Oct 06 '11 at 17:36
  • Thank you! I actually implemented this change right before you mentioned it but it did fix everything. There's no real reason why I'm choosing to use executeUpdate other than the fact that I'm used to using it. Would update -> save complete faster? – Benjamin Kovach Oct 06 '11 at 19:01

3 Answers3

2

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
}
ataylor
  • 64,891
  • 24
  • 161
  • 189
1

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?

tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • I have a Call domain object, yes, but it's getting cluttered with other stuff and was just wondering if there was a way I could do it without storing it in the object itself. Only storing the elapsed time would be preferable. :) – Benjamin Kovach Oct 06 '11 at 14:41
1

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.

GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67
  • So it sounds like I just need to create a startTime variable for the Call object... I'm fairly new to software development, but I guess it's not that weird to have a ton of variables in an object. I can just do that. Thank you! – Benjamin Kovach Oct 06 '11 at 14:47