Use of @Field (Field is variable name)

I saw a reference to this feature tonight in reference to persisting data outside of State and it sounded like an interesting optimization for something I'm working on.

Does anyone know anything about this. Something beginning with an ampersand is not an easy topic to search for.

groovy.transform.Field is an annotation that creates a class private field from the annotated variable.

Here is an example driver from Hubitat that uses it for static data:

1 Like

A couple of things to consider if you plan to use a Field for something other than fixed/static data:

  1. It is possible to create race conditions if multiple methods are running concurrently.
  2. When code is updated, the class is replaced and fields will be reinitialized.

Also see


Thanks for the reply. I'm familiar with the static use case as you have demonstrated. See the link below in the next post that implies a dynamic use of Field.

Actually the inference I picked up on came from one of your posts

Specifically, "This can store data between runs and keep it out of db."

I read that as being able to set the value of a Field dynamically, but thus far I have considered Field to be a static allocation, at least in Hubitat's implementation, so it made me curious and there are some things I'd like to keep out of state if possible.

In that post you say "See notes from me referring to @Field" but I can't discern the context of where to look. Do you recall what it was?

The reference a couple above I think is it.

I have found you can keep some stuff you use regularly in @ Field as a cache

ie if it is empty you fill it in, but otherwise you don't have at runtime to fill in or create over and over again. This does depend on how much the code really runs....for webcore that can run a lot with any pistons, this helps a lot for performance.

Sometimes you don't need to bother with this if you don't run much...

1 Like

Just for people unfamiliar with the impact of this. If you edit you code you can’t just continue running it. You must restart the app again


That sounds like a headache for development.

Because you don't which function is going to be called initialize(), refresh(), parse() etc you have to have some kind of function that checks the state of these FIELD variables and fills them in if they are empty?

Sort of sounds like a volatile state variable.


I make use of this in my drivers for storing a Map that lets me generate the settings based on the device/firmware. I have a hard coded master map in the driver code but then when a device is loaded it compiles a separate map based on the device/firmware combo. Then when the device page is loaded it just loops that map to generate the settings presented. Yes, I do have a function which verifies it is built and if not, it builds it on the fly. I am using a ConcurrentHashMap per the suggestion of a dev after I was having minor issues with a regular map.

I felt like that was better than having to compile the list on the fly from the hard coded map every time the page was loaded.

Seems to work pretty good, at one time I ran it by the Hubitat devs and was told it was a good idea.

The other thing I am doing is storing the config responses from the device in a map, in the device "data". I ran into some race conditions with this where stuff was being read/written so fast it was stepping on itself and missing things. I solved this by storing it primarily in a Field Map now, and then it writes it out to the data value when done so the user can see it if needed.


This might be a good way to think about it.
(If memory serves, similar to the notes above about updating code, I believe the Field will also be reinitialized when the hub restarts.)

1 Like

Yes I think it is, I restarted mine earlier today, and did not open any devices page. This driver I have been working on I have the device set on permanent debug logging. Just opened the device page and this log lines means my settings map was blank and it had to rebuild it from the master list in the code.


1 Like