Click or drag to resize

Getting Started with the REST Interface

The xTend Framework may also be accessed via an HTTP based REST interface, which provides interoperability with non-Microsoft development platforms and operating systems.

Available Channels

By default, the xTend REST interface is published on TCP port 6063. Two REST based channels are available for use on this port:

JSON (Javascript Object Notation) REST Channel

http://[myserver]:6063/FactoryLogix_xTendAPIService/json/[ServiceName]

POX (Plain Old XML) REST Channel

http://[myserver]:6063/FactoryLogix_xTendAPIService/pox/[ServiceName]

Online help may be accessed for each service using your browser, and navigating to a URL formatted like this:

http://[myserver]:6063/FactoryLogix_xTendAPIService/json/[ServiceName]/help

For Example:

http://[myserver]:6063/FactoryLogix_xTendAPIService/json/ConnectionServices/help

Firewall Settings and Network Setup

The xTend REST interface communicates with your FactoryLogix xTend API Server using HTTP protocol on a custom TCP port (6063). In order to operate correctly, you must allow inbound traffic to the xTend server on the ports listed below. Any firewalls installed on the xTend server itself, or between your xTend application and the xTend server must be configured to allow this traffic:

xTend REST/HTTP Protocol

TCP Port 6063

JQuery CORS (Cross-Origin Resource Sharing) Support

If you are using the xTend REST interface via Javascript / JQuery, it is very likely that your code is part of a web site running on a different server or domain than the xTend API server. By default, JQuery will not allow a REST call originating on one web site to be made to a different site, unless the alternate site is "CORS enabled". The FactoryLogix xTend API has built-in support for CORS, enabling REST calls to be made from a different origin than the xTend API server. This frees API developers to make REST calls from any origin they wish.

Connecting xTend API Server With REST, and Making xTend Service Calls

The first step in using the xTend API is establishing a connection to the xTend API server. To accomplish this, the Connect method is utilized.

The following HTML5 / Javascript code example demonstrates the basic coding patterns that are used to make service calls to the xTend API via REST.

The page allows connection / disconnection from an xTend API server, and also provides an example of how to look up the next expected Operation for a given production unit (identified by its barcode).

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>

    body{
            font-family: Arial, Helvetica, sans-serif;
            font-size: 12pt;
            background-color:#e0e0ff;
        }


    th, td {
                border: 1px solid black;
                border-collapse: collapse;
            }

    table {
                border: 1px solid black;
                border-collapse: collapse;
                width:50%;
                background-color:white;
            }
    </style>
</head>
<body onload="onLoad()" onclose="onclose()">
    <h1>Connect to FactoryLogix xTend API</h1>
    <button style="width:80px;" onclick="OnLogin()" id="loginButton">Login</button>
    <button style="width:80px;margin-left:20px" onclick="OnLogout()" id="logoutButton">Logout</button>
    <p></p><p></p>
    <table id="table1">
        <col style="width:180px"/>
        <tr>
            <td>Server Url</td>
            <td><input style="width:99%; border-style:none" id="serverEdit"/></td>
        </tr>
        <tr>
            <td>User Name</td>
            <td><input style="width:99%; border-style:none" id="usernameEdit"/></td>
        </tr>
        <tr>
            <td>Password</td>
            <td><input style="width:99%; border-style:none" id="passwordEdit" type="password" /></td>
        </tr>
        <tr>
            <td>Database Connection</td>
            <td></td>
        </tr>
        <tr>
            <td>Session ID</td>
            <td></td>
        </tr>
        <tr>
            <td>Last Error</td>
            <td>---</td>
        </tr>
    </table>
    <p></p><p></p>
    <table id="table2">
        <col style="width:180px" />
        <col/>
        <col style="width:200px" />
        <tr>
            <td>Barcode</td>
            <td><input id="barcodeEdit" style="width:99%; border-style:none" onkeypress="OnKeyPressBarcode(event)"/></td>
            <td><button id="nextOperationButton" style="width:100%" onclick="OnGetNextOperation()">Get Next Operation</button></td>
        </tr>
        <tr>
            <td>Next Operation</td>
            <td><p id="nextOperationResult"></p></td>
            <td></td>
        </tr>
    </table>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <script >

        var FactoryLogixServerUrl = 'http://myserver:6063/FactoryLogix_xTendAPIService/json/';
        var ResultObject = null;
        var SessionId = null;
        var UserName = "AegisAdmin";
        var Password = "";
        var LastBatchId = null;
        var LastProcess = null;

        function OnLogin()
        {
            FactoryLogixServerUrl = serverEdit.value;
            UserName = usernameEdit.value;
            Password = passwordEdit.value;

            // Check for existing session and logout.
            if (SessionId != null) OnLogout();

            // Obtain the default database connection name.
            MakeServiceCall("ConnectionServices", "GetDefaultDatabaseConnection", "{}");

            var dbConn = ResultObject.GetDefaultDatabaseConnectionResult;
            table1.rows[3].cells[1].innerHTML = dbConn;

            // Connect and login to the xTend API and obtain a session token.
            MakeServiceCall("ConnectionServices", "Connect", '{"serverName":"jwalls", "userName": "' + UserName + '", "password":"' + 
                Password + '", "databaseConnection":"' + dbConn + '"}');

            SessionId = ResultObject.ConnectResult;
            table1.rows[4].cells[1].innerHTML = SessionId;
            label2.innerHTML = SessionId;
        }

        function OnLogout() {

            // Disconnect and logout from the xTend API.
            if (SessionId != null)
            {
                MakeServiceCall("ConnectionServices", "Disconnect", '{"sessionId":"' + SessionId + '"}');
                SessionId = null;
                table1.rows[3].cells[1].innerHTML = "";
                table1.rows[4].cells[1].innerHTML = "";
            }
        }

        function OnGetNextOperation() 
        {
            GetNextOperation(barcodeEdit.value);
        }

        function OnKeyPressBarcode(e)
        {
            if (event.charCode == 13)
            {
                GetNextOperation(barcodeEdit.value);
            }
        }

        function GetNextOperation(barcode)
        {
            nextOperationResult.innerHTML = "";
            if (barcode == null || barcode.length < 1) return;

            if (SessionId == null)
            {
                ShowError("Please Login");
                return;
            }

            // Make sure item exists.
            var params = '{"sessionId":"' + SessionId + '", "itemUID":"' + barcode + '"}';
            MakeServiceCall("ItemServices", "GetItem", params);

            if (ResultObject == null) return;
            if (ResultObject.GetItemResult == null)
            {
                ShowError("Barcode Not Found");
                return;
            }

            // Load the Process Data (if new Batch)
            LoadProcess(ResultObject.GetItemResult.ActiveBatchId)
            if (LastProcess == null) return;

            // Get Next Operation
            MakeServiceCall("TrackingServices", "GetNextOperation", '{"sessionId":"' + SessionId + '", "UID":"' + barcode + '"}');
            if (ResultObject == null)
            {
                ShowError("Cannot Determine Next Operation for Barcode:  " + barcode);
                return;
            }

            var operation = FindOperation(ResultObject.GetNextOperationResult);

            if (operation == null)
                nextOperationResult.innerHTML = ResultObject.GetNextOperationResult;
            else
                nextOperationResult.innerHTML = operation.Name;
        }

        function LoadProcess(activeBatchId)
        {
            if (activeBatchId == LastBatchId) return;

            LastProcess = null;
            LastBatchId = null;

            // Find the Batch
            var params = '{"sessionId":"' + SessionId + '", "criteria":[{"SearchFieldName":"2","SearchValue":"' + activeBatchId + '"}],' +
                         '"sorting":[{"FieldName":"1","SortMode":"0"}], "pageSize":"1", "pageNumber":"1"}';

            MakeServiceCall("BatchServices", "FindBatches", params);
            if (ResultObject == null) return;

            var processId = ResultObject.FindBatchesResult.Results[0].ProcessId;

            params = '{"sessionId":"' + SessionId + '", "processId":"' + processId + '"}';
            MakeServiceCall("ProcessServices", "GetProcess", params);
            if (ResultObject == null) return;

            LastProcess = ResultObject.GetProcessResult;
            LastBatchId = activeBatchId;
        }

        function FindOperation(operationId)
        {
            for (var i = 0; i < LastProcess.PrimaryProcessFlow.Operations.length; i++)
            {
                var op = LastProcess.PrimaryProcessFlow.Operations[i];
                if (op.Id == operationId) return op;

                var opType = op.__type.toString();

                if (opType.lastIndexOf("OperationGroup:") == 0) 
                {
                    for (var j = 0; j < op.Operations.length; j++)
                    {
                        var op2 = op.Operations[j];
                        if (op2.Id == operationId) return op2;
                    }
                }
            }

            for (var i = 0; i < LastProcess.OutOfRouteOperations.length; i++)
            {
                var op = LastProcess.OutOfRouteOperations[i];
                if (op.Id == operationId) return op;
            }

            for (var i = 0; i < LastProcess.OutOfRouteFlows.length; i++)
            {
                var flow = LastProcess.OutOfRouteFlows[i];
                for (var j = 0; j < flow.Operations.length; j++)
                {
                    var op = flow.Operations[j];
                    if (op.Id == operationId) return op;

                    var opType = op.__type.toString();

                    if (opType.lastIndexOf("OperationGroup:") == 0)
                    {
                        for (var k = 0; k < op.Operations.length; k++)
                        {
                            var op2 = op.Operations[k];
                            if (op2.Id == operationId) return op2;
                        }
                    }
                }
            }

            return null;
        }

        function onLoad()
        {
            serverEdit.value = FactoryLogixServerUrl;
            usernameEdit.value = UserName;
            passwordEdit.value = Password;
        }

        function onClose() {
            OnLogout();
        }

        function MakeServiceCall(serviceName, methodName, params)
        {
            $.support.cors = true;

            var endpointUrl = FactoryLogixServerUrl + serviceName + '/' + methodName;
            var action = "POST";
            var dataFormat = "json";
            var contentHeader = "application/json";

            $.ajax({
                type: action,
                data: params,
                url: endpointUrl,
                dataType: dataFormat,
                processData: true,
                async: false,
                contentType: contentHeader,
                success: ServiceSucceeded,
                error: ServiceFailed
            });
        }

        // ---- If Error -------------------        
        function ServiceFailed(result)
        {
            var errorMessage = "ERROR";
            if (has(result, 'responseText'))
                errorMessage = result.responseText;
            else if (has(result, 'statusText'))
                errorMessage = result.statusText;

            ResultObject = null;
            ShowError(errorMessage);
        }

        function ShowError(errorMsg)
        {
            table1.rows[5].cells[1].innerHTML = errorMsg;
        }

        // ---- If Success -------------------        
        function ServiceSucceeded(result)
        {
            table1.rows[5].cells[1].innerHTML = "---";

            ResultObject = result;
        }

        function has(object, key) {
            return object ? hasOwnProperty.call(object, key) : false;
        }

    </script>

</body>
</html>