State and atomicState DB storage and return values


(www.rboyapps.com - Make your home your butler!) #1

@slagle @jody.albritton

Am facing a very weird situation, in my SmartApp now() is an object of type java.lang.Long
For another user, @Manhmai612, it’s returning a BigDecimal, how it is this possible?

Here the code that works fine for me:

atomicState."lastMotionCheck${camera.id}" = now()
log.trace "Initializing last motion event checked at ${new Date(atomicState."lastMotionCheck${camera.id}").format("EEE MMM dd yyyy HH:mm:ss z", timeZone)}"

But for @Manhmai612 it throws this error:

groovy.lang.GroovyRunTimeException: Could not find matching constructor for: java.util.Date(java.math.BigInteger)


( I hate Mondays) #2

May I recommend using a variable instead of the atomicState? Two reasons. Efficiency and Consistency - looks like the atomicState is messing with your data type.

long time = now()
atomicState."lastMotionCheck${camera.id}" = time
log.trace "Initializing last motion event checked at ${new Date(time).format("EEE MMM dd yyyy HH:mm:ss z", timeZone)}"

Using atomicState will force a db read which means time/resources. You don’t need to read from atomicState, since you just set it. Use a temp variable instead.


(www.rboyapps.com - Make your home your butler!) #3

Doesn’t work, there’s a bug in the state variable (see my other thread) because of which only atomicState works when working in a Parent SmartApp - Child DH relationship.

This variable is accessed from the SA while context of the DH calling the parent SA method, only atomicState works and I need it stored for future access.

I really need an answer from ST on why now() returns BigDecimal for some users and Long for some. It’s really messing things up.


( I hate Mondays) #4

Try with a variable, not a state variable.

state.variable <<< this is a state variable
def variable <<< this is a local variable (memory allocated throughout the execution of the current method)

Using def allows loose type casting.


(Marc) #5

I vaguely remember @tonesto7 running into this issue when I was beta testing the Rachio app. Different servers had different settings. @tonesto7?


(www.rboyapps.com - Make your home your butler!) #6

I don’t you’re getting what I’m saying, I NEED to store the value for future use (with Dates again). Anyways this was never a problem until recently.


( I hate Mondays) #7

Try type casting it to (long)…

atomicState.whatever = (long) now()

But regardless, you should still use a variable, rather than that second atomicState (the read) - you’re wasting time and resources reading a value from the db which you just set and could already have. (unless the code above is only as an example to replicate the issue)


(www.rboyapps.com - Make your home your butler!) #8

Honestly? Why have specifications? If objects can return random values I’m just going to give up on this platform. I have a simple question for ST, what is the return type for now()? Long or BigInteger?

How many places am I going to start putting checks and for what values? What if it returns a Double tomorrow?


(www.rboyapps.com - Make your home your butler!) #9

Was it to do with now()?


(www.rboyapps.com - Make your home your butler!) #10

I have a feeling this is a ST Database issue, see this:

It’s not that now() is returning a BigInteger, when storing it in the database it’s storing it or retrieving it as a BigInteger instead of a long.

@ady624 to your point, if this is a DB bug are you going to typecast every value returned from state and atomicState? It could convert an double to BigDecimal, what then? I don’t think it’s reasonable to start checking the value returned by the ST DB. This is clear bug with the platform and it only seems to be affecting some instance/users.


(Jim Anderson) #11

Just for context/explanation, yes now() does indeed return a long.

When saved to state or atomic state, the values are serialized to a JSON string using groovy’s JsonSlurper. When pulled back out of state, the values are “inflated” back into one of the following types:

"true" or "false" values returned as Boolean
"null" values returned as null
any decimal values returned as BigDouble
any other numeric values returned as BigInteger


(www.rboyapps.com - Make your home your butler!) #12

Hey thanks for that Jim, that was super helpful. So in context of this line, you’re saying that any value that is stored as Long in state/atomicState will be returned as BigInteger.

If so how has my original code been working for the past few months. Date() only takes Long and it’s been working fine (and actually continues to work for 99.9% of the users). Just trying to understand this so that it can handled correctly going forward.


(Jim Anderson) #13

I meant to ask/confirm that it was something you’re seeing recently, sorry about that! When about did you notice a change?


(www.rboyapps.com - Make your home your butler!) #14

I haven’t noticed a change personally. Two users who’re using the Blink app have noticed the changes recently (can’t pin point the date since the apps have been running and when they reinitialized their apps today it threw the error).

But so far only 2 users have reported this issue. So just to be clear, what the app has been doing is:

  1. Save the Long value returned by now() into an atomicState variable
  2. Use that atomicState variable to instantiate a new Date() object

The above has been working fine for everyone until recently, even now it’s working for 99.9% of the users just 2 users have reported that Date() is now throwing an exception about the BigInteger. There could be others but until they hit that code likely on a reinitialization of the app, we won’t know.


(www.rboyapps.com - Make your home your butler!) #15

Jim check this out, I just did a quick test on my setup here. Here’s the code used to test the value:

            log.warn "LONGVALUE: ${atomicState."lastMotionCheck${camera.id}".longValue()}"
            if (atomicState."lastMotionCheck${camera.id}" instanceof Long)
                	log.warn "It's LONG"
            if (atomicState."lastMotionCheck${camera.id}" instanceof BigInteger)
                	log.warn "It's BigInteger"

Here is the output :slight_smile:

54c0864d-498f-4cbc-9aec-fb5b922f50c0 5:46:29 PM: warn It’s LONG
54c0864d-498f-4cbc-9aec-fb5b922f50c0 5:46:29 PM: warn LONGVALUE: 1471988789016

It appears to be returning a Long and not a BigInteger as you had indicated. However the Long does appear to have a longValue() method to it.

So I’m a little confused now. Is it supposed to be Long or BigInteger?

EDIT: I’m also wondering if it’s a shard thing. Maybe some shards are returning Long and possibly after the recent Grails upgrade some shards are returning BigInteger?


(Jim Anderson) #16

Yeah I may be wrong, or looking at newer code than is deployed, or a bit of both :slight_smile:

I tested and see the same thing as you. Will follow up when I know more.


(www.rboyapps.com - Make your home your butler!) #17

Okay and I was just looking at a lot of the code out there using state and atomicState, if it now starts returning BigDecimal and BigInteger it’s going to mess up a lot of the code. There are all kinds of stuff being being stored in state/atomicState including maps. This would require a major rewrite of a lot the code since many API like Date() don’t accept BigInteger/BigDecimal

Coming back to your point, yes please do let us know and if the “newer” code deployed is returning BigInteger instead of Long maybe please revert back to the Long. Either way until this is resolved I can’t provide a reliable solution the users so I’m just going to wait for you. Thanks.


(www.rboyapps.com - Make your home your butler!) #18

Jim, another 2 more just reported the same issue. That’s 4 now and I suspect it’s going to start going up real quick :grimacing:


(Ryan Applegate) #19

You should now see Long values coming back again.


(www.rboyapps.com - Make your home your butler!) #20

Thank you for the update Ryan. I will ask the users to check again.
So for clarification if a Long is stored in state and atomicState then a Long will be returned. Can you please clarify for future reference the expected behavior of state and atomicState when storing and retrieving different types of objects and data types.

Thank you Jim for taking this up.