Using Finsemble APIs
Your Finsemble smart desktop can include diverse types of apps, such as Web, .NET, Java, and so on. You can build these apps with any appropriate framework or API native to their platform. For example, you can use React, Angular, vanilla JavaScript and so on,. on the Web, WPF or WinForms in .NET/.NET core, Swing or JavaFX in Java. In addition, Finsemble provides a number of its own APIs that you can use to build or upgrade apps and services so that they work together, or interoperate, seamlessly in your smart desktop:- HTML5 - For browser-based apps we recommend that you try HTML5 first. You can use the HTML5 API in Finsemble the same way as you would in the browser. This approach works well in many cases, but the options for making apps work together or send messages to each other are limited to JavaScript only and constrained by standard web security. If you need more than that, consider the next 3 choices.
- FDC3 - Finsemble provides implementations (JavaScript, Java & .NET) of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) Desktop Agent API. FDC3 defines itself as "an open standard for interoperability between applications on the financial desktop" that is rapidly becoming ubiquitous on financial services desktops. It should be your first choice for building workflows and communication between apps in your smart desktop (without needing a backend server).
- Finsemble Client API - For visual integration or low-level coding, use Finsemble's proprietary APIs (JavaScript, Java & .NET).
- FinsembleWindow - For window manipulation beyond
window.open()
,fdc3.open()
andLauncherClient.showWindow()
use the FinsembleWindow API (JavaScript, Java & .NET).
Types of application
Finsemble supports a number of classes of application that can work with our APIs:
Application (app): A piece of software designed to fulfill a particular purpose. It can communicate with other apps by using the FDC3 Desktop Agent API. In Finsemble, apps are usually launched by the user, form part of a workspace, and display a window.
App instance: Each copy of an app you start becomes an independent app instance.
noteYou can configure apps to allow only a single instance (a singleton app) to be spawned, but the default is to allow multiple instances.
There is no limit on the number of instances you can have. Each instance has its own
instanceId
(in fdc3) andwindowName
(in Finsemble). You can use either the instance ID or the window name, as appropriate for the API you are using, to access an app instance individually.
App service: A special type of application that Finsemble usually starts during the boot phase, rather than being launched by a user. An app service typically provides some form of desktop infrastructure. It usually doesn't display a window or belong to a workspace, but it is still a component of the desktop. You can implement one in any technology with FDC3 support, including HTML5, .NET, Java.
Freestanding application: An application that is started outside of Finsemble, but that can still connect to it using an adapter such as the .NET, Java, or JavaScript adapters that Finsemble provides. A freestanding app can be either native or web. There is no limit on the number of feestanding app instances you can have.
UI component: A basic Finsemble component that provides a user interface through a window, but isn’t a full app in its own right. It can't communicate by using the FDC3 API and uses the Finsemble Client APIs instead.
Applications can also be classified by the technologies used to build them:
- Web app: An app built using web technologies and rendered by a web view in a window that Finsemble provides. Finsemble injects its Client APIs and the FDC3 API into Web applications, while freestanding web applications can use the Finsemble JavaScript adapter to gain access to the FDC3 API.
- Native app: An app that is written for a specific platform or device. Native apps aren’t based on web technologies and/or aren’t running in a window that Finsemble provides. You can manage Windows for native apps alongside Finsemble-provided web windows. These windows can gain access to the FInsemble Client APIs and the FDC3 API by using the Finsemble native adapters for .NET, .NET Core, and Java.
- Hybrid app: A standalone native app that incorporates a web view, within which a web app runs. The Web app acts as an External Web Application and can use the Finsemble JavaScript adapter to gain access to the FDC3 API.
Getting access to the APIs
Web apps running in Finsemble
HTML5 and standard Web APIs
Finsemble web windows are based on Chromium and provide access to all client-side Web APIs with JavaScript bindings. Use them as you would an app built for use in a browser.
By default, Electron grants all Chromium permissions protecting web APIs, but you can grant or refuse them by applying a security policy or individual permissions in your configuration for each app. See the security policies documentation for details.
If you're working with an app that uses a web API but needs customization in Finsemble, you can either use a preload or detect Finsemble by checking for window.finsemble
and implement different behavior.
FDC3
Finsemble's JavaScript implementation of FDC3 is available at window.fdc3
as defined in the FDC3 Standard. For more details about how to access the FDC3 API see the Finsemble Interop tutorial and the 'Supported Platforms' section of the FDC3 documentation. For an API reference and usage examples see the Desktop Agent API reference in the FDC3 documentation.
Example
Typescript types and utility functions for use with the FDC3 API are available via the FDC3 NPM module.
Finsemble Client APIs
Finsemble provides a range of its own client APIs for built-in Finsemble services that you can use to enhance your applications and smart desktop. Features that you can access via these APIs include authentication, storage integration, configuration management, hotkeys, search, notifications, workspaces, centralized logging, dialog management, and window management.
You can access Finsemble Client APIs via window.FSBL.Clients
in both applications and app services. See the master list of API reference docs for these APIs for more details about each API.
For details about using TypeScript with Finsemble's Client APIs see the 'Integrating HTML Applications' tutorial.
If you need to use a Finsemble client API as your application initializes, wrap calls in this event listener to ensure that client-side initialization of the API clients is complete:
FSBL.addEventListener("onReady", init);
function init() {
//Make Finsemble API calls here, for example:
FSBL.Clients.SearchClient.register({...},
(err, response) => {
//provider has been registered
});
}
If you are using Finsemble APIs in a preload script, expand this pattern to:
if (window.FSBL && FSBL.addEventListener) {
FSBL.addEventListener("onReady", init);
} else {
window.addEventListener("FSBLReady", init);
}
If you need to work with low-level window management functions and event listeners beyond what is available via the Window and AppsClient Client APIs, use the FinsembleWindow API to retrieve a window wrapper.
Low-level interactions with windows can affect their management by Finsemble's built-in services. For this reason we recommend that you don’t use this API unless you must. Contact support@cosaic.io if you need help.
To access a wrap for the current window, use window.finsembleWindow
.
To retrieve a wrap for a remote window you need the windowName
, or a unique identifier for a window that represents an instance of an application. Window names are returned when spawning applications via the AppsClient API and for all active windows when you call the LauncherClient.getActiveDescriptors()
API.
let winName = <window name>;
const { wrap } = await FSBL.FinsembleWindow.getInstance({ windowName: winName });
fin/e2o/Finsemble.system
You can use low-level APIs, including window.fin
, window.e2o
, and window.FSBL.System
, that other Finsemble APIs and services use to implement functionality.
These APIs are not intended for use by apps. Don’t use them directly because they are subject to change without notice.
External Web applications
Occasionally, you might need to integrate a web or Electron app running outside of Finsemble with apps running in Finsemble. To do so you can use the Finsemble JavaScript adapter, which can make an authenticated connection to Finsemble over which you make FDC3 API calls.
For more details about how to connect to Finsemble with the JavaScript adapter, see its documentation.
Connections from freestanding web applications, which aren’t launched by Finsemble, need to be authenticated for access to particular features and can be used to secure communications. See Authenticating apps for more info.
.NET and Java apps
.NET and Java apps can use APIs provided by their respective platforms (as is the case for Web apps and Web APIs). Finsemble also provides native API adapters for .NET and Java apps that include clients for the FDC3 API, Finsemble Client APIs and FinsembleWindow APIs (whose API signatures match those provided for JavaScript as closely as possible ensuring functional parity for native and web applications).
Here's a .NET example:
static void Main(string[] args)
{
// Initialize Finsemble
FSBL = new Finsemble(args, null);
// The event is fired after a connection to Finsemble is established
FSBL.Connected += OnConnected;
// Pass your appId
FSBL.Connect("WindowlessExample");
}
private static void OnConnected(object sender, EventArgs e)
{
FSBL.Logger.Log("Windowless example connected to Finsemble.");
// If the Finsemble app config contains ` "appService": true, "waitForInitialization": true `,
// signal to Finsemble that appService initialization is complete.
FSBL.PublishReady();
}
For more about how to use the Finsemble native adapters, see the 'Logical Integration' section of the 'Integrating Native apps tutorial'.
Connections from freestanding native apps, which aren’t launched by Finsemble, need to be authenticated for access to particular features and can be used to secure communications. See Authenticating apps for more info.
Using window.open()
in Finsemble
Some web apps make use of HTML5's window.open() call to pop open new windows in a browser. Calling window.open() from an app running in Finsemble will also open a new window. Finsemble will honor the requested width and height of the window. This window will be provided with a Finsemble window title bar, allowing them to snap like other Finsemble windows.
There are a few behaviors to know about using window.open
in Finsemble.
- Window title bars are always injected in windows opened by
window.open()
(as opposed to being separated from your app's content like most apps). It is possible for the title bar's CSS to affect the rendering of your app, requiring customization to remove any conflicts. - Windows opened by
window.open()
are not added to the workspace. The user must manually close them when they are no longer needed. - Windows opened by
window.open()
inherit their app config (that isSpawnParams
) from their parent. A parent can use thechildWindowOptions
section of its config to specify any overrides to this behavior for windows that it opens viawindow.open()
.
If you need more control over your windows, you can replace window.open()
with calls to LauncherClient.spawn()
by loading the nativeOverrides.js preload ($moduleRoot/preloads/nativeOverrides.js). When you use this preload, window.open()
no longer returns a window object. The JavaScript and DOM will therefore be physically separated between the parent and child windows.
The nativeOverrides.js preload also overrides JavaScript's alert()
code, re-routing those messages to Finsemble's notifications. If you want to override window.open()
, but not alert()
, you must create your own preload, copying only the required code from nativeOverrides.js.
Windows opened by links with a target
attribute have the same behaviors as those called by window.open()
.
Finsemble API conventions
Terminology
componentType
: Identifier for an individual component and used (often as part of a 'window identifier') to address particular apps through Finsemble Client APIs. As most components are also applications, they will generally use their 'appId' as their component type.
- display name: The human-friendly string used to represent a particular app in dialogs and menus (e.g. the FDC3 intent resolver, or the Toolbars launcher menus). In FDC3 App Directories, this is usually represented by the 'title' field.
- Finsemble Client APIs: Finsemble's proprietary APIs that provide support for both Visual & Logical integration, as well of other aspects of making your applications work well on and integrate with the desktop. The Client APIs are automatically injected into HTML5 windows (at
FSBL.Clients.*
) or provided by .NET and Java libraries that you can import into your application. - FinsembleWindow: Finsemble's window management proxy interface, enabling both local and remote control of 'component' 'windows'.
- title: The FDC3 app directory record field that provides a display name for an app: The human-friendly string used to represent a particular app in dialogs and menus. Often confused with the window title.
- window: a, typically rectangular, frame through which a user can interact with an application. Finsemble provides web-windows, rendered via Chromium and Electron, within which web/javascript applications run and can integrate and manage other 'native' windows via a process called 'assimilation'.
windowName
: Finsemble's internal, unique identifier for a window. Used to address, or provide details on, particular instances of applications.- window title: The string displayed in a window's title bar, which will usually differ from its 'appId', 'title' and 'display name', by incorporating details of its current context, in much the same way as the title of a browser tab does.
WindowIdentifier
: An object with bothwindowName
andcomponentType
properties used to address particular windows through the Finsemble Client APIs.- workspace: A layout of applications, with internal state data for each, that may be saved and restored at a later time.
Standardized callbacks and Go language (golang) style promises
Finsemble's API calls use the convention of returning errors rather than throwing exceptions. Most Finsemble API calls are asynchronous, and therefore the returned values and errors are retrieved via a promise. This approach is sometimes referred to as golang style error handling, because of Go's standardization on the approach.
A typical Finsemble API call follows this pattern:
const { err, data } = await FSBL.Clients.WindowClient.getComponentState({field: "myfield"});
if(err || !data){
// Handle your error condition. By convention, err will be a string.
// For functions that don't return data, leave off the `|| !data`
}else{
// If err is null or undefined, then no error has occurred.
// Do something with the returned data (which will be typed automatically)
}
This approach contrasts with the exception style of handling that was made popular by object oriented languages such as C++ and Java, and which is commonly used by many JavaScript libraries.
The primary rationale for the golang style approach is that it makes a distinction between "exceptions" (situations that the code doesn't anticipate) and "errors" (situations that the code does anticipate). For instance, "division by zero" is an exception. It points to a bug in the underlying function. But a website returning 404 is merely an error condition. It does not point to a bug in the underlying code but simply indicates the application has entered a valid error state. Golang style error handling encourages developers to explicitly handle error states rather than allowing them to percolate up the stack as exceptions. Often, this allows for quicker debugging of error conditions through more informative end user or log messages. Meanwhile, exceptions themselves, usually bugs, when allowed to percolate to the top of the stack, generate a useful stack trace and allow for a "fail fast" approach to development (as opposed to catching exceptions within a code stack where they might be hidden from users or logs) .
By convention, most Finsemble API calls also accept a callback as the final parameter. This can be used as an alternative to awaiting a promise.
FSBL.Clients.WindowClient.getComponentState({field: "myfield"}, (err, data) => {
if(err || !data){
// Handle your error condition. By convention, err will be a string.
// For functions that don't return data, leave off the `|| !data`
}else{
// If err is null or undefined, then no error has occurred.
// Do something with the returned data (which will be typed automatically)
}
});
.NET API
See https://documentation.finsemble.com/docs/add-apps/native/IntegratingNativeApps#logically-integrating-native-apps for information on using Finsemble's .NET and Java APIs.
::: note
Function names are capitalized in Finsemble's .NET library. For instance, FSBL.Clients.WindowClient.getComponentState()
in JavaScript is equivalent to FSBL.WindowClient.GetComponentState()
in .NET.
:::
The Finsemble .NET library does not use golang style error handling. All errors take the form of exceptions.
try{
JToken state = await FSBL.WindowClient.GetComponentState(new JObject{ ["field"] = "myfield"});
// Do something with the returned data (which will be typed automatically)
}catch(Exception e){
// Handle your error condition. The "e.Message" contains a Finsemble error message.
}
Most Finsemble .NET APIs also support a callback function as an optional final parameter.
Java API
See https://documentation.finsemble.com/docs/add-apps/native/IntegratingNativeApps#logically-integrating-native-apps for information on using Finsemble's .NET and Java APIs.
Finsemble's Java API does not support an equivalent asynchronous await
style function syntax in Java. All Java API calls require a callback function to be passed as the final parameter.
FSBL.getClients().getWindowClient().getComponentState(new JSONObject() {{ put("field","myField");}},(err, data) -> {
if(err==null){
// Handle your error condition. By convention, err will be a string.
}else{
// If err is null then no error has occurred.
// Do something with the returned data (which will be a JSONObject)
}
})
Apps, components, and Window names
Apps in your smart desktop are uniquely identified by their appId
field. Multiple instances of the same app may be launched.
Every window in Finsemble is identified by a unique windowName
.
Some Finsemble APIs use a WindowIdentifier
, which is just an object wrapper around a windowName
and other, optional, fields. Therefore, in most cases an object with a windowName
property is all that is required.
Example WindowIdentifier
{
windowName: "MyAppId-GH121-LKKJK2-5FGFD-SDFDFF-IYUYU"
}
Call FSBL.Clients.WindowClient.getWindowIdentifier()
within a running app to get its current window identifier (which contains the window name).
Window names are reused when launching saved workspaces.
Finsemble's UI Components do not have an appId
. These are referred to by their component name, such as "Toolbar" or "NotificationCenter", which can show up under the componentName
field.
Window titles
The text that appears in an app's title bar can come from several sources. The following order of precedence is used by Finsemble to determine what to display:
- User-defined title - Users can double click on the title in a tab and enter their own title.
WindowClient.setWindowTitle()
- Calls to this API can be used to set the title at runtime.- Config:
foreign.components.["Window Manager"].title
- A proprietary Finsemble config in an app's host manifest section. document.title
- The title set by the app itself in JavaScript, or with the<title>
tag.- Config: AppD
title
field - The FDC3 standard title field in an app's AppD config entry.
If none of these values are set then the app's title will be blank.
Typescript generics
Many of Finsemble's API functions support Typescript generics. This feature can increase type safety in your application and make coding easier by providing type information to your IDEs auto-complete.
Typescript generics are optional.
In the following example, the data
object will automatically have the type MyResponseType
.
const { err, data } = await FSBL.Clients.RouterClient.query<MyQueryType,MyResponseType>("myChannel", myQuery);
See the API reference for each API function to determine which generics are available. Your IDE may also display generics when hovering over a function call.
See also
Integrating freestanding apps with the JavaScript adapter
Developing FDC3-compliant apps