How to do DataModel versioning

Hello,

We are experiencing an unexpected situation with the DataModel instance of our InstallationNodeContribution object, in the context of a version upgrade, i.e. our InstallationNodeContribution adding additional features to pre-existing configurations.

The flow is as follows:

  1. when our InstallationNodeContribution instance is created, it receives its DataModel instance dm
  2. we’re detecting that dm is behind the most recent schema, and upgrade it accordingly in memory (using dm.set methods)
    • so far so good
  3. later, when the user visits the installation node in the UI, our SwingInstallationNodeView is invoked (to display the installation) and gets its data from our InstallationNodeContribution
    • so far as we can tell, it’s the same instances of InstallationNodeContribution and DataModel as in steps 1 and 2
    • no other InstallationNodeContribution was created
    • yet the data contained in our dm instance at that point in time is no longer what it was after step 2; dm now contains the old data before our upgrade (old version number, old fields and values)

We found this comment on the forum:
Installation DataModel don't restore its values - #13 by jbm. It seems to indicate that DataModel.set may be ignored. Yet, we couldn’t identify any function in the API allowing us to commit, force-save or otherwise handle data conversion.

Where is our error? What is the expected way of versioning the DataModel object bound to an InstallationNodeContribution?

Any help would be most appreciated.

I’m not too sure what you mean by version upgrade - could you explain? I would also like if you show me where you have implemented the dm.set and dm.get? :slight_smile:

Hi,

So in the DataModel object of our installation node, one of the fields is a PROP_VERSION number. This allows us to recognize installation node data that originates from older versions of our URCap, and adapt this data with new/changed fields expected by the newer version of the code.

In the constructor of our installation node (point 1 in my initial description), when we receive the datamodel object (to my knowledge this is the only point in time when a datamodel object is handed out to code that we control), we stash that pointer as a member variable, and we scan its contents to determine whether or not it needs to be upgraded, doing model.get(PROP_VERSION). If the resulting version is < the version expected by this revision of the URCap, we do model.set(…) to adapt the old installation node.

So it looks like this in the code:

	public LinearMotionInstallationNodeContribution(InstallationAPIProvider apiProvider, DataModel model, LinearMotionInstallationNodeView view) {
		this.model = model;
                // [...]
		if (model.get(PROP_VERSION, "").equals("2")) {
			upgradeDataModelToV3();
                        // [...]
	}

	private void upgradeDataModelToV3() {
		String[] lLMAxes = getLMAxesRaw();
		String[] lLMAxesUpgraded = new String[PROP_LM_CONFIG_ATTRIBUTES.length * lLMAxes.length / 7];
		for (int i = 0; i < lLMAxes.length; i += 7) {
			lLMAxesUpgraded[i] = // [...]
		}
		model.set(PROP_LM_CONFIG, lLMAxesUpgraded);
	}

The issue we observe is that later on, when the user visits the installation node in the UI, somehow the datamodel instance no longer has the corrected fields. It’s as if our datamodel had been modified behind the scenes without us being told.

I have just made a simple program using api 1.7.0 to test the scenario you have described. The program looks something like this:


It seems to be changing the value to 3 and works fine with model.set when accessing the installationNode UI later on. I hope I Understood your problem - else let me know.

Thank you, yes that’s exactly our scenario. Somehow in our openView, we’re seeing the old version. We did confirm with traces that we had successfully modified the model instance (in our constructor), and that it was the same object instance in openView (with old, unmodified contents). We’re observing this with the simulators v5.4 and v3.10.

If our intended usage is correct, and the actual behavior we observe is abnormal, please let me know…

We could try and pinpoint repro steps. We did have a v1->v2 transition months ago that seemed to work flawlessly. It’s our v2->v3 transition that is misbehaving. It looks as though the UR platform was unilaterally modifying our datamodel after our installation node’s constructor had been invoked.

Just some clarification. On point 3 on the main/first post - When you say “Later, when the user visits the installation node in the UI…” do you mean later as if the robot has been on all the time; just going back and fort between program tab and installation tab or as in the installation has been saved after the modification and loaded again after the robot has been restarted?

Also it was possible to save the transition from v1 > v2 but not v2 > v3 in this case when you say that the value reversed to the old version - did you mean to v1 or v2?

Hi, regarding your first question,

  • I’m just starting the simulator
    • which loads immediately the default installation config
    • which in my case contains a config of my urcap [at v2]
    • and thus invokes immediately my installation node constructor
    • and therefore triggers my in-memory conversion of that datamodel to v3
    • when I double-check the resulting datamodel post-conversion to v3, it looks fine
  • then I immediately go and visit the installation in the UI
    • which triggers the openView
    • it’s there that somehow, the contents of the datamodel appear to have been reset to the original v2 contents
    • even though the datamodel instance is the same and the installation node instance is the same as encountered at startup (judging from the java pseudo-address given by toString(), and considering also that no other instance of my installation node is created)
  • there is no explicit save involved in the scenario

Regarding your second question, if I mentioned v1->v2, which for us happened months ago, it’s just that I don’t recall encountering this problem back then.

n.b. everything behaves as if, at the moment I click on the installation menu to view my urcap installation, the UR platform was reloading behind the scenes the config file into the same datamodel instance it had given me when it first created my installation node at startup.

One difficulty I have been facing is that I couldn’t figure how to attach jdb to the urcap in simulation. I tried launching the simulator with the jdwp agentlib but I have been unsuccessful. If I knew how to do this I might be able to get a stack trace of who is modifying my datamodel object, assuming it’s happening via one of the set methods.

I tried to load the saved data from the default installation and modify it using the constructor and nothing really happened so I see the problem.

I don’t think that using checks and modification inside a constructor is a good idea. It works fine inside openView() and CloseView() methods. In programNode we use undoredo manager to handle changes to datamodel but that is not available in installation node. I would suggest to use other things to trigger the change.

According to the URCaps Tutorial, section 7.2 on Installation Nodes:

“All modications to the supplied data model from the installation
node constructor are ignored when existing installation is loaded. This means that ideally
the installation node constructor should not set anything in the data model.”

So essentially, if you change the DataModel in the Constructor for CreationContext == LOAD, the changes are discarded after the constructor is done.

4 Likes

Ah… thank you so much for clarifying this!
So it sounds like we’ll simply move our installation’s versioning to openView.