Skip to content
Data & Connectivity > AMI Client

Java Client

Overview

The Java Client provides users the option to interface with AMI from external Java applications.

Follow the steps below to quickly configure and set up a Java application to interface with AMI.

Setup

Requirements

  1. Java Client packages

    • These are the AMI Client packages that ship with AMI
    • There are 3 Java interfaces:

      1
      2
      3
      com.f1.ami.client.AmiClient
      com.f1.ami.client.AmiClientListener
      com.f1.ami.client.AmiClientCommandDef
      
  2. Connection details of the AMI instance the Client is interfacing with

    • Hostname of the AMI Center or Relay instance (e.g: localhost)
    • The connection port number, set in the ami.port property (default is 3289)

Quickstart: AMI Client Java Code

package com.demo.runmaintest;

import java.util.Map;

import com.f1.ami.client.AmiClient;
import com.f1.ami.client.AmiClientCommandDef;
import com.f1.ami.client.AmiClientListener;
import com.f1.base.Complex;
import com.f1.utils.OH;
import com.f1.utils.concurrent.HasherMap;

public class SampleClient implements AmiClientListener {
    public static final byte OPTION_AUTO_PROCESS_INCOMING = 2;

    public static void main(String a[]) throws Exception {
        AmiClient client = new AmiClient();
        client.addListener(new SampleClient(client));
        client.start("localhost", 3289, "demo", OPTION_AUTO_PROCESS_INCOMING);
        while (true)
            OH.sleep(1000); // Keep process alive
    }

    private AmiClient amiClient;

    public SampleClient(AmiClient client) {
        this.amiClient = client;
    }
    @Override
    public void onMessageReceived(AmiClient source, long now, long seqnum, int status, CharSequence message) {
        System.out.println("Message received: " + message);
    }
    @Override
    public void onMessageSent(AmiClient source, CharSequence message) {
        System.out.println("Message sent: " + message);
    }
    @Override
    public void onConnect(AmiClient source) {
        System.out.println("Connected");
    }
    @Override
    public void onDisconnect(AmiClient source) {
        System.out.println("Disconnected");
    }
    @Override
    public void onLoggedIn(AmiClient amiClient) {
        // We've successfully connected an logged in, let's register stuff.
        System.out.println("Logged in");
        // Send message
        this.amiClient.startObjectMessage("SampleOrders", "1");
        // Send as String
        // addMessageParamString(String key, String value)
        this.amiClient.addMessageParamString("Order", "Order");
        // Send as int
        // addMessageParamInt(String key, int value)
        this.amiClient.addMessageParamInt("Quantity", 1000);
        // Send as double
        // addMessageParamDouble(String key, double value)
        this.amiClient.addMessageParamDouble("Price", 2703.1995);
        // Send as long
        // addMessageParamLong(String key, long value)
        this.amiClient.addMessageParamLong("Price2", (long) 2703.1995);
        // Send as float
        // addMessageParamFloat(String key, float value)
        this.amiClient.addMessageParamFloat("Volume", (float) 0.45466549498);
        // Send as boolean
        // addMessageParamBoolean(String key, boolean value)
        this.amiClient.addMessageParamBoolean("GTC", false);
        // Send as json object
        // addMessageParamJson(String key, Object value)
        Map<String, String> map = new HasherMap<String, String>();
        map.put("key", "val");
        this.amiClient.addMessageParamJson("Table", map);
        // Send as binary
        // addMessageParamBinary(String key, byte[] value)
        byte[] binary = "hello world".getBytes();
        this.amiClient.addMessageParamBinary("Val", binary);
        // Send as enum
        // addMessageParamEnum(String key, CharSequence value)
        this.amiClient.addMessageParamEnum("Num", "ENUM");
        // Send as object
        // addMessageParamObject(String key, Object value)
        Complex i = new Complex(1,1);
        this.amiClient.addMessageParamObject("Data", i);
        this.amiClient.sendMessageAndFlush();

        // Register a  command
        AmiClientCommandDef def = new AmiClientCommandDef("sample_cmd_def");
        def.setConditions(AmiClientCommandDef.CONDITION_USER_CLICK);
        this.amiClient.sendCommandDefinition(def);
        this.amiClient.flush();
        System.out.println("Sent command");
    }
        @Override
    public void onCommand(AmiClient source, String requestId, String cmd, String userName, String type, String id, Map<String, Object> params) {
        // Do business logic triggered by callback
        System.out.println("On command");
        source.startResponseMessage(requestId, 1, "Okay").addMessageParamLong("sample_user_callback", 45).sendMessageAndFlush();
    }
}

Sending Objects to AMI

Once the AmiClient is connected to AMI Realtime Backend API, the Client can start sending messages.

See the AMI Realtime Message Object O for more details.

AmiClient Java Class

Warning

Each individual AmiClient object is not thread-safe.

For multi-threaded cases, each thread should have its own instance of AmiClient.

AmiClient startObjectMessage(String type, CharSequence id)

Starts an object (O) message. Param id is optional.

AmiClient startObjectMessage(String type, CharSequence id, long expiresOn)

Starts an object (O) message. Param id is optional. If the param expiresOn is: set to 0 the object does not expire, a positive value the object expires at an epoch absolute time, a negative value the object expires in an offset time(milliseconds) into the future.

void addMessageParamObject(String key, Object value)

Add an Object parameter to the current message being built corresponding to some key in an AMI target object.

AmiClient addMessageParams(Map<String, Object> params)

See com.f1.ami.client.AmiClient (javadoc for other addMessageParam[types])

boolean sendMessage

Finalize and send the current message, returns true if successful

void flush()

Send pending message buffer to AMI, can be called at anytime

boolean sendMessageAndFlush()

Send pending message to AMI and block until the message is fully read by AMI, returns true if successful

Register and Send Commands

Commands can be created and registered to AMI via the AmiClientCommandDef Java class. This defines the command and how it appears in AMI.

Any behavior and callbacks invoked in AMI by the command must then be configured in the Client. This is done with the AmiClientListener onCommand() method.

The examples below show how to register a command within your Client application and process it.

Note

This is equivalent to sending a "Command" AMI Realtime Message from the Client and receiving a "Response" message from AMI. See this page for more information.

Example: Register Commands Java Code

Within your Java Client:

public class SampleClient implements AmiClientListener { 

//Creates a new command
AmiClientCommandDef commandDef = new AmiClientCommandDef("COMMAND_ID");
//Sets the name of the command on the frontend
commandDef.setName("Command Name");
//Specifies when to show the command
commandDef.setFilterClause("panel.title==\"PanelName\"");
//Specifies an additional param from the source table to be passed to the onCommand params
commandDef.setFields("id");
//Sends a command (C) declaration via the AMI Client
client.sendCommandDefinition(commandDef); 

Example: Process Command Callback Java Code

@Override
public void onCommand(AmiClient source, String requestId, String cmd, String userName, String type, String id, Map<String, Object> params) {
    String origRequestId = requestId;
    int status = 1;
    String message = "Okay";
    //Starts a response (R) message
    source.startResponseMessage(origRequestId, status, message);
    //Get additional params defined by AmiClientCommandDef.setFields
    long id = (long)params.get("id");
    source.addMessageParamLong("id", id);
    source.sendMessageAndFlush();
}

AmiClientAsServer

The steps to set up the interface for the AmiClientAsServer is similar to the AmiClient interface.

Configuration

To set it up, you will require the following configuration in your local.properties:

1
2
3
4
5
6
ami.relay.fh.active=$${ami.relay.fh.active},csocket  
ami.relay.fh.csocket.start=true  
ami.relay.fh.csocket.class=com.f1.ami.relay.fh.AmiClientSocketFH  
ami.relay.fh.csocket.props.amiId=client_socket  
ami.relay.fh.csocket.props.port=1234  
ami.relay.fh.csocket.props.host=localhost

Example: AmiClientAsServer Java Code

package com.f1.ami.client;

import java.io.IOException;
import java.net.Socket;
import java.util.Map;

public class AmiClientAsServerTest implements AmiClientAsServerFactory, AmiClientListener {
    public static void main(String a[]) throws IOException {
        new AmiClientAsServer(1234, null, null, new AmiClientAsServerTest());
    }

    @Override
    public void onClient(Socket socket, AmiClient client) throws IOException {
        client.addListener(this);
        client.start(socket, "demo", AmiClient.ENABLE_AUTO_PROCESS_INCOMING);
        client.startObjectMessage("ClientAsServer", null);
        client.addMessageParamString("key", "Hello!");
        client.addMessageParamLong("now", System.currentTimeMillis());
        client.addMessageParamDouble("now", System.currentTimeMillis());
        client.sendMessageAndFlush();
    }

    @Override
    public void onMessageReceived(AmiClient rawClient, long now, int seqnum, int status, CharSequence message) {
        System.out.println("On Message Received: " + message);
    }

    @Override
    public void onMessageSent(AmiClient rawClient, CharSequence message) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onConnect(AmiClient rawClient) {
        System.out.println("Connected");
    }

    @Override
    public void onDisconnect(AmiClient rawClient) {
        System.out.println("Disconnected");
    }

    @Override
    public void onCommand(AmiClient rawClient, String requestId, String cmd, String userName, String objectType, String objectId, Map<String, Object> params) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onLoggedIn(AmiClient rawClient) {
        System.out.println("Loggedin");
    }
}

Center Subscription using AMI Client

The AMI Center Client is used to create real-time subscriptions to one or more tables in a Center.

Once subscribed, any changes made to the tables will be published to the client.

A full example can be found here. For the empty Java interface, see below.

AmiCenterClientListener Java File

package centerclient;

import com.f1.ami.amicommon.AmiCenterDefinition;
import com.f1.ami.amicommon.centerclient.AmiCenterClientListener;
import com.f1.ami.amicommon.centerclient.AmiCenterClientObjectMessage;
import com.f1.ami.client.AmiCenterClient;
import com.f1.bootstrap.ContainerBootstrap;

public class CenterClient implements AmiCenterClientListener {

    public CenterClient() {
    }

    public static void main(String[] args) throws Exception {
        new ContainerBootstrap(CenterClient.class, args);
        AmiCenterClient centerClient = new AmiCenterClient("demo");
        centerClient.connect("center_name", "center_host", 3270, new CenterClient());//Replace with your inputs
        //Subscribe to both table "A" and "__TABLE"
        centerClient.subscribe("center_name", Collections.singleton("A", "__TABLE"));
        while (true);
    }

    @Override
    public void onCenterConnect(AmiCenterDefinition center) {
    }

    @Override
    public void onCenterDisconnect(AmiCenterDefinition center) {
    }

    @Override
    public void onCenterMessage(AmiCenterDefinition center, AmiCenterClientObjectMessage m) {
    }

    @Override
    public void onCenterMessageBatchDone(AmiCenterDefinition center) {
    }

}