You are here: FME Server Developer's Guide > Developing with the Web Services > FME Server Transformation Services > Java Tutorial

Java Tutorial

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

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

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

Web Services API Demo - Java

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

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

Working with Workspaces

Web services are run on workspaces which reside in repositories. Furthermore, each workspace can be setup to have a different subset of published parameters and web services available. However, the Web Services API does not provide any means of determining the available repositories, workspaces, and their respective published parameters and services available.

Developers can either:

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

Our REST API supports Working with Repositories, Working with Workspaces, and Working with Jobs. Although not listed in the REST tutorial (but included in our demo), REST can determine the available services for a given workspace. (See Working with Web Services.)

Working with Java and XML

For the purpose of this tutorial, we will be using a built in XML parser in Java. 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 an XML document.

private Document parseXML(String contents) throws Exception

{

DocumentBuilderFactory dbf = DocumentBuilderFactory.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 and knowing the URI to the workspace (which can be generated from the repository and workspace name).

String fmeUrl = "http://"+host_+":"+port_+"/fmerest/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();

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 service

PostMethod 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 all services. These settings range in complexity from adding a description to scheduling the service to run at a later date. For more information, see Transformation Manager.

For our example, we set a high value for the priority of this job, in order to tell the FME Server to execute it before other tasks. This is not necessary but 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 their respective input types.

// for the request to run the service

String runUrl = serviceURL;

PostMethod runMethod = new PostMethod(runUrl);

 

NodeList nl_parameters = doc.getElementsByTagName("parameter");

 

// get value for each parameter

for (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("description").item(0).getTextContent();

String defaultValue = el.getElementsByTagName("defaultValue").item(0).getTextContent();

String optionsType = el.getElementsByTagName("optionsType").item(0).getTextContent();

 

if (optionsType.equals("SINGLECHOICE_CONFIG")) {

// single choice, so choose it

NodeList 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 the number (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")) {

// prompt the user for each choice

NodeList 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 the default 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 input

String value = getInput(display + "(default = '" + defaultValue + "') ");

// use default if nothing provided

if (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 be saved or run in another application (ie. Google Earth for .kmz files).

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 user

String runContents = runMethod.getResponseBodyAsString();

System.out.println(runContents);

}

else

{

// we had best download this file to a location

String filePath = getInput("Please enter the location you would 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 is not binary data

fileStream.println(new String(responseBody));

 

fileStream.close();

file.close();

}

Safe Software Inc. www.safe.com