21 Replies Latest reply on Jun 1, 2017 9:49 AM by ckulak RSS
    ckulak Apprentice

    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

      • Re: Modify service code programmatically
        pchung Collaborator

        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
          ckulak Apprentice

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

          • Re: Modify service code programmatically
            carlesc Heavyweight Champ

            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
              chadha Apprentice
              //
              // 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
                ckulak Apprentice

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