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

Modify service code programmatically

SOLVED
ckulak
Newbie

Modify service code programmatically

Hello,

Is there some simple solution for modifying the service implementation programmatically? I could create an empty service using AddServiceDefinition, but now I'm stuck with filling it.

I tried to do something like Export to XML > Modify XML > Import from XML, and the first two steps work fine, but for some reason I couldn't import the XML. Apparently the Importer servlet works differently from the regular TWX REST interfaces, and I can't figure out how to use it.

Is there any better way to do it, or maybe some example? Thanks!

Regards,

Constantine

Tags (1)
1 ACCEPTED SOLUTION

Accepted Solutions

Re: Modify service code programmatically

Hi Constantine,

Let me give an example of dynamic code execution that can be used in the platform.

For this to work you need to have a wrapper service, called let's say "Execute Service". You can run inside a single line, a javascript function called eval(string) which takes a string input parameter.

So you have 2 choices: you either store the command itself in a property so whenever you want to modify the implementation you set the property to a new value (can be an through an editor inside a mashup) or you can simply have the service accepting the command as a parameter.

Can this be applied in your use case?

View solution in original post

21 REPLIES 21

Re: Modify service code programmatically

AddServiceDefinition is there to create a definition so that i can be bound as a Remote Service.

It isn't meant to allow for dynamic 'local' Service and Service Script creation.

Re: Modify service code programmatically

Thanks Pai. What would be the best way to create a local service with JS body?

Re: Modify service code programmatically

Unfortunately I don't know of a way to do it permanently.

But you could store jscript in a datatable and execute that ... since this is pushing the boundaries of what is possible and what is recommended and what can become incredibly dangerous, email me and I can share an example.

Re: Modify service code programmatically

Constantine,

Any update on this? Was Pai Chung's post helpful? If so, could you click on the "correct answer" or "mark as helpful" button and let us know?

Re: Modify service code programmatically

Hello Jeremy, unfortunately there's still no good answer for this question.

Re: Modify service code programmatically

So far, Costin's answer to this topic seems to be the closest to the solution: AddDynamicSubscription help

Re: Modify service code programmatically

Hi Constantine,

Let me give an example of dynamic code execution that can be used in the platform.

For this to work you need to have a wrapper service, called let's say "Execute Service". You can run inside a single line, a javascript function called eval(string) which takes a string input parameter.

So you have 2 choices: you either store the command itself in a property so whenever you want to modify the implementation you set the property to a new value (can be an through an editor inside a mashup) or you can simply have the service accepting the command as a parameter.

Can this be applied in your use case?

View solution in original post

Re: Modify service code programmatically

Hello Vladimir,

If I remember correctly, eval() was not available in TWX Rhino.

/ Constantine

Re: Modify service code programmatically

eval is available.

let me just stress again that this is very dangerous, because now you are going to allow non validated code to run.

Re: Modify service code programmatically

Hello Pai,

Indeed, I tested and it works! I believe it didn't work before, but that might have been my memory issue

Cool, that's all I need, thanks.

/ Constantine

Re: Modify service code programmatically

I (obviously) agree with Pai. The context in which I used this was to build sequences of predefined services at runtime.

Having to write the service at runtime is definitely not  a suggested course of action, just technically possible if you implement it.

Re: Modify service code programmatically

Vladimir, we'll use it in controlled and safe way, for sure. It's just easier than implementing some custom business rules engine. I marked your answer correct, thanks!

/ Constantine

Re: Modify service code programmatically

eval it's evil but for a flexible solution it's the swiss tool, I can't live without it.

Re: Modify service code programmatically

Currently my main concern about it is performance.

Re: Modify service code programmatically

I'm using it on a lot of places, and it's not the bootle neck.

Re: Modify service code programmatically

//

// For this example, we'll have an Math service

// which takes two numbers, and an operation.

// The result will be that operation performed on the two inputs.

//

// We either need an Application Key,

// or user credentials to perform the reads and writes.

// App keys are a little safer.

// In this demo, we'll store it on the Entity as a Property.

var appKey = me.appKey;

//

// The service name needs to be unique and not already in use.

var serviceName = "MyMath";

//

// What are the inputs to the service?

// We'll define them nicely here, but manipulate this object later.

var parameters = {

    "op" : "STRING",

    "x" : "NUMBER",

    "y" : "NUMBER"

};

//

// What datatype does the service return?

// If it's an infotable,

// then you'll also have to specify the data shape

// as part of the resultType's aspect,

// but I won't demonstrate that here.

var output = "NUMBER";

//

// What is the actual service script?

// We'll define it here as an array of lines, and then join them together.

var serviceScript = [

    "var result = (function() {",

    "  switch(op) {",

    "    case \"add\": return x + y;",

    "    case \"sub\": return x - y;",

    "    case \"mult\": return x * y;",

    "    case \"div\": return x / y;",

    "    default: return op in Math ? Math[op](x, y) : 0;",

    "  };",

    "})();",

].join("\n");

////////

//

// Let's convert the friendly parameter definition

// into the structure that ThingWorx uses:

var parameterDefinitions = Object.keys(parameters).reduce(function(parameterDefinitions, parameterName, index) {

    var parameterType = parameters[parameterName];

    parameterDefinitions[parameterName] = {

        "name": parameterName,

        "aspects": {},

        "description": "",

        "baseType": parameterType,

        "ordinal": index

    };

    return parameterDefinitions;

}, {});

//

//  Now let's set up our service definition and implementation.

var definition = {

    "isAllowOverride": false,

    "isOpen": false,

    "sourceType": "Unknown",

    "parameterDefinitions": parameterDefinitions,

    "name": serviceName,

    "aspects": {

        "isAsync": false

    },

    "isLocalOnly": false,

    "description": "",

    "isPrivate": false,

    "sourceName": "",

    "category": "",

    "resultType": {

        "name": "result",

        "aspects": {},

        "description": "",

        "baseType": output,

        "ordinal": 0

    }

};

var implementation = {

    "name": serviceName,

    "description": "",

    "handlerName": "Script",

    "configurationTables": {

        "Script": {

            "isMultiRow": false,

            "name": "Script",

            "description": "Script",

            "rows": [{

                "code": serviceScript

            }],

            "ordinal": 0,

            "dataShape": {

                "fieldDefinitions": {

                    "code": {

                        "name": "code",

                        "aspects": {},

                        "description": "code",

                        "baseType": "STRING",

                        "ordinal": 0

                    }

                }

            }

        }

    }

};

////////

//

// Here are the URLs we'll need in order to make updates.

// You can change the thing name ('ServiceModifier' here)

// to something else.

// If you use credentials instead of an app key,

// then you can remove the appKey parameter here,

// but you'll have to add the username and password

// to the two ContentLoaderFunctions calls.

var url = {

    export : "http://127.0.0.1:8080/Thingworx/Things/ServiceModifier?Accept=application/json&appKey="+appKey,

    import : "http://127.0.0.1:8080/Thingworx/Things/ServiceModifier?appKey="+appKey

};

//

// We can download the entity to modify as a JSON object.

// Older versions of ThingWorx might not support this.

var config = Resources.ContentLoaderFunctions.GetJSON({

    url : url.export,

});

//

// We have to modify both the 'effectiveShape',

// as well as the 'thingShape'.

config.effectiveShape.serviceDefinitions[serviceName] = definition;

config.effectiveShape.serviceImplementations[serviceName] = implementation;

config.thingShape.serviceDefinitions[serviceName] = definition;

config.thingShape.serviceImplementations[serviceName] = implementation;

// Finally, we can push our updates back into ThingWorx.

Resources.ContentLoaderFunctions.PutText({

    url : url.export,

    content : JSON.stringify(config),

    contentType : "application/json",

});

// The end.

Re: Modify service code programmatically

Awesome, that's exactly what I was looking for! Thanks.

/ Constantine

Re: Modify service code programmatically

Can you actually do this though? I believe this needs an Administrator account to do the Import/Export?

Re: Modify service code programmatically

It would be nice to see how they do it in Utilities, but I'm too lazy to check it.

Re: Modify service code programmatically

As far as I know, you need a user account who has permission to Read and Update the Entity.

Re: Modify service code programmatically

There's a document with the "correct answer" now: https://community.thingworx.com/docs/DOC-3853

Announcements

Check out the upcoming Expert Session: Understanding ThingWorx Navigate Licensing in Community "Customer Events" section.