Your First Extension: Part 3c – The Dark Art of Property Synchronization
This is part of a tutorial series on creating extension components for Design Studio.
Before we actually start making use of the properties that we defined in the last session, we need to take a side trip into theory. We’ll do this in order to spare you hair pulling moments, later on, when you can’t figure out why your properties are “working” sometimes, but not at other times.
Where the Properties Are
The fist thing to keep in mind is that component properties live in two or three places, depending on whether we are running in the designer, or whether the app is running and being accessed via a browser. The three possible places are:
- The Server: During design, this is the copy of the property that is shown in the properties sheet (if it is visible). During runtime, this is the copy that the server maintains and the copy that scripts interact with.
- Canvas/Client: This is the copy that lives in the client browser or design studio canvas and this is the copy that you’ll be working with in your component.js file.
When and how they are synchronized
There are two simple rules for how properties are synchronized:
- If the change is happening on the server (in the properties sheet, or via BIAL script), then it is automatically propagated to all other copies.
That’s it! Now let’s take a look at what this means in practice.
As we’re keeping two or three copies of all of our properties, we need a way to make sure that they are all synchronized. How exactly this is done depends on where the value is changed. In the following examples, let’s presume that all copies of some hypothetical property start with the value “A” and we’ll change it to “B”.
If the change happens on the properties sheet, during design time:
- The designer changes the value to “B” in the properties sheet.
- The changed value is messaged out to both the component in the canvas and the APS. This happens automatically.
These property changes will be saved in the app.
If the change happens on the APS, during design time:
- The designer changes the value to “B” in the APS.
- The server update is not automatic and and firePropertiesChanged() must be called to copy it to the server.
- The property update on the server cascades the change out to the canvas as well.
These property changes will be saved in the app.
If the change happens on the client, during run time:
- The property value to is changed to “B” in the client.
- When firePropertiesChanged() is called, the updated property value is copied to the server.
If the change happens on the server, during run time (it was set via BIAL script):
- The property value to is changed to “A” on the server.
- The changed property value is propagated to the client.
Mistakes and Pitfalls. Things go bad when…
So far, we’ve covered the scenarios that are supposed to work. There are also mistakes and pitfalls to watch out for.
If the change happens on the canvas, during design time:
- The property value to is changed to “B” in the canvas.
- Component.js also has a firePropertiesChanged() implementation, however, it only works at runtime. Attempts to push a property update to the server copy will fail.
These property changes will not be saved in the app.
There is no “initial push” of property values from the server. Only changed values are propagated. This means that if I don’t change a value from the default via the properties pane, no property value will be pushed to the client. So if A is the default value in the properties pane and the designer never changes it, then it will be undefined in the client and APS. The solution to this is to explicitly initialize every property in the APS and component.js. Yes, it is tedious, but it will save you from wondering why the property is undefined in the client some times, but not others.
Forgetting to fire firePropertiesChanged() will also result in different property values being on the server and client.
As always, the completed extension (as of part 3) is available as a Github repository.
Next time, we’ll put this theory into practice and start using our properties to define our gauge.
Very clear explanation as always. Since you mentioned default values and property propagation, I thought I'd add one additional feature/quirk. Perhaps it'll spare some folks some headache, or spark some conversation:
In contribution.xml, let's say you have a property named 'title' of type 'String' and the default value is 'My Title'). I've noticed that via the APS that I cannot set 'title' to blank (literally I mean a string of ""). It will revert it back to the default value of 'My Title'.
While sometimes this is actually beneficial, as reverting to default can be nice, it did make me question my sanity for quite a while until I realized that it was the server trying to do me a favor. (However, sometimes these "favors" work against me, and cause me more work.)
I assume that the server interprets this as unassigned/blank/void and then looks up the default value and reapplies/propagates it back to APS and canvas. As a result, there are some times that I cannot set a default value, because I do indeed want to change a property to blank.
Great post!! Is there will be any solution to the problem Mike specified in future? and a quick question. Consider I change a property in client B, as you specified in third example and triggering a firePropertiesChanged, the property value will be updated to server. it seems you left out what will happen in APS. From my assumption,it won't update the APS right?
Thanks for the article, it clears out our head on how to handle those properties !
Although, I have a question if I may, related to those properties.
We are deploying DS 1.5 with a generic template in order to replace the WADs, and we quickly found out that a configuration file (global and by query name) would be a nice feature. Even one to define a global configuration, like the System.
We started the extension as a Datasource to read a JSON file. Everything went well until we tried to use it in the "OnStartup" event of the application. The configuration file has been specified in a property (in config.xml) without an APS.
Basically, inside the OnStartup, we are unable to get the configuration file name property value. After the event, everything is fine.
We wanted, for exemple, to set the XSYSTEM value to X on startup.
Could you advise ? Are we doomed to fail or is there a possibility to do it ?
Thank you !
The property is in config.xml and there is no APS, so you are configuring it via the properties page. I spoke with Reiner about it and he says that if the variable is stored in the .biapp file, then it should be available at startup. I tested this by creating a simple app with the coloredbox sample. In the application OnStartup() event, I execute to following code:
It works and shows whatever the current color is. How is the variable being filled? If it set at design time, in the properties pane?