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.
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
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 |
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.
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>