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

Community Tip - Did you get called away in the middle of writing a post? Don't worry you can find your unfinished post later in the Drafts section of your profile page. X

Extension Package: Detecting ThingStart in a ThingShape (but not using the Event)

jasong
12-Amethyst

Extension Package: Detecting ThingStart in a ThingShape (but not using the Event)

I am developing a ThingShape in Java and I would like to detect ThingStart on the Thing(s) that my ThingShape is implemented by to get some default values set up for the my ThingShape class. The obvious way to do this is to self-subscribe to the ThingStart event, and I suspect that would likely work, but my requirements need to allow for ThingStart to still be be self-subscribed from any of these Things that my ThingShape will reside on.

As of ThingWorx 6.x, you can no longer subscribe to events at multiple levels of the ThingTemplate and ThingShape stack, so once I subscribe to ThingStart, nothing else can do it, no other ThingShapes or Templates can, it's no unavailable. So I am looking for an alternative.

This is easy with Things, as we have access to protected void initializeThing()​ which gets us an ability to initialize some things at what is essentially ThingStart.

But I cannot find a way to detect this event in a ThingShape.

I added a standard constructor, but the constructor seems to be fired at ThingWorx start.

Are they any options here? If not, can there be in future versions? I have a workaround for this immediate need but I felt the question should be asked anyway.

9 REPLIES 9

Hi Jason,

I faced the same problem on normal (Javascript) ThingShape's, ThingTemplates when they added the limitation on 6.5.

What I came out was to add a ThingShape to all the things which it's the only one that subscribes to ThingStart event, and that ThingShape subscription it's the one which does the "constructor" function. The idea it's to call a "Init_"+Shape/Template name on each implemented / inherited, and then you just need to implement that one whenever you want to initialize something on the corresponding ThingShape/ThingTemplate. It's not the most efficient way, but without multiple subscriptions to the same thing/event from the same Thing, this it's the best we can get. It's a shame they limited it, still I don't understand why, and I had though conversations with R&D about it...

Here it's the code of my ThingStart Subscription ( you can do it with a Try/Catch or with a check !=undefined on the Service Name ):

// -- Initialize Implemented Shapes

var implementedShapes = me.GetImplementedShapes();

var nImplementedShapes = implementedShapes.rows.length;

for (var i=0;i<nImplementedShapes;i++) {

  var shape = implementedShapes.rows;

  if (shape.name!=="myThingShapeName") {

      try {

          me["Init_"+shape.name]();

      } catch(err) {

      }

   }

}

// -- Initialize ThingTemplate/Shape Hierarchy Top-Down

var methodsToCall = [];

methodsToCall.push("Init_"+me.name);

var parentName = me.thingTemplate;

methodsToCall.push("Init_"+parentName);

var parent = ThingTemplates[parentName];

while (parentName) {

    parentName = parent.GetBaseThingTemplate();

    if (!parentName) {

        break;

    }

    methodsToCall.push("Init_"+parentName);

    parent = ThingTemplates[parentName];

}

while (methodsToCall.length) {

    try {

        me[methodsToCall.pop()]();

     } catch(err) {

    }

}

jasong
12-Amethyst
(To:CarlesColl)

That's a good solution - unfortunately it won't work for my use case, but I like it and I will keep it in mind. I have some similar things that feel a tad hacky but ultimately work really well.

It's also good to see a fellow CTO working Saturdays and still available to reach out to help others!

Yup I have other tricky solutions ( like having multiple subscription to the same DataChange Event on the same thing, or Delayed DataChange events,... )

Working on Saturdays and or Sundays yes, but just for fun

Carles.

brue
12-Amethyst
(To:jasong)

Jason,

Would the initializeEntity() API help you? Here's its javadoc:

"Initializes the internal state of the entity. This method may be called more than once on the same entity
during initialization.

All metadata, including aspects and configuration tables, are available at this point in the lifecycle.
throws Exception if an error occurs during the initialization process"

jasong
12-Amethyst
(To:brue)

I am unsure how I would access that API - ThingShapes are created as POJOs so I have nothing to override.

I think I saw in the manual that you could potentially create ThingShapes as extending Thing. IN that case you could @Override initializeEntity. So I tried that and I never hit that code.

But since I am fairly new to this, maybe I am missing something.

brue
12-Amethyst
(To:jasong)

Hey Jason,

I found some time to play with your use case a little bit.  I don't recall which version of ThingWorx you're on, but if you are using the Extension SDK 6.6 you can add "extends ThingShape" (not Thing ) to your POJO Shape. Doing this gets you to the initializeEntity API I mentioned. I was also able to get my extension ThingShape(now extending ThingShape) hitting breakpoints inside initializeEntity() so I know that it's possible. Whether it's going to work with what you're trying to achieve, I'm not sure, but this sounds like a possible avenue.

PS. By the time my breakpoint was hit inside my ThingShape.initializeEntity(), my ThingShape instance was a full blown initialized entity.

jasong
12-Amethyst
(To:brue)

Great, I will try this again. I am on 6.6.

I didn't hit the breakpoint but it's safe to say I tested this too quickly right before a meeting and could have easily made a mistake and didn't look too hard since I didn't even know if it was possible. Will try again, thanks for the help.

ufraz
7-Bedrock
(To:jasong)

Hie Jason,

Did you find a solution for this. I am also fairly new to all this but wanted to do something similar.

I need one subscription to setDefaults of a top level AssetModel shape and then also setDefaults of a DeviceModel template that inherits from this AssetModel. both are setting totally different defaults but equally important at two independent levels.

will be interesting to see how you solved it.

jasong
12-Amethyst
(To:ufraz)

I never really solved this. The workaround was to have a subscription on the Thing to AnyDataChange, and then I fire my own identical event called DeviceAnyDataChange from that subscription. That preserves an Event for others to use, but it's not a good solution.

Announcements


Top Tags