210
FME ® Server 2013 Developer's Guide E-mail: [email protected] • Web: www.safe.com

FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME® Server 2013 Developer's Guide

E-mail: [email protected] • Web: www.safe.com

Page 2: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

2 FME Server Developer's Guide

Page 3: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Safe Software Inc. makes no warranty either expressed or implied, includ-ing, but not limited to, any implied warranties of merchantability or fitnessfor a particular purpose regarding these materials, and makes such mate-rials available solely on an “as-is” basis.

In no event shall Safe Software Inc. be liable to anyone for special, col-lateral, incidental, or consequential damages in connection with or arisingout of purchase or use of these materials. The sole and exclusive liability ofSafe Software Inc., regardless of the form or action, shall not exceed thepurchase price of the materials described herein.

This manual describes the functionality and use of the software at the timeof publication. The software described herein, and the descriptions them-selves, are subject to change without notice.

Copyright

© 1994 – 2013 Safe Software Inc. All rights are reserved.

Revisions

Every effort has been made to ensure the accuracy of this document. SafeSoftware Inc. regrets any errors and omissions that may occur and wouldappreciate being informed of any errors found. Safe Software Inc. will cor-rect any such errors and omissions in a subsequent version, as feasible.Please contact us at:

Safe Software Inc.7445 – 132nd Street, Suite 2017Surrey, BCCanada V3W 1J8

www.safe.com

Safe Software Inc. assumes no responsibility for any errors in this doc-ument or their consequences, and reserves the right to make improve-ments and changes to this document without notice.

Trademarks

FME is a registered trademark of Safe Software Inc.

3 FME Server Developer's Guide

Page 4: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

All brands and their product names mentioned herein may be trademarks orregistered trademarks of their respective holders and should be noted assuch.

Document Information

Document Name: FME Server Developer's Guide

Version: FME Server 2013

Updated: December 2013

FME Server Developer's Guide 4

Page 5: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Contents

Introduction 7

Developing on the Web 9

FME Server Services 9JavaScript 10Java 20Sample XML Response 29Sample JSON Response 31Uploading Data and Running a Workspace in a Single Call - SampleWeb Form 32REST Service 35JavaScript 35Java 57FME Server REST Playground 76

Developing with the Core APIs 77

Java 77Java Quick Start 78Java Tutorial 81Java Example 95.NET 115.NET Quick Start 116.NET Tutorial 119.NET Example 133C++ 151C++ Quick Start 152C++ Tutorial 157C++ Example 172

Configuring CORS Filters 205

Enable CORS Filter 205Restrict CORS Filter 206Filter init parameters 207

5 FME Server Developer's Guide

Page 6: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

6 FME Server Developer's Guide

Page 7: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IntroductionThis FME Server's Developer's Guide provides quick-start, tutorial, and sam-ple program resources to help you get started with the FME Server APIs.

Inside the Developer's Guide:

Section Description

"FME Server Serv-ices" on page 9

Resources for getting started with the Web Serv-ices APIs, using either Java or JavaScript.

"REST Service"on page 35

Resources for developing custom web clients usingthe REST API.

FME Server Core Resources for developing applications to managethe FME Server Core in Java, Managed Code, orC++.

"ConfiguringCORS Filters" onpage 205

Instructions for configuring cross-origin resourcesharing (CORS) filters for the FME Server web serv-ices.

For comprehensive API Reference documentation, consult the FME ServerReference Manual.

If you are an administrator looking for the most common administrationtasks, including installation, refer to the FME Server Administrator's Guide.For less common administrative tasks, refer to fmepedia.com. If you are aWorkspace Author, refer to the FME Server Author Tutorial and the FMEServer Training course materials.

FME Server Developer's Guide 7

Page 8: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

8 FME Server Developer's Guide

Page 9: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

Developing on the Web

FME Server ServicesFME Server lets your organization address diverse spatial, and non-spatial,data requirements using a single enterprise solution. FME Server provides aService-Oriented Architecture (SOA) that brings all the capabilities of theFME platform to a server environment, creating a full Spatial Extract, Trans-form, and Load (ETL) capability.

The capabilities of FME are presented through a number of interfaces, includ-ing the Notification Service, web-based services such as the Data Downloadservice, and application interfaces, including the Web User Interface, FMEServer Console and FME Workbench.

Additionally, programmatic interfaces provide an extra layer of cus-tomization. This Developer's Guide provides resources for getting startedwith FME Server services using the following interfaces:

n "JavaScript" on next page

n "Java" on page 20

Through these interfaces, organizations can apply the power of FME at theorganization or web level for the first time.

FME Server provides the following services:

n Data Download Service

n Data Streaming Service

n Job Submitter Service

n KML Network Link Service

n Notification Service

n Catalog Service

n OGC Web Feature Service

n OGC Web Mapping Service

FME Server Developer's Guide 9

Page 10: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

The following services act as helper services that provide data or pro-grammatic access to FME Server:

n Data Upload Service

n Web Connection (SOAP Communication) Service

n REST Service

n Token Service

API Documentation

For a complete listing of web application parameters, properties and othermaterial for each FME Server web service, consult the FME Server Ref-erence Manual.

Also in this section:

n "Sample XML Response" on page 29 (Data Download Service)

n "Sample JSON Response" on page 31 (Data Download Service)

n "Uploading Data and Running a Workspace in a Single Call - SampleWeb Form" on page 32 (Data Upload Service)

JavaScript

In this section:

Section Description

"JavaScriptQuick Start" onthe facing page

Setting up a JavaScript project in Visual Studio,and a pointer to the Web Service API command-line demo application.

"JavaScript Tuto-rial" on page 12

Code for common requests using the Web ServicesAPI.

"Sample Java-Script Program"on page 18

Sample program to send a GET request to the DataDownload Service.

Developing on the Web

10 FME Server Developer's Guide

Page 11: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

JavaScript Quick Start

The FME Web Services API can be used by anything that can send andreceive HTTP requests. However, we will be focusing on JavaScript here.

API Files

The FME Web Services API can be view in the API section.

Setting Up a JavaScript Project Using Visual Studio

1. Start Visual Studio.

2. Choose File > New > Web Site.

In this example, we'll create an empty web project and name it FME-ServerWebServicesAPIDemo.

You can now start to create web applications using the FME Server Web Serv-ices API interfaces by using native AJAX calls.

Running the API Sample demo

A sample command-line demo application illustrating the use of the FMEServer Web Service API is available in Java and JavaScript versions.

This demo can be used to ensure that everything has been setup properly,and contains code that may be useful for your development process. (Morein-depth coverage can be found in the later sections.)

The JavaScript/HTML source code is located in:

<FMEServerDir>\Server\sdk\doc\javascript\FMEServerWebServicesAPIDemo.html

Note: Clicking on the above link will likely cause your browser toattempt to run the program (due to the html extension). Thiswill not work due to JavaScript security issues. You can eitherright-click and save the links or open the links and ViewSource.

FME Server Developer's Guide 11

Page 12: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Place the file into the same machine on your FME Server, and access FME-ServerWebServicesAPIDemo.html via a web browser. Pop-ups must beenabled for it to work.

JavaScript Tutorial

This topic is for developers who want to build web applications using FMEServer Web Services API. This topic contains code for common requestswith FME Server Web Services API.

This tutorial for JavaScript, but the same concept can be applied to otherprogramming languages.

Please note that the sample code provided is intended for demonstrationpurposes only:

Web Services API Demo - JavaScript

For demonstration purposes a sample JavaScript web application has beencreated to illustrate many of the common FME Web Service API conceptswith sample code. The sample application must be run on the machine FMEServer is hosted on. When the command line application opened in a webbrowser, JavaScript will render a popup containing instructions.

Note: Our demo also takes advantage of our REST API. The reasonbehind this will become obvious as you read on.

Working with Workspaces

Web services are run on workspaces which reside in repositories. Futher-more, each workspace can be setup to have a different subset of publishedparameters and web services available. However, the Web Services APIdoes not provide any means of determining the available repositories,workspaces, and their respective published parameters and serives avail-able.

Developers can either:

Require the application user to know in advance the service, repository andworkspace names, refusing any invalid requests

Use one of the other APIs available to determine the information

Developing on the Web

12 FME Server Developer's Guide

Page 13: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

Of the available APIs, the REST API is the most compatible because:

REST also accepts HTTP requests

Replies in the same choice of formats (html, xml, json)

Our REST API supports "Working with Repositories" on page 63, "Workingwith Workspaces" on page 64, and "Working with Jobs" on page 74. Althoughnot listed in the REST tutorial, (but included in our demo), REST can deter-mine the available services for a given workspace.

Working with JavaScript and Ajax

For the purpose of this tutorial, we will be creating a popup window that inter-acts with the user.

The first step with any FME REST API call using javascript is to create an ajaxsession.

var httpRequest;if (window.XMLHttpRequest){

httpRequest = new XMLHttpRequest();}else{

// for older versions of Internet ExplorerhttpRequest = new ActiveXObject("MSXML2.XMLHTTP.3.0");

}

httpRequest.open(method, url, true);

Once the connection has been established, setup the response handler.

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

// code to deal with response goes here

FME Server Developer's Guide 13

Page 14: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

}else{

// an error occurred - varies depending on request(see API docs)alert("An error occurred");

}}

}

A very important step is ensure you send a message after setting thereponse handler so that a response will be received.

// null for certain requestshttpRequest.send(parameters);

Working with Web Services

How to list available services

Listing the services available for a workspace can be done using REST andknowing the URI to the workspace (which can be generated from the repos-itory and workspace name).

httpRequest.open("GET", workspaceURI + "/.json", true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

var reply = eval("(" + httpRequest.responseText + ")");

// generate an output message based on the responsereceivedvar reply = eval("(" + httpRequest.responseText + ")");var outputDoc = "Services:";// check that there are services available for thisworkspace

Developing on the Web

14 FME Server Developer's Guide

Page 15: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

if (typeof(reply.ser-viceResponse.workspace.services.service) != 'unde-fined'){

var services = reply.ser-viceResponse.workspace.services.service;outputDoc += dropdownHTML('service', "win-dow.opener.createForm()", services);

}else{

outputDoc += "No Services Available<br/>";}

}else{

println("Error");}

}}httpRequest.send(null);

Running the Web Service

To run the web service, we can send an HTTP request to the server.

For the purpose of this example, we will create a form using JavaScript andsend the request via an HTML form submit.

outputDoc += "<form name='serviceForm' method='post'action='"

+ workspaceService.service.urlPattern + "/"+ workspaceService.repository.name + "/"+ workspaceService.workspace.name + "'>";

// here we can add any parameters and tm_directives

outputDoc += "<input type='submit' value='Run'/>";outputDoc += "</form>";

FME Server Developer's Guide 15

Page 16: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Working with Transformation Manager Directives

Transformation Manager Directives are settings that can be applied to allservices. These settings range in complexity from adding a description toscheduling the service to run at a later date. A list of TM directives can befound here

For our example, we set a high value for the priority of this job, in order totell the FME Server to execute it before other tasks. This is not necessarybut just done to illustrate how to set directives.

outputDoc += "<input type='hidden' name='tm_priority'value='80'>";

Working with Published Parameters

Through REST, we can easily obtain a list of published parameters and theirrespective input types.

Furthermore, we can create place each published parameter as a field inthe form. Based on the response received from the REST call, we can deter-mine information regarding each published parameter, and provide a user-friendly interface with labels, dropdown menus, and text fields.

parameters = work-spaceService.workspace.parameters.parameter;// if parameters is not an array, it's a single parameterif (parameters.length == null){

parameters = workspaceService.workspace.parameters;}

// add each parameter as a field in the formfor (var i in parameters){

var parameter = parameters[i];outputDoc += "<label>" + parameter.description +"</label>";// use <select> for single and multi-choice optionsif (parameter.optionsType == "MULTICHOICE_CONFIG"

Developing on the Web

16 FME Server Developer's Guide

Page 17: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

|| parameter.optionsType == "SINGLECHOICE_CONFIG"){

// name based on responseoutputDoc += "<select name='" + parameter.name + "'";// allow multiple for multi-choiceif (parameter.optionsType == "MULTICHOICE_CONFIG"){

outputDoc += " multiple='true' ";}outputDoc += ">";// add each optionvar options = parameter.options.option;for (var j in options){

var value = options[j].value;// use a display alias if possiblevar display = (typeof(options[j].displayAlias) =="undefined")

? options[j].value: options[j].displayAlias;

outputDoc += "<option value='" + value + "'";// select the default valueif (parameter.defaultValue == value){

outputDoc += " selected='selected' ";}outputDoc += ">" + display + "</option>";

}outputDoc += "</select>";

}else{// for everything else, default to a text fieldoutputDoc += "<input type='text' size='50' name='"

+ parameter.name + "' value='" + param-eter.defaultValue + "'>"

}outputDoc += "<br/>";

}

FME Server Developer's Guide 17

Page 18: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Handling Responses

The format received will vary depending on the service used. XML, json,and html can be parsed and/or displayed. Any other format should besaved or run in another application (ie. Google Earth for .kmz files).

Since our demo created a form submission, the web browser will deal withthe response based on the MIME-type.

Sample JavaScript Program

Send a GET request to Data Download Service by JavaScript

The sample code below sends the request through GET usingXMLHttpRequest object and reads response text. The function eval() iscalled to parse the text into JSON object. It validates the service status issuccess. If true, the URL for the downloaded result is printed. Otherwise anerror message is printed. Also the server request, server status messageand job status are printed.

Note: You might need to modify the hard-coded URL for this demoto work.

Sample Code

<html><head>

<title>FME Server Web Services Demo - Data Download</title></head><body>

<!-- This script will create a pop-up with the results of run-ning a workspace -->

<script type="text/javascript">// URL with parameters for workspace// Note: you may need to modify the hard-coded URL for this

demo to workvar url = "http:/-

/localhost/fmedatadownload/Samples/austinApartments.fmw?opt_respon-seformat=json";

var width = 800;var height = 400;// request handlervar httpRequest;if (window.XMLHttpRequest){

Developing on the Web

18 FME Server Developer's Guide

Page 19: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

httpRequest = new XMLHttpRequest();}else{

// for older versions of Internet ExplorerhttpRequest = new ActiveXObject("MSXML2.XMLHTTP.3.0");

}httpRequest.open("GET", url, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4 && httpRequest.status ==200)

{var reply = eval("(" + httpRequest.responseText + ")

");var outputDoc = "Service Response: ";if (reply.serviceResponse.statusInfo.status == "suc-

cess"){

var downloadURL = reply.serviceResponse.url;

outputDoc += "Service succeeded. <br/>DownloadURL: ";

outputDoc += "<a href=\"" + downloadURL + "\">" +downloadURL + "</a><br/>";

}else{

outputDoc+= "Service failed. Error message:";outputDoc+= reply.ser-

viceResponse.service.message;}outputDoc+= "FME transformation result:<br/>";outputDoc+= "Request: " + reply.ser-

viceResponse.fmeTransformationResult.fmeServerResponse.request +"<br/>";

outputDoc+= "Status message: " + reply.ser-viceResponse.fmeTransformationResult.fmeServerResponse.statusMessage +"<br/>";

outputDoc+= "Job status: " + reply.ser-viceResponse.fmeTransformationResult.fmeServerResponse.jobStatus +"<br/>";

// create a window for the outputvar outputWindow = window.open('','',

'width='+width+',height='+height);outputWindow.document.write(outputDoc);outputWindow.focus();

}}// send a request so we get a replyhttpRequest.send(null);

FME Server Developer's Guide 19

Page 20: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

</script></body>

</html>

Java

In this section:

Section Description

"JavaQuickStart"below

Setting up a Java project using Eclipse and the ApacheHTTP client, and running the Web Service API command-line demo application.

"JavaTutorial"on page23

Code for common requests using the Web Services API.

SampleJava Pro-gram

Sample program to send a POST request to the Job Sub-mitter Service.

Java Quick Start

The FME Web Services API can be used by anything that can send andreceive HTTP requests. However, we will be focusing on Java here.

API Files

Setting up a Java Project Using Eclipse and Apache HTTP Client

1. Visit http://hc.apache.org to download the Apache HTTP Client.

2. You will also need the following dependencies:

n commons-codec

n commons-logging

n junit

Refer to http://hc.apache.org/httpclient-3.x/dependencies.html for details.

3. Unzip the downloaded file.

Developing on the Web

20 FME Server Developer's Guide

Page 21: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

You should see a lib folder containing several JAR files.

4. Start Eclipse.

5. Choose File > New > Project, and select Java Project.

6. Enter FMEServerWebServicesDemo for the project name.

7. In the Java Settings dialog under the Libraries tab, click on Add Exter-nal JARs button.

FME Server Developer's Guide 21

Page 22: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

8. Select the commons-httpclient, commons-codec, and commons-log-ging JAR files in the Apache HTTP Client lib folder to add to yourproject.

The names may be different depending on version. You may alsoselect all JARs in the folder.

9. Now add a Java Class file, and import the Apache HTTP Client names-pace.

This, for example, can be done with the following line of code:

import org.apache.commons.httpclient.*;

Developing on the Web

22 FME Server Developer's Guide

Page 23: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

Running the API Sample demo

A sample command-line demo application illustrating the use of the FMEServer Web Service API is available in Java and JavaScript versions.

This demo can be used to ensure that everything has been setup properly,and contains code that may be useful for your development process. (Morein-depth coverage can be found in the later sections.)

The Java command-line application requires two parameters: the FMEServer host and FME Server port.

The Java source code is located in:

<FMEServerDir>\Server\sdk\doc\java\FMEServerWebServicesAPIDemo.java

Add the source code to your project, and run.

Usage:

FMEServerWebServicesAPIDemo<fmeServerHost><fmeServerPort>

n <fmeServerHost> represents the name of the host on which the WebServer is running

n <fmeServerPort> represents the TCP/IP port number the Web Serveris listening on for requests. The default value is 80 and this is usuallycorrect for most FME Server installations.

Java Tutorial

This topic is for developers who want to build web applications using FMEServer Web Services API. This topic contains code for common requests withFME Server Web Services API.

This tutorial is for Java, but the same concept can be applied to other pro-gramming languages.

Please note that the sample code provided is intended for demonstration pur-poses only:

Web Services API Demo - Java

FME Server Developer's Guide 23

Page 24: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

For demonstration purposes a sample JavaScript web application has beencreated to illustrate many of the common FME Web Service API conceptswith sample code. The sample application must be run on the machine FMEServer is hosted on. When the command line application opened in a webbrowser, JavaScript will render a popup containing instructions.

Note: Our demo also takes advantage of our REST API. The reasonbehind this will become obvious as you read on.

Working with Workspaces

Web services are run on workspaces which reside in repositories. Fur-thermore, each workspace can be setup to have a different subset of pub-lished parameters and web services available. However, the Web ServicesAPI does not provide any means of determining the available repositories,workspaces, and their respective published parameters and services avail-able.

Developers can either:

n Require the application user to know in advance the service, repos-itory and workspace names, refusing any invalid requests

n Use one of the other APIs available to determine the information

Of the available APIs, the REST API is the most compatible because:

n REST also accepts HTTP requests

n Replies in the same choice of formats (html, xml, json)

Our REST API supports "Working with Repositories" on page 63, "Workingwith Workspaces" on page 64, and "Working with Jobs" on page 74.Although not listed in the REST tutorial (but included in our demo), RESTcan determine the available services for a given workspace. (See "Workingwith Web Services" on the facing page.)

Working with Java and XML

For the purpose of this tutorial, we will be using a built in XML parser inJava. First, we must import the required packages:

import javax.xml.parsers.DocumentBuilder;

Developing on the Web

24 FME Server Developer's Guide

Page 25: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

import javax.xml.parsers.DocumentBuilderFactory;

Let us also create a function that can take a string and transform it to an XMLdocument.

private Document parseXML(String contents) throws Exception{

DocumentBuilderFactory dbf = Doc-umentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();InputSource is = new InputSource();is.setCharacterStream(new StringReader(contents));Document doc = db.parse(is);return doc;

}

Working with Web Services

How to list available services

Listing the services available for a workspace can be done using REST andknowing the URI to the workspace (which can be generated from the repos-itory and workspace name).

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repository+"/"+workspace+".xml?token="+token_;GetMethod method = new GetMethod(fmeUrl);

client_.executeMethod(method);String contents = method.getResponseBodyAsString();

Document doc = parseXML(contents);NodeList nl = doc.getElementsByTagName("service");

String msg = "Services:\n";String[] services = new String[nl.getLength()];

for (int s = 0; s < nl.getLength(); s++) {services[s] = ((Element)nl.item(s)).getElementsByTagName("uri").item(0).getTextContent();

FME Server Developer's Guide 25

Page 26: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

String serviceName = ((Element)nl.item(s))-.getElementsByTagName("name").item(0).getTextContent();msg += (s+1) + ". " + serviceName + "\n";

}

Running the Web Service

To run the web service, we can send an HTTP request to the server.

As with any other HTTP request:

// for the request to run the servicePostMethod runMethod = new PostMethod(serviceURL);

// here we can add any parameters and tm_directives

client_.executeMethod(runMethod);

Working with Transformation Manager Directives

Transformation Manager Directives are settings that can be applied to allservices. These settings range in complexity from adding a description toscheduling the service to run at a later date. A list of TM directives can befound here.

For our example, we set a high value for the priority of this job, in order totell the FME Server to execute it before other tasks. This is not necessarybut just done to illustrate how to set directives.

method.addParameter("tm_priority","80");

Working with Published Parameters

Through REST, we can easily obtain a list of published parameters and theirrespective input types.

// for the request to run the serviceString runUrl = serviceURL;PostMethod runMethod = new PostMethod(runUrl);

NodeList nl_parameters = doc.getElementsByTagName("param-eter");

Developing on the Web

26 FME Server Developer's Guide

Page 27: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

// get value for each parameterfor (int s = 0; s < nl_parameters.getLength(); s++){

Element el = (Element)nl_parameters.item(s);String name = el.getElementsByTagName("name").item(0).-getTextContent();String display = el.getElementsByTagName("descrip-tion").item(0).getTextContent();String defaultValue = el.getElementsByTagName("default-Value").item(0).getTextContent();String optionsType = el.getElementsByTagName("option-sType").item(0).getTextContent();

if (optionsType.equals("SINGLECHOICE_CONFIG")) {// single choice, so choose itNodeList nl_options = el.getElementsByTagName("option");String msg = display + "\n";String[] options = new String[nl_options.getLength()];

for (int i = 0; i < nl_options.getLength(); i++) {options[i] = ((Element)nl_options.item(i))-.getElementsByTagName("value").item(0).getTextContent();msg += (i+1) + ". " + options[i] + "\n";

}

String selected = getInput(msg + "Please select thenumber (default = "+defaultValue+"):");if (selected == "") {

runMethod.addParameter(name, defaultValue);} else {

//parameters.put(name, options[Integer.parseInt(selected)-1]);runMethod.addParameter(name, options[Integer.parseInt(selected)-1]);

}

} else if (optionsType.equals("MULTICHOICE_CONFIG")) {

FME Server Developer's Guide 27

Page 28: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

// prompt the user for each choiceNodeList nl_options = el.getElementsByTagName("option");System.out.println(display + "(Multiple options, enter'Y'/'N' or return for the default value.)");

for (int i = 0; i < nl_options.getLength(); i++) {String value = ((Element)nl_options.item(i))-.getElementsByTagName("value").item(0).-getTextContent();String choice = getInput(value + " (default = '" +(value.equals(defaultValue) ? "Y" : "N") + "') ?");

// add the choice if the user specified "Y" or thedefault choice was selected (and was "Yes")if (choice.equals("Y") || choice.equals("y") ||

(choice.equals("") && defaultValue.equals(value))) {

runMethod.addParameter(name+"[]", value);}

}

} else {// for everything else, default to a text inputString value = getInput(display + "(default = '" +defaultValue + "') ");// use default if nothing providedif (value == "") {

value = defaultValue;}//parameters.put(name, value);runMethod.addParameter(name, value);

}}

Handling Responses

The format received will vary depending on the service used. XML, json,and html can be parsed and/or displayed. Any other format should besaved or run in another application (ie. Google Earth for .kmz files).

Developing on the Web

28 FME Server Developer's Guide

Page 29: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

String contentType = runMethod.getResponseHeader("Content-Type").getValue();if (contentType.contains("text/xml") || contentType.contains("text/html") || contentType.contains("text/json")){

// print this out to the userString runContents = runMethod.getResponseBodyAsString();System.out.println(runContents);

}else{

// we had best download this file to a locationString filePath = getInput("Please enter the location youwould like to save this file to: ");

FileOutputStream file = new FileOutputStream(filePath);PrintStream fileStream = new PrintStream(file);

if (client_.executeMethod(method) != 200){

throw new Exception("Getting workspace failed");}

byte[] responseBody = method.getResponseBody();

// Deal with the response.// Use caution: ensure correct character encoding and isnot binary datafileStream.println(new String(responseBody));

fileStream.close();file.close();

}

Sample XML Response

XML Response: Data Download Service

A complete XML response from Data Download Service:

<?xml version="1.0" encoding="ISO-8859-1"?><serviceResponse><statusInfo>

FME Server Developer's Guide 29

Page 30: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

<status>success</status><mode>sync</mode>

</statusInfo><fmeTransformationResult><fmeEngineResponse><outputLocation>C:\Program Files\Apache Software Foundation\Tomcat

5.5\webapps\ROOT\fmedatadownloadresults\FME_3320_1246037797730_3320871476699.zip

</outputLocation><resultPrefix>http:</resultPrefix><statusNumber>0</statusNumber><logFileLocation>C:/Program Files/FME-

Server/Logs/datadownload/FME_3320_1246037788246_332087-1476708.log</logFileLocation>

<numFeaturesOutput>49</numFeaturesOutput><statusMessage>Translation Successful</statusMessage><resul-

tRootDir>//KENOBI:8080/fmedatadownloadresults</resultRootDir></fmeEngineResponse><fmeServerResponse><serviceSuccess>true</serviceSuccess><serviceMsg>success</serviceMsg><id>54</id><resultSuccess>true</resultSuccess><timeFinished>Fri-26-Jun-2009 10:36:37 AM</timeFinished><requesterHost>Kenobi</requesterHost><jobStatus>SUCCESS</jobStatus><result>0:Translation Successful|OutputLocation=C:\Program Files\Apache

Software Foundation\Tomcat 5.5\webapps\ROOT\fmedatadownloadresults\FME_3320_1246037797730_33208-71476699.zip|ResultPrefix=http:|ResultRootDir=//KENOBI:8080/fmedatadownloadresults|NumFeaturesOutput=49|LogFileLocation=C:/ProgramFiles/FMEServer/Logs/datadownload/FME_3320_1246037788246_3320871476708.log

</result><description>null</description><timeRequested>Fri-26-Jun-2009 10:36:28 AM</timeRequested><requesterResultPort>3172</requesterResultPort><request>"Samples/austinApartments/austinApartments.fmw" -XML_PARAMETER

<?xml version="1.0" encoding="ISO-8859-1"?><TRANSFORMATION_REQUEST><P-UBLISHED_PARAMETER name="--OPT_responseFormat">XML</PUBLISHED_PARAM-ETER><FME_DIRECTIVE name="-OGCKML_1_DATASET">!FME_AUTO_DIR_NAME!\austinApartments.kml</FME_DIRECTIVE></TRANSFORMATION_REQUEST>

</request><priority>100</priority><timeStarted>Fri-26-Jun-2009 10:36:28 AM</timeStarted><requestKeyword>FILE_DOWNLOAD_SERVICE</requestKeyword>

</fmeServerResponse>

Developing on the Web

30 FME Server Developer's Guide

Page 31: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

</fmeTransformationResult><url>http://KENOBI:8080/fmedatadownloadresults/FME_3320_1246037797730_3320871476699.zip</url><jobID>54</jobID>

</serviceResponse>

Sample JSON Response

JSON Response: Data Download Service

A complete JSON response from Data Download Service:

{"serviceResponse": {"fmeTransformationResult": {

"fmeEngineResponse": {"logFileLocation": "C:/Program Files/FME-

Server/Logs/datadownload/FME_3320_1246037788246_3320871476708.log","numFeaturesOutput": 49,"outputLocation": "C:\\Program Files\\Apache Software Foun-

dation\\Tomcat 5.5\\webapps\\ROOT\\fmedatadownloadresults\\FME_3320_1246037797730_3320871476699.zip",

"resultPrefix": "http:","resultRootDir": "//KENOBI:8080/fmedatadownloadresults","statusMessage": "Translation Successful","statusNumber": 0

},"fmeServerResponse": {

"description": null,"id": 54,"jobStatus": "SUCCESS","priority": 100,"request": "\"Samples/austinApartments/austinApartments.fmw\" -

XML_PARAMETER <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>-<TRANSFORMATION_REQUEST><PUBLISHED_PARAMETER name=\"--OPT_respon-seFormat\">XML</PUBLISHED_PARAMETER><FME_DIRECTIVE name=\"-OGCKML_1_DATASET\">!FME_AUTO_DIR_NAME!\\austinApartments.kml</FME_DIREC-TIVE></TRANSFORMATION_REQUEST>",

"requestKeyword": "FILE_DOWNLOAD_SERVICE","requesterHost": "Kenobi","requesterResultPort": 3172,"result": "0:Translation Successful|OutputLocation=C:\\Program

Files\\Apache Software Foundation\\Tomcat 5.5\\webapps\\-ROOT\\fmedatadownloadresults\\FME_3320_1246037797730_33208-71476699.zip|ResultPrefix=http:|ResultRootDir=//KENOBI:8080/fmedatadownloadresults|NumFeaturesOutput=49|LogFileLocation=C:/ProgramFiles/FMEServer/Logs/datadownload/FME_3320_1246037788246_3320871476708.log",

"resultSuccess": true,"serviceMsg": "success","serviceSuccess": true,"timeFinished": "Fri-26-Jun-2009 10:36:37 AM","timeRequested": "Fri-26-Jun-2009 10:36:28 AM",

FME Server Developer's Guide 31

Page 32: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

"timeStarted": "Fri-26-Jun-2009 10:36:28 AM"}

},"jobID": 54,"statusInfo": {

"mode": "sync","status": "success"

},"url": "http://KENOBI:8080/fmedatadownloadresults/FME_3320_

1246037797730_3320871476699.zip"}}

Uploading Data and Running a Workspace in a Single Call -Sample Web Form

You can post source data directly to FME Server's Data Upload Service andrun a workspace in one step. The HTML web form for this scenario requiresthe following components:

n URL for HTTP Post - The URL in the action field of the form is in thefollowing syntax:

http://<host>:<-port>/f-meserver/invoke/<service>/<repository>/<Workspace>.fmw

For example:

http://-fme-server.com/fmeserver/invoke/datastreaming/readjpg.fmw

n File input field - There must be one or more file input fields to letthe user select the data for upload. For example:

<input type=file id='source' name=SourceDataset_JPEGs>

n Multipart form - The form must be a multipart form, as specified inthis line:

enctype="multipart/form-data"

Developing on the Web

32 FME Server Developer's Guide

Page 33: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME Server Services

n Specifying the upload file - Specify the base file name of theuploaded file to the parameter for the source dataset in a hidden field.For example:

<input type="hidden" id= "basename" name="Sour-ceDataset_JPEG" value="File.JPG" /><br/>

Example

The following is a simple HTML web form that can be used to post a file to theData Upload Service via the FME Server Web User Interface, and invoke theworkspace. The form contains some Java Script to send the base file nameof the uploaded file.

<!-- Modify the URL to your FME Server Workspace in the'action' field as needed using the following syntax --><!-- http://<host>:<-port>/f-meserver/invoke/<service>/<repository>/<Workspace>.fmw --><form method="post"enctype="multipart/form-data"onsubmit="return validateForm()"action="http://ya-ne:80-80/fmeserver/invoke/fmedatastreaming/Support/readjpg.fmw"><p>Upload file here:<input type=file id='source' name=SourceDataset_JPEGs > <br></p><!-- Source Dataset Published Parameter should be the 'name'of this input field --><input type="hidden" id= "basename" name="SourceDataset_JPEG" value="File.JPG" /><br/><input type="submit" value="Run"></form><!-- Suppy Base Name only to Published Parameter --><script>function validateForm() {

var SourceFile = source.value

FME Server Developer's Guide 33

Page 34: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

basename.value=SourceFile.replace(/\\/g,'/').replace( /.*\//, '' );

}</script>

Developing on the Web

34 FME Server Developer's Guide

Page 35: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

REST ServiceThe REST service provides an underlying REST-based communication mech-anism for client-service applications. It provides a client with the same func-tionality as the FME Server API in C++, Java and .Net, therefore it's alsoreferred as the REST API. The REST service supports multiple response for-mats, including XML, JSON and HTML. It is not a user-oriented service thatdelivers translation results.

This Developer's Guide provides resources for getting started with FMEServer Web Services in the following interfaces:

n "JavaScript" below

n "Java" on page 57

Additionally, the FME Server REST Playground provides a host of interactiveexamples of applications for various FME Web Server services, includingData Download, Data Streaming, Data Upload, Notification, and others.

API Documentation

For a complete listing of REST API methods, response codes, and error mes-sages, consult the FME Server Reference Manual.

JavaScript

In this section:

Topic Description

"JavaScriptQuick Start" onnext page

Setting up a JavaScript project in Visual Studio, andrunning the REST API command-line demo appli-cation.

"JavaScript Tuto-rial" on page 37

Code for common requests using the REST API.

"Tutorial Sam-ple" on page 56

Tutorial source code.

FME Server Developer's Guide 35

Page 36: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

JavaScript Quick Start

The REST API can be browsed through a web browser athttp://<host>:<port>/fmerest/.

Setting Up a JavaScript Project Using Visual Studio

1. Start Visual Studio.

2. Choose File > New > Web Site. In this example, we'll create anempty web project and name it FMEServerRESTAPIDemo.

3. You can now start to create web applications using the FME ServerREST API interfaces by using native AJAX calls.

Running the API Sample demo

A sample command-line demo application illustrating the use of the FMEServer REST API is available in Java and JavaScript versions. The Java-Script version, however, has limited functionality due to security issues.

This demo can be used to ensure that everything has been setup properly,and contains code that may be useful for your development process. (Morein-depth coverage can be found in the later sections.)

The JavaScript/HTML source code is located in:

<FME-Server-Dir>\Server\sdk\doc\javascript\FMEServerRESTAPIDemo.html

Also required is the source code for the popup:

<FMEServerDir>\Server\sdk\doc\javascript\prompt.html

Note: Clicking on the above links will likely cause your browser toattempt to run the program (due to the html extension). Thiswill not work due to JavaScript security issues. You caneither right-click and save the links, or open the links andselect View Source.

36 FME Server Developer's Guide

Page 37: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

Add the two html files into the same machine on your FME Server, andaccess FMEServerRESTAPIDemo.html via a web browser. Pop-ups must beenabled for the prompt to work.

JavaScript Tutorial

This topic is for developers who want to build applications using FME ServerREST API in JavaScript. This topic contains code for common requests withFME Server REST API.

The JavaScript version handles json replies, whereas the Java version usesthe xml version. To see the html version, go to http://<host>:<p-ort>/fmerest.

Many common operations such as obtaining a server session, managingrepository items and resources, and running workspaces are outlined. Pleasenote that the sample code provided is intended for demonstration purposesonly.

Each of the following examples are live demos. If you click either link, it dis-plays the results of the code. To see the source code, you can either:

n Right-click a link, save it to your computer, and then view the code inyour favorite text editor.

n Right-click the link and view the source.

n Tutorial Demo - JavaScript

n "Tutorial Sample" on page 56

Note: Due to the security issues with JavaScript, our demo containsless functionality. Furthermore, the JavaScript demo must berun on the Web Server that FME Server resides.

Working with JavaScript and Ajax

Because JavaScript doesn't have a command-line interface that can delayexecution until user input is received, we will create something simple tomimic the functionality within a browser using a div and modal windows.

The div will be used as an output for anything we must display to the user:

function println(msg)

FME Server Developer's Guide 37

Page 38: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

{var output = document.getElementById("view");output.innerHTML += msg + "\n";output.scrollTop = output.scrollHeight - out-put.clientHeight;

}

We will also prompt the user for input using a modal popup, which can beused to receive user input:

function getInput(promptMessage){

var settings = "dialogWidth:320px; dialogHeight:100px;center:yes; edge:raised; scroll:no; status:no;";var input = window.showModalDialog("prompt.html", prompt-Message, settings);if (input == null || input == false){

throw "System:Quit";}println(promptMessage + " " + input);return input;

}

The first step with any FME REST API call using javascript is to create anajax session.

var httpRequest;if (window.XMLHttpRequest){

httpRequest = new XMLHttpRequest();}else{

// for older versions of Internet ExplorerhttpRequest = new ActiveXObject("MSXML2.XMLHTTP.3.0");

}httpRequest.open(method, url, true);

Once the connection has been established, setup the response handler.

38 FME Server Developer's Guide

Page 39: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

// code to deal with response goes here}else{

// an error occurred - varies depending on request(see API docs)alert("An error occurred");

}}

}

A very important step is to ensure a message is sent after setting thereponse handler, otherwise a response will not be received.

// null for certain requestshttpRequest.send(parameters);

Working with Token Security

The simplest method to authenticate a user using the REST API is through thefmetoken security.

First, generate a token for a set period of time using the user's credentials.

For the duration specified, the token will be valid, and should be used when-ever accessing the REST API.

httpRequest.open("POST", "/fmetoken/service/generate",true);httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");var param = "user="+userid_+"&password="+password_+"&e-xpiration=1&timeunit=hour";httpRequest.setRequestHeader("Content-length",param.length);httpRequest.setRequestHeader("Connection", "close");

FME Server Developer's Guide 39

Page 40: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

token_ = httpRequest.responseText;}else{

println("Error: Authentication failure.");}

}}httpRequest.send(param);

Working with Repositories

A repository is a central place to store items, resources and other thingsthat enable the FME Server to perform its functions. A typical item is aworkspace, a custom format or a custom transformer. Associated withitems are resources.

How to list available repositories

Listing repositories requires a GET request, with no parameters.

httpRequest.open("GET", "/fme-rest/repositories.json?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

var reply = eval("(" + httpRequest.responseText + ")");// verify repositories existif (typeof(reply.serviceResponse.repositories) !='undefined'){

40 FME Server Developer's Guide

Page 41: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

var repositories = reply.ser-viceResponse.repositories.repository;for (var i in repositories){

println(repositories[i].name);}

}else{

println("No Repositories");}

}else{

println("Error");}

}}httpRequest.send(null);

How to add repositories

Repositories are uniquely identified by their name. A new repository can becreated by specifying a new repository name and a repository description.Adding a repository requires a POST method, with the parameters sent.

Note: If you don’t check if a repository with the same name alreadyexists and then add a repository with the same name, theexisting repository will be overwritten.

httpRequest.open("POST", "http:/-/localhost/fmerest/repositories.json?token="+token_, true);httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");var param = "repository="+name+"&description="+description;httpRequest.setRequestHeader("Content-length",param.length);httpRequest.setRequestHeader("Connection", "close");httpRequest.onreadystatechange = function(){

FME Server Developer's Guide 41

Page 42: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

println("Repository added");}else{

println("Failed to add repository");}

}}httpRequest.send(param);

How to remove repositories

Removing a repository requires the name of the repository. It’s importantto know that removing a repository will also remove any items andresources in it.

httpRequest.open("DELETE", "/fme-rest/repositories/"+name+".json?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

println("Repository removed");}else{

println("Failed to remove repository");}

}}httpRequest.send(null);

42 FME Server Developer's Guide

Page 43: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

Working with Workspaces

A workspace is a type of repository item so the concepts in this section willalso apply to other repository items such as custom formats and customtransformers. A workspace normally has an FMW file extension, whereas cus-tom formats have a FDS file extension and custom transformers have a FMXfile extension.

FME workspaces are created through FME Workbench and can be publishedto an FME Server repository so that multiple users can access them. Work-spaces in the FME Server repository can also be downloaded, modified, andthen published again.

A default installation of FME Server comes with a number of demo work-spaces but most users will create their own workspaces. In this section, it’sassumed you will either use one of the demo workspaces or create a work-space of your own using FME Workbench.

How to list workspaces in a repository

Workspace names can be quickly listed using repository methods that getthe workspace summaries of a workspace. More detailed information aboutworkspaces can be fetched with the uri's provided.

httpRequest.open("GET", "/fme-rest/repositories/"+name+".json?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

var reply = eval("(" + httpRequest.responseText + ")");if (typeof(reply.ser-viceResponse.repository.workspaces) != 'undefined'){

var workspaces = reply.ser-viceResponse.repository.workspaces;for (var i in workspaces){

println(workspaces[i].name);

FME Server Developer's Guide 43

Page 44: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

}}else{

println("No Workspaces Found");}

}else{

println("Error: "+httpRequest.responseText);}

}}httpRequest.send(null);

How to add workspaces to a repository

Adding workspaces using REST and webpages is not possible due to PUT notbeing supported in major web browsers. The only work around is to use theFME Web Services API provided.

How to get workspaces from a repository

To get a workspace from a repository, the repository name, the local work-space file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name(ie. foo.fmw) are required. The workspace name uniquely identifies a work-space in a repository and should match the workspace you wish to get.When getting a workspace, the actual workspace file is downloaded fromthe FME Server repository to the specified local workspace file path.

win-dow.l-ocation="/fmerest/repositories/"+repositoryName+"/"+workspaceName+"?token="+token_;

How to remove workspaces in a repository

To remove a worksapce in a repository, the repository name and the work-space name are required.

httpRequest.open("DELETE", "/fme-rest/re-

44 FME Server Developer's Guide

Page 45: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

pos-ito-ries/"+repositoryName+"/"+workspaceName+".json?token="+token_,true);

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

println("Workspace removed");}else{

println("Failed to remove workspace");}

}}httpRequest.send(null);

Working with Resources

Some workspaces may require resources to successfully run. Any resourcesassociated with a workspace are placed with the workspace and areaccessed through the repository object.

How to list resources for a workspace

To view the resources that already exist for a workspace, the repositoryname and the workspace name are required.

httpRequest.open("GET", "/fme-rest/re-positories/"+repositoryName+"/"+workspaceName+"/resources.json?token="+token_,true);

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

FME Server Developer's Guide 45

Page 46: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

var reply = eval("(" + httpRequest.responseText + ")");

if (typeof(reply.serviceResponse.resources.resource)!= 'undefined'){

var resources = reply.serviceResponse.resources;for (var i in resources){

println(resources[i].name);}

}else{

println("No Resources Found");}

}else{

println("Error");}

}}httpRequest.send(null);

How to add resources for a workspace

Adding resources using REST and web pages is not possible due to PUTmethod not being supported in major web browsers. The only work aroundis to use the REST API Demo - JavaScript provided.

How to get resources for a workspace

To get a resource for a workspace, the repository name, the workspacename, the local resource file path (ie. C:\myresources\resource.csv)and the resource name (ie. resource.csv) are required. The resource nameuniquely identifies a resource for a workspace and should match theresource you wish to get. When getting a resource, the actual resource fileis downloaded from the FME Server repository to the local resource filepath.

46 FME Server Developer's Guide

Page 47: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

var repositoryName = getInput("Please enter the repositoryname for the resource to get:");var workspaceName = getInput("Please enter the workspacename for the resource to get:");var resourceName = getInput("Please enter the resource namefor the resource to get:");

win-dow.l-ocation="/fmerest/repositories/"+repositoryName+"/"+workspaceName+"/resources/"+resourceName+"?token="+token_;

How to remove resources for a workspace

To remove a specific resource from a workspace, the repository name, work-space name, and resource name are required. Removing a specific work-space will also remove all associated resources for the workspace.

httpRequest.open("DELETE", "/fme-rest/re-positories/"+repositoryName+"/"+workspaceName+"/resources/"+resourceName+".json?token="+token_,true);

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

println("Resource removed");}else{

println("Failed to remove resource");}

}}httpRequest.send(null);

Working with Services

Services require administrative privileges to access. The token serviceshould be enabled (default installation).

FME Server Developer's Guide 47

Page 48: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

How to list available services

Listing services requires the GET method and the url.

httpRequest.open("GET", "/fme-rest/services.json?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

var reply = eval("(" + httpRequest.responseText + ")");

if (typeof(reply.serviceResponse.services.service)!= 'undefined'){

var resources = reply.ser-viceResponse.services.service;for (var i in resources){

println(resources[i].name);}

}else{

println("No Resources Found");}

}else{

println("Error");}

}}httpRequest.send(null);

48 FME Server Developer's Guide

Page 49: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

How to add services

To add a new service, the service name, service display name, descriptionand URL pattern are required. If there is an existing service with the samename, it will be replaced.

httpRequest.open("POST", "/fme-rest/services.json?token="+token_, true);

httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");var param = "service="+name;param += "&description="+description;param += "&displayname="+displayName;param += "&urlpattern="+urlPattern;param += "&isenabled=true";param += "&isregallowed=true";

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

println("Service added");}else{

println("Failed to add service");}

}}httpRequest.send(param);

How to remove services

To remove a service, only the service name which uniquely identifies theservice is required.

FME Server Developer's Guide 49

Page 50: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

httpRequest.open("DELETE", "/fme-rest/services/"+name+".json?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

println("Service removed");}else{

println("Failed to remove service");}

}}httpRequest.send(null);

Running Workspaces

Once a workspace is published to an FME Server repository, the workspacecan be run. This can be done by constructing and then sending a GETrequest to the URL as defined by the REST API documentation. Normallyusers would create their own workspaces, but for this example we will beusing a demo workspace that is included with the default installation of theFME Server.

Some workspaces have published parameters that can be set. Some havedefault values but others need to be explicitly set before we are able to runthe workspace. These depend on the workspace itself.

To get a list of the published parameters available for the workspace:

httpRequest.open("GET", "/fme-rest/re-positories/"+repositoryName+"/"+workspaceName+"/parameters.json?token="+token_,true);

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

50 FME Server Developer's Guide

Page 51: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

if (httpRequest.status == 200){

var reply = eval("(" + httpRequest.responseText + ")");if (typeof(reply.ser-viceResponse.parameters.parameter) != 'undefined'){

var parameter = reply.ser-viceResponse.parameters.parameter;for (var i in parameter){

println(parameter[i].description + " ("+ parameter[i].name + ")");

}}else{

println("No Parameters Found");}

}else{

println("Error");}

}}httpRequest.send(null);

To set such a published parameter - in this case MAXY - add it to the param-eter to be sent:

parameter += "&MAXY=50";

Note: Values for published parameters must always be passed as astring, regardless of what they actually represent.

There also exist directives that are always available from the FME Server. Alist of TM directives can be found in Transformation Manager Directives. Forour example, we set a high value for the priority of this job, in order to tellthe FME Server to execute it before other tasks. This is not necessary butjust done to illustrate how to set directives.

FME Server Developer's Guide 51

Page 52: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

parameter += "&tm_priority=50";

The transformation result has a number of methods for obtaining differentparts of information from the FME Server response. In our example weparse and display a few important points from the string that was receivedfrom the server. In certain scenarios, the clients may want to do their ownparsing on this string instead of relying on the provided methods.

httpRequest.open("POST", "/fme-rest/re-positories/"+repositoryName+"/"+workspaceName+"/run.json?token="+token_,true);

httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");var param = "";httpRequest.setRequestHeader("Content-length",param.length);httpRequest.setRequestHeader("Connection", "close");

httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

// generate an output message based on the responsereceivedvar reply = eval("(" + httpRequest.responseText + ")");

var result = reply.ser-viceResponse.fmeTransformationResult;var output = "Job status: " + result.fm-eServerResponse.jobStatus + "\n";output+= "FME transformation result:\n";output+= "Request: " + result.fm-eServerResponse.request + "\n";

52 FME Server Developer's Guide

Page 53: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

output+= "Reply message: " + result.fm-eServerResponse.result + "\n";

println(output);}else{

println("Error");}

}}httpRequest.send(param);

Working with Jobs

How to list all jobs

Jobs fall into one of four categories: completed, queued, scheduled, and run-ning. In order to list each job, we must iterate through all the categories.

var categories = ["running", "completed", "scheduled","queued"];

listJobCategory(categories);}

function listJobCategory(categories){

if (categories.length == 0){return;}category = categories.shift();

httpRequest.open("GET", "/fme-rest/jobs/"+category+".json?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

FME Server Developer's Guide 53

Page 54: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

var reply = eval("(" + httpRequest.responseText +")");if (typeof(reply.serviceResponse.jobs.job) !='undefined'){

var jobs = reply.serviceResponse.jobs.job;var output = new Array();

for (var i in jobs){

output.push(jobs[i].ID);}println(category);println(output.join(","));

}else{

println("No Parameters Found");}

}else{

println("Error");}listJobCategory(categories);}

}httpRequest.send(null);

}

How to view the details of a job

To view the details of a specific job, the job ID is required.

httpRequest.open("GET", "/fme-rest/jobs/"+id+".json?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200)

54 FME Server Developer's Guide

Page 55: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

{var reply = eval("(" + httpRequest.responseText + ")");var job = reply.serviceResponse.job;// display any details hereprintln("ID: " + job.ID);println("Status: " + job.jobStatus);

}else{

println("Error");}

}}httpRequest.send(null);

How to delete finished jobs

As jobs are completed, the list piles up. To clear the list of finished jobs,simply send a DELETE request.

httpRequest.open("DELETE", "/fme-rest/jobs/completed.xml?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

println("Completed jobs removed");}else{

println("Failed to remove completed jobs");}

}}httpRequest.send(null);

How to cancel a queued job

To cancel a queued job, the job ID is required.

FME Server Developer's Guide 55

Page 56: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

httpRequest.open("DELETE", "/fme-rest/jobs/"+id+"/cancel.json?token="+token_, true);httpRequest.onreadystatechange = function(){

if (httpRequest.readyState == 4){

if (httpRequest.status == 200){

println("Job cancelled");}else{

println("Failed to cancel job");}

}}httpRequest.send(null);

Tutorial Sample

<html><head><script type="text/javascript">

function formSubmit() {window.returnValue = document.getElementById('prompt-Text').value

window.close();}

function formCancel() {window.returnValue = false;window.close();

}

window.onload = function() {var str = window.dialogArguments;if(str){

56 FME Server Developer's Guide

Page 57: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

document.getElementsByTagName("label")[0].innerHTML =str;document.getElementById("promptText").focus();

}}</script></head><body><form id="promptForm" method="post" action="" onsub-mit="formSubmit(); return false;"><label for="promptText"></label><br /><input type="text" name="promptText" id="promptText" /> <br/><input type="submit" name="btnOK" id="btnOK" value="OK" /><input type="button" name="btnCancel" id="btnCancel"value="Quit" onclick="formCancel()"/></form></body></html>

Java

In this section:

Topic Description

"Java QuickStart" below

Setting up a Java project using Eclipse and theApache HTTP client, and running the REST API com-mand-line demo application.

"Java Tutorial"on page 61

Code for common requests using the REST API.

REST API Demo- Java

Sample Java application using the REST API.

Java Quick Start

The REST API can be browsed through a web browser at http://<host>:<p-ort>/fmerest/.

FME Server Developer's Guide 57

Page 58: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Setting up a Java Project Using Eclipse and Apache HTTP Client

1. Visit http://hc.apache.org to download the Apache HTTP Client.

You will also need the following dependencies:

commons-codec

commons-logging

junit

Refer to http://hc.apache.org/httpclient-3.x/dependencies.html for details.

2. Unzip the downloaded file.

You should see in the lib folder containing several JAR files.

3. Start Eclipse.

4. Choose File > New > Project and select Java Project.

58 FME Server Developer's Guide

Page 59: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

5. Enter FMEServerRESTAPIDemo for the project name.

6. In the Java Settings dialog under the Libraries tab, click on Add Exter-nal JARs button and select the commons-httpclient, commons-codec,and commons-logging JAR files in the Apache HTTP Client lib folderto add to your project.

The names may be different depending on version. You may alsoselect all JARs in the folder.

FME Server Developer's Guide 59

Page 60: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

7. Now add a Java Class file and import the Apache HTTP Client names-pace.

This, for example, can be done with the following line of code:

import org.apache.commons.httpclient.*;

Running the API Sample demo

A sample command-line demo application illustrating the use of the FMEServer REST API is available in Java and JavaScript versions. The Java-Script version, however, has limited functionality due to security issues.

60 FME Server Developer's Guide

Page 61: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

This demo can be used to ensure that everything has been setup properly,and contains code that may be useful for your development process. (Morein-depth coverage can be found in the later sections.)

The Java command-line application requires two parameters: the FMEServer host and FME Server port.

The Java source code was developed using Java JDK V1.5 and is located in:

<FMEServerDir>\Server\sdk\doc\java\FMEServerRESTAPIdemo.java

Add the source code to your project, and run.

Usage: FMEServerRESTAPIDemo <fmeServerHost> <fmeServerPort>

Note: <fmeServerHost> represents the name of the host on whichthe Web Server is running.

<fmeServerPort> represents the TCP/IP port number the WebServer is listening on for requests. The default value is 80 andthis is usually correct for most FME Server installations.

Java Tutorial

This topic is for developers who want to build applications using FME ServerREST API in Java. This topic contains code for common requests with FMEServer REST API.

The JavaScript version handles json replies, whereas the Java version usesthe xml version. To see the html version, go to http://<host>:<p-ort>/fmerest.

Many common operations such as obtaining a server session, managingrepository items and resources, and running workspaces are outlined. Pleasenote that the sample code provided is intended for demonstration purposesonly:

REST API Demo - Java

FME Server Developer's Guide 61

Page 62: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Working with Java and XML

For the purpose of this tutorial, we will be using a built in XML parser inJava. First, we must import the required packages:

import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;

Let us also create a function that can take a string and transform it to anXML document.

private Document parseXML(String contents) throws Exception{

DocumentBuilderFactory dbf = Doc-umentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();InputSource is = new InputSource();is.setCharacterStream(new StringReader(contents));Document doc = db.parse(is);return doc;

}

Working with Token Security

The simplest method to authenticate a user using the REST API is throughthe fmetoken security.

First, generate a token for a set period of time using the user's credentials.

For the duration specified, the token will be valid, and should be used when-ever accessing the REST API.

String fmeUrl = "http://"+host_+":"+port_+"/-fmetoken/service/generate";

PostMethod method = new PostMethod(fmeUrl);method.addParameter("user", userid_);method.addParameter("password", password_);method.addParameter("expiration", "1");method.addParameter("timeunit", "hour");

if (client_.executeMethod(method) == 200)

62 FME Server Developer's Guide

Page 63: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

{token_ = method.getResponseBodyAsString();

}else{

throw new Exception("Authentication failed");}

Working with Repositories

A repository is a central place to store items, resources and other things thatenable the FME Server to perform its functions. A typical item is a work-space, a custom format or a custom transformer. Associated with items areresources.

How to list available repositories

Listing repositories requires a GET request, with no parameters.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/repositories.xml?token="+token_;GetMethod method = new GetMethod(fmeUrl);

client_.executeMethod(method);String contents = method.getResponseBodyAsString();

Document doc = parseXML(contents);NodeList nl = doc.getElementsByTagName("repository");

for (int s = 0; s < nl.getLength(); s++) {System.out.println(((Element)nl.item(s))-.getElementsByTagName("name").item(0).getTextContent());

}

How to add repositories

Repositories are uniquely identified by their name. A new repository can becreated by specifying a new repository name and a repository description.Adding a repository requires a POST method, with the parameters sent.

FME Server Developer's Guide 63

Page 64: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Note: If you don’t check if a repository with the same namealready exists and then add a repository with the samename, the existing repository will be overwritten.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/repositories.xml?token="+token_;PostMethod method = new PostMethod(fmeUrl);

method.addParameter("repository", name);method.addParameter("description", description);

if (client_.executeMethod(method) != 200){

throw new Exception("Repository creation failed: " + meth-od.getResponseBodyAsString());

}

How to remove repositories

Removing a repository requires the name of the repository. It’s importantto know that removing a repository will also remove any items andresources in it.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/repositories/"+name+".xml?token="+token_;DeleteMethod method = new DeleteMethod(fmeUrl);

if (client_.executeMethod(method) != 200){

throw new Exception("Repository deletion failed");}

Working with Workspaces

A workspace is a type of repository item so the concepts in this section willalso apply to other repository items such as custom formats and customtransformers. A workspace normally has an FMW file extension, whereas

64 FME Server Developer's Guide

Page 65: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

custom formats have a FDS file extension and custom transformers have aFMX file extension.

FME workspaces are created through FME Workbench and can be publishedto an FME Server repository so that multiple users can access them. Work-spaces in the FME Server repository can also be downloaded, modified, andthen published again.

A default installation of FME Server comes with a number of demo work-spaces but most users will create their own workspaces. In this section, it’sassumed you will either use one of the demo workspaces or create a work-space of your own using FME Workbench.

How to list workspaces in a repository

Workspace names can be quickly listed using repository methods that getthe workspace summaries of a workspace. More detailed information aboutworkspaces can be fetched with the uri's provided.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/repositories/"+name+".xml?token="+token_;GetMethod method = new GetMethod(fmeUrl);

client_.executeMethod(method);String contents = method.getResponseBodyAsString();

Document doc = parseXML(contents);NodeList nl = doc.getElementsByTagName("workspace");

for (int s = 0; s < nl.getLength(); s++) {System.out.println(((Element)nl.item(s))-.getElementsByTagName("name").item(0).getTextContent());

}

How to add workspaces to a repository

To add a new workspace to a repository, the repository name, the work-space file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name

FME Server Developer's Guide 65

Page 66: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

(ie. foo.fmw) are required. When adding a workspace, the actual work-space file is uploaded to the FME Server repository.

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+".xml?token="+token_;PutMethod method = new PutMethod(fmeUrl);

method.setRequestEntity(new FileRequestEntity(

new File(workspaceFilePath), "doesn't matter"));

if (client_.executeMethod(method) != 200){

throw new Exception("Adding workspace failed");}

How to get workspaces from a repository

To get a workspace from a repository, the repository name, the local work-space file path (ie. C:\myworkspaces\foo.fmw) and the workspace name(ie. foo.fmw) are required. The workspace name uniquely identifies a work-space in a repository and should match the workspace you wish to get.When getting a workspace, the actual workspace file is downloaded fromthe FME Server repository to the specified local workspace file path.

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+".xml?token="+token_;

GetMethod method = new GetMethod(fmeUrl);

FileOutputStream file = new FileOutputStream(work-spaceFilePath);PrintStream fileStream = new PrintStream(file);if (client_.executeMethod(method) != 200){

throw new Exception("Getting workspace failed");

66 FME Server Developer's Guide

Page 67: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

}

byte[] responseBody = method.getResponseBody();// Deal with the response.// Use caution: ensure correct character encoding and is notbinary datafileStream.println(new String(responseBody));

fileStream.close();file.close();

How to remove workspaces in a repository

To remove a worksapce in a repository, the repository name and the work-space name are required.

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+".xml?token="+token_;

DeleteMethod method = new DeleteMethod(fmeUrl);if (client_.executeMethod(method) != 200){

throw new Exception("Workspace deletion failed");}

Working with Resources

Some workspaces may require resources to successfully run. Any resourcesassociated with a workspace are placed with the workspace and areaccessed through the repository object.

How to list resources for a workspace

To view the resources that already exist for a workspace, the repositoryname and the workspace name are required.

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+"/resources.xml?token="+token_;

FME Server Developer's Guide 67

Page 68: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

GetMethod method = new GetMethod(fmeUrl);

client_.executeMethod(method);String contents = method.getResponseBodyAsString();

Document doc = parseXML(contents);NodeList nl = doc.getElementsByTagName("resource");

for (int s = 0; s < nl.getLength(); s++) {System.out.println(((Element)nl.item(s))-.getElementsByTagName("name").item(0).getTextContent());

}

How to add resources for a workspace

To add a new resource for a workspace, the repository name, the work-space name, the resource file path (ie. C:\myresources\resource.csv)and the resource name (ie. resource.csv) are required. When adding aresource, the actual resource file is uploaded to the FME Server repository.

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+"/resources/"+resourceName+".xml?token="+token_;

PutMethod method = new PutMethod(fmeUrl);

method.setRequestEntity(new FileRequestEntity(

new File(resourceFilePath), ""));

if (client_.executeMethod(method) != 200){

throw new Exception("Resource addition failed");}

68 FME Server Developer's Guide

Page 69: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

How to get resources for a workspace

To get a resource for a workspace, the repository name, the workspacename, the local resource file path (ie. C:\myresources\resource.csv) andthe resource name (ie. resource.csv) are required. The resource nameuniquely identifies a resource for a workspace and should match theresource you wish to get. When getting a resource, the actual resource file isdownloaded from the FME Server repository to the local resource file path.

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+"/resources/"+resourceName+".xml?token="+token_;

GetMethod method = new GetMethod(fmeUrl);

if (client_.executeMethod(method) != 200){

throw new Exception("Resource download failed");}

FileOutputStream file = new FileOutputStream(resource-FilePath);PrintStream fileStream = new PrintStream(file);byte[] responseBody = method.getResponseBody();

// Deal with the response.// Use caution: ensure correct character encoding and is notbinary datafileStream.println(new String(responseBody));

fileStream.close();file.close();

How to remove resources for a workspace

To remove a specific resource from a workspace, the repository name, work-space name, and resource name are required. Removing a specific work-space will also remove all associated resources for the workspace.

FME Server Developer's Guide 69

Page 70: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+"/resources/"+resourceName+".xml?token="+token_;

DeleteMethod method = new DeleteMethod(fmeUrl);

if (client_.executeMethod(method) != 200){

throw new Exception("Resource deletion failed");}

Working with Services

Services require administrative privileges to access. The token serviceshould be enabled (default installation).

How to list available services

Listing services requires the GET method and the url.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/services.xml?token="+token_;

GetMethod method = new GetMethod(fmeUrl);

client_.executeMethod(method);String contents = method.getResponseBodyAsString();

Document doc = parseXML(contents);NodeList nl = doc.getElementsByTagName("service");

for (int s = 0; s < nl.getLength(); s++) {System.out.println(((Element)nl.item(s))-.getElementsByTagName("name").item(0).getTextContent());

}

70 FME Server Developer's Guide

Page 71: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

How to add services

To add a new service, the service name, service display name, descriptionand URL pattern are required. If there is an existing service with the samename, it will be replaced.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/services.xml";

PostMethod method = new PostMethod(fmeUrl);method.addParameter("token", token_);method.addParameter("service", name);method.addParameter("description", description);method.addParameter("displayname", displayName);method.addParameter("urlpattern", urlPattern);method.addParameter("isenabled", "true");method.addParameter("isregallowed", "true");

if (client_.executeMethod(method) != 200){

throw new Exception("Service creation failed");}

How to remove services

To remove a service, only the service name which uniquely identifies theservice is required.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/services/"+name+".xml?token="+token_;DeleteMethod method = new DeleteMethod(fmeUrl);

if (client_.executeMethod(method) != 200){

throw new Exception("Service deletion failed");}

FME Server Developer's Guide 71

Page 72: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Running Workspaces

Once a workspace is published to an FME Server repository, the workspacecan be run. This can be done by constructing and then sending a GETrequest to the URL as defined by the REST API documentation. Normallyusers would create their own workspaces, but for this example we will beusing a demo workspace that is included with the default installation of theFME Server.

Some workspaces have published parameters that can be set. Some havedefault values but others need to be explicitly set before we are able to runthe workspace. These depend on the workspace itself.

To get a list of the published parameters available for the workspace:

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+"/parameters.xml?token="+token_;

GetMethod method = new GetMethod(fmeUrl);

client_.executeMethod(method);String contents = method.getResponseBodyAsString();

Document doc = parseXML(contents);NodeList nl = doc.getElementsByTagName("parameter");

for (int s = 0; s < nl.getLength(); s++){

System.out.println(((Element)nl.item(s))-.getElementsByTagName("name").item(0).getTextContent());

}

To set such a published parameter - in this case MAXY - add it to the param-eter to be sent:

method.addParameter("MAXY", "50");

72 FME Server Developer's Guide

Page 73: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

Note: Values for published parameters must always be passed as astring, regardless of what they actually represent.

There also exist directives that are always available from the FME Server. Alist of TM directives can be found in Transformation Manager Directives. Forour example, we set a high value for the priority of this job, in order to tellthe FME Server to execute it before other tasks. This is not necessary butjust done to illustrate how to set directives.

method.addParameter("tm_priority", "50");

The transformation result has a number of methods for obtaining differentparts of information from the FME Server response. In our example weparse and display a few important points from the string that was receivedfrom the server. In certain scenarios, the clients may want to do their ownparsing on this string instead of relying on the provided methods.

String fmeUrl = "http://"+host_+":"+port_+"/f-mer-est/repositories/"+repositoryName+"/"+workspaceName+"/run.xml";

PostMethod method = new PostMethod(fmeUrl);method.addParameter("token", token_);// add published parameters

System.out.println("Sending a transformation request to theFME Server...\n");

// Submit the transformation request. This method will blockuntil// transformation results are available. (Users who wish tosubmit jobs// asynchronously should instead use set the parameter toasynchronous method.)client_.executeMethod(method);String contents = method.getResponseBodyAsString();

Document doc = parseXML(contents);

FME Server Developer's Guide 73

Page 74: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

NodeList nl = doc.getElementsByTagName("fme-ServerResponse");

System.out.println("The following information was parsedfrom the response:\n");System.out.println("============");for (int s = 0; s < nl.getLength(); s++){

System.out.println("Job Status: "+((Element)nl.item(s))-.getElementsByTagName("jobStatus").item(0).getTextContent());System.out.println("Job Id: "+((Element)nl.item(s))-.getElementsByTagName("id").item(0).getTextContent());

}System.out.println("============");

Working with Jobs

How to list all jobs

Jobs fall into one of four categories: completed, queued, scheduled, andrunning. In order to list each job, we must iterate through all the cat-egories.

String[] categories = {"running","completed","scheduled","queued"

};

for (String category : categories){

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/jobs/"+category+".xml?token="+token_;GetMethod method = new GetMethod(fmeUrl);

client_.executeMethod(method);String contents = method.getResponseBodyAsString();

74 FME Server Developer's Guide

Page 75: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

REST Service

Document doc = parseXML(contents);NodeList nl = doc.getElementsByTagName("job");

System.out.println(category + ":");

for (int s = 0; s < nl.getLength(); s++){

System.out.println(((Element)nl.item(s))-.getElementsByTagName("ID").item(0).getTextContent());

}}

How to view the details of a job

To view the details of a specific job, the job ID is required.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/jobs/"+id+".xml?token="+token_;GetMethod method = new GetMethod(fmeUrl);

client_.executeMethod(method);String contents = method.getResponseBodyAsString();

Document doc = parseXML(contents);NodeList nl = doc.getElementsByTagName("job");

for (int s = 0; s < nl.getLength(); s++){

System.out.println(((Element)nl.item(s))-.getElementsByTagName("ID").item(0).getTextContent());// add any extra things to view here;

}

How to delete finished jobs

As jobs are completed, the list piles up. To clear the list of finished jobs,simply send a DELETE request.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/jobs/completed.xml?token="+token_;

FME Server Developer's Guide 75

Page 76: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

DeleteMethod method = new DeleteMethod(fmeUrl);if (client_.executeMethod(method) != 200){

throw new Exception("Job deletion failed");}

How to cancel a queued job

To cancel a queued job, the job ID is required.

String fmeUrl = "http://"+host_+":"+port_+"/f-merest/jobs/"+id+"/cancel.xml?token="+token_;

PostMethod method = new PostMethod(fmeUrl);if (client_.executeMethod(method) != 200){

throw new Exception("Job cancellation failed");}

FME Server REST PlaygroundThe FME Server REST Playground is a set of interactive examples that illus-trate how to build applications for various FME Web Server services, includ-ing Data Download, Data Streaming, Data Upload, Notification, and others.

New examples are constantly being added.

To access the REST Playground: click here.

76 FME Server Developer's Guide

Page 77: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

Developing with the Core APIsThe FME Server Core manages job requests (queuing, request routing, sched-uling) and repository contents (workspaces, custom formats, custom trans-formers, data).

This section provides quick-start, tutorial, and sample applications to man-age the FME Server Core, using the following interfaces:

n "Java" below

n ".NET" on page 115

n "C++" on page 151

JavaIn this section:

Topic Description

"JavaQuick Start" on nextpage

Setting up a Java project using Eclipse, and running theFME Server API command-line demo application.

"Java Tuto-rial " onpage 81

Outlines common operations using the FME Server API,such as obtaining a server session, managing repos-itories, and running workspaces.

"JavaExample"on page 95

A demo application using the FME Server API.

Java API Documentation

Available here.

Java Quick Start

Setting Up a Java Project Using Eclipse

1. Start Eclipse.

2. Choose File > New > Project and select Java Project.

FME Server Developer's Guide 77

Page 78: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

3. Enter FMEServerAPIDemo for the project name.

4. In the Java Settings dialog under the Libraries tab, click on Add Exter-nal JARs button and select all the JARs in the<FMEServerDir>\Server\sdk\java folder to add to your project.

Developing with the Core APIs

78 FME Server Developer's Guide

Page 79: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

5. Now add a Java Class file and import the FME Server Java API names-pace. This for example can be done with the following line of code:

import COM.safe.fmeserver.api.*;

Running the API Sample demo...

A sample command-line demo application illustrating the use of the FMEServer API is available in C++, .Net, and Java versions.

This demo can be used to ensure that everything has been setup properly,and contains code that may be useful for your development process. (Morein-depth coverage can be found in the later sections.)

FME Server Developer's Guide 79

Page 80: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

If security is enabled for FME Server, your application must provide a clientID that has been registered with FME Server. The client ID for the demoapplication is app_apidemo. By default, the demo's client ID is not reg-istered with FME Server, and you must register the client ID. (See"Resources" on page 1 for more information.)

The command-line application requires two parameters: the FME Serverhost and FME Server port.

Note: <fmeServerHost> represents the name of the host on whichthe FME Server is running.

<fmeServerPort> represents the TCP/IP port number theFME Server is listening on for requests. The default value is7071 and this is usually correct for most FME Server instal-lations.

The Java source code was developed using Java JDK V1.5 and is located in:

<FMEServerDir>\Server\sdk\-samples\apidemo\java\FMEServerAPIDemo.java

...using the new project from the previous section

Add the source code to your project, and run.

...independently or with another IDE

To compile:

<jdkInstallDir>\bin\javac.exe FMEServerAPIDemo.java

To run:

<jdkInstallDir>\bin\java.exe -cp .;..\..-\..\Java\fmeserverapi.jar;..\..\..\Java\jaxen-1.1.1.jar;..\..\..\Java\dom4j-1.6.1.jar FMEServerAPIDemo<fmeServerHost> <fmeServerPort>

Developing with the Core APIs

80 FME Server Developer's Guide

Page 81: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

Java Tutorial

This documentation serves as a primer for developers that wish to developapplications using the FME Server API. Many common operations such asobtaining a server session, managing repository items and resources, andrunning workspaces are outlined. Please note that the sample code providedis intended for demonstration purposes only:

API Demo - Java

For demonstration purposes a sample command line application has beencreated to illustrate many of the common FME Server API concepts with sam-ple code. The sample command line application takes two parameters. Thefirst parameter is the FME Server host name and the second parameter isthe FME Server port number. When the command line application isexecuted, you will be prompted for your credentials. (Leave blank for secu-rity-disabled configurations.) Upon verification, a menu is displayed whichprompts you to select a given command. Additional information may berequired depending on the command selected.

FME Server Developer's Guide 81

Page 82: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Sample code is available in Java, C++ and .NET. Please refer to the "JavaQuick Start " on page 78 for information on how to set up your developmentenvironment.

If security is enabled for FME Server, this application's client ID - app_apidemo - is not registered with FME Server, and you must register theclient ID for it to work. (See "Resources" on page 1 for more information.

Working with Server Sessions

The first step in working with the FME Server API is to create a server ses-sion. To create a server session, you use a factory method as shown below.

IFMEServerSession serverSession_ = FME-Server.createServerSession();

Once a server session is created, you can create the objects required to ini-tialize it. To initialize a server session, a connection info object that spec-ifies the server connection parameters needs to be created as shownbelow.

IFMEServerConnectionInfo connectionInfo_= serverSession_.createServerConnectionInfo(host, port,"", "");

If security is enabled, then a client ID must also be provided as a sessiondirective. (See "Enabling SSL on the Application Server" on page 1 and"FME Server Web Service Security Concepts" on page 1.) The client IDmust match the client ID you configured in FME Server.

Note: Providing a client ID on a security-disabled system will notlead to any negative behaviour - the username, password,and client ID will simply be ignored.

Map directives = new HashMap();directives.put(IFMEServerAPIConstants.kKeywordClientID,clientid_);serverSession_.init(connectionInfo_, (Map)(directives));

Developing with the Core APIs

82 FME Server Developer's Guide

Page 83: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

Once a server session is initiated, you can now create any additional objectsto interact with the FME Server. This includes being able to manage itemsand resources with the Repository Manager and running workspaces with theTransformation Manager.

An important consideration when working with server sessions is to ensureyou release your server session when done. If you initialize server sessionswithout ever releasing them, you may eventually run out of connectionrelated resources. Releasing a server session is shown below.

serverSession_.disconnect();

Note: The FME Server API is case insensitive but case preserving forall unique identifiers such as repository name, workspacename, resource name, service name, etc.

Working with Repositories

The Repository Manager component of the FME Server manages repos-itories. A repository is a central place to store items, resources and otherthings that enable the FME Server to perform its functions. A typical item is aworkspace, a custom format or a custom transformer. Associated with itemsare resources.

To access a repository, you will need to get the Repository Manager objectfrom the server session as shown below.

IFMERepositoryManager repositoryMgr_ = server-Session_.getRepositoryManager();

How to list available repositories

The Repository Manager object allows us to get all available repositories.

ArrayList<IFMERepository> repositoryList = repos-itoryMgr_.getRepositories(null);for (IFMERepository repository : repositoryList){

System.out.format("%s %s\n",repository.getName(),repository.getDescription());

}

FME Server Developer's Guide 83

Page 84: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

How to add repositories

Repositories are uniquely identified by their name. A new repository can becreated by specifying a new repository name and a repository description.

Note: If you don't check if a repository with the same namealready exists and then add a repository with the samename, you will need to handle either the FME Server excep-tion or error that is returned.

if (!repositoryMgr_.repositoryExists(name)){

repositoryMgr_.addRepository(name, description);}else{

throw new FMEServerException("There is already a repos-itory with this name!");

}

How to remove repositories

Removing a repository requires the name of the repository. It's importantto know that removing a repository will also remove any items andresources in it.

if (!repositoryMgr_.removeRepository(name)){

throw new FMEServerException("There is no repository withthis name!");

}

Working with Workspaces

A workspace is a type of repository item so the concepts in this section willalso apply to other repository items such as custom formats and customtransformers. A workspace normally has an FMW file extension, whereascustom formats have a FDS file extension and custom transformers have aFMX file extension.

Developing with the Core APIs

84 FME Server Developer's Guide

Page 85: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

FME workspaces are created through FME Workbench and can be publishedto an FME Server repository so that multiple users can access them. Work-spaces in the FME Server repository can also be downloaded, modified, andthen published again.

A default installation of FME Server comes with a number of demo work-spaces but most users will create their own workspaces. In this section, it'sassumed you will either use one of the demo workspaces or create a work-space of your own using FME Workbench.

How to list workspaces in a repository

Workspace names can be quickly listed using repository methods that getthe workspace summaries of a workspace. More detailed information aboutworkspaces can also be fetched with other repository methods.

ArrayList<IFMERepository> repositories = repos-itoryMgr_.getRepositories(null);for (IFMERepository repository : repositories){

ArrayList<IFMEWorkspaceSummary> workspaceSummaries =repository.getWorkspaceSummaries(null);for (IFMEWorkspaceSummary workspaceSummary : work-spaceSummaries){

System.out.format("Repository:%s %s %s ON:%s\n",repository.getName(),workspaceSummary.getTitle(),workspaceSummary.getName(),workspaceSummary.getIsEnabled());

}}

How to add workspaces to a repository

To add a new workspace to a repository, the repositosry name, the work-space file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name(ie. foo.fmw) are required. When adding a workspace, the actual workspacefile is uploaded to the FME Server repository.

FME Server Developer's Guide 85

Page 86: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);if (!repository.itemExists(workspaceName)){

repository.addItem(workspaceName, workspaceFilePath);}else{

throw new FMEServerException("There is already a work-space with this name!");

}

How to update workspaces in a repository

To update a workspace in a repository, the repository name, the workspacefile path (ie. "C:\myworkspaces\foo.fmw") and the workspace name (ie.foo.fmw) are required. The workspace name uniquely identifies a work-space in a repository and should match the workspace you wish to update.When updating a workspace, the actual workspace file is uploaded to theFME Server repository.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);if (repository.itemExists(workspaceName)){

repository.updateItem(workspaceName, workspaceFilePath);}else{

throw new FMEServerException("There is no workspace withthis file name!"); }

How to get workspaces from a repository

To get a workspace from a repository, the repository name, the local work-space file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name(ie. foo.fmw) are required. The workspace name uniquely identifies a work-space in a repository and should match the workspace you wish to get.

Developing with the Core APIs

86 FME Server Developer's Guide

Page 87: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

When getting a workspace, the actual workspace file is downloaded from theFME Server repository to the specified local workspace file path.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);if (repository.itemExists(workspaceName)){

repository.getItem(workspaceName, workspaceFilePath);}else{

throw new FMEServerException("There is no workspace withthis file name!");

}

How to remove workspaces in a repository

To remove a workspace in a repository, the repository name and the work-space name are required.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);if (!repository.removeItem(workspaceName)){

throw new FMEServerException("There is no workspace withthis file name!");

}

Working with Resources

Some workspaces may require resources to successfully run. Any resourcesassociated with a workspace are placed with the workspace and areaccessed through the repository object.

How to list resources for a workspace

To view the resources that already exist for a workspace, the repositoryname and the workspace name are required.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);

FME Server Developer's Guide 87

Page 88: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IFMEWorkspace workspace = repository.getWorkspace(work-spaceName);

ArrayList<IFMEResource> resources = workspace.getResources();for (IFMEResource resource : resources){

System.out.format("%s %s\n",resource.getName(),resource.getDescription());

}

How to add resources for a workspace

To add a new resource for a workspace, the repository name, the work-space name, the resource file path (ie. "C:\myresources\resource.csv) andthe resource name (ie. resource.csv) are required. When adding aresource, the actual resource file is uploaded to the FME Server repository.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);if (!repository.resourceExists(workspaceName, resource-Name)){

repository.addResource(workspaceName, resourceName,resourceFilePath);

}else{

throw new FMEServerException("There is already a resourcewith this name!");

}

How to update resources for a workspace

To update a resource for a workspace, the repository name, the workspacename, the resource file path (ie. "C:\myresources\resource.csv") and the

Developing with the Core APIs

88 FME Server Developer's Guide

Page 89: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

resource name (ie. resource.csv) are required. The resource name uniquelyidentifies a resource for a workspace and should match the resource youwish to update. When updating a resource, the actual resource file isuploaded to the FME Server repository.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);if (repository.resourceExists(workspaceName, resourceName)){

repository.updateResource(workspaceName, resourceName,resourceFilePath);

}else{

throw new FMEServerException("There is no resource withthis name!");

}

How to get resources for a workspace

To get a resource for a workspace, the repository name, the workspacename, the local resource file path (ie. "C:\myresources\resource.csv") andthe resource name (ie. resource.csv) are required. The resource nameuniquely identifies a resource for a workspace and should match theresource you wish to get. When getting a resource, the actual resource file isdownloaded from the FME Server repository to the local resource file path.

FMERepository repository = repositoryMgr_.getRepository(repositoryName);if (repository.resourceExists(workspaceName, resourceName)){

repository.getResource(workspaceName, resourceName,resourceFilePath);

}else{

throw new FMEServerException("There is no resource withthis name!");

}

FME Server Developer's Guide 89

Page 90: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

How to remove resources for a workspace

To remove a specific resource from a workspace, the repository name,workspace name, and resource name are required. Removing a specificworkspace will also remove all associated resources for the workspace.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);if (!repository.removeResource(workspaceName, resource-Name)){

throw new FMEServerException("There is no resource withthis name!");

}

Working with Services

The default installation of FME Server makes available a number of serv-ices, each providing a specific functionality to the end-user. The serviceobject provides you with information about these services such as the serv-ice name and service URL pattern. It also allows you to create new servicedescriptions for services that you may wish to create.

How to list available services

To list the available services the Repository Manager object is required.

ArrayList<IFMEService> services = repos-itoryMgr_.getServices(null);for (IFMEService service : services){

System.out.format("%s %s %s ON:%s %s\n",service.getDisplayName(),service.getName(),service.getURLPattern(),service.getIsEnabled(),service.getDescription());

}

Developing with the Core APIs

90 FME Server Developer's Guide

Page 91: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

How to add services

To add a new service, the service name, service display name, descriptionand URL pattern are required.

IFMEService service = serverSession_.createService(name, dis-playName, description, urlPattern);if (!repositoryMgr_.serviceExists(name)){

repositoryMgr_.addService(service);}else{

throw new FMEServerException("There is already a servicewith this name!");

}

How to update services

To add a new service, the service name, service display name, descriptionand URL pattern are required. The service name uniquely identifies a serv-ice.

IFMEService service = serverSession_.createService(name, dis-playName, description, urlPattern);if (repositoryMgr_.serviceExists(name)){

repositoryMgr_.updateService(service);}else{

throw new FMEServerException("There is no service withthis name!");

}

How to remove services

To remove a service, only the service name which uniquely identifies theservice is required.

if (!repositoryMgr_.removeService(name))

FME Server Developer's Guide 91

Page 92: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

{ throw new FMEServerException("There is no service withthis name!");

}

Running Workspaces

Once a workspace is published to an FME Server repository, the workspacecan be run. This can be done by constructing and then submitting a jobrequest using the Transformation Manager object. Normally users wouldcreate their own workspaces, but for this example we will be using a demoworkspace that is included with the default installation of the FME Server.

First step is to connect to the transformation manager, the component ofthe FME Server that handles job requests.

IFMETransformationManager transformationMgr = ses-sion_.getTransformationManager();

Next, we need to create a transformation request that will be submitted tothe FME Server. The expected parameters are:

n The name of an FME Server node subsection, as defined in the node'sconfiguration. SERVER_CONSOLE_CLIENT is one such subsection, partof the default configuration that ships with the FME Server. Each sub-section specifies various processing directives (e.g. the folder whereoutput should be placed). For information on the different sub-sections, please refer to <FMEServerDir>\Server\f-meServerConfig.txt.

n The unique name of the repository that contains the target file, demo-download is one such repository, which contains the workspace "aus-tin.fmw".

n The name of a workspace, mapping file or command file that is to beexecuted by FME. In the latter case, the file is assumed to reside inthe FME_MAPPING_DIR that has been set for the subsection that weselected with the first parameter. Here, we specify a workspacecalled austin.fmw from the demodownload repository.

Developing with the Core APIs

92 FME Server Developer's Guide

Page 93: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

IFMETransformationRequest req = ses-sion_.createTransformationRequest(

"SERVER_CONSOLE_CLIENT", "demodownload", "aus-tin.fmw");

Some workspaces have published parameters that can be set. Some havedefault values but others need to be explicitly set before we are able to runthe workspace. These depend on the workspace itself. To set such a pub-lished parameter - in this case MAX_FEATURES:

req.setPublishedParameter("MAX_FEATURES", "2000");

Note: Values for published parameters must always be passed asstrings, regardless of what they actually represent.

There also exist directives that are always available from the FME Server. Alist of TM directives can be found here. Since we are functionality specificallyfor setting TM directives, we do not need the "tm_" prefix. For our example,we set a high value for the priority of this job, in order to tell the FME Serverto execute it before other tasks. This is not necessary but just done to illus-trate how to set directives.

req.setTMDirective("priority", 42);

Once all parameters and directives have been set, we can submit ourrequest to the FME Server. A transformation request can be submitted eithersynchronously or asynchronously.

If a job is submitted synchronously, the method call will be blocked until thejob has finished. The results are stored in a transformation result object.

IFMETransformationResult result = transformer.transactJob(req);

If a job is submitted asynchronously, the method call will immediately returnthe job ID, which can be used to check if the job has finished. Checking theresult of a specified transformation job can be done in a wait-loop until theresult is available.

IFMETransformationResult result = server-Session_.createTransformationResult();long jobID = transformer.submitJob(req);

FME Server Developer's Guide 93

Page 94: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

while (!transformer.getJobResult(jobID, result)){

// Wait for 500 millisecondsThread.sleep(500);

}

The transformation result object has a number of methods for obtaining dif-ferent parts of information from the FME Server response. In our examplewe first display the raw, unparsed string that was received from theserver. In certain scenarios, the clients may want to do their own parsingon this string instead of relying on the provided methods.

System.out.println(result.getFMEServerResponse());

We can now display additional pieces of information. First, we check thatthe transformation was successful and, if so, we list some of the returnedproperties. Properties are stored as name = value pairs, though some ofthem may be null.

if (!result.getTransformationSuccess()){

throw new FMEServerException("Transformation failed.\nTheerror was: "

+ result.getStatusMessage());}else{

System.out.println("Transformation successful!");System.out.println("The following information was parsedfrom the response:");for (Map.Entry<String,String> prop : result.g-etAllProperties().entrySet()){

// We ignore the null-valued properties and list allthe rest if (prop.getValue().length() > 0){

System.out.println(prop.getKey() + " = " + prop.ge-tValue());

}}

Developing with the Core APIs

94 FME Server Developer's Guide

Page 95: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

}

Java Example/*==========================================================-====================

Name : FMEServerAPIDemo.javaSystem : FME Server APILanguage : JavaPurpose : FMEServerAPIDemo sample application

Author Date Changes made------------------ ------------ -------------------------------Sample Jun 19, 2008 Original Definition

Copyright (c) 1994 - 2011, Safe Software Inc.All Rights ReservedThe entire risk as to the results and performance of thesoftware,supporting text and other information contained in thisfile(collectively called the "Software") is with the user.AlthoughSafe Software Incorporated has used considerable effortsin preparingthe Software, Safe Software Incorporated does not warranttheaccuracy or completeness of the Software. In no event willSafe SoftwareIncorporated be liable for damages, including loss of prof-its orconsequential damages, arising out of the use of the Soft-ware.

============================================================-==================*/

import java.io.BufferedReader;import java.io.File;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;

FME Server Developer's Guide 95

Page 96: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

import java.util.Map;import COM.safe.fmeserver.api.*;public class FMEServerAPIDemo{

// The repository managerprivate IFMERepositoryManager repositoryMgr_ = null;

// Used to read content from the userprivate BufferedReader br_ = null;

// The server sessionprivate IFMEServerSession serverSession_ = null;

private String userid_ = null;private String password_ = null;private String clientid_ = "app_apidemo";

public FMEServerAPIDemo(String host, int port) throwsFMEServerException{

serverSession_ = FMEServer.createServerSession();

br_ = new BufferedReader(new InputStreamReader(Sys-tem.in));

try{getConnectionInfo();}catch (IOException e){System.err.println(e.getMessage());}

IFMEServerConnectionInfo connectionInfo_ = server-Session_.createServerConnectionInfo(host, port, use-rid_, password_);Map&lt;String, String&gt; directives = new Hash-Map&lt;String, String&gt;();directives.put(IFME-ServerAPIConstants.kKeywordClientID, clientid_);

Developing with the Core APIs

96 FME Server Developer's Guide

Page 97: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

serverSession_.init(connectionInfo_, (Map&lt;String,String&gt;)(directives));

repositoryMgr_ = serverSession_.getRepositoryManager();

}

public void getConnectionInfo() throws IOException{

System.out.println("Please enter server connectioncredentials.");System.out.print("UserId:");userid_ = br_.readLine();

if (!userid_.equals("") ){

System.out.print("Password:");password_ = br_.readLine();

}}

public void execute(){

displayMainMenu();try{

int choice = getMenuChoice();executeMenuChoice(choice);

}catch (NumberFormatException e){

System.err.println("Invalid input!");}catch (Exception e){

System.err.println(e.getMessage());}

}

private void cleanup(){

FME Server Developer's Guide 97

Page 98: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

if (serverSession_ != null){try{

serverSession_.disconnect();serverSession_ = null;

}catch(FMEServerException e){

System.err.println(e.getMessage());}

}}

private void displayMainMenu(){

System.out.print("\n\n"s+ "===FME Server API Demo===\n"+ "1. List available repositories\n"+ "2. Add a repository\n"+ "3. Remove a repository\n"+ "4. List available workspaces\n"+ "5. Add a workspace\n"+ "6. Update a workspace\n"+ "7. Get a workspace\n"+ "8. Remove a workspace\n"+ "9. List resources of a workspace\n"+ "10. Add a resource\n"+ "11. Update a resource\n"+ "12. Get a resource\n"+ "13. Remove a resource\n"+ "14. List available services\n"+ "15. Add a service\n"+ "16. Update a service\n"+ "17. Remove a service\n"+ "18. Run a workspace\n"+ "0. Quit\n"+ "\nSELECT: ");

}

Developing with the Core APIs

98 FME Server Developer's Guide

Page 99: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

private int getMenuChoice() throws Num-berFormatException, IOException{

return Integer.parseInt(br_.readLine());}

private void executeMenuChoice(int choice) throws Excep-tion{

switch (choice){

case 1:listRepositories();break;

case 2:addRepository();break;

case 3:removeRepository();break;

case 4:listWorkspaces();break;

case 5:addWorkspace();break;

case 6:updateWorkspace();break;

case 7:getWorkspace();break;

case 8:removeWorkspace();break;

case 9:listResources();break;

case 10:addResource();break;

case 11:

FME Server Developer's Guide 99

Page 100: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

updateResource();break;

case 12:getResource();break;

case 13:removeResource();break;

case 14:listServices();break;

case 15:addService();break;

case 16:updateService();break;

case 17:removeService();break;

case 18:runWorkspace();break;

case 0:cleanup();System.exit(0);

default:System.err.println("Invalid option!");return;

}System.out.println("\nThe operation was a success");

}

private void listRepositories() throws Exception{

ArrayList&lt;IFMERepository&gt; repositoryList =repositoryMgr_.getRepositories(null);for (IFMERepository repository : repositoryList){

System.out.format("%s %s\n",repository.getName(),

Developing with the Core APIs

100 FME Server Developer's Guide

Page 101: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

repository.getDescription());}

}

private void addRepository() throws Exception{

String name = getInput("Please enter the name for thenew repository:");String description = getInput("Please enter thedescription for the new repository:");

if (!repositoryMgr_.repositoryExists(name)){

repositoryMgr_.addRepository(name, description);}else{

throw new FMEServerException("There is already arepository with this name!");

}}

private void removeRepository() throws Exception{

String name = getInput("Please enter the name for therepository to remove:");

if (!repositoryMgr_.removeRepository(name)){

throw new FMEServerException("There is no repos-itory with this name!");

}}

private void listWorkspaces() throws Exception{

ArrayList&lt;IFMERepository&gt; repositories = repos-itoryMgr_.getRepositories(null);for (IFMERepository repository : repositories){

FME Server Developer's Guide 101

Page 102: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

ArrayList&lt;IFMEWorkspaceSummary&gt; work-spaceSummaries = repository.getWorkspaceSummaries(null);for (IFMEWorkspaceSummary workspaceSummary : work-spaceSummaries){

System.out.format("Repository:%s %s %sON:%s\n",

repository.getName(),workspaceSummary.getTitle(),workspaceSummary.getName(),workspaceSummary.getIsEnabled());

}}

}

private void addWorkspace() throws Exception{

String repositoryName = getInput("Please enter therepository name for the new workspace:");String workspaceFilePath = getInput("Please enterthe file path for the new workspace to add:");String workspaceName = new File(work-spaceFilePath).getName();

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);if (!repository.itemExists(workspaceName)){

repository.addItem(workspaceName, work-spaceFilePath);

}else{

throw new FMEServerException("There is already aworkspace with this name!");

}}private void updateWorkspace() throws Exception

Developing with the Core APIs

102 FME Server Developer's Guide

Page 103: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

{String repositoryName = getInput("Please enter therepository name for the workspace to update:");String workspaceFilePath = getInput("Please enter thefile path for the workspace to update:");String workspaceName = new File(work-spaceFilePath).getName();

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);if (repository.itemExists(workspaceName)){

repository.updateItem(workspaceName, work-spaceFilePath);

}else{

throw new FMEServerException("There is no work-space with this file name!");

}}private void getWorkspace() throws Exception{

String repositoryName = getInput("Please enter therepository name for the workspace to get:");String workspaceName = getInput("Please enter thename of the workspace to get:");String workspaceFilePath = getInput("Please enter thelocal file path for the workspace to get:");

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);if (repository.itemExists(workspaceName)){

repository.getItem(workspaceName, work-spaceFilePath);

}else{

throw new FMEServerException("There is no work-space with this file name!");

FME Server Developer's Guide 103

Page 104: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

}}

private void removeWorkspace() throws Exception{

String repositoryName = getInput("Please enter therepository name for the workspace to remove:");String workspaceName = getInput("Please enter thename of the workspace to remove:");

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);if (!repository.removeItem(workspaceName)){

throw new FMEServerException("There is no work-space with this file name!");

}}

private void listResources() throws Exception{

String repositoryName = getInput("Please enter therepository name for the resources:");String workspaceName = getInput("Please enter theworkspace name for the resources:");

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);IFMEWorkspace workspace = repository.getWorkspace(workspaceName);

ArrayList&lt;IFMEResource&gt; resources = work-space.getResources();for (IFMEResource resource : resources){

System.out.format("%s %s\n",resource.getName(),resource.getDescription());

}}

Developing with the Core APIs

104 FME Server Developer's Guide

Page 105: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

private void addResource() throws Exception{

String repositoryName = getInput("Please enter therepository name for the new resource:");String workspaceName = getInput("Please enter theworkspace name for the new resource:");String resourceFilePath = getInput("Please enter thefile path for the new resource to add:");String resourceName = new File(resource-FilePath).getName();

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);if (!repository.resourceExists(workspaceName,resourceName)){

repository.addResource(workspaceName, resource-Name, resourceFilePath);

}else{

throw new FMEServerException("There is already aresource with this name!");

}}

private void updateResource() throws Exception{

String repositoryName = getInput("Please enter therepository name for the resource to update:");String workspaceName = getInput("Please enter theworkspace name for the resource to update:");String resourceFilePath = getInput("Please enter thefile path for the resource to update:");String resourceName = new File(resource-FilePath).getName();

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);if (repository.resourceExists(workspaceName, resource-Name))

FME Server Developer's Guide 105

Page 106: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

{repository.updateResource(workspaceName, resource-Name, resourceFilePath);

}else{

throw new FMEServerException("There is noresource with this name!");

}}

private void getResource() throws Exception{

String repositoryName = getInput("Please enter therepository name for the resource to get:");String workspaceName = getInput("Please enter theworkspace name for the resource to get:");String resourceName = getInput("Please enter theresource name for the resource to get:");String resourceFilePath = getInput("Please enter thelocal file path for the resource to get:");

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);if (repository.resourceExists(workspaceName,resourceName)){

repository.getResource(workspaceName, resource-Name, resourceFilePath);

}else{

throw new FMEServerException("There is noresource with this name!");

}}

private void removeResource() throws Exception{

String repositoryName = getInput("Please enter therepository name for the resource to remove:");

Developing with the Core APIs

106 FME Server Developer's Guide

Page 107: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

String workspaceName = getInput("Please enter theworkspace name for the resource to remove:");String resourceName = getInput("Please enter theresource name for the resource to remove:");

IFMERepository repository = repos-itoryMgr_.getRepository(repositoryName);if (!repository.removeResource(workspaceName,resourceName)){

throw new FMEServerException("There is no resourcewith this name!");

}}

private void listServices() throws Exception{

ArrayList<IFMEService> services = repos-itoryMgr_.getServices(null);for (IFMEService service : services){

System.out.format("%s %s %s ON:%s %s\n",service.getDisplayName(),service.getName(),service.getURLPattern(),service.getIsEnabled(),service.getDescription());

}}

private void addService() throws Exception{

String name = getInput("Please enter the name of thenew service:");String urlPattern = getInput("Please enter the URLpattern of the new service:");String displayName = getInput("Please enter the dis-play name of the new service:");String description = getInput("Please enter thedescription of the new service:");

FME Server Developer's Guide 107

Page 108: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IFMEService service = serverSession_.createService(name, displayName, description, urlPattern);

if (!repositoryMgr_.serviceExists(name)){

repositoryMgr_.addService(service);}else{

throw new FMEServerException("There is already aservice with this name!");

}}

private void updateService() throws Exception{

String name = getInput("Please enter the name of theservice to update:");String urlPattern = getInput("Please enter the URLpattern of the service to update:");String displayName = getInput("Please enter the dis-play name of the service to update:");String description = getInput("Please enter thedescription of the service to update:");

IFMEService service = serverSession_.createService(name, displayName, description, urlPattern);

if (repositoryMgr_.serviceExists(name)){

repositoryMgr_.updateService(service);}else{

throw new FMEServerException("There is no servicewith this name!");

}}

private void removeService() throws Exception{

Developing with the Core APIs

108 FME Server Developer's Guide

Page 109: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

String name = getInput("Please enter the name of theservice to remove:");

if (!repositoryMgr_.removeService(name)){

throw new FMEServerException("There is no servicewith this name!");

}}

private void runWorkspace() throws Exception{

IFMETransformationManager transformer = server-Session_.getTransformationManager();

// Create an IFMETransformationnRequest object toencapsulate our// transformation request that will be submitted tothe server. The// createTransformationRequest(...) method expectsthree parameters: 1.// The name of an FME Server node subsection, asdefined in the node's// configuration. SERVER_CONSOLE_CLIENT is one suchsubsection that is// part of the default configuration that ships withthe FME Server. Each// subsection specifies various processing directives(e.g., the folder// where output should be placed). For information onthe different// subsections, please refer to// &lt;FMEServer-Install-Dir&gt;\Server\fmeServerConfig.txt 2. The unique name// for the repository that contains the mapping fileor command file to be// executed by FME.String repositoryName = getInput("Please enter therepository name for the workspace to run:");String workspaceName = getInput("Please enter thename of the workspace to run:");

FME Server Developer's Guide 109

Page 110: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IFMETransformationRequest req= serverSession_.createTransformationRequest("SERVER_CONSOLE_CLIENT",

repositoryName,workspaceName);

// Set published parameters that have been exposedby the workspace. Both// the name of the published parameter and thedesired value are simple// Strings, even if the value happens to have anumeric interpretation.// Here, we set a published parameter called MAX_FEA-TURES that controls// how many features will be read in from the sourcedataset(s). Published// parameters depend on the workspace that is beingrun.

req.setPublishedParameter("MAX_FEATURES", "2000");

// We can also set certain transformation managerdirectives that// determine how our transformation request will beprocessed. Unlike// published parameters, which are determined byeach workspace's author// and thus vary from one workspace to another, theavailable directives// are constant for all transformation requests. Acomplete list of// directives can be found in the FME Server doc-umentation. Here, we set a// high priority for this job to suggest that itshould be given// precedence over other, lower-priority, jobs.

req.setTMDirective("priority", 42);

Developing with the Core APIs

110 FME Server Developer's Guide

Page 111: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

System.out.println("Sending a transformation requestto the FME Server...\n");

// Submit the transformation request. This methodwill block until// transformation results are available. (Users whowish to submit jobs// asynchronously should instead use the submitJob(...) method.) The// returned results are stored in an IFME-TransformationResult object,// which is the companion to the IFME-TransformationRequest object that we// submitted.

IFMETransformationResult result = trans-former.transactJob(req);

// The transformation result object receives a resultstring from the// server and parses it to extract many differentpieces of information// about the job result. However, users who wish todo their own parsing// of the raw server response, or wish to log thisstring, may obtain the// unparsed response string using the getFME-ServerResponse() method. Here,// we use that method to print out the responsestring to the standard// output.

System.out.println("Response received:\n");System.out.println(result.getFMEServerResponse());System.out.println();

// The IFMETransformationResult interface definesmany accessor methods

FME Server Developer's Guide 111

Page 112: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

// for retrieving specific information from theparsed result. We only// demonstrate a small subset of those methods here;a full list is// available in the FME Server API documentation.The// getTransformationSuccess() method returns trueif, and only if, the// transformation was successful. Here, we check tosee if the// transformation was successful and then print outa message accordingly.

if (!result.getTransformationSuccess()){

// The transformation was not successful. Weinform the user of this// and then use getStatusMessage() to get theerror message that was// returned by the server (e.g., "File austin.fmwcould not be found.")

throw new FMEServerException("Transformationfailed.\nThe error was: "

+ result.getStatusMessage());}else{

// The transformation was successful. We inform theuser of this.System.out.println("Transformation successful!");

// The transformation result object contains manyname-value pairs that// are extracted from the SUCCESS_RESPONSE definedin the FME Server// node subsection. In addition to these pairs,there are also several

Developing with the Core APIs

112 FME Server Developer's Guide

Page 113: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Java

// name-value pairs added by the server: the timethat the job was sent// to an FME Server node for processing (time-Started), the job ID (id),// etcetera. The getAllProperties() method returns amap of all these// name-value pairs. Here, we iterate over this map -- using its entry// set -- and simply print out its contents in theform "name = value".

System.out.println("The following information wasparsed from the response:\n");System.out.println("============");for (Map.Entry&lt;String, String&gt; prop : result.g-etAllProperties().entrySet()){

// It is possible for keys to be present that havea null value (for// example, "priority" will map to null if nopriority was specified// for this job). We want to skip over such name-value pairs,// printing out only those pairs for which a non-null value exists.// We filter the pairs by checking whether thelength of the value// string is greater than 0 -- i.e., that a usefulvalue exists:

if (prop.getValue().length() &gt; 0){

System.out.println(prop.getKey() + " = " +prop.getValue());

}}System.out.println("============");}

}

FME Server Developer's Guide 113

Page 114: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

private String getInput(String promptMessage) throwsException{

System.out.print(promptMessage + "\t");return br_.readLine();

}

/*** This program accepts two parameters.** First parameter is the FME Server host. ie. local-host* Second parameter is the FME Server port. ie. 7071*/public static void main(String args[]) throws FME-ServerException{

String host = null;int port = 0;

// Extract the arguments from the command lineif (args.length != 2){

argError();}else{

host = args[0];try{

port = Integer.parseInt(args[1]);}catch (NumberFormatException nfe){

argError();}

}

FMEServerAPIDemo demo = new FMEServerAPIDemo(host,port);

Developing with the Core APIs

114 FME Server Developer's Guide

Page 115: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

while (true){

demo.execute();}

}

private static void argError(){

System.err.println("USAGE:\n\tFMEServerAPIDemo&lt;host&gt; &lt;port&gt;");System.exit(-1);

}}

.NETIn this Section:

Topic Description

".NETQuick Start" on nextpage

Setting up a .NET project in Visual Studio, and running theFME Server API command-line demo application.

".NET Tuto-rial " onpage 119

Outlines common operations using the FME Server API,such as obtaining a server session, managing repos-itories, and running workspaces.

".NETExample"on page133

A sample application using the FME Server API.

.NET API Documentation

Available here.

FME Server Developer's Guide 115

Page 116: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET Quick Start

Setting Up a .NET Project Using Visual Studio

1. Start Visual Studio.

2. Choose File > New Project.

In this example, we'll create a Visual C# project with the ConsoleApplication template and name it FMEServerAPIDemo.

3. On the References folder in the Solution Explorer, click on Add Ref-erence … to add a reference to the FME Server .NET API.

Developing with the Core APIs

116 FME Server Developer's Guide

Page 117: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

4. The file name for the FME Server .NET API assembly is fme-serverdotnetapi.dll and is located at <FME-ServerDir>\Server\sdk\dotnet\fmeserverapidotnet.dll. Browseto the location of the fmeserverapidotnet.dll and select it.

FME Server Developer's Guide 117

Page 118: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

5. The namespace for the FME Server .NET API isSafe.FMEServer.API. Before developing your .NET application youmay wish to import the types defined in the Safe.FMEServer.APInamespace. In the C# language, the using keyword is for exampleused as follows:

using Safe.FMEServer.API;

Running the API Sample demo...

A sample command-line demo application illustrating the use of the FMEServer API is available in C++, .Net, and Java versions.

This demo can be used to ensure that everything has been setup properly,and contains code that may be useful for your development process. (Morein-depth coverage can be found in the later sections.)

Developing with the Core APIs

118 FME Server Developer's Guide

Page 119: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

If security is enabled for FME Server, your application must provide a clientID that has been registered with FME Server. The client ID for the demoapplication is app_apidemo. By default, the demo's client ID is not registeredwith FME Server, and you must register the client ID. (See "Resources" onpage 1 for more information.)

The command-line application requires two parameters: the FME Server hostand FME Server port.

Note: <fmeServerHost> represents the name of the host on whichthe FME Server is running.

<fmeServerPort> represents the TCP/IP port number the FMEServer is listening on for requests. The default value is 7071and this is usually correct for most FME Server installations.

The C# .NET source code was developed using Microsoft Visual Studio 2005and is located in:

<FMEServerDir>\Server\sdk\-samples\apidemo\dotnet\FMEServerAPIDemo.cs

...using the new project from the previous section

Add the source code to your project, and run.

...independently or with another IDE

Please reference the following file in your program:

<FMEServerDir>\Server\sdk\dotnet\fmeserverapidotnet.dll

.NET Tutorial

This documentation serves as a primer for developers that wish to developapplications using the FME Server API. Many common operations such asobtaining a server session, managing repository items and resources, andrunning workspaces are outlined. Please note that the sample code providedis intended for demonstration purposes only:

API Demo - .NET

FME Server Developer's Guide 119

Page 120: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

For demonstration purposes a sample command line application has beencreated to illustrate many of the common FME Server API concepts withsample code. The sample command line application takes two parameters.The first parameter is the FME Server host name and the second parameteris the FME Server port number. When the command line application isexecuted, you will be prompted for your credentials. (Leave blank for secu-rity-disabled configurations.) Upon verification, a menu is displayed whichprompts you to select a given command. Additional information may berequired depending on the command selected.

Sample code is available in Java, C++ and .NET. Please refer to the ".NETQuick Start " on page 116 for information on how to set up your devel-opment environment.

If security is enabled for FME Server, this application's client ID - app_apidemo - is not registered with FME Server, and you must register theclient ID for it to work. (See "Resources" on page 1 for more information.)

Developing with the Core APIs

120 FME Server Developer's Guide

Page 121: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

Working with Server Sessions

The first step in working with the FME Server API is to create a server ses-sion. To create a server session, you use a factory method as shown below.

IFMEServerSession serverSession_ = FME-Server.createServerSession();

Once a server session is created, you can create the objects required to ini-tialize it. To initialize a server session, a connection info object that specifiesthe server connection parameters needs to be created as shown below.

IFMEServerConnectionInfo connectionInfo_= serverSession_.createServerConnectionInfo(host, port,"", "");

If security is enabled, then a client ID must also be provided as a sessiondirective. (See "Enabling SSL on the Application Server" on page 1 and "FMEServer Web Service Security Concepts" on page 1.) The client ID must matchthe client ID you configured in FME Server.

Note: Providing a client ID on a security-disabled system will notlead to any negative behaviour - the username, password, andclient ID will simply be ignored.

IDictionary<string, string> directives = new Dic-tionary<string, string>();

directives.Add("CLIENT_ID", clientId_);serverSession_.Init(connectionInfo_, directives);

Once a server session is initiated, you can now create any additional objectsto interact with the FME Server. This includes being able to manage itemsand resources with the Repository Manager and running workspaces with theTransformation Manager.

An important consideration when working with server sessions is to ensureyou release your server session when done. If you initialize server sessionswithout ever releasing them, you may eventually run out of connectionrelated resources. Releasing a server session is shown below.

serverSession_.disconnect();

FME Server Developer's Guide 121

Page 122: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Note: The FME Server API is case insensitive but case preservingfor all unique identifiers such as repository name, workspacename, resource name, service name, etc.

Working with Repositories

The Repository Manager component of the FME Server manages repos-itories. A repository is a central place to store items, resources and otherthings that enable the FME Server to perform its functions. A typical item isa workspace, a custom format or a custom transformer. Associated withitems are resources.

To access a repository, you will need to get the Repository Manager objectfrom the server session as shown below.

IFMERepositoryManager repositoryMgr_ = server-Session_.getRepositoryManager();

How to list available repositories

The Repository Manager object allows us to get all available repositories.

IFMERepository[] repositoryList = repos-itoryMgr_.GetRepositories(null);foreach (IFMERepository repository in repositoryList){

Console.Write("{0} {1}\n", repository.Name, repos-itory.Description);

}

How to add repositories

Repositories are uniquely identified by their name. A new repository can becreated by specifying a new repository name and a repository description.

Note: If you don't check if a repository with the same namealready exists and then add a repository with the samename, you will need to handle either the FME Server excep-tion or error that is returned.

if (!repositoryMgr_.repositoryExists(name))

Developing with the Core APIs

122 FME Server Developer's Guide

Page 123: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

{ repositoryMgr_.addRepository(name, description);

}else{

throw new FMEServerException("There is already a repos-itory with this name!");

}

How to remove repositories

Removing a repository requires the name of the repository. It's important toknow that removing a repository will also remove any items and resourcesin it.

if (!repositoryMgr_.removeRepository(name)){

throw new FMEServerException("There is no repository withthis name!");

}

Working with Workspaces

A workspace is a type of repository item so the concepts in this section willalso apply to other repository items such as custom formats and customtransformers. A workspace normally has an FMW file extension, whereas cus-tom formats have a FDS file extension and custom transformers have a FMXfile extension.

FME workspaces are created through FME Workbench and can be publishedto an FME Server repository so that multiple users can access them. Work-spaces in the FME Server repository can also be downloaded, modified, andthen published again.

A default installation of FME Server comes with a number of demo work-spaces but most users will create their own workspaces. In this section, it'sassumed you will either use one of the demo workspaces or create a work-space of your own using FME Workbench.

FME Server Developer's Guide 123

Page 124: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

How to list workspaces in a repository

Workspace names can be quickly listed using repository methods that getthe workspace summaries of a workspace. More detailed information aboutworkspaces can also be fetched with other repository methods.

IFMERepository[] repositoryList = repos-itoryMgr_.GetRepositories(null);foreach (IFMERepository repository in repositoryList){

IFMEWorkspaceSummary[] workspaceSummaries = repos-itory.GetWorkspaceSummaries(null);foreach (IFMEWorkspaceSummary workspaceSummary in work-spaceSummaries){

Console.Write("Repository:{0} {1} {2} ON:{3}\n",repository.Name,workspaceSummary.Title,workspaceSummary.Name,workspaceSummary.IsEnabled);

}}

How to add workspaces to a repository

To add a new workspace to a repository, the repositosry name, the work-space file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name(ie. foo.fmw) are required. When adding a workspace, the actual work-space file is uploaded to the FME Server repository.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);if (!repository.ItemExists(workspaceName)){

repository.AddItem(workspaceName, workspaceFilePath);}else{

Developing with the Core APIs

124 FME Server Developer's Guide

Page 125: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

throw new FMEServerException("There is already a work-space with this name!");

}

How to update workspaces in a repository

To update a workspace in a repository, the repository name, the workspacefile path (ie. "C:\myworkspaces\foo.fmw") and the workspace name (ie.foo.fmw) are required. The workspace name uniquely identifies a workspacein a repository and should match the workspace you wish to update. Whenupdating a workspace, the actual workspace file is uploaded to the FMEServer repository.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);if (repository.ItemExists(workspaceName)){

repository.UpdateItem(workspaceName, workspaceFilePath);}else{

throw new FMEServerException("There is no workspacewith this file name!");

}

How to get workspaces from a repository

To get a workspace from a repository, the repository name, the local work-space file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name(ie. foo.fmw) are required. The workspace name uniquely identifies a work-space in a repository and should match the workspace you wish to get. Whengetting a workspace, the actual workspace file is downloaded from the FMEServer repository to the specified local workspace file path.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);if (repository.ItemExists(workspaceName)){

repository.GetItem(workspaceName, workspaceFilePath);}

FME Server Developer's Guide 125

Page 126: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

else{

throw new FMEServerException("There is no workspace withthis file name!");

}

How to remove workspaces in a repository

To remove a workspace in a repository, the repository name and the work-space name are required.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);if (!repository.RemoveItem(workspaceName)){

throw new FMEServerException("There is no workspace withthis file name!");

}

Working with Resources

Some workspaces may require resources to successfully run. Anyresources associated with a workspace are placed with the workspace andare accessed through the repository object.

How to list resources for a workspace

To view the resources that already exist for a workspace, the repositoryname and the workspace name are required.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);IFMEWorkspace workspace = repository.GetWorkspace(work-spaceName);

IFMEResource[] resources = workspace.Resources;foreach (IFMEResource resource in resources){

Console.Write("{0} {1}\n", resource.Name, resource.D-escription);

}

Developing with the Core APIs

126 FME Server Developer's Guide

Page 127: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

How to add resources for a workspace

To add a new resource for a workspace, the repository name, the workspacename, the resource file path (ie. "C:\myresources\resource.csv) and theresource name (ie. resource.csv) are required. When adding a resource, theactual resource file is uploaded to the FME Server repository.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);if (!repository.ResourceExists(workspaceName, resourceName)){

repository.AddResource(workspaceName, resourceName,resourceFilePath);

}else{

throw new FMEServerException("There is already a resourcewith this name!");

}

How to update resources for a workspace

To update a resource for a workspace, the repository name, the workspacename, the resource file path (ie. "C:\myresources\resource.csv") and theresource name (ie. resource.csv) are required. The resource name uniquelyidentifies a resource for a workspace and should match the resource youwish to update. When updating a resource, the actual resource file isuploaded to the FME Server repository.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);if (repository.ResourceExists(workspaceName, resourceName)){

repository.UpdateResource(workspaceName, resourceName,resourceFilePath);

}else{

FME Server Developer's Guide 127

Page 128: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

throw new FMEServerException("There is no resource withthis name!");

}

How to get resources for a workspace

To get a resource for a workspace, the repository name, the workspacename, the local resource file path (ie. "C:\myresources\resource.csv") andthe resource name (ie. resource.csv) are required. The resource nameuniquely identifies a resource for a workspace and should match theresource you wish to get. When getting a resource, the actual resource fileis downloaded from the FME Server repository to the local resource filepath.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);if (repository.ResourceExists(workspaceName, resourceName)){

repository.GetResource(workspaceName, resourceName,resourceFilePath);

}else{

throw new FMEServerException("There is no resource withthis name!");

}

How to remove resources for a workspace

To remove a specific resource from a workspace, the repository name,workspace name, and resource name are required. Removing a specificworkspace will also remove all associated resources for the workspace.

IFMERepository repository = repositoryMgr_.GetRepository(repositoryName);if (!repository.RemoveResource(workspaceName, resource-Name)){

throw new FMEServerException("There is no resource withthis name!");

Developing with the Core APIs

128 FME Server Developer's Guide

Page 129: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

}

Working with Services

The default installation of FME Server makes available a number of services,each providing a specific functionality to the end-user. The service object pro-vides you with information about these services such as the service nameand service URL pattern. It also allows you to create new service descrip-tions for services that you may wish to create.

How to list available services

To list the available services the Repository Manager object is required.

ArrayList<IFMEService> services = repositoryMgr_.getServices(null);for (IFMEService service : services){

System.out.format("%s %s %s ON:%s %s\n",service.getDisplayName(),service.getName(),service.getURLPattern(),service.getIsEnabled(),service.getDescription());

}

How to add services

To add a new service, the service name, service display name, descriptionand URL pattern are required.

IFMEService service = serverSession_.CreateService(name, dis-playName, description, urlPattern);if (!repositoryMgr_.ServiceExists(name)){

repositoryMgr_.AddService(service);}else{

throw new FMEServerException("There is already a servicewith this name!");

}

FME Server Developer's Guide 129

Page 130: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

How to update services

To add a new service, the service name, service display name, descriptionand URL pattern are required. The service name uniquely identifies a serv-ice.

IFMEService service = serverSession_.CreateService(name,displayName, description, urlPattern);if (repositoryMgr_.ServiceExists(name)){

repositoryMgr_.UpdateService(service);}else{

throw new FMEServerException("There is no service withthis name!");

}

How to remove services

To remove a service, only the service name which uniquely identifies theservice is required.

if (!repositoryMgr_.RemoveService(name)){

throw new FMEServerException("There is no service withthis name!");

}

Running Workspaces

Once a workspace is published to an FME Server repository, the workspacecan be run. This can be done by constructing and then submitting a jobrequest using the Transformation Manager object. Normally users wouldcreate their own workspaces, but for this example we will be using a demoworkspace that is included with the default installation of the FME Server.

First step is to connect to the transformation manager, the component ofthe FME Server that handles job requests.

Developing with the Core APIs

130 FME Server Developer's Guide

Page 131: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

IFMETransformationManager transformationMgr = ses-sion_.GetTransformationManager();

Next, we need to create a transformation request that will be submitted tothe FME Server. The expected parameters are:

n The name of an FME Server node subsection, as defined in the node'sconfiguration. SERVER_CONSOLE_CLIENT is one such subsection, partof the default configuration that ships with the FME Server. Each sub-section specifies various processing directives (e.g. the folder whereoutput should be placed). For information on the different subsections,please refer to <FMEServerDir>\Server\fmeServerConfig.txt.

n The unique name of the repository that contains the target file, demo-download is one such repository, which contains the workspace "aus-tin.fmw".

n The name of a workspace, mapping file or command file that is to beexecuted by FME. In the latter case, the file is assumed to reside in theFME_MAPPING_DIR that has been set for the subsection that weselected with the first parameter. Here, we specify a workspace calledaustin.fmw from the demodownload repository.

IFMETransformationRequest req = ses-sion_.CreateTransformationRequest(

"SERVER_CONSOLE_CLIENT", "demodownload", "aus-tin.fmw");

Some workspaces have published parameters that can be set. Some havedefault values but others need to be explicitly set before we are able to runthe workspace. These depend on the workspace itself. To set such a pub-lished parameter - in this case MAX_FEATURES:

req.SetPublishedParameter("MAX_FEATURES", "2000");

Note: Values for published parameters must always be passed asstrings, regardless of what they actually represent.

There also exist directives that are always available from the FME Server. Alist of TM directives can be found here. Since we are functionality specificallyfor setting TM directives, we do not need the "tm_" prefix. For our example,

FME Server Developer's Guide 131

Page 132: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

we set a high value for the priority of this job, in order to tell the FMEServer to execute it before other tasks. This is not necessary but just doneto illustrate how to set directives.

req.SetTMDirective("priority", 42);

Once all parameters and directives have been set, we can submit ourrequest to the FME Server. A transformation request can be submittedeither synchronously or asynchronously.

If a job is submitted synchronously, the method call will be blocked untilthe job has finished. The results are stored in a transformation resultobject.

IFMETransformationResult result = transformer.TransactJob(req);

If a job is submitted asynchronously, the method call will immediatelyreturn the job ID, which can be used to check if the job has finished. Check-ing the result of a specified transformation job can be done in a wait-loopuntil the result is available.

IFMETransformationResult result = server-Session_.CreateTransformationResult();long jobID = transformationMgr.SubmitJob(req);while (!transformationMgr.GetJobResult(jobID, result)){

// Wait for 500 millisecondsThread.Sleep(500);

}

The transformation result object has a number of methods for obtaining dif-ferent parts of information from the FME Server response. In our examplewe first display the raw, unparsed string that was received from theserver. In certain scenarios, the clients may want to do their own parsingon this string instead of relying on the provided methods.

Console.WriteLine(result.FMEServerResponse);

Developing with the Core APIs

132 FME Server Developer's Guide

Page 133: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

We can now display additional pieces of information. First, we check that thetransformation was successful and, if so, we list some of the returned prop-erties. Properties are stored as name = value pairs, though some of themmay be null.

if (!result.TransformationSuccess){

throw new FMEServerException("Transformation failed.\nTheerror was: " + result.StatusMessage);

}else{

Console.WriteLine("Transformation successful!");Console.WriteLine("The following information was parsedfrom the response:\n");Console.WriteLine("============");foreach (KeyValuePair<string, string> pair in result.G-etAllProperties()){

Console.WriteLine(pair.Key + " = " + pair.Value);}Console.WriteLine("============");

}

.NET Example/*==========================================================-==================

Name : FMEServerAPIDemo.csSystem : FME Server APILanguage : C#Purpose : FMEServerAPIDemo sample application

Author Date Changes made------------------ ------------ -------------------------------Sample Jun 19, 2008 Original definition

Copyright (c) 1994 - 2011, Safe Software Inc.All Rights Reserved

FME Server Developer's Guide 133

Page 134: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

This software may not be copied or reproduced, in all orin part,without the prior written consent of Safe Software Inc.The entire risk as to the results and performance of thesoftware,supporting text and other information contained in thisfile(collectively called the "Software") is with the user.In no event will Safe Software Incorporated be liable fordamages,including loss of profits or consequential damages, aris-ing out ofthe use of the Software.

===========================================================-================= */using System;using System.Collections.Specialized;using System.Collections.Generic;using System.Text;using System.IO;using Safe.FMEServer.API;namespace FMEServerAPIDemo{

public class FMEServerAPIDemo{

private IFMERepositoryManager repositoryMgr_;private IFMEServerSession serverSession_;private string userId_ = "";private string password_ = "";private string clientId_ = "app_apidemo";public FMEServerAPIDemo(string host, int port){

serverSession_ = FMEServer.CreateServerSession();GetConnectionInfo();IFMEServerConnectionInfo connInfo_ = server-Session_.CreateServerConnectionInfo(host, port, use-rId_, password_);IDictionary<string, string> directives = new Dic-tionary<string, string>();

Developing with the Core APIs

134 FME Server Developer's Guide

Page 135: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

directives.Add("CLIENT_ID", clientId_);serverSession_.Init(connInfo_, directives);repositoryMgr_ = serverSession_.GetRepositoryManager();

}public void GetConnectionInfo(){

Console.WriteLine("Please enter server connection cre-dentials.");Console.Write("UserId:");userId_ = Console.ReadLine();if (userId_ != ""){

Console.Write("Password:");password_ = Console.ReadLine();

}}public void Execute(){

DisplayMainMenu();try{

int choice = GetMenuChoice();ExecuteMenuChoice(choice);

}catch (FormatException){

Console.Error.WriteLine("Invalid input!");}catch (Exception e){

Console.Error.WriteLine(e.Message);}

}private void Cleanup(){

if (serverSession_ != null){

try{

serverSession_.Disconnect();serverSession_ = null;

FME Server Developer's Guide 135

Page 136: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

}catch (FMEServerException e){

Console.Error.WriteLine(e.Message);}

}}private int GetMenuChoice(){

return Int32.Parse(Console.ReadLine());}private void ExecuteMenuChoice(int choice){

switch (choice){

case 1:ListRepositories();break;

case 2:AddRepository();break;

case 3:RemoveRepository();break;

case 4:ListWorkspaces();break;

case 5:AddWorkspace();break;

case 6:UpdateWorkspace();break;

case 7:GetWorkspace();break;

case 8:RemoveWorkspace();break;

case 9:ListResources();

Developing with the Core APIs

136 FME Server Developer's Guide

Page 137: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

break;case 10:

AddResource();break;

case 11:UpdateResource();break;

case 12:GetResource();break;

case 13:RemoveResource();break;

case 14:ListServices();break;

case 15:AddService();break;

case 16:UpdateService();break;

case 17:RemoveService();break;

case 18:RunWorkspace();break;

case 0:Cleanup();Environment.Exit(0);break;

default:Console.Error.WriteLine("Invalid option!");return;

}Console.WriteLine("\nThe operation was a suc-cess");

}private void DisplayMainMenu(){

Console.Write("\n\n"

FME Server Developer's Guide 137

Page 138: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

+ "===FME Server API Demo===\n"+ "1. List available repositories\n"+ "2. Add a repository\n"+ "3. Remove a repository\n"+ "4. List available workspaces\n"+ "5. Add a workspace\n"+ "6. Update a workspace\n"+ "7. Get a workspace\n"+ "8. Remove a workspace\n"+ "9. List resources of a workspace\n"+ "10. Add a resource\n"+ "11. Update a resource\n"+ "12. Get a resource\n"+ "13. Remove a resource\n"+ "14. List available services\n"+ "15. Add a service\n"+ "16. Update a service\n"+ "17. Remove a service\n"+ "18. Run a workspace\n"+ "0. Quit\n"+ "\nSELECT: ");

}private void ListRepositories(){

IFMERepository[] repositoryList = repos-itoryMgr_.GetRepositories(null);foreach (IFMERepository repository in repos-itoryList){

Console.Write("{0} {1}\n", repository.Name, repos-itory.Description);

}}private void AddRepository(){

string name = GetInput("Please enter the name forthe new repository:");string description = GetInput("Please enter thedescription for the new repository:");if (!repositoryMgr_.RepositoryExists(name)){

Developing with the Core APIs

138 FME Server Developer's Guide

Page 139: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

repositoryMgr_.AddRepository(name, description);}else{

throw new FMEServerException("There is already arepository with this name!");

}}private void RemoveRepository(){

string name = GetInput("Please enter the name for therepository to remove:");if (!repositoryMgr_.RemoveRepository(name)){

throw new FMEServerException("There is no repos-itory with this name!");

}}private void ListWorkspaces(){

IFMERepository[] repositoryList = repos-itoryMgr_.GetRepositories(null);foreach (IFMERepository repository in repositoryList){IFMEWorkspaceSummary[] workspaceSummaries = repos-itory.GetWorkspaceSummaries(null);foreach (IFMEWorkspaceSummary workspaceSummary inworkspaceSummaries){

Console.Write("Repository:{0} {1} {2} ON:{3}\n",repository.Name,workspaceSummary.Title,workspaceSummary.Name,workspaceSummary.IsEnabled);

}}

}private void AddWorkspace(){

string repositoryName = GetInput("Please enter therepository name for the new workspace:");

FME Server Developer's Guide 139

Page 140: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

string workspaceFilePath = GetInput("Please enterthe file path for the new workspace to add:");string workspaceName = new FileInfo(work-spaceFilePath).Name;IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);if (!repository.ItemExists(workspaceName)){

repository.AddItem(workspaceName, work-spaceFilePath);

}else{

throw new FMEServerException("There is already aworkspace with this name!");

}}private void UpdateWorkspace(){

string repositoryName = GetInput("Please enter therepository name for the workspace to update:");string workspaceFilePath = GetInput("Please enterthe file path for the workspace to update:");string workspaceName = new FileInfo(work-spaceFilePath).Name;IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);if (repository.ItemExists(workspaceName)){

repository.UpdateItem(workspaceName, work-spaceFilePath);

}else{

throw new FMEServerException("There is no work-space with this file name!");

}}private void GetWorkspace(){

Developing with the Core APIs

140 FME Server Developer's Guide

Page 141: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

String repositoryName = GetInput("Please enter therepository name for the workspace to get:");String workspaceName = GetInput("Please enter thename of the workspace to get:");String workspaceFilePath = GetInput("Please enter thelocal file path for the workspace to get:");IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);if (repository.ItemExists(workspaceName)){

repository.GetItem(workspaceName, work-spaceFilePath);

}else{

throw new FMEServerException("There is no work-space with this file name!");

}}private void RemoveWorkspace(){

string repositoryName = GetInput("Please enter therepository name for the workspace to remove:");string workspaceName = GetInput("Please enter thename of the workspace to remove:");IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);if (!repository.RemoveItem(workspaceName)){

throw new FMEServerException("There is no work-space with this file name!");

}}private void RunWorkspace(){

IFMETransformationManager transformationMgr = server-Session_.GetTransformationManager();// Create an IFMETransformationnRequest object toencapsulate our// transformation request that will be submitted tothe server.

FME Server Developer's Guide 141

Page 142: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

// The createTransformationRequest(...) methodexpects three parameters:// 1. The name of an FME Server node subsection, asdefined in the// node's configuration. SERVER_CONSOLE_CLIENT isone such// subsection that is part of the default con-figuration that ships// with the FME Server. Each subsection spec-ifies various// processing directives (e.g., the folder whereoutput should// be placed). For information on the different sub-sections, please// refer to <FMEServer-Install-Dir>\Server\fmeServerConfig.txt// 2. The unique name for the repository that con-tains the mapping file// or command file to be executed by FME.string repositoryName = GetInput("Please enter therepository name for the workspace to run:");string workspaceName = GetInput("Please enter thename of the workspace to run:");

IFMETransformationRequest req =serverSession_.CreateTransformationRequest("SERVER_CONSOLE_CLIENT",repositoryName, workspaceName);

// Set published parameters that have been exposedby the workspace.// Both the name of the published parameter and thedesired value// are simple strings, even if the value happens tohave a numeric// interpretation.// Here, we set a published parameter called MAX_FEA-TURES that// controls how many features will be read in fromthe source dataset(s).

Developing with the Core APIs

142 FME Server Developer's Guide

Page 143: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

// Published parameters depend on the workspace thatis being run.

req.SetPublishedParameter("MAX_FEATURES", "2000");

// We can also set certain transformation managerdirectives that determine how// our transformation request will be processed.Unlike published// parameters, which are determined by each work-space's author and// thus vary from one workspace to another, the avail-able directives// are constant for all transformation requests. Acomplete// list of directives can be found in the FME Serverdocumentation.// Here, we set a high priority for this job to sug-gest that it// should be given precedence over other, lower-prior-ity, jobs.

req.SetTMDirective("priority", 42);Console.WriteLine("Sending a transformation requestto the FME Server...\n");

// Submit the transformation request. This methodwill// block until transformation results are available.(Users who wish// to submit jobs asynchronously should instead usethe submitJob(...)// method.) The returned results are stored in// an IFMETransformationResult object, which is thecompanion to the// IFMETransformationRequest object that we sub-mitted.

IFMETransformationResult result = trans-formationMgr.TransactJob(req);

FME Server Developer's Guide 143

Page 144: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

// The transformation result object receives aresult string from the// server and parses it to extract many differentpieces of// information about the job result. However, userswho wish to// do their own parsing of the raw server response,or wish to// log this string, may obtain the unparsed responsestring using// the getFMEServerResponse() method. Here, we usethat method to// print out the response string to the standard out-put.

Console.WriteLine("Response received:\n");Console.WriteLine(result.FMEServerResponse);Console.WriteLine();

// The IFMETransformationResult interface definesmany accessor methods// for retrieving specific information from theparsed result. We// only demonstrate a small subset of those methodshere; a full list// is available in the FME Server API documentation.// The getTransformationSuccess() method returnstrue if, and only if,// the transformation was successful. Here, we checkto see if the// transformation was successful and then print outa message accordingly.

if (!result.TransformationSuccess){

// The transformation was not successful. Weinform the user of this// and then use getStatusMessage() to get theerror message that

Developing with the Core APIs

144 FME Server Developer's Guide

Page 145: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

// was returned by the server (e.g., "File aus-tin.fmw could not// be found.")throw new FMEServerException("Transformationfailed.\nThe error was: " + result.StatusMessage);

}else{

// The transformation was successful. We informthe user of this.Console.WriteLine("Transformation successful!");

// The transformation result object contains manyname-value pairs// that are extracted from the SUCCESS_RESPONSEdefined in the// FME Server node subsection. In addition tothese pairs, there// are also several name-value pairs added by theserver:// the time that the job was sent to an FME Servernode for// processing (timeStarted), the job ID (id),etcetera.// The getAllProperties() method returns a map ofall these// name-value pairs. Here, we iterate over thismap -- using its// entry set -- and simply print out its contentsin the form// "name = value".Console.WriteLine("The following information wasparsed from the response:\n");Console.WriteLine("============");foreach (KeyValuePair<string, string> pair inresult.GetAllProperties()){

Console.WriteLine(pair.Key + " = " +pair.Value);

}Console.WriteLine("============");

FME Server Developer's Guide 145

Page 146: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

}}private void ListResources(){

String repositoryName = GetInput("Please enter therepository name for the resources:");String workspaceName = GetInput("Please enter theworkspace name for the resources:");IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);IFMEWorkspace workspace = repository.GetWorkspace(workspaceName);IFMEResource[] resources = workspace.Resources;foreach (IFMEResource resource in resources){

Console.Write("{0} {1}\n", resource.Name,resource.Description);

}}private void AddResource(){

string repositoryName = GetInput("Please enter therepository name for the new resource:");string workspaceName = GetInput("Please enter theworkspace name for the new resource:");string resourceFilePath = GetInput("Please enter thefile path for the new resource to add:");string resourceName = new FileInfo(resource-FilePath).Name;IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);if (!repository.ResourceExists(workspaceName,resourceName)){

repository.AddResource(workspaceName, resource-Name, resourceFilePath);

}else{

throw new FMEServerException("There is already aresource with this name!");

Developing with the Core APIs

146 FME Server Developer's Guide

Page 147: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

}}private void UpdateResource(){

string repositoryName = GetInput("Please enter therepository name for the resource to update:");string workspaceName = GetInput("Please enter theworkspace name for the resource to update:");string resourceFilePath = GetInput("Please enter thefile path for the resource to update:");string resourceName = new FileInfo(resource-FilePath).Name;IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);if (repository.ResourceExists(workspaceName, resource-Name)){

repository.UpdateResource(workspaceName, resource-Name, resourceFilePath);

}else{

throw new FMEServerException("There is no resourcewith this name!");

}}private void GetResource(){

string repositoryName = GetInput("Please enter therepository name for the resource to get:");string workspaceName = GetInput("Please enter theworkspace name for the resource to get:");string resourceName = GetInput("Please enter theresource name for the resource to get:");string resourceFilePath = GetInput("Please enter thelocal file path for the resource to get:");IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);if (repository.ResourceExists(workspaceName, resource-Name)){

FME Server Developer's Guide 147

Page 148: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

repository.GetResource(workspaceName, resource-Name, resourceFilePath);

}else{

throw new FMEServerException("There is noresource with this name!");

}}private void RemoveResource(){

string repositoryName = GetInput("Please enter therepository name for the resource to remove:");string workspaceName = GetInput("Please enter theworkspace name for the resource to remove:");string resourceName = GetInput("Please enter theresource name for the resource to remove:");IFMERepository repository = repos-itoryMgr_.GetRepository(repositoryName);if (!repository.RemoveResource(workspaceName,resourceName)){

throw new FMEServerException("There is noresource with this name!");

}}private void ListServices(){

IFMEService[] services = repositoryMgr_.GetServices(null);foreach (IFMEService service in services){

Console.Write("{0} {1} {2} ON:{3} {4}\n",service.DisplayName,service.Name,service.URLPattern,service.IsEnabled,service.Description);

}}private void AddService()

Developing with the Core APIs

148 FME Server Developer's Guide

Page 149: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

.NET

{string name = GetInput("Please enter the name of thenew service:");string urlPattern = GetInput("Please enter the URLpattern of the new service:");string displayName = GetInput("Please enter the dis-play name of the new service:");string description = GetInput("Please enter thedescription of the new service:");IFMEService service = serverSession_.CreateService(name, displayName, description, urlPattern);if (!repositoryMgr_.ServiceExists(name)){

repositoryMgr_.AddService(service);}else{

throw new FMEServerException("There is already aservice with this name!");

}}private void UpdateService(){

String name = GetInput("Please enter the name of theservice to update:");String urlPattern = GetInput("Please enter the URLpattern of the service to update:");String displayName = GetInput("Please enter the dis-play name of the service to update:");String description = GetInput("Please enter thedescription of the service to update:");IFMEService service = serverSession_.CreateService(name, displayName, description, urlPattern);if (repositoryMgr_.ServiceExists(name)){

repositoryMgr_.UpdateService(service);}else{

throw new FMEServerException("There is no servicewith this name!");

FME Server Developer's Guide 149

Page 150: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

}}private void RemoveService(){

string name = GetInput("Please enter the name forthe service to remove:");if (!repositoryMgr_.RemoveService(name)){

throw new FMEServerException("There is no servicewith this name!");

}}private string GetInput(string promptMessage){

Console.Write(promptMessage + "\t");return Console.ReadLine();

}private static void ArgError(){

Console.Error.WriteLine("USAGE:\n\tFMEServerAPIDemo<host> <port>");Environment.Exit(0);

}

// This program accepts two parameters.//// First parameter is the FME Server host. ie. local-host// Second parameter is the FME Server port. ie. 7071public static void Main(string[] args){

string host = null;int port = 0;

// Extract the arguments from the command lineif (args.Length != 2){

ArgError();}else{

Developing with the Core APIs

150 FME Server Developer's Guide

Page 151: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

host = args[0];try{

port = Int32.Parse(args[1]);}catch (FormatException){

ArgError();}

}FMEServerAPIDemo demo = new FMEServerAPIDemo(host,port);while (true){

demo.Execute();}

}}

}

C++In this Section:

Topic Description

"C++Quick Start" on nextpage

Setting up a project in Visual Studio, and running the FMEServer API command-line demo application.

"C++ Tuto-rial " onpage 157

Outlines common operations using the FME Server API,such as obtaining a server session, managing repos-itories, and running workspaces.

"C++Example"on page172

Sample application using the FME Server API.

C++ API Documentation

Available here.

FME Server Developer's Guide 151

Page 152: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++ Quick Start

Setting Up a C++ Project Using Visual Studio

1. Start Visual Studio.

2. Choose File > New Project.

3. The <FMEServerDir>\Server\sdk\cpp folder contains the filesneeded for the FME Server C++ API other than FME Objects.

In general, your C++ application must do the following:

n Link in fmeserverapi.lib in your project

n Include the directory of the header files in your project

n Include the directory of the FME Objects header files in yourproject

n Ensure the messages folder is in the same directory as yourapplication

n Ensure the FME Server C++ API DLLs can be loaded by yourapplication. This can be done by ensuring the path to the FMEServer C++ API folder is in your Path Environment Variable orensuring the files are in the same directory as your application

4. Choose Project > Properties to open up the Properties dialog for theproject. Under C/C++ > General > Additional Include Directories,add the path to the <FMEServerDir>\Server\sdk\cpp folder.

Also include a directory for the FME Objects directory containing theheader files (depending on where you installed FME Objects).

Developing with the Core APIs

152 FME Server Developer's Guide

Page 153: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

5. If you installed the 64-bit version of FME Server, be sure to set the tar-get machine platform to x64.

6. Under C++ > Precompiled Headers, set Create/Use PrecompiledHeader to Not Using Precompiled Headers.

7. Under Linker > Input > Additional Dependencies, add the path to the<FMEServerDir>\Server\sdk\cpp\fmeserverapi.lib file.

FME Server Developer's Guide 153

Page 154: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

8. Copy the <FMEServerDir>\Server\sdk\cpp\messages folder intothe same directory of your application.

9. Since our sample application is in a different folder from the FMEServer C++ API folder, add the <FMEServerDir>\Server\sdk\cpp tothe Path Environment Variable. You may need to restart Visual Studioor your computer for the new Path settings to take effect.

Note: An easier approach is to just copy the contents of theFME Server C++ API folder into the directory of yourapplication. By doing that you can avoid setting thePath Environment Variable.

Developing with the Core APIs

154 FME Server Developer's Guide

Page 155: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

10. You can now start to create C++ applications using the FME ServerC++ API interfaces by including any header files required. For exam-ple, to use the IFMEServerSession interface you would including the fol-lowing in your source code:

#include <ifmeserversession.h>

FME Server Developer's Guide 155

Page 156: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Running the API Sample demo...

A sample command-line demo application illustrating the use of the FMEServer API is available in C++, .Net, and Java versions.

This demo can be used to ensure that everything has been setup properly,and contains code that may be useful for your development process. (Morein-depth coverage can be found in the later sections.)

If security is enabled for FME Server, your application must provide a clientID that has been registered with FME Server. The client ID for the demoapplication is app_apidemo. By default, the demo's client ID is not reg-istered with FME Server, and you must register the client ID.

The command-line application requires two parameters: the FME Serverhost and FME Server port.

Note: <fmeServerHost> represents the name of the host on whichthe FME Server is running.

<fmeServerPort> represents the TCP/IP port number theFME Server is listening on for requests. The default value is7071 and this is usually correct for most FME Server instal-lations.

The C++ source code was developed using Microsoft Visual Studio 2005and is located in:

<FMEServerDir>\Server\sdk\samples\apidemo\cpp\FMEServer-APIDemo.cpp

...using the new project from the previous section

Add the source code to your project, and run.

...independently or with another IDE

This source code can be compiled and run against a default installation ofFME Server. Please have the following files in the same directory as yourprogram:

<FMEServerDir>\Server\sdk\cpp\fmeserverapi.dll

Developing with the Core APIs

156 FME Server Developer's Guide

Page 157: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

<FMEServerDir>\Server\sdk\cpp\icudt32_fme.dll<FMEServerDir>\Server\sdk\cpp\icuin32_fme.dll<FMEServerDir>\Server\sdk\cpp\icuuc32_fme.dll<FMEServerDir>\Server\sdk\cpp\xerces-c_2_6_fme.dll<FMEServerDir>\Server\sdk\cpp\messages directory

C++ Tutorial

This documentation serves as a primer for developers that wish to developapplications using the FME Server API. Many common operations such asobtaining a server session, managing repository items and resources, andrunning workspaces are outlined. Please note that the sample code providedis intended for demonstration purposes only:

API Demo - C++

For demonstration purposes a sample command line application has beencreated to illustrate many of the common FME Server API concepts with sam-ple code. The sample command line application takes two parameters. Thefirst parameter is the FME Server host name and the second parameter isthe FME Server port number. When the command line application isexecuted, you will be prompted for your credentials. (Leave blank for secu-rity-disabled configurations.) Upon verification, a menu is displayed whichprompts you to select a given command. Additional information may berequired depending on the command selected.

FME Server Developer's Guide 157

Page 158: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Sample code is available in Java, C++ and .NET. Please refer to the "C++Quick Start " on page 152 for information on how to set up your devel-opment environment.

If security is enabled for FME Server, this application's client ID - app_apidemo - is not registered with FME Server, and you must register theclient ID for it to work. (See "Resources" on page 1 for more information.)

Working with Server Sessions

The first step in working with the FME Server API is to create a server ses-sion. To create a server session, you use a factory method as shown below.

IFMEServerSession* serverSession_ = NULL;FME_createServerSession(serverSession_);

Once a server session is created, you can create the objects required to ini-tialize it. To initialize a server session, a connection info object that spec-ifies the server connection parameters needs to be created as shownbelow.

IFMEServerConnectionInfo* connectionInfo_

Developing with the Core APIs

158 FME Server Developer's Guide

Page 159: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

= serverSession_->createServerConnectionInfo(*host, port,*userID, *password);

If security is enabled, then a client ID must also be provided as a sessiondirective. (See "Enabling SSL on the Application Server" on page 1 and "FMEServer Web Service Security Concepts" on page 1.) The client ID must matchthe client ID you configured in FME Server.

Note: Providing a client ID on a security-disabled system will notlead to any negative behavior - the username, password, andclient ID will simply be ignored.

IFMEServerStringArray* directives = serverSession_->creat-eServerStringArray();directives->append(kKeywordClientID);directives->append("app_apidemo");serverSession_->init(*connectionInfo_, directives);

Once a server session is initiated, you can now create any additional objectsto interact with the FME Server. This includes being able to manage itemsand resources with the Repository Manager and running workspaces with theTransformation Manager.

An important consideration when working with server sessions is to ensureyou release your server session when done. If you initialize server sessionswithout ever releasing them, you may eventually run out of connectionrelated resources. Releasing a server session is shown below.

serverSession_->disconnect();

Note: The FME Server API is case insensitive but case preserving forall unique identifiers such as repository name, workspacename, resource name, service name, etc.

Working with Repositories

The Repository Manager component of the FME Server manages repos-itories. A repository is a central place to store items, resources and otherthings that enable the FME Server to perform its functions. A typical item is a

FME Server Developer's Guide 159

Page 160: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

workspace, a custom format or a custom transformer. Associated withitems are resources.

To access a repository, you will need to get the Repository Manager objectfrom the server session as shown below.

IFMEServerRepositoryManager* repositoryMgr_ = server-Session_->getRepositoryManager();

How to list available repositories

The Repository Manager object allows us to get all available repositories.

IFMEServerStatus* status = repositoryMgr_->getRepositories(NULL, *repositories);if (isSuccess(status)){

for (FME_UInt32 i = 0; i < repositories->entries(); i++){

IFMEServerRepository* repository = (*repositories)(i);repository->getName(*name);repository->getDescription(*description);cout << name->data() << " " << description->data()<< endl;

}}

How to add repositories

Repositories are uniquely identified by their name. A new repository can becreated by specifying a new repository name and a repository description.

Note: If you don't check if a repository with the same namealready exists and then add a repository with the samename, you will need to handle either the FME Server excep-tion or error that is returned.

IFMEServerStatus* status = repositoryMgr_->addRepository(*name, *description);if (isSuccess(status))

Developing with the Core APIs

160 FME Server Developer's Guide

Page 161: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

{cout << "Added the repository\n";

}

How to remove repositories

Removing a repository requires the name of the repository. It's important toknow that removing a repository will also remove any items and resourcesin it.

IFMEServerStatus* status = repositoryMgr_->removeRepository(*name, exists);if (isSuccess(status)){

cout << "Removed the repository\n";}

Working with Workspaces

A workspace is a type of repository item so the concepts in this section willalso apply to other repository items such as custom formats, custom trans-formers, and templates. A workspace normally has an FMW file extension,whereas custom formats have a FDS file extension, custom transformershave a FMX file extension, and templates have a .fmwt extension.

FME workspaces are created through FME Workbench and can be publishedto an FME Server repository so that multiple users can access them. Work-spaces in the FME Server repository can also be downloaded, modified, andthen published again.

A default installation of FME Server comes with a number of sample work-spaces but most users will create their own workspaces. In this section, it'sassumed you will either use one of the demo workspaces or create a work-space of your own using FME Workbench.

How to list workspaces in a repository

Workspace names can be quickly listed using repository methods that getthe workspace summaries of a workspace. More detailed information aboutworkspaces can also be fetched with other repository methods.

for (FME_UInt32 i = 0; i < repositories->entries(); i++)

FME Server Developer's Guide 161

Page 162: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

{IFMEServerRepository* repository = (*repositories)(i);status = repository->getWorkspaceSummaries(NULL, *wor-kspaceSummaries);if (isSuccess(status)){

for (FME_UInt32 j = 0; j < workspaceSummaries->entries(); j++){

IFMEServerString* workspaceTitle = serverSession_->createServerString();IFMEServerString* workspaceName = serverSession_->createServerString();IFMEServerWorkspaceSummary* workspaceSummary = (*wor-kspaceSummaries)(j);repository->getName(*repositoryName);workspaceSummary->getTitle(*workspaceTitle);workspaceSummary->getName(*workspaceName);cout << "Repository: "<< repositoryName->data() << "" << workspaceTitle->data() << " " << workspaceName->data() << " ON:" << workspaceSummary->getIsEnabled() << endl;

serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(workspaceTitle);

}}

}

How to add workspaces to a repository

To add a new workspace to a repository, the repositosry name, the work-space file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name(ie. foo.fmw) are required. When adding a workspace, the actual work-space file is uploaded to the FME Server repository.

status = repository->addItem(*workspaceName, *wor-kspaceFilePath);if (isSuccess(status)){

cout << "Added the workspace\n";

Developing with the Core APIs

162 FME Server Developer's Guide

Page 163: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

}

How to update workspaces in a repository

To update a workspace in a repository, the repository name, the workspacefile path (ie. "C:\myworkspaces\foo.fmw") and the workspace name (ie.foo.fmw) are required. The workspace name uniquely identifies a workspacein a repository and should match the workspace you wish to update. Whenupdating a workspace, the actual workspace file is uploaded to the FMEServer repository.

status = repository->updateItem(*workspaceName, *workspaceFilePath);

if (isSuccess(status)){

cout << "Updated the workspace\n";}

How to get workspaces from a repository

To get a workspace from a repository, the repository name, the local work-space file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name(ie. foo.fmw) are required. The workspace name uniquely identifies a work-space in a repository and should match the workspace you wish to get. Whengetting a workspace, the actual workspace file is downloaded from the FMEServer repository to the specified local workspace file path.

status = repository->getItem(*workspaceName, *wor-kspaceFilePath, exists);if (isSuccess(status)){

cout << "Get workspace succeeded\n";}

How to remove workspaces in a repository

To remove a workspace in a repository, the repository name and the work-space name are required.

FME_Boolean existsWorkspace = FME_FALSE;

FME Server Developer's Guide 163

Page 164: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

status = repository->removeItem(*workspaceName, existsWork-space);if (isSuccess(status)){

cout << "Removed the workspace\n";}

Working with Resources

Some workspaces may require resources to successfully run. Anyresources associated with a workspace are placed with the workspace andare accessed through the repository object.

How to list resources for a workspace

To view the resources that already exist for a workspace, the repositoryname and the workspace name are required.

status = repository->getResources(*workspaceName, NULL,*resources);if (isSuccess(status)){

for (FME_UInt32 i = 0; i < resources->entries(); i++){

IFMEServerString* resourceName = serverSession_->creat-eServerString();IFMEServerString* resourceDescription = serverSession_->createServerString();IFMEServerResource* resource = (*resources)(i);resource->getName(*resourceName);resource->getDescription(*resourceDescription);cout << workspaceName->data() << " " << repos-itoryName->data() << endl;serverSession_->destroyServerString(resourceDe-scription);serverSession_->destroyServerString(resourceName);

}}

Developing with the Core APIs

164 FME Server Developer's Guide

Page 165: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

How to add resources for a workspace

To add a new resource for a workspace, the repository name, the workspacename, the resource file path (ie. "C:\myresources\resource.csv) and theresource name (ie. resource.csv) are required. When adding a resource, theactual resource file is uploaded to the FME Server repository.

status = repository->addResource(*workspaceName, *resourc-eName, *resourceFilePath);if (isSuccess(status)){

cout << "Added the resource\n";}

How to update resources for a workspace

To update a resource for a workspace, the repository name, the workspacename, the resource file path (ie. "C:\myresources\resource.csv") and theresource name (ie. resource.csv) are required. The resource name uniquelyidentifies a resource for a workspace and should match the resource youwish to update. When updating a resource, the actual resource file isuploaded to the FME Server repository.

status = repository->updateResource(*workspaceName, *resourc-eName, *resourceFilePath);if (isSuccess(status)){

cout << "Updated the resource\n";}

How to get resources for a workspace

To get a resource for a workspace, the repository name, the workspacename, the local resource file path (ie. "C:\myresources\resource.csv") andthe resource name (ie. resource.csv) are required. The resource nameuniquely identifies a resource for a workspace and should match theresource you wish to get. When getting a resource, the actual resource file isdownloaded from the FME Server repository to the local resource file path.

status = repository->getResource(*workspaceName, *resourc-eName, *resourceFilePath, exists);

FME Server Developer's Guide 165

Page 166: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

if (isSuccess(status)){

cout << "Get resource succeeded\n";}

How to remove resources for a workspace

To remove a specific resource from a workspace, the repository name,workspace name, and resource name are required. Removing a specificworkspace will also remove all associated resources for the workspace.

FME_Boolean existsResource = FME_FALSE;status = repository->removeResource(*workspaceName,*resourc-eName, existsResource);if (isSuccess(status)){

cout << "Removed the resource\n";}

Working with Services

The default installation of FME Server makes available a number of serv-ices, each providing a specific functionality to the end-user. The serviceobject provides you with information about these services such as the serv-ice name and service URL pattern. It also allows you to create new servicedescriptions for services that you may wish to create.

How to list available services

To list the available services the Repository Manager object is required.

IFMEServerServiceVector* services = serverSession_->creat-eServiceVector();IFMEServerStatus* status = repositoryMgr_->getServices(NULL, *services);if (isSuccess(status)){

IFMEServerString* name = serverSession_->creat-eServerString();IFMEServerString* urlPattern = serverSession_->creat-eServerString();

Developing with the Core APIs

166 FME Server Developer's Guide

Page 167: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

IFMEServerString* description = serverSession_->creat-eServerString();IFMEServerString* displayName = serverSession_->creat-eServerString();for (FME_UInt32 i = 0; i < services->entries(); i++){

IFMEServerService* service = (*services)(i);service->getName(*name);service->getURLPattern(*urlPattern);service->getDescription(*description);service->getDisplayName(*displayName);cout << name->data()

<< " " << displayName->data()<< " " << urlPattern->data()<< " ON:" << service->getIsEnabled()<< " " << description->data() << endl;

}serverSession_->destroyServerString(name);serverSession_->destroyServerString(urlPattern);serverSession_->destroyServerString(description);serverSession_->destroyServerString(displayName);

}serverSession_->destroyServiceVector(services);

How to add services

To add a new service, the service name, service display name, descriptionand URL pattern are required.

status = repositoryMgr_->addService(*service);if (isSuccess(status)){

cout << "Added the service\n";}

How to update services

To add a new service, the service name, service display name, descriptionand URL pattern are required. The service name uniquely identifies a serv-ice.

status = repositoryMgr_->updateService(*service);

FME Server Developer's Guide 167

Page 168: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

if (isSuccess(status)){

cout << "Updated the service\n";}

How to remove services

To remove a service, only the service name which uniquely identifies theservice is required.

IFMEServerStatus* status = repositoryMgr_->removeService(*name, exists);if (isSuccess(status)){

if (!exists){

cout << "There is no service with this name!" ;}

}

Running Workspaces

Once a workspace is published to an FME Server repository, the workspacecan be run. This can be done by constructing and then submitting a jobrequest using the Transformation Manager object. Normally users wouldcreate their own workspaces, but for this example we will be using a demoworkspace that is included with the default installation of the FME Server.

First step is to connect to the transformation manager, the component ofthe FME Server that handles job requests.

IFMEServerTransformationManager* transformationMgr = server-Session_->getTransformationManager();

Next, we need to create a transformation request that will be submitted tothe FME Server. The expected parameters are:

n The name of an FME Server node subsection, as defined in the node'sconfiguration. SERVER_CONSOLE_CLIENT is one such subsection, partof the default configuration that ships with the FME Server. Each

Developing with the Core APIs

168 FME Server Developer's Guide

Page 169: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

subsection specifies various processing directives (e.g. the folderwhere output should be placed). For information on the different sub-sections, please refer to <FMEServerDir>\Server\fme-EngineConfig.txt.

n The unique name of the repository that contains the target file, demo-download is one such repository, which contains the workspace "aus-tin.fmw".

n The name of a workspace, mapping file or command file that is to beexecuted by FME. In the latter case, the file is assumed to reside in theFME_MAPPING_DIR that has been set for the subsection that weselected with the first parameter. Here, we specify a workspace calledaustin.fmw from the demodownload repository.

IFMEServerTransformationRequest* req =serverSession_->createTransformationRequest(*su-bsectionName, *repositoryName, *workspaceName);

Some workspaces have published parameters that can be set. Some havedefault values but others need to be explicitly set before we are able to runthe workspace. These depend on the workspace itself. To set such a pub-lished parameter - in this case MAX_FEATURES:

*parmName = "MAX_FEATURES";*parmValue = "2000";req->setPublishedParameter(*parmName, *parmValue);

Note: Values for published parameters must always be passed asstrings, regardless of what they actually represent.

There also exist directives that are always available from the FME Server. Alist of TM directives can be found in "Transformation Manager Directives" onpage 1. We do not need the "tm_" prefix. For our example, we set a highvalue for the priority of this job, in order to tell the FME Server to execute itbefore other tasks. This is not necessary but just done to illustrate how to setdirectives.

*directiveName = "priority";*directiveValue = "42";

FME Server Developer's Guide 169

Page 170: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

req->setTMDirective(*directiveName, *directiveValue);

Once all parameters and directives have been set, we can submit ourrequest to the FME Server. A transformation request can be submittedeither synchronously or asynchronously.

If a job is submitted synchronously, the method call will be blocked untilthe job has finished. The results are stored in a transformation resultobject.

IFMEServerTransformationResult* result = serverSession_->createTransformationResult();transformationMgr->transactJob(*req, *result);

If a job is submitted asynchronously, the method call will immediatelyreturn the job ID, which can be used to check if the job has finished. Check-ing the result of a specified transformation job can be done in a wait-loopuntil the result is available.

long jobID = 0;transformationMgr->submitJob(*req, jobID);FME_Boolean resultAvailable = FME_FALSE;do{

transformationMgr->getJobResult(jobID, resultAvailable,*result);// Wait for 500 millisecondsSleep(500);

} while (!resultAvailable);

The transformation result object has a number of methods for obtaining dif-ferent parts of information from the FME Server response. In our examplewe first display the raw, unparsed string that was received from theserver. In certain scenarios, the clients may want to do their own parsingon this string instead of relying on the provided methods.

result->getFMEServerResponse(*fmeServerResponse);cout << "Response received:\n" << fmeServerResponse->data()<< endl;

Developing with the Core APIs

170 FME Server Developer's Guide

Page 171: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

We can now display additional pieces of information. First, we check that thetransformation was successful and, if so, we list some of the returned prop-erties. Properties are stored as name = value pairs, though some of themmay be null.

if (!result->getTransformationSuccess()){

IFMEServerString* status = serverSession_->creat-eServerString();result->getStatusMessage(*status);cout << "Transformation failed.";cout << "The error was: " << status->data();serverSession_->destroyServerString(status);

}else{

cout << "Transformation successful!\n";cout << "The following information was parsed from theresponse:\n";cout << "============\n";IFMEServerString* timeReq = serverSession_->creat-eServerString();IFMEServerString* timeStart = serverSession_->creat-eServerString();IFMEServerString* timeEnd = serverSession_->creat-eServerString();IFMEServerString* reqHost = serverSession_->creat-eServerString();IFMEServerString* reqKwd = serverSession_->creat-eServerString();FME_Int32 id;FME_Int32 statNo;result->getID(id);result->getTimeRequested(*timeReq);result->getTimeStarted(*timeStart);result->getTimeFinished(*timeEnd);result->getRequesterHost(*reqHost);result->getRequestKeyword(*reqKwd);result->getStatusNumber(statNo);cout

FME Server Developer's Guide 171

Page 172: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

<< "ID: " << id << endl<< "Time Requested: " << timeReq->data() << endl<< "Time Started: " << timeStart->data() << endl<< "Time Finished: " << timeEnd->data() << endl<< "Request Host: " << reqHost->data() << endl<< "Request Keyword: " << reqKwd->data() << endl<< "Status Number: " << statNo << endl;

serverSession_->destroyServerString(timeReq);serverSession_->destroyServerString(timeStart);serverSession_->destroyServerString(timeEnd);serverSession_->destroyServerString(reqHost);serverSession_->destroyServerString(reqKwd);

}

C++ Example/*=========================================================-===================

Name : FMEServerAPIDemo.cppSystem : FME Server APILanguage : C++Purpose : FMEServerAPIDemo sample application

Author Date Changes made------------------ ------------ -------------------------------Sample Jun 19, 2008 Original definition

Copyright (c) 1994 - 2011, Safe Software Inc.All Rights ReservedThis software may not be copied or reproduced, in all orin part,without the prior written consent of Safe Software Inc.The entire risk as to the results and performance of thesoftware,supporting text and other information contained in thisfile(collectively called the "Software") is with the user.In no event will Safe Software Incorporated be liable fordamages,including loss of profits or consequential damages, aris-ing out of

Developing with the Core APIs

172 FME Server Developer's Guide

Page 173: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

the use of the Software.============================================================-================ */#define WIN32#include <fmeservertypes.h>#include <ifmeserverattribute.h>#include <ifmeserverdataset.h>#include <ifmeserverparameter.h>#include <ifmeserverrepository.h>#include <ifmeserverrepositorymanager.h>#include <ifmeserversession.h>#include <ifmeserverrepositorymanager.h>#include <ifmeserverrepository.h>#include <ifmeserverstring.h>#include <ifmeserverstatus.h>#include <ifmeserverworkspacesummary.h>#include <ifmeservertransformationrequest.h>#include <ifmeservertransformationmanager.h>#include <ifmeservertransformationresult.h>#include <ifmeserverworkspace.h>#include <ifmeserverresource.h>#include <ifmeserverservice.h>#include <iostream>#include <string>using namespace std;class FMEServerAPIDemo{private:

IFMEServerSession* serverSession_;

IFMEServerRepositoryManager* repositoryMgr_;

public:

FME Server Developer's Guide 173

Page 174: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

//------------------------------------------------------------------// Constructor.FMEServerAPIDemo(const char* hostArg, const char* por-tArg);//------------------------------------------------------------------// Destructor.virtual ~FMEServerAPIDemo();//------------------------------------------------------------------// Will display the menu and execute the user's choice.void execute();

private:void displayMainMenu();int getMenuChoice();void executeMenuChoice(int choice);void listRepositories();void addRepository();void removeRepository();void listWorkspaces();void addWorkspace();void updateWorkspace();void getWorkspace();void removeWorkspace();void runWorkspace();void listResources();void addResource();void updateResource();void getResource();void removeResource();void listServices();void addService();void removeService();void updateService();void addCustomFormat();void remCustomFormat();void updateCustomFormat();void addCustomTransformer();void remCustomTransformer();

Developing with the Core APIs

174 FME Server Developer's Guide

Page 175: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

void updateCustomTransformer();// ---------------------------------------------------------------------// Sets the IFMEServerString input content to what theuser enters.// promptMessage will be displayed to tell the user whatto enter.void getInput(IFMEServerString& input, const char* prompt-Message);// ---------------------------------------------------------------------// Returns true if serverStatus is NULL. If serverStatusisn't NULL,// its content is displayed and the object is deleted.FME_Boolean isSuccess(IFMEServerStatus*& serverStatus);

};//==========================================================-===============//FMEServerAPIDemo::FMEServerAPIDemo(const char* hostArg,const char* portArg){

// From ifmeserversession.h, factory classFME_createServerSession(serverSession_);IFMEServerString* host = serverSession_->creat-eServerString();IFMEServerString* userID = serverSession_->creat-eServerString();IFMEServerString* password = serverSession_->creat-eServerString();IFMEServerString* clientId = serverSession_->creat-eServerString();IFMEServerStringArray* directives = serverSession_->creat-eServerStringArray();*host = hostArg;FME_UInt16 port = atoi(portArg);cout << "Please enter server connection credentials." <<endl;getInput(*userID, "UserId:");if (userID->length() > 0)

FME Server Developer's Guide 175

Page 176: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

{getInput(*password, "Password:");directives->append(kKeywordClientID);directives->append("app_apidemo");}IFMEServerConnectionInfo* connectionInfo_ = server-Session_->createServerConnectionInfo(*host, port, *us-erID, *password);serverSession_->init(*connectionInfo_, directives);repositoryMgr_ = serverSession_->getRepositoryManager();serverSession_->destroyServerConnectionInfo(con-nectionInfo_);serverSession_->destroyServerStringArray(directives);serverSession_->destroyServerString(clientId);serverSession_->destroyServerString(password);serverSession_->destroyServerString(userID);serverSession_->destroyServerString(host);

}//=========================================================-================//FMEServerAPIDemo::~FMEServerAPIDemo(){

IFMEServerStatus* status = serverSession_->disconnect();isSuccess(status);FME_destroyServerSession(serverSession_);

}//=========================================================-================//void FMEServerAPIDemo::execute(){

displayMainMenu();int choice = getMenuChoice();executeMenuChoice(choice);

}//=========================================================-================

Developing with the Core APIs

176 FME Server Developer's Guide

Page 177: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

//int FMEServerAPIDemo::getMenuChoice(){

int choice;// Check if input is valid, and if not clear and ignorethe streamif (!(cin >> choice)){

cin.clear();}cin.ignore(numeric_limits<streamsize>::max(), '\n');return choice;

}//==========================================================-===============//void FMEServerAPIDemo::executeMenuChoice(int choice){

switch(choice){

case 1:listRepositories();break;

case 2:addRepository();break;

case 3:removeRepository();break;

case 4:listWorkspaces();break;

case 5:addWorkspace();break;

case 6:updateWorkspace();break;

case 7:getWorkspace();

FME Server Developer's Guide 177

Page 178: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

break;case 8:

removeWorkspace();break;

case 9:listResources();break;

case 10:addResource();break;

case 11:updateResource();break;

case 12:getResource();break;

case 13:removeResource();break;

case 14:listServices();break;

case 15:addService();break;

case 16:updateService();break;

case 17:removeService();break;

case 18:runWorkspace();break;

case 0:exit(0);break;

default:cout << "Invalid option!\n";break;

}

Developing with the Core APIs

178 FME Server Developer's Guide

Page 179: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

}//==========================================================-===============//void FMEServerAPIDemo::displayMainMenu(){

cout << "\n\n" <<"===FME Server API Demo===\n" <<"1. List available repositories\n" <<"2. Add a repository\n" <<"3. Remove a repository\n" <<"4. List available workspaces\n" <<"5. Add a workspace\n" <<"6. Update a workspace\n" <<"7. Get a workspace\n" <<"8. Remove a workspace\n" <<"9. List resources of a workspace\n" <<"10. Add a resource\n" <<"11. Update a resource\n" <<"12. Get a resource\n" <<"13. Remove a resource\n" <<"14. List available services\n" <<"15. Add a service\n" <<"16. Update a service\n" <<"17. Remove a service\n" <<"18. Run a workspace\n" <<"0. Quit\n" <<"\nSELECT: ";

}//==========================================================-===============//void FMEServerAPIDemo::listRepositories(){

IFMEServerRepositoryVector* repositories = serverSession_->createRepositoryVector();IFMEServerString* description = serverSession_->creat-eServerString();

FME Server Developer's Guide 179

Page 180: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IFMEServerString* name = serverSession_->creat-eServerString();IFMEServerStatus* status = repositoryMgr_->getR-epositories(NULL, *repositories);if (isSuccess(status)){

for (FME_UInt32 i = 0; i < repositories->entries();i++){

IFMEServerRepository* repository = (*repositories)(i);repository->getName(*name);repository->getDescription(*description);cout << name->data() << " " << description->data()<< endl;

}}serverSession_->destroyRepositoryVector(repositories);serverSession_->destroyServerString(description);serverSession_->destroyServerString(name);

}//=========================================================-================//void FMEServerAPIDemo::addRepository(){

IFMEServerString* name = serverSession_->creat-eServerString();IFMEServerString* description = serverSession_->creat-eServerString();getInput(*name, "Please enter the name for the new repos-itory:\t");getInput(*description, "Please enter the description forthe new repository:\t");IFMEServerStatus* status = repositoryMgr_->addRepository(*name, *description);if (isSuccess(status)){

cout << "Added the repository\n";}

Developing with the Core APIs

180 FME Server Developer's Guide

Page 181: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

serverSession_->destroyServerString(name);serverSession_->destroyServerString(description);

}//==========================================================-===============//void FMEServerAPIDemo::removeRepository(){

FME_Boolean exists = FME_FALSE;IFMEServerString* name = serverSession_->creat-eServerString();getInput(*name, "Please enter the name for the repositoryto remove:\t");IFMEServerStatus* status = repositoryMgr_->re-moveRepository(*name, exists);if (isSuccess(status)){

cout << "Removed the repository\n";}serverSession_->destroyServerString(name);

}//==========================================================-===============//void FMEServerAPIDemo::listWorkspaces(){

IFMEServerRepositoryVector* repositories = serverSession_->createRepositoryVector();IFMEServerWorkspaceSummaryVector* workspaceSummaries =serverSession_->createWorkspaceSummaryVector();IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerStatus* status = repositoryMgr_->getRepositories(NULL, *repositories);if (isSuccess(status)){

for (FME_UInt32 i = 0; i < repositories->entries();i++){

FME Server Developer's Guide 181

Page 182: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IFMEServerRepository* repository = (*repositories)(i);status = repository->getWorkspaceSummaries(NULL,*workspaceSummaries);if (isSuccess(status)){

for (FME_UInt32 j = 0; j < workspaceSummaries->entries(); j++){

IFMEServerString* workspaceTitle = server-Session_->createServerString();IFMEServerString* workspaceName = server-Session_->createServerString();IFMEServerWorkspaceSummary* workspaceSummary =(*workspaceSummaries)(j);repository->getName(*repositoryName);workspaceSummary->getTitle(*workspaceTitle);workspaceSummary->getName(*workspaceName);cout << "Repository: "<< repositoryName->data()<< " " << workspaceTitle->data() << " " << work-spaceName->data() << " ON:" << work-spaceSummary->getIsEnabled() << endl;serverSession_->destroyServerString(work-spaceName);serverSession_->destroyServerString(work-spaceTitle);

}}

}}

serverSession_->destroyRepositoryVector(repositories);serverSession_->destroyWorkspaceSummaryVector(work-spaceSummaries);serverSession_->destroyServerString(repositoryName);

}//=========================================================-================//

Developing with the Core APIs

182 FME Server Developer's Guide

Page 183: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

void FMEServerAPIDemo::addWorkspace(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();FME_Boolean exists = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerString* workspaceName = serverSession_->creat-eServerString();IFMEServerString* workspaceFilePath = serverSession_->createServerString();getInput(*repositoryName, "Please enter the repositoryname for the new workspace:\t");getInput(*workspaceName, "Please enter the name for thenew workspace:\t");getInput(*workspaceFilePath, "Please enter the file pathfor the workspace to add:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, exists);if (isSuccess(status)){

status = repository->addItem(*workspaceName, *wor-kspaceFilePath);if (isSuccess(status)){

cout << "Added the workspace\n";}

}serverSession_->destroyRepository(repository);serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(workspaceFilePath);

}//==========================================================-===============//void FMEServerAPIDemo::updateWorkspace(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();

FME Server Developer's Guide 183

Page 184: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

FME_Boolean exists = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerString* workspaceName = serverSession_->creat-eServerString();IFMEServerString* workspaceFilePath = serverSession_->createServerString();getInput(*repositoryName, "Please enter the repositoryname for the workspace to update:\t");getInput(*workspaceName, "Please enter the name for theworkspace to update:\t");getInput(*workspaceFilePath, "Please enter the file pathfor the workspace to update:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, exists);if (isSuccess(status)){

status = repository->updateItem(*workspaceName, *wor-kspaceFilePath);if (isSuccess(status)){

cout << "Updated the workspace\n";}

}

serverSession_->destroyRepository(repository);serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(workspaceFilePath);

}//=========================================================-================//void FMEServerAPIDemo::getWorkspace(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();FME_Boolean exists = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();

Developing with the Core APIs

184 FME Server Developer's Guide

Page 185: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

IFMEServerString* workspaceName = serverSession_->creat-eServerString();IFMEServerString* workspaceFilePath = serverSession_->createServerString();getInput(*repositoryName, "Please enter the repositoryname for the workspace to get:\t");getInput(*workspaceName, "Please enter the name for theworkspace to get:\t");getInput(*workspaceFilePath, "Please enter the local filepath for the workspace to get:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, exists);if (isSuccess(status)){

status = repository->getItem(*workspaceName, *wor-kspaceFilePath, exists);if (isSuccess(status)){

cout << "Get workspace succeeded\n";}

}serverSession_->destroyRepository(repository);serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(workspaceFilePath);

}//==========================================================-===============//void FMEServerAPIDemo::removeWorkspace(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();FME_Boolean existsRepository = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerString* workspaceName = serverSession_->creat-eServerString();getInput(*repositoryName, "Please enter the repositoryname for the workspace to remove:\t");

FME Server Developer's Guide 185

Page 186: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

getInput(*workspaceName, "Please enter the name of theworkspace to remove:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, existsRepository);if (isSuccess(status)){

FME_Boolean existsWorkspace = FME_FALSE;status = repository->removeItem(*workspaceName,existsWorkspace);if (isSuccess(status)){

cout << "Removed the workspace\n";}

}serverSession_->destroyRepository(repository);serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);

}//=========================================================-================//void FMEServerAPIDemo::runWorkspace(){

IFMEServerString* subsectionName = serverSession_->creat-eServerString();IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerString* workspaceName = serverSession_->creat-eServerString();IFMEServerString* parmName = serverSession_->creat-eServerString();IFMEServerString* parmValue = serverSession_->creat-eServerString();IFMEServerString* directiveName = serverSession_->creat-eServerString();IFMEServerString* directiveValue = serverSession_->creat-eServerString();IFMEServerString* fmeServerResponse = serverSession_->createServerString();

Developing with the Core APIs

186 FME Server Developer's Guide

Page 187: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

IFMEServerTransformationManager* transformationMgr =serverSession_->getTransformationManager();

// Create an IFMETransformationRequest object to encap-sulate our// transformation request that will be submitted to theserver.// The createTransformationRequest(...) method expectsthree parameters:// 1. The name of an FME Server node subsection, asdefined in the// node's configuration. SERVER_CONSOLE_CLIENT is one such// subsection that is part of the default configurationthat ships// with the FME Server. Each subsection specifies various// processing directives (e.g., the folder where outputshould// be placed). For information on the different sub-sections, please// refer to <FMEServer-Install-Dir>\Server\fmeServerConfig.txt// 2. The unique name for the repository that contains themapping file// or command file to be executed by FME.

*subsectionName = "SERVER_CONSOLE_CLIENT";getInput(*repositoryName, "Please enter the repositoryname for the workspace to run:\t");getInput(*workspaceName, "Please enter the name of theworkspace to run:\t");IFMEServerTransformationRequest* req =

serverSession_->createTransformationRequest(*su-bsectionName, *repositoryName, *workspaceName);

// Set published parameters that have been exposed by theworkspace.// Both the name of the published parameter and thedesired value// are simple Strings, even if the value happens to have anumeric// interpretation.

FME Server Developer's Guide 187

Page 188: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

// Here, we set a published parameter called MAX_FEATURESthat// controls how many features will be read in from thesource dataset(s).// Published parameters depend on the workspace that isbeing run.

*parmName = "MAX_FEATURES";*parmValue = "2000";req->setPublishedParameter(*parmName, *parmValue);

// We can also set certain transformation manager direc-tives that determine how// our transformation request will be processed. Unlikepublished// parameters, which are determined by each workspace'sauthor and// thus vary from one workspace to another, the availabledirectives// are constant for all transformation requests. A com-plete// list of directives can be found in the FME Server doc-umentation.// Here, we set a high priority for this job to suggestthat it// should be given precedence over other, lower-priority,jobs.

*directiveName = "priority";*directiveValue = "42";req->setTMDirective(*directiveName, *directiveValue);cout << "Sending a transformation request to the FMEServer...\n";

// Submit the transformation request. This method will// block until transformation results are available.(Users who wish// to submit jobs asynchronously should instead use thesubmitJob(...)// method.) The returned results are stored in

Developing with the Core APIs

188 FME Server Developer's Guide

Page 189: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

// an IFMEServerTransformationResult object, which is thecompanion to the// IFMEServerTransformationRequest object that we sub-mitted.

IFMEServerTransformationResult* result = serverSession_->createTransformationResult();transformationMgr->transactJob(*req, *result);

// The transformation result object receives a resultstring from the// server and parses it to extract many different piecesof// information about the job result. However, users whowish to// do their own parsing of the raw server response, orwish to// log this string, may obtain the unparsed responsestring using// the getFMEServerResponse() method. Here, we use thatmethod to// print out the response string to the standard output.

result->getFMEServerResponse(*fmeServerResponse);cout << "Response received:\n" << fmeServerResponse->data() << endl;

// The IFMEServerTransformationResult interface definesmany accessor methods// for retrieving specific information from the parsedresult. We// only demonstrate a small subset of those methods here;a full list// is available in the FME Server API documentation.// The getTransformationSuccess() method returns true if,and only if,// the transformation was successful. Here, we check tosee if the// transformation was successful and then print out a mes-sage accordingly.

FME Server Developer's Guide 189

Page 190: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

if (!result->getTransformationSuccess()){

// The transformation was not successful. We informthe user of this// and then use getStatusMessage() to get the errormessage that// was returned by the server (e.g., "File austin.fmwcould not// be found.")

IFMEServerString* status = serverSession_->creat-eServerString();result->getStatusMessage(*status);cout << "Transformation failed.";cout << "The error was: " << status->data();serverSession_->destroyServerString(status);

}else{

// The transformation was successful. We inform theuser of this.cout << "Transformation successful!\n";

// The transformation result object contains manyname-value pairs// that are extracted from the SUCCESS_RESPONSEdefined in the// FME Server node subsection. In addition to thesepairs, there// are also several name-value pairs added by theserver:// the time that the job was sent to an FME Servernode for// processing (timeStarted), the job ID (id),etcetera.// The getAllProperties() method returns a map of allthese// name-value pairs. Here, we iterate over this map --using its

Developing with the Core APIs

190 FME Server Developer's Guide

Page 191: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

// entry set -- and simply print out its contents inthe form// "name = value".

cout << "The following information was parsed from theresponse:\n";cout << "============\n";// display a few of the propertiesIFMEServerString* timeReq = serverSession_->creat-eServerString();IFMEServerString* timeStart = serverSession_->creat-eServerString();IFMEServerString* timeEnd = serverSession_->creat-eServerString();IFMEServerString* reqHost = serverSession_->creat-eServerString();IFMEServerString* reqKwd = serverSession_->creat-eServerString();FME_Int32 id;FME_Int32 statNo;result->getID(id);result->getTimeRequested(*timeReq);result->getTimeStarted(*timeStart);result->getTimeFinished(*timeEnd);result->getRequesterHost(*reqHost);result->getRequestKeyword(*reqKwd);result->getStatusNumber(statNo);cout

<< "ID: " << id << endl<< "Time Requested: " << timeReq->data() << endl<< "Time Started: " << timeStart->data() << endl<< "Time Finished: " << timeEnd->data() << endl<< "Request Host: " << reqHost->data() << endl<< "Request Keyword: " << reqKwd->data() << endl<< "Status Number: " << statNo << endl;

serverSession_->destroyServerString(timeReq);serverSession_->destroyServerString(timeStart);serverSession_->destroyServerString(timeEnd);serverSession_->destroyServerString(reqHost);serverSession_->destroyServerString(reqKwd);

}serverSession_->destroyServerString(subsectionName);

FME Server Developer's Guide 191

Page 192: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(parmName);serverSession_->destroyServerString(parmValue);serverSession_->destroyServerString(directiveName);serverSession_->destroyServerString(directiveValue);serverSession_->destroyServerString(fmeServerResponse);

}//=========================================================-================//void FMEServerAPIDemo::listResources(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();IFMEServerResourceVector* resources = serverSession_->createResourceVector();FME_Boolean exists = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerString* workspaceName = serverSession_->creat-eServerString();getInput(*repositoryName, "Please enter the repositoryname for the resources:\t");getInput(*workspaceName, "Please enter the workspace namefor the resources:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, exists);if (isSuccess(status)){

status = repository->getResources(*workspaceName,NULL, *resources);if (isSuccess(status)){

for (FME_UInt32 i = 0; i < resources->entries();i++){

IFMEServerString* resourceName = serverSession_->createServerString();

Developing with the Core APIs

192 FME Server Developer's Guide

Page 193: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

IFMEServerString* resourceDescription = server-Session_->createServerString();IFMEServerResource* resource = (*resources)(i);resource->getName(*resourceName);resource->getDescription(*resourceDescription);cout << resourceName->data() << " " << resourceDe-scription->data() << endl;serverSession_->destroyServerString(resourceDe-scription);serverSession_->destroyServerString(resourceName);

}}

}

serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(repositoryName);serverSession_->destroyResourceVector(resources);serverSession_->destroyRepository(repository);

}//==========================================================-===============//void FMEServerAPIDemo::addResource(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();IFMEServerResource* resource = serverSession_->crea-teResource();FME_Boolean exists = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerString* workspaceName = serverSession_->creat-eServerString();IFMEServerString* resourceName = serverSession_->creat-eServerString();IFMEServerString* resourceFilePath = serverSession_->creat-eServerString();getInput(*repositoryName, "Please enter the repositoryname for the new resource:\t");

FME Server Developer's Guide 193

Page 194: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

getInput(*workspaceName, "Please enter the workspace namefor the new resource:\t");getInput(*resourceName, "Please enter the name for thenew resource:\t");getInput(*resourceFilePath, "Please enter the file pathfor the new resource to add:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, exists);if (isSuccess(status)){

status = repository->addResource(*workspaceName,*resourceName, *resourceFilePath);if (isSuccess(status)){

cout << "Added the resource\n";}

}serverSession_->destroyRepository(repository);serverSession_->destroyResource(resource);serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(resourceName);serverSession_->destroyServerString(resourceFilePath);

}//=========================================================-================//void FMEServerAPIDemo::updateResource(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();IFMEServerResource* resource = serverSession_->crea-teResource();FME_Boolean exists = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerString* workspaceName = serverSession_->creat-eServerString();IFMEServerString* resourceName = serverSession_->creat-eServerString();

Developing with the Core APIs

194 FME Server Developer's Guide

Page 195: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

IFMEServerString* resourceFilePath = serverSession_->creat-eServerString();getInput(*repositoryName, "Please enter the repositoryname for the resource to update:\t");getInput(*workspaceName, "Please enter the workspace namefor the resource to update:\t");getInput(*resourceName, "Please enter the name for theresource to update:\t");getInput(*resourceFilePath, "Please enter the file pathfor the resource to update:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, exists);if (isSuccess(status)){

status = repository->updateResource(*workspaceName,*resourceName, *resourceFilePath);if (isSuccess(status)){

cout << "Updated the resource\n";}

}serverSession_->destroyRepository(repository);serverSession_->destroyResource(resource);serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(resourceName);serverSession_->destroyServerString(resourceFilePath);

}//==========================================================-===============//void FMEServerAPIDemo::getResource(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();IFMEServerResource* resource = serverSession_->crea-teResource();FME_Boolean exists = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();

FME Server Developer's Guide 195

Page 196: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IFMEServerString* workspaceName = serverSession_->creat-eServerString();IFMEServerString* resourceName = serverSession_->creat-eServerString();IFMEServerString* resourceFilePath = serverSession_->createServerString();getInput(*repositoryName, "Please enter the repositoryname for the resource to get:\t");getInput(*workspaceName, "Please enter the workspace namefor the resource to get:\t");getInput(*resourceName, "Please enter the resource namefor the resource to get:\t");getInput(*resourceFilePath, "Please enter the file pathfor the resource to get:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, exists);if (isSuccess(status)){

status = repository->getResource(*workspaceName,*resourceName, *resourceFilePath, exists);if (isSuccess(status)){

cout << "Get resource succeeded\n";}

}serverSession_->destroyRepository(repository);serverSession_->destroyResource(resource);serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(resourceName);serverSession_->destroyServerString(resourceFilePath);

}//=========================================================-================//void FMEServerAPIDemo::removeResource(){

IFMEServerRepository* repository = serverSession_->crea-teRepository();

Developing with the Core APIs

196 FME Server Developer's Guide

Page 197: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

IFMEServerResource* resource = serverSession_->crea-teResource();FME_Boolean existsRepository = FME_FALSE;IFMEServerString* repositoryName = serverSession_->creat-eServerString();IFMEServerString* workspaceName = serverSession_->creat-eServerString();IFMEServerString* resourceName = serverSession_->creat-eServerString();getInput(*repositoryName, "Please enter the repositoryname for the resource to remove:\t");getInput(*workspaceName, "Please enter the workspace namefor the resource to remove:\t");getInput(*resourceName, "Please enter the resource namefor the resource to remove:\t");IFMEServerStatus* status = repositoryMgr_->getRepository(*repositoryName, *repository, existsRepository);if (isSuccess(status)){

FME_Boolean existsResource = FME_FALSE;status = repository->removeResource(*workspaceName,*resourceName, existsResource);if (isSuccess(status)){

cout << "Removed the resource\n";}

}serverSession_->destroyRepository(repository);serverSession_->destroyResource(resource);serverSession_->destroyServerString(repositoryName);serverSession_->destroyServerString(workspaceName);serverSession_->destroyServerString(resourceName);

}//==========================================================-===============//

void FMEServerAPIDemo::listServices(){IFMEServerServiceVector* services = serverSession_->creat-eServiceVector();

FME Server Developer's Guide 197

Page 198: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

IFMEServerStatus* status = repositoryMgr_->getServices(NULL, *services);if (isSuccess(status)){

IFMEServerString* name = serverSession_->creat-eServerString();IFMEServerString* urlPattern = serverSession_->creat-eServerString();IFMEServerString* description = serverSession_->creat-eServerString();IFMEServerString* displayName = serverSession_->creat-eServerString();for (FME_UInt32 i = 0; i < services->entries(); i++){

IFMEServerService* service = (*services)(i);service->getName(*name);service->getURLPattern(*urlPattern);service->getDescription(*description);service->getDisplayName(*displayName);cout << name->data()

<< " " << displayName->data()<< " " << urlPattern->data()<< " ON:" << service->getIsEnabled()<< " " << description->data() << endl;

}serverSession_->destroyServerString(name);serverSession_->destroyServerString(urlPattern);serverSession_->destroyServerString(description);serverSession_->destroyServerString(displayName);

}serverSession_->destroyServiceVector(services);

}//=========================================================-================//void FMEServerAPIDemo::addService(){

IFMEServerService* service = serverSession_->creat-eService();

Developing with the Core APIs

198 FME Server Developer's Guide

Page 199: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

IFMEServerString* name = serverSession_->creat-eServerString();IFMEServerString* urlPattern = serverSession_->creat-eServerString();IFMEServerString* displayName = serverSession_->creat-eServerString();IFMEServerString* description = serverSession_->creat-eServerString();getInput(*name, "Please enter the name of the new serv-ice:\t");getInput(*urlPattern, "Please enter the URL pattern of thenew service:\t");getInput(*displayName, "Please enter the display name ofthe new service:\t");getInput(*description, "Please enter the description ofthe new service:\t");service->setName(*name);service->setURLPattern(*urlPattern);service->setDisplayName(*displayName);service->setDescription(*description);service->setIsEnabled(FME_TRUE);FME_Boolean existsService = FME_FALSE;IFMEServerStatus* status = repositoryMgr_->serviceExists(*name, existsService);if (isSuccess(status)){

if (!existsService){

status = repositoryMgr_->addService(*service);if (isSuccess(status)){

cout << "Added the service\n";}

}else{

cout << "A service with this name already exists!";}

}

serverSession_->destroyServerString(name);

FME Server Developer's Guide 199

Page 200: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

serverSession_->destroyServerString(urlPattern);serverSession_->destroyServerString(displayName);serverSession_->destroyServerString(description);serverSession_->destroyService(service);

}//=========================================================-================//void FMEServerAPIDemo::updateService(){

FME_Boolean exists = FME_FALSE;IFMEServerService* service = serverSession_->creat-eService();IFMEServerString* name = serverSession_->creat-eServerString();IFMEServerString* urlPattern = serverSession_->creat-eServerString();IFMEServerString* displayName = serverSession_->creat-eServerString();IFMEServerString* description = serverSession_->creat-eServerString();getInput(*name, "Please enter the name of the service toupdate:\t");getInput(*urlPattern, "Please enter the URL pattern ofthe service to update:\t");getInput(*displayName, "Please enter the display name ofthe service to update:\t");getInput(*description, "Please enter the description ofthe service to update:\t");IFMEServerStatus* status = repositoryMgr_->getService(*name, *service, exists);if (isSuccess(status)){

service->setURLPattern(*urlPattern);service->setDisplayName(*displayName);service->setDescription(*description);status = repositoryMgr_->updateService(*service);if (isSuccess(status)){

cout << "Updated the service\n";

Developing with the Core APIs

200 FME Server Developer's Guide

Page 201: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

}}serverSession_->destroyServerString(name);serverSession_->destroyServerString(urlPattern);serverSession_->destroyServerString(displayName);serverSession_->destroyServerString(description);serverSession_->destroyService(service);

}//==========================================================-===============//void FMEServerAPIDemo::removeService(){

FME_Boolean exists = FME_FALSE;IFMEServerString* name = serverSession_->creat-eServerString();getInput(*name, "Please enter the name of the service toremove:\t");IFMEServerStatus* status = repositoryMgr_->removeService(*name, exists);if (isSuccess(status)){

if (!exists){

cout << "There is no service with this name!" ;}

}

serverSession_->destroyServerString(name);}//==========================================================-===============//FME_Boolean FMEServerAPIDemo::isSuccess(IFMEServerStatus*&serverStatus){

FME_Boolean isSuccessful = FME_TRUE;if (serverStatus){

FME Server Developer's Guide 201

Page 202: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

isSuccessful = FME_FALSE;cout << serverStatus->getErrorMessage();serverSession_->destroyServerStatus(serverStatus);

}return isSuccessful;

}//=========================================================-================//void FMEServerAPIDemo::getInput(IFMEServerString& input,const char* promptMessage){

string stringInput;cout << promptMessage;getline(cin, stringInput, '\n');input.set(stringInput.c_str(), (FME_UInt32)string-Input.length());

}//=========================================================-================//void argError(){

cout << "USAGE:\n\tFMEServerAPIDemo <host> <port>";exit(-1);

};//=========================================================-================// This program accepts two parameters.//// First parameter is the FME Server host. ie. localhost// Second parameter is the FME Server port. ie. 7071//int main(int argc, char *argv[]){

if (argc != 3){

Developing with the Core APIs

202 FME Server Developer's Guide

Page 203: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

C++

argError();}else{

FMEServerAPIDemo demo(argv[1], argv[2]);while (true){

demo.execute();}

}return 0;

}

FME Server Developer's Guide 203

Page 204: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

204 FME Server Developer's Guide

Page 205: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Enable CORS Filter

Configuring CORS FiltersCross-origin resource sharing (CORS) is included with FME Server and is dis-abled by default. You must manually enable the CORS filter for each webservice or web interface applicable. To do this for a particular web appli-cation, open its deployment descriptor in a text editor and uncomment theCORS filter directives at the end of the file.

Enable CORS Filter1. Open the WEB-INF/web.xml file of the web application where you want

to enable CORS

For example, the default location of this file for the Job Submitter serv-ice is \FM-EServer\Utilities\tomcat\webapps\fmejobsubmitter\WEB-

INF\web.xml.

2. Uncomment the CORS configuration directives. For example:

<!-- Cross-Origin Resource Sharing - Filter Con-figuration

Enabling this filter allows you to control cross-origin requests rather than coping with traditionalbrowser restrictions.Uncomment the section below and configure the "init-param" elements that meet your CORS requirements.CORS Configuration - http://s-oftware.dzhuvinov.com/cors-filter-configuration.htmlSee Also the FME Server Reference Manual

--><filter><filter-name>CORS</filter-name><filter-class>com.t-hetransactioncompany.cors.CORSFilter</filter-class>

</filter>

By default the CORS filter is configured to be enabled for every pos-sible URI to the web application. This can be adjusted using J2EE

FME Server Developer's Guide 205

Page 206: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

filters. (For more information, see the J2EE v2.5 Servlet Spec-ification.)

<filter-mapping><filter-name>CORS</filter-name><url-pattern>/*</url-pattern>

</filter-mapping>

For a complete CORS filter declaration and mapping example, seethe web.xml of the demo CORS application included with the down-load package.

3. Restart the web application or server.

Note: By default the CORS filter applies a "public access" CORS pol-icy, allowing all cross-site requests (including cre-dentials/cookies). Leaving the CORS Filter at this setting isappropriate for most situations, as the intent of CORS is notto add server security, but to protect the browser, includinglegitimate JavaScript apps running in it and the user's con-fidential data, such as cookies.

Restrict CORS FilterThe CORS filter can be run with no additional configuration in most sit-uations. By default it operates in public mode: It informs the browser thatrequests from any origin are accepted and that they may include optionalcredentials such as cookies.

The default CORS behavior can be overridden by adding one or moreexplicit init-param elements to the filter declaration in the WEB-INF/web.xml descriptor file.

For example, to allow CORS requests from http://example.com only:

<filter><filter-name>CORS</filter-name><filter-class>com.t-hetransactioncompany.cors.CORSFilter</filter-class><init-param>

Configuring CORS Filters

206 FME Server Developer's Guide

Page 207: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Filter init parameters

<param-name>cors.allowOrigin</param-name><param-value>http://safe.com</param-value>

</init-param></filter>

For a complete CORS filter declaration, configuration and mapping example,see the web.xml of the demo CORS application included with the downloadpackage.

Note: You must restart the web application or server after makingCORS configuration changes.

Filter init parametersn cors.allowGenericHttpRequests {true|false}

Defaults to true.

If true, generic HTTP requests are allowed to pass through the filter.Else, only valid and accepted CORS requests are allowed.

n cors.allowOrigin {"*"|origin-list}

Defaults to *.

Whitespace-separated list of origins that the CORS filter must allow.Requests from origins not included are refused with an HTTP 403 "For-bidden" response. If set to *, any origin is allowed.

Example: Allow any origin:

*

Example: Allow cross-domain requests from the following three orig-ins only:

http://fmeserver.com http://safe.com:8080https://my.own.net

n code.allowSubdomains {true|false}

Defaults to false.

FME Server Developer's Guide 207

Page 208: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

If true, the CORS filter allows requests from any origin that is a sub-domain origin of the allowed origins. A subdomain is matched by com-paring its scheme and suffix (host name/IP address and optional portnumber).

Example: If the explicitly allowed origin is http://example.com andsubdomains are allowed, all of the following origins are also allowed:

http://www.fmeserver.comhttp://secure.fmeserver.comhttp://passport.fmeserver.com

These non-matching origins, however, will be denied:

http://www.fmeserver.com:8080https://foo.fmeserver.comhttp://myexample.com

n cors.supportedMethods {method-list}

Defaults to "GET, POST, HEAD, OPTIONS".

List of supported HTTP methods. These are advertised through theAccess-Control-Allow-Methods header and must also be imple-mented by the actual CORS web service. Requests for methods notincluded here are refused by the CORS filter with an HTTP 405"Method not allowed" response.

Example: Allow only GET cross-origin requests:

GET

Example: Allow the methods for a typical RESTful web service:

GET, POST, HEAD, PUT, DELETE

cors.supportedHeaders {header-list}

Defaults to empty list.

The names of the supported author request headers. These are adver-tised through the Access-Control-Allow-Headers header.

Configuring CORS Filters

208 FME Server Developer's Guide

Page 209: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Filter init parameters

An author request header is any custom header set by the browserJavaScript application through the XMLHttpRequest.s-etRequestHeader() method.

Example: Inform the browser that the following author request head-ers are supported:

Content-Type, X-Requested-With

n cors.exposedHeaders {header-list}

Defaults to empty list.

List of the response headers other than simple response headers thatthe browser should expose to the author of the cross-domain requestthrough the XMLHttpRequest.getResponseHeader() method. TheCORS filter supplies this information through the Access-Control-Expose-Headers header.

Example: Inform the browser that the following custom headers aresafe to be exposed to the script that initiated the cross-domainrequest:

X-Custom-1, X-Custom-2

n cors.supportsCredentials {true|false}

Defaults to true.

Indicates whether user credentials, such as cookies, HTTP authen-tication or client-side certificates, are supported. The CORS filter usesthis value in constructing the Access-Control-Allow-Credentialsheader.

n cors.maxAge {int}

Defaults to -1 (unspecified).

Indicates how long the results of a preflight request can be cached bythe web browser, in seconds. If-1, the time is unspecified. This infor-mation is passed to the browser via the Access-Control-Max-Ageheader.

FME Server Developer's Guide 209

Page 210: FME Server Developer's Guide - Safe Softwaredocs.safe.com/fme/2013/pdf/FMEServer_DevelopersGuide.pdf · Introduction ThisFMEServer'sDeveloper'sGuideprovidesquick-start,tutorial,andsam-pleprogramresourcestohelpyougetstartedwiththeFMEServerAPIs

Example: Specify that the browser should cache preflight requestsfor 1 hour:

3600

Note: You must restart the web application or server after makingCORS configuration changes.

See Also

n http://software.dzhuvinov.com/cors-filter.html

n http://www.w3.org/TR/cors/

n Filter Declaration

n Filter Mapping

Configuring CORS Filters

210 FME Server Developer's Guide