When data is not one of the atomic types supported by Ignition (for example a dictionary, or a reference to a class instance), what is the best way to handle sharing data across multiple windows within a project?
We have come at this from a number of angles, all of which work - but some are cumbersome or may have limitations we are not fully aware of.
Ideally it would be nice for every window to be able to access shared data. We have used client tags with serialized data for this purpose before (i.e. JSON encode/decode), but this is not as clean as we would like, and the inability to create tags within the client tag provider in v8 makes this more limited than in previous versions.
We had considered using a dedicated project script as a data store, but saving changes to any script in the project seems to reinitialize data in all scripts - so we are unsure how stable this data is in other client refresh/update scenarios.
Would like to hear how others handle this. Thank you.
In vision, you can attach arbitrary objects to windows and components with Swing’s .putClientProperty() method. Many examples here on the forum.
In the gateway and for certain cases in Vision clients, you can use system.util.getGlobals() to stash arbitrary objects. However, there are some gotchas:
Actual persistence of getGlobals has varied across versions. Badly broken in the middle of v7.9 all the through early v8.1. I created a work-around for those who need it via system.util.persistent. Also on this forum.
Placing anything in any persistent dictionary that isn’t a native jython type or java object risks huge memory leaks. Especially true for python class instances. They must be replaced with updated instances whenever your scripts reload or the entire previous interpreter will get stuck in memory.
Long-running threads that work with persistent objects need to be interruptible/joinable on demand, or they will also leak entire interpreters.
I’ve been playing with a pattern where I only put native objects into persistent dictionaries. For convenience and code flexibility, I then define classes that place all of their state in a dictionary provided to __init__. Any nested functionality is implemented with such classes, where the inner object dictionary is saved in the outer object dictionary (directly or in a list). Nested classes would be “re-instantiated” during their container’s __init__.
In the top level of the relevant script module(s), the outermost instance(s) are re-established in script module variable(s) after the class definitions, using the persistent dictionary(ies).
With this approach the persistent dictionaries (and nested dictionaries or lists of dictionaries) contain no code or other non-native elements. And therefore do not hold up garbage collection of the interpreter that created them.