cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

ThingWorx Navigate is now Windchill Navigate Learn More

Translate the entire conversation x

InfoTable example in ThingWorx documentation (NativeObject cannot be cast to value collection)

MA8731174
16-Pearl

InfoTable example in ThingWorx documentation (NativeObject cannot be cast to value collection)

Hi everyone,

While experimenting with InfoTables inside a ThingWorx service, I ran into some confusion regarding a documentation example that seems to contradict actual platform behavior. I’d like to get clarification (and maybe spark some discussion) around this.

 

Documentation Example

In the documentation , I found the following pattern:

var referencedInfoTable = Things["thingName"].myInfoTable;
var tableLength = referencedInfoTable.rows.length;

for (let i = 0; i < tableLength; i++) {
  referencedInfoTable.rows[i] = {
    field1: i,
    field2: i * 2,
    field3: i * 3
  };
}

Things["thingName"].myInfoTable = referencedInfoTable;

// Comment from docs:
// "Because you are not using .AddRow() it doesn't require access to the referenced object's .AddRow() method,
// therefore it doesn't need to access the cache."

 

 

The Problem

When this code runs in ThingWorx (especially versions 9+ and 10+), it throws:

 

 
class org.mozilla.javascript.NativeObject cannot be cast to class com.thingworx.types.collections.ValueCollection

 

From what I understand, this happens because each rows[i] is a ThingWorx ValueCollection, and replacing it directly with a plain JavaScript object (NativeObject) breaks the expected Java type when saving back to a Thing property.


Working Version

Here’s the corrected version that works safely in all cases:

var referencedInfoTable = Things["thingName"].myInfoTable.clone();
var tableLength = referencedInfoTable.rows.length;

for (let i = 0; i < tableLength; i++) {
    referencedInfoTable.rows[i].field1 = i;
    referencedInfoTable.rows[i].field2 = i * 2;
    referencedInfoTable.rows[i].field3 = i * 3;
}

Things["thingName"].myInfoTable = referencedInfoTable;

 

This avoids replacing the ValueCollection and simply modifies its internal fields — no casting errors, and it persists correctly.

 

My Question

Why does the documentation show replacing the entire row object instead of updating the existing ValueCollection fields?

Was that example intended:

  • only for in-memory testing (without writing back to a Thing property)?

  • or is there some other underlying purpose (e.g., caching demonstration)?

Would love to hear your insights or any official clarification from PTC on this one.
Thanks in advance for helping me (and probably a lot of others) understand the intended usage pattern here!

 

 

ACCEPTED SOLUTION

Accepted Solutions

Thanks for info @Rocko 

 

I have undetstood now that this behavior happens because there’s an important difference between an InfoTable Thing Property and an InfoTable used as a service parameter or local variable.

When you access an InfoTable that belongs to a Thing, for example:

var myInfo = Things["MyThing"].MyInfoTableProperty;

you’re actually working with a proxy object that is directly linked to the Thing’s property and its defined DataShape.
Because of that, ThingWorx already knows the field names and data types, so you can modify rows directly (e.g., myInfo.rows[i] = {...}) and then assign it back:

Things["MyThing"].MyInfoTableProperty = myInfo;

This works because the proxy handles the validation and synchronization for you.

 

 

However, when you use an InfoTable as a service input or output parameter, even if it uses the same DataShape, it’s not connected to any Thing property. It’s just a local runtime object in memory, not a proxy.


ThingWorx does not automatically apply DataShape validation to direct row assignments in this case, so code like this will fail:

inputTable.rows[i] = { temperature: 25 };

 

The correct way to work with service InfoTables is to use the ThingWorx API methods:

var newTable = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape({
    infoTableName: "InfoTable",
    dataShapeName: "MyDataShape"
});

newTable.AddRow({ temperature: 25, pressure: 12 });
result = newTable;

or, if you just want to edit existing rows:

inputTable.rows.toArray().forEach(function(row) {
    row.temperature = 25;
});

 

In short:

  • Thing property InfoTables = proxy objects tied to a Thing → can be modified directly.

  • Service InfoTables = local copies → must use AddRow() or API methods to update

View solution in original post

3 REPLIES 3
Rocko
19-Tanzanite
(To:MA8731174)

The code block you are quoting is introduced with the following text: "Avoid manipulating Thing properties directly as this can result in persistent synchronization issues and loss of performance." The point is to not access the infotable row props if the infotable is a thing property because each update has to go through the cache. Instead, take an "offline" infotable (i.e not being a thing property) and update that all you want, and then write it back once.

 

What you reference is the third example in that section, labelled as "for your information", with the point being mentioned in the comment, to not access through the methods. That it's not working is probably an oversight and you can report this with the top-right mail button to the doc team.

Thanks for info @Rocko 

 

I have undetstood now that this behavior happens because there’s an important difference between an InfoTable Thing Property and an InfoTable used as a service parameter or local variable.

When you access an InfoTable that belongs to a Thing, for example:

var myInfo = Things["MyThing"].MyInfoTableProperty;

you’re actually working with a proxy object that is directly linked to the Thing’s property and its defined DataShape.
Because of that, ThingWorx already knows the field names and data types, so you can modify rows directly (e.g., myInfo.rows[i] = {...}) and then assign it back:

Things["MyThing"].MyInfoTableProperty = myInfo;

This works because the proxy handles the validation and synchronization for you.

 

 

However, when you use an InfoTable as a service input or output parameter, even if it uses the same DataShape, it’s not connected to any Thing property. It’s just a local runtime object in memory, not a proxy.


ThingWorx does not automatically apply DataShape validation to direct row assignments in this case, so code like this will fail:

inputTable.rows[i] = { temperature: 25 };

 

The correct way to work with service InfoTables is to use the ThingWorx API methods:

var newTable = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape({
    infoTableName: "InfoTable",
    dataShapeName: "MyDataShape"
});

newTable.AddRow({ temperature: 25, pressure: 12 });
result = newTable;

or, if you just want to edit existing rows:

inputTable.rows.toArray().forEach(function(row) {
    row.temperature = 25;
});

 

In short:

  • Thing property InfoTables = proxy objects tied to a Thing → can be modified directly.

  • Service InfoTables = local copies → must use AddRow() or API methods to update

slangley
23-Emerald III
(To:MA8731174)

Hi @MA8731174 

 

It appears that you have found the answer to your question.  For the benefit of other Community Members who may have the same question, it would be helpful if you could designate the appropriate response as the Accepted Solution.

Thanks for using the PTC Community!

Regards,
 

--Sharon

Announcements


Top Tags