Skip to content
Data > Clients

AMI Client

The AMI Client is a flexible tool enabling bi-directional communication with external applications via AMI Relay. It works by sending Realtime Messages, AMI’s internal messaging protocol, which enables external commands to be processed by AMI.

Overview

The AMI Client is a built-in mechanism within the 3forge platform enabling external applications to interact and communicate with AMI. Its primary use is to respond automatically to different events while the communication is active.

It can be fully and freely configured, allowing users to define custom actions in response to specified events. This includes:

  • Handling incoming messages
  • Notifying when a message is sent
  • Alerting on connection status, like when the client connects, disconnects, or successfully logs in
  • Processing and responding to command callbacks

The Client is designed for bi-directional communication and can also be used to publish messages back to AMI. This allows for commands to be sent to AMI from an external application using Realtime Messages.

AMI Client Library

The AMI Client is supported in the following three languages:

All three client versions use the AmiClientListener interface to allow developers to define what behavior should be executed when each event occurs.

The AMI Client is not thread-safe. Multiple threads should not access the same client.

AMI Client Structure

AMI Client is primarily backed by three Java classes, using a Subject-Observer approach:

  1. AmiClient (Subject)

    • AmiClient is the lowest level class and establishes and manages communication from AMI to an external application over the Relay.
    • It contains the functionality for sending and receiving Realtime Messages to AMI.
  2. AmiClientListener (Observer)

    • The AmiClientListener is an interface responsible for all the event handling for an AmiClient connection.
    • It contains a reference to an AmiClient object, allowing the listener to both send and receive messages to AMI.
  3. AmiClientCommandDef

    • AmiClientCommandDef is a configuration class allowing users to define their own executable commands in AMI, e.g: a “send order” command, which can then be sent to AMI.
    • The actual functionality and logic of the command callback is then defined in the AmiClientListener instance.

To create an instance of an AMI Client, you will need to implement an AmiClientListener in your language of choice from the list above.

Implementation

Details will vary depending on the language, but the core implementation for an AMI Client is the same across each library.

In general, creating and using an instance of an AMI Client should follow these steps:

  1. Create an AMI Client application using the AmiClientListener interface.
  2. Within the application implementing the listener, initialize an AmiClient object which enables connection to and from AMI.
  3. (Optionally) Create command definitions using AmiClientCommandDef objects and send those to AMI via the Client.
  4. Implement any logic and other handling needed in the AmiClientListener methods. This includes using the AmiClient object to send and receive Realtime Messages to AMI.

AmiClientListener Methods

Logic for handling events should be implemented by the user in the AmiClientListener. This includes:

  • Starting and establishing the connection to AMI
  • Sending and receiving messages (see the AmiClient methods for details)
  • Events that occur on connect or disconnect

When implementing the interface, there are 6 methods that can be overridden which are listed below. Use these methods to handle any logic for those specific events.

Note

Calls to each method may be slightly different across different libraries. The information is provided for the base Java classes.

Please use this as reference only and refer to the specific library pages for examples in the corresponding language.

void onMessageReceived(...)

public void onMessageReceived(AmiClient rawClient, long now, long seqnum, int status, CharSequence message);
Parameter Description
rawClient Represents the AmiClient's internal connection to the AMI server
now Time in ms that the message was received
seqnum Sequence number, or (Q) param, of the received message
status Status, or (S) param, of the received message
message Message, or (M) param, contents of the received message
  • If the ENABLE_QUIET option is not set, then each message sent to AMI will be followed be a status (M) message that is sent back to the Client
  • Use this method to determine what if any actions should be performed by the Client, e.g:
    1
    2
    3
    4
    @Override
    public void onMessageReceived(AmiClient rawClient, long now, long seqnum, int status, CharSequence message) {
        System.out.println("Message received: " + message);
    }
    

void onMessageSent(...)

public void onMessageSent(AmiClient rawClient, CharSequence message);
Parameter Description
rawClient Represents the AmiClient's internal connection to the AMI server
message The buffer of the message that was just sent
  • Fired after each message is sent using any AmiClient send message method
  • Use this method to determine what if any actions should be performed by the Client when a message is sent to AMI, e.g:
    1
    2
    3
    4
    @Override
    public void onMessageSent(AmiClient rawClient, CharSequence message) {
        System.out.println("Message sent: " + message);
    }
    

void onConnect(...)

public void onConnect(AmiClient rawClient);
Parameter Description
rawClient Represents the AmiClient's internal connection to the AMI server
  • Called after a successful connection, but before a login attempt
  • Use this method to determine what if any actions should be performed by the Client on connection, e.g:
    1
    2
    3
    4
    @Override
    public void onConnect(AmiClient rawClient) {
        System.out.println("Connected");
    }
    

void onDisconnect(...)

public void onDisconnect(AmiClient rawClient);
Parameter Description
rawClient Represents the AmiClient's internal connection to the AMI server
  • Called after a client/server connection has been disconnected
  • Use this method to determine what if any actions should be performed by the Client on disconnect, e.g:
    1
    2
    3
    4
    @Override
    public void onConnect(AmiClient rawClient) {
        System.out.println("Disconnected");
    }
    

void onCommand(...)

public void onCommand(AmiClient rawClient, String requestId, String cmd, String userName, String objectType, String objectId, Map<String, Object> params);
Parameter Description
rawClient Represents the AmiClient's internal connection to the AMI server
requestId Unique identifier for this execute command (E). Should be included in the response
cmd ID of the command (C)
userName Username of the command caller (U)
objectType Type of object the command was called on
objectId The ID of the object (O)
params Any additional parameters of the received object in key-value pairs
  • Called when an execute (E) command is received from the server
  • These can be user-defined commands specified with AmiClientCommandDef objects
  • Use this method to configure what behavior the Client should perform when a command has been executed in AMI, e.g:
    1
    2
    3
    4
    5
    6
    7
    8
    @Override
    public void onCommand(AmiClient rawClient, String requestId, String cmd, String userName, String type, String id, Map<String, Object> params) {
        System.out.println("Command received: " + cmd);
    
        // Start a response (R) message that will appear in AMI 
        rawClient.startResponseMessage(requestId, 0, "command received by client");
        rawClient.sendMessageAndFlush();
    }
    

void onLoggedIn(...)

public void onLoggedIn(AmiClient rawClient);
Parameter Description
rawClient Represents the AmiClient's internal connection to the AMI server
  • Called after a successful login (L) has processed by the AMI Relay server
  • Use this method to determine what if any actions should be performed by the Client on login, e.g:
    1
    2
    3
    4
    @Override
    public void onLoggedIn(AmiClient amiClient) {
        System.out.println("Logged in");
    }
    

AmiClient Methods

There are several methods in the AmiClient class that are used to send messages to and from AMI. You will need to call these methods from within your AMI Client application (AmiClientListener) to interface with AMI.

Listed below are the available AmiClient methods that can be called from an AMI Client instance.

Note

Calls to each method may be slightly different across different libraries. The information is provided for the base Java classes.

Please use this as reference only and refer to the specific library pages for examples in the corresponding language.

Options

These are optional flags that can be set to configure the Client. These are passed in when the Client is started as the parameter int options.

Option Value Description
ENABLE_QUIET 4 Same as setting O="QUIET" in the login message. Tells AMI Relay not to send message ack back to the Client
ENABLE_AUTO_PROCESS_INCOMING 2 By default, this Client will automatically read inbound messages and process them in a separate thread. If disabled, you must manually call pumpIncomingEvent()
DISABLE_AUTO_RECONNECT 8 By default, this Client will keep trying to reconnect to the AMI server
ENABLE_SEND_TIMESTAMPS 32 Whether this Client should send timestamps. Useful for enabling delayed message detection
ENABLE_SEND_SEQNUM 64 Whether this Client should send sequence numbers. Useful for linking a Client message to a message in AMI
LOG_CONNECTION_RETRY_ERRORS 128 Whether this Client should log errors each time a connection retry fails. If not set, then just on the first connection failure
LOG_MESSAGES 256 If set, all messages will be logged using standard java.util.logging.Logger framework
ENABLE_AUTO_FLUSH_OUTGOING 512 If set, a separate thread is started which will automatically flush messages as they are written

Connection Handling

Method Name Alternative Overloads Description Return Value
void start(String host, int port, String loginId, int options)
  • void start(Socket socket, String loginId, int options)
  • void start(String host, int port, String loginId, int options, File keystoreFile, com.f1.base.Password keystorePassword)
  • void start(String host, int port, String loginId, int options, File keystoreFile, String keystorePassword)
Starts the connection with the supplied parameters. Overloaded methods can be used to optionally supply SSL connection details
int getOptions() Options passed into start() Summed value of supplied options
void close() Close the connection and stop trying to reconnect
boolean connect() Try and reconnect, will also send login (L) instructions true if connected
boolean isConnected() Check if there is a live connection to AMI true if connected
void addListener(AmiClientListener listener) Add a new listener for receiving callbacks on important events that occur during connection with AMI
void removeListener(AmiClientListener listener) Remove an existing listener
#java long getAutoReconnectFrequencyMs() Get how many ms to wait before trying to reconnect when in a disconnected state value of autoReconnectFrequencyMs
#java long setAutoReconnectFrequencyMs() Set the value in ms to wait before trying to reconnect when in a disconnected state value of autoReconnectFrequencyMs
boolean getDebugMessages() Get whether debug messages have been enabled true if enabled
void setDebugMessages() Set whether debug messages are enabled
boolean waitForLogin(long i) Check whether AMI is waiting for a login true if waiting

Message Handling

Method Name Alternative Overloads Description Return Value
boolean sendMessageAndFlush() Send the pending message to AMI and block until the message is fully read by AMI
void sendMessageAndFlush(CharSequence cs) Send the input message to AMI and block until the message is fully read by AMI false if there was an io error
void flush() Send pending message buffer to AMI. Can be called anytime
boolean pumpIncomingEvent() Check for an incoming message and fire appropriate callback if found. Available only if ENABLE_AUTO_PROCESS_INCOMING is disabled true if a message was processed, false if there were no queued messages for processing
AmiClient startStatusMessage() Starts a status (S) message. Note, this is deprecated This instance
AmiClient startObjectMessage(String type, CharSequence id) AmiClient startObjectMessage(String type, CharSequence id, long expiresOn) Starts an object (O) message.
  • type = target table, or (T) param
  • id = unique ID for that object, or (I) param (Optional)
  • expiresOn = time in ms in the future that the object should expire on, or (E) param (Optional)
This instance
AmiClient startResponseMessage(String origRequestId) AmiClient startResponseMessage(String origRequestId, int status, String message) Starts a response (R) message.
  • origRequestId = AMI generated ID for this command, or the (I) param
  • status = status of the command, or (S) param (Optional)
  • message = message to be sent to the Client, or (M) param (Optional)
This instance
AmiClient startCommandDefinition(String id) Start a command definition (C) message. Give the command an id, or (I) field This instance
AmiClient startDeleteMessage(String type, String id) Start a delete (D) message.
  • type = the target table, or (T) param, to delete from
  • id = the id of the object to delete, or the (I) field
This instance
void sendPause(int delayMs) Start a pause (P) message. delayMs = the number of ms to pause by, or (D) param
AmiClient addMessageParamNull(CharSequence key) Add a parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamString(CharSequence key, CharSequence value)
  • AmiClient addMessageParamString(CharSequence key, char value)
  • AmiClient addMessageParamString(CharSequence key, CharSequence value), int start, int end
Add a String parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamEnum(CharSequence key, CharSequence value) AmiClient addMessageParamEnum(CharSequence key, CharSequence value, int start, int end) Add an Enum parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamJson(CharSequence key, Object value) Add an JSON parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamBinary(CharSequence key, byte[] value) AmiClient addMessageParamBinary(CharSequence key, byte[] value), int start, int end Add a Binary parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamLong(CharSequence key, long value) Add a Long parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamInt(CharSequence key, int value) Add an Int parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamDouble(CharSequence key, double value) Add a Double parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamDoubleEncoded(CharSequence key, double value) Add an encoded Double parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamFloat(CharSequence key, float value) Add a Float parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamFloatEncoded(CharSequence key, float value) Add an encoded Float parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addMessageParamBoolean(CharSequence key, boolean value) Add a Boolean parameter to the current message being built corresponding to some key in an AMI target object This instance
AmiClient addRawText(CharSequence text, int start, int end) Bypass this API and send the raw chars directly to AMI. The user is responsible for properly escaping, quoting, etc. This instance
boolean sendMessage() Finalize and send the message currently being built false if there was an io issue
void resetMessage() Reset the pending message, a new message will need to be restarted
AmiClient addMessageParams(Map<String,Object> params) Convenience message for quickly sending all the params from the supplied map where the key corresponds to some key in AMI and the object is the supplied value This instance
void addMessageParamObject(String key, Object value) Convenience message for sending a boxed value. Value types are considered by the method such that "123" is sent as a String, 123 as an int, 123d as a double, etc.
void flushAndWaitForReplys(int timeoutMs) Flush existing messages and wait for a response
void sendCommandDefinition(AmiClientCommandDef def) Send a command (C) declaration to AMI by passing it a pre-defined AmiClientCommandDef object
CharSequence getOutputBuffer() Get the current output message buffer The output message buffer
AmiClient startMessage(char type) Start a message of the supplied type (O, I, E, etc) This instance
long resetSeqNum(long seqnum) The sequence number to include on the next startMessage(...) when ENABLE_SEND_SEQNUM is enabled The old seqnum
long getAutoFlushBufferMillis() Get the value of the autoflush delay. Default is 2ms The autoflush delay in ms
void setAutoFlushBufferMillis() Set the value of the autoflush delay. A higher number increases throughput at the cost of latency
int getBufferSizeOut() Get the buffer size in Bytes for the outbound buffer (will force flush when buffer is filled). Default is 8192 Buffer size of outbound buffer
void setBufferSizeOut(int bufferSizeOut) Set the buffer size in Bytes for the outbound buffer (will force flush when buffer is filled). Default is 8192
int int getBufferSizeIn() Get the buffer size in Bytes for the inbound buffer (number of Bytes attempted to be read off the socket in a single call). Default is 8192 Buffer size of inbound buffer
void setBufferSizeIn(int bufferSizeIn) Set the buffer size in Bytes for the inbound buffer (number of Bytes attempted to be read off the socket in a single call). Default is 8192

AmiClientCommandDef Methods

Users can define their own executable commands from the Client that can be called within AMI which will trigger a callback that then gets sent back to the Client.

This is equivalent to calling a user sending a (C) message to AMI, then AMI sending an (E) message, followed by some optional event handling done in the Client which can include a (R) message. This handling is done in the onCommand(...) method.

Listed below are the available methods for defining an AmiClientCommandDef object.

Note

Calls to each method may be slightly different across different libraries. The information is provided for the base Java classes.

Please use this as reference only and refer to the specific library pages for examples in the corresponding language.

Settable Parameters

Method Name Description
AmiClientCommandDef setCommandId(String commandId) Set the unique ID attributed to that command. Equivalent to the (I) param
AmiClientCommandDef setLevel(Integer level) Set the permissions level of the command. 0 means remove the command, any other number is used for entitlements. Equivalent to (L) param
AmiClientCommandDef setWhereClause(String whereClause) Set which rows the command will be available at. Equivalent to (W) param
AmiClientCommandDef setHelp(String help) Set a help text that will be displayed in AMI. Equivalent to (H) param
AmiClientCommandDef setName(String name) Set the name of the command. This is what is displayed in AMI. Equivalent to (H) param
AmiClientCommandDef setPriority(Integer priority) Set the priority for display. Commands with higher priority are listed above lower priority in context menu where 0 is highest. Equivalent to (P) param
AmiClientCommandDef setEnabledExpression(String enabledExpression) Set the command to be enabled only where the expression holds. Equivalent to (E) param
AmiClientCommandDef setStyle(String style) Set style of the menu item in a JSON format. Equivalent to (S) param
AmiClientCommandDef setSelectMode(Integer min, Integer max) Constrains number of rows that can be selected. Equivalent to (M) param
AmiClientCommandDef setFields(String fields) Set the parameter the returned execute command should include. Equivalent to (F) param
AmiClientCommandDef setFilterClause(String filterClause) Set a filter on what target objects the command should be available on. Equivalent to (T) param
AmiClientCommandDef setConditions(String... conditions) Set the conditions in AMI on which the command should execute. The accepted conditions are listed below. Equivalent to (C) param

Conditions

Condition Value Description
CONDITION_NOW "now" Fires when sent
CONDITION_USER_CLICK "user_click" Fires on user-click
CONDITION_USER_LOGIN "user_open_layout" Fires when user opens layout
CONDITION_USER_LOGOUT "user_close_layout" Fires when user logs out