You are here: FME Server Developer's Guide > Developing with the Core APIs > Java > Java Tutorial

Java Tutorial

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

API Demo - Java

For demonstration purposes a sample command line application has been created to illustrate many of the common FME Server API concepts with sample code. The sample command line application takes two parameters. The first parameter is the FME Server host name and the second parameter is the FME Server port number. When the command line application is executed, you will be prompted for your credentials. (Leave blank for security-disabled configurations.) Upon verification, a menu is displayed which prompts you to select a given command. Additional information may be required depending on the command selected.

Sample code is available in Java, C++ and .NET. Please refer to the Java Quick Start for information on how to set up your development 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 the client ID for it to work. (See Resources for more information.

Working with Server Sessions

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

IFMEServerSession serverSession_ = FMEServer.createServerSession();

Once a server session is created, you can create the objects required to initialize it. To initialize a server session, a connection info object that specifies the 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 session directive. (See Enabling SSL on the Application Server and FME Server Web Service Security Concepts.) The client ID must match the client ID you configured in FME Server.

Note:  Providing a client ID on a security-disabled system will not lead 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));

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

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

serverSession_.disconnect();

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

Working with Repositories

The Repository Manager component of the FME Server manages repositories. A repository is a central place to store items, resources and other things that enable the FME Server to perform its functions. A typical item is a workspace, a custom format or a custom transformer. Associated with items are resources.

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

IFMERepositoryManager repositoryMgr_ = serverSession_.getRepositoryManager();

How to list available repositories

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

ArrayList<IFMERepository> repositoryList = repositoryMgr_.getRepositories(null);

for (IFMERepository repository : repositoryList)

{

System.out.format("%s %s\n",

repository.getName(),

repository.getDescription());

}

How to add repositories

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

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

if (!repositoryMgr_.repositoryExists(name))

{

repositoryMgr_.addRepository(name, description);

}

else

{

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

}

How to remove repositories

Removing a repository requires the name of the repository. It's important to know that removing a repository will also remove any items and resources in it.

if (!repositoryMgr_.removeRepository(name))

{

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

}

Working with Workspaces

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

FME workspaces are created through FME Workbench and can be published to an FME Server repository so that multiple users can access them. Workspaces in the FME Server repository can also be downloaded, modified, and then published again.

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

How to list workspaces in a repository

Workspace names can be quickly listed using repository methods that get the workspace summaries of a workspace. More detailed information about workspaces can also be fetched with other repository methods.

ArrayList<IFMERepository> repositories = repositoryMgr_.getRepositories(null);

for (IFMERepository repository : repositories)

{

ArrayList<IFMEWorkspaceSummary> workspaceSummaries = repository.getWorkspaceSummaries(null);

for (IFMEWorkspaceSummary workspaceSummary : workspaceSummaries)

{

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 workspace file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name (ie. foo.fmw) are required. When adding a workspace, the actual workspace file is uploaded to the FME Server repository.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);

if (!repository.itemExists(workspaceName))

{

repository.addItem(workspaceName, workspaceFilePath);

}

else

{

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

}

How to update workspaces in a repository

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

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);

if (repository.itemExists(workspaceName))

{

repository.updateItem(workspaceName, workspaceFilePath);

}

else

{

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

How to get workspaces from a repository

To get a workspace from a repository, the repository name, the local workspace file path (ie. "C:\myworkspaces\foo.fmw") and the workspace name (ie. foo.fmw) are required. The workspace name uniquely identifies a workspace in a repository and should match the workspace you wish to get. When getting a workspace, the actual workspace file is downloaded from the FME 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 with this file name!");

}

How to remove workspaces in a repository

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

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);

if (!repository.removeItem(workspaceName))

{

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

}

Working with Resources

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

How to list resources for a workspace

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

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);

IFMEWorkspace workspace = repository.getWorkspace(workspaceName);

 

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 workspace name, the resource file path (ie. "C:\myresources\resource.csv) and the resource name (ie. resource.csv) are required. When adding a resource, the actual 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 resource with this name!");

}

How to update resources for a workspace

To update a resource for a workspace, the repository name, the workspace name, the resource file path (ie. "C:\myresources\resource.csv") and the resource name (ie. resource.csv) are required. The resource name uniquely identifies a resource for a workspace and should match the resource you wish to update. When updating a resource, the actual resource file is uploaded 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 with this name!");

}

How to get resources for a workspace

To get a resource for a workspace, the repository name, the workspace name, the local resource file path (ie. "C:\myresources\resource.csv") and the resource name (ie. resource.csv) are required. The resource name uniquely identifies a resource for a workspace and should match the resource you wish to get. When getting a resource, the actual resource file is downloaded 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 with this 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 specific workspace will also remove all associated resources for the workspace.

IFMERepository repository = repositoryMgr_.getRepository(repositoryName);

if (!repository.removeResource(workspaceName, resourceName))

{

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

}

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 provides you with information about these services such as the service name and service URL pattern. It also allows you to create new service descriptions 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, description and URL pattern are required.

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

if (!repositoryMgr_.serviceExists(name))

{

repositoryMgr_.addService(service);

}

else

{

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

}

How to update services

To add a new service, the service name, service display name, description and URL pattern are required. The service name uniquely identifies a service.

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

if (repositoryMgr_.serviceExists(name))

{

repositoryMgr_.updateService(service);

}

else

{

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

}

How to remove services

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

if (!repositoryMgr_.removeService(name))

{

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

}

Running Workspaces

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

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

IFMETransformationManager transformationMgr = session_.getTransformationManager();

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

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

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

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

There also exist directives that are always available from the FME Server. A list of TM directives can be found Transformation Manager Directives. Since we are functionality specifically for 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 Server to execute it before other tasks. This is not necessary but just done to illustrate how to set directives.

req.setTMDirective("priority", 42);

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

If a job is submitted synchronously, the method call will be blocked until the job 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 return the job ID, which can be used to check if the job has finished. Checking the result of a specified transformation job can be done in a wait-loop until the result is available.

IFMETransformationResult result = serverSession_.createTransformationResult();

long jobID = transformer.submitJob(req);

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

{

// Wait for 500 milliseconds

Thread.sleep(500);

}

The transformation result object has a number of methods for obtaining different parts of information from the FME Server response. In our example we first display the raw, unparsed string that was received from the server. In certain scenarios, the clients may want to do their own parsing on 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 that the transformation was successful and, if so, we list some of the returned properties. Properties are stored as name = value pairs, though some of them may be null.

if (!result.getTransformationSuccess())

{

throw new FMEServerException("Transformation failed.\nThe error was: "

+ result.getStatusMessage());

}

else

{

System.out.println("Transformation successful!");

System.out.println("The following information was parsed from the response:");

for (Map.Entry<String,String> prop : result.getAllProperties().entrySet())

{

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

{

System.out.println(prop.getKey() + " = " + prop.getValue());

}

}

}

Safe Software Inc. www.safe.com