4 Replies Latest reply on Mar 17, 2017 4:07 AM by jdurand RSS
    jdurand Explorer

    Create service programmatically

    Hi,

     

    I would like to build a form which will allow users to create services without entering the composer.

    So is it possible to create services programmatically without using remote services ?

     

    Regards

      • Re: Create service programmatically
        pchung Collaborator

        there is another thread talking about this

        Modify service code programmatically

          • Re: Create service programmatically
            jdurand Explorer

            Ok so it is not :/

              • Re: Create service 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.