# Writing a trading adapter

A trading integration adapter integrates your bank’s trading systems with the Caplin Platform.

icon:tv[] Download the [presentations](https://docs.caplin.com/developer/tutorial-resources/platform/presentation-Caplin_Platform_IntegrationSuite.zip) for this course.

## Overview

Trading requires a flow of interaction between the client and the server, conducted over a messaging channel. A messaging channel is a bi-directional, one-to-one subscription between the client and the adapter.

A trade may require several messages to be passed between the adapter and the client. For example, the adapter may send prices to the client before the client decides to execute a trade (as in RFS trades); the adapter may send message acknowledgements to the server (e.g. Execute Ack messages); or the client may choose to stop the trade while it is executing by sending a message to the adapter.

The message choreography between client and adapter is tracked by a state machine called the trade model. Each message between the client and the adapter causes a transition between states.

## Tutorial objectives

In this tutorial, you will achieve the following objectives:

* Create a trade model that represents the trading workflow
* Create a trading adapter
* Connect the trading adapter to a mock server
* Submit trades using a test HTML page and the StreamLink JS library

## Download Caplin’s training project

See [Download Caplin’s training project](platbsc-pricing-integration-adapter-1.md#download-templates) in the _Writing a pricing adapter (1)_ tutorial.

## Create a Trading Adapter project

Create a new adapter project based on the Trading Adapter example.

Follow the steps below:

1. Copy the `TradingAdapter` directory to your `caplin-training` directory:

   ```
   $ cp -r ~/caplin-training/CaplinTrainingBackendProject-version/TradingAdapter ~/caplin-training/TradingAdapter
   ```

   ```plantuml
   @startsalt
   scale 1.25
   {
   {T
    + <color:goldenrod><&folder></color> home   
    ++ <color:goldenrod><&folder></color> //username//
    +++ <color:goldenrod><&folder></color> caplin-training
    ++++ <color:goldenrod><&folder></color> **TradingAdapter**
    +++++ <color:goldenrod><&folder></color> blade
    +++++ <color:goldenrod><&folder></color> build
    +++++ <color:goldenrod><&folder></color> gradle
    +++++ <color:goldenrod><&folder></color> lib
    +++++ <color:goldenrod><&folder></color> src
    +++++ <color:goldenrod><&folder></color> .gradle
    +++++ <color:goldenrod><&folder></color> .idea
    +++++ <color:cornflowerblue><&file></color> build.grade
    +++++ <color:cornflowerblue><&file></color> gradlew
    +++++ <color:cornflowerblue><&file></color> gradlew.bat
    +++++ <color:cornflowerblue><&file></color> README.md
    +++++ <color:cornflowerblue><&file></color> settings.gradle
    ++++ <color:goldenrod><&file></color> CaplinTrainingBackendProject.zip
   }
   }
   @endsalt
   ```

### Project dependencies

Choose one of the methods below to resolve project dependencies:

<details>
<summary>Local libraries</summary>

Requires Jar files supplied by your trainer or downloaded from [Caplin Downloads](https://account.caplin.com/account/downloads) by your Caplin account holder.

Copy the following dependency Jar files to your project’s `lib` directory:

* **Java DataSource API:** `datasource-java-_version_-jar-with-dependencies.jar`
* **Java Trading API**: `trading-datasource-_version_.jar`

```plantuml
@startsalt
scale 1.25
{
{T
 + <color:goldenrod><&folder></color> home   
 ++ <color:goldenrod><&folder></color> //username//
 +++ <color:goldenrod><&folder></color> caplin-training
 ++++ <color:goldenrod><&folder></color> TradingAdapter
 +++++ <color:goldenrod><&folder></color> blade
 +++++ <color:goldenrod><&folder></color> gradle
 +++++ <color:goldenrod><&folder></color> lib
 ++++++ <color:cornflowerblue><&file></color> **datasource-java-//version//-jar-with-dependencies.jar**
 ++++++ <color:cornflowerblue><&file></color> **trading-datasource-//version//.jar**
 +++++ <color:goldenrod><&folder></color> src
 +++++ <color:cornflowerblue><&file></color> build.gradle
 +++++ <color:cornflowerblue><&file></color> settings.gradle
}
}
@endsalt
```
</details>

<details>
<summary>Caplin software repository</summary>

Requires network access to Maven Central, network access to https://repository.caplin.com, and a Caplin customer account. 

In the file `~/.gradle/gradle.properties`, declare the following properties and assign them your Caplin username and password:

**File: ~/.gradle/gradle.properties**

```
caplinUsername=__username__
caplinPassword=__password__
```

In the project’s `build.gradle` file, modify the `repositories { … }` block so that it lists the project’s `lib` directory, Maven Central, and Caplin’s software repository:

**File: build.gradle**

```groovy
repositories {
    flatDir {
        dirs 'lib'
    }
    mavenCentral()
    maven {
        credentials {
            username "$caplinUsername"
            password "$caplinPassword"
        }
        url "https://repository.caplin.com"
    }
}
```
</details>

## Import the project into Eclipse

Follow the instructions for your IDE below.

<details>
<summary>IntelliJ</summary>

To import your project into IntelliJ, follow the steps below:

1. Click **File > New > Project from existing sources**
2. Select the project’s Gradle build file: `~/caplin-training/TradingAdapter/build.gradle`
</details>

<details>
<summary>Eclipse</summary>

To import your project into Eclipse, follow the steps below:

1. In Eclipse, click **File > Import**. The Import dialog opens.
2. From the Import dialog, click **Existing Gradle Project**. The Import Gradle Project dialog opens.
3. Under **Project location**, deselect **Use default location**
4. In the **Location** field, select your trading adapter’s project directory.

   **💡 TIP**\
   If you are using Cygwin, your project directory is `C:/cygwin64/home/__username__/caplin-training/TradingAdapter`
5. Click **Finish**
</details>

## Running your adapter during development

To run the adapter from your IDE during development, you need to perform two tasks:

* Deploy your adapter’s configuration to your Deployment Framework. Your adapter project includes configuration files that are required by Liberator and/or Transformer.
* Configure the environment in which your IDE runs your adapter. This is called a "run configuration" in Eclipse and IntelliJ.

### Deploy your adapter’s configuration

The Trading Adapter example includes a Gradle task that builds an installation kit that contains just your adapter’s configuration (no binary). This kit can be deployed to your Deployment Framework like any other installation kit.

Follow the steps below:

1. From the root of your adapter project, run the command below:

   ```
   $ ./gradlew assemble -PconfigOnly
   ```

   The installation kit is written to the directory `build/distributions`.
2. Copy the installation kit to the `kits` directory of your Deployment Framework. Do not extract the archive.
3. From the root directory of your Deployment Framework, run the command below to deploy the kit:

   ```
   $ ./dfw deploy
   ```
4. From the root directory of your Deployment Framework, run the command below to confirm that your adapter’s configuration has deployed:

   ```
   $ ./dfw versions
   ```

### Create a run configuration in your IDE

Follow the instructions for your IDE below.

<details>
<summary>IntelliJ</summary>

To create a run configuration in IntelliJ, follow the steps below:

1. Click **Run > Edit Configurations**
2. Click **Add new run configuration**, and click **Application** from the context menu.
3. Set **Name** to 'Trading Adapter'
4. Set **JDK or JRE** to your OpenJDK (Java 8 or Java 11)
5. Set **Classpath** to the classpath of the module below:

   ```
   TradingAdapter.main
   ```
6. Set **Main class** to the text below:

   ```
   com.caplin.TradingAdapter
   ```
7. Set **Program arguments** to the text below:

   ```
   -f etc/datasource.conf --trading-property-file=etc/trading-provider.properties
   ```
8. Set **Working directory** to the adapter’s `DataSource` directory in your Deployment Framework:

   **Linux, macOS**

   ```
   __deployment_framework_root__/active_blades/TradingAdapter/DataSource
   ```

   **Windows**

   ```
   __deployment_framework_root__\kits\PricingAdapter\TradingAdapter-0.0.0\DataSource
   ```
9. Set **Environment variables** to the text below:

   ```
   CONFIG_BASE=__deployment_framework_root__/global_config/
   ```

   **❗ IMPORTANT**\
   The value of CONFIG_BASE must end in a trailing forward-slash (`/`)
10. Click **OK** to close the dialog.

To run the Pricing Adapter, click **Run > Run 'Trading Adapter'**.
</details>

<details>
<summary>Eclipse</summary>

To run your adapter in Eclipse for the first time, follow the steps below:

1. In Eclipse, click **Run > Run Configurations**. The Run Configurations dialog appears.
2. From the list of configuration types, right-click **Java Application** and select **New**
3. In the **Name** box, type 'TradingAdapter'.
4. In the **Project** box, select the TradingAdapter project.
5. In the **Main class** box, select `com.caplin.TradingAdapter`
6. Click the **Arguments** tab
7. In the **Working directory** box, select **Other**, click **File System**, and select the path to your adapter’s `DataSource` directory in your Deployment Framework.

   **Linux, macOS**

   ```
   __deployment_framework_root__/active_blades/TradingAdapter/DataSource
   ```

   **Windows**

   ```
   __deployment_framework_root__\kits\PricingAdapter\TradingAdapter-0.0.0\DataSource
   ```
8. Under the **Environment** tab, click **New**, and create a new environment variable `CONFIG_BASE` and assign it the value below:

   ```
   __deployment_framework_root__/global_config/
   ```

   **❗ IMPORTANT**\
   The value of CONFIG_BASE must end in a trailing forward-slash (`/`).
9. Under the **Common** tab, in **Display in favorites menu**, select **Run**.
10. Click **Run**

To run your adapter on subsequent occasions, click **Run > Run**, or press Ctrl-F11.
</details>

## Project structure

The project example includes the skeleton code for a trading adapter:

* **`com.caplin.TradingAdapter.java`**\
This is the main class for the project. When the adapter runs, it creates a new [DataSource](https://docs.caplin.com/developer/api/datasource_java/latest/com/caplin/datasource/DataSource.html) instance and a new `ExampleTradingApplicationListener` instance.
* **`com.caplin.ExampleTradingApplicationListener.java`**\
This class implements the [TradingApplicationListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradingApplicationListener.html) interface and registers itself with a new instance of [TradingProvider](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradingProvider.html). As a [TradingApplicationListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradingApplicationListener.html), this class is notified by the [TradingProvider](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradingProvider.html) of connection and channel events. When this class is informed that a [TradeChannel](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeChannel.html) object has been created, it registers a new instance of `ExampleTradeChannelListener` as the [TradeChannelListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeChannelListener.html) for the channel.
* **`com.caplin.ExampleTradeChannelListener.java`**\
A separate instance of this class is registered as a [TradeChannelListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeChannelListener.html) with each [TradeChannel](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeChannel.html) object. This class is notified when a [Trade](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/Trade.html) object is created or closed. When this class is informed that a [Trade](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/Trade.html) object has been created, it registers a new instance of `ExampleTradeListener` as the [TradeListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeListener.html) for the [Trade](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/Trade.html).
* **`com.caplin.ExampleTradeListener.java`**\
A separate instance of this class is registered as a [TradeListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeListener.html) with each [Trade](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/Trade.html) object. This class is notified when an event is raised on the [Trade](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/Trade.html) object’s trade model.
* **`blade/DataSource/etc/trademodels.xml`**\
The trade model to be used by this adapter’s [com.caplin.trading.TradingProvider](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradingProvider.html) instance. The name and location of this file are set in the adapter’s configuration file for the Java Trading API:  [trading-provider.properties](https://github.com/caplin/project-templates/blob/training/trading-template/blade/DataSource/etc/trading-provider.properties)

Class diagram:

```plantuml
@startuml
package com.caplin.trading {

  interface TradingApplicationListener {
    +channelClosed()
    +channelCreated()
    +peerUp()
    +peerDown()
  }

  interface TradeChannelListener {
    +tradeClosed()
    +tradeCreated()
  }

  interface TradeListener {
    +receiveEvent()
  }

  class TradingProvider {
    +createTrade()
  }

}

package com.caplin.datasource {

  class DataSource {

  }

}

class TradingAdapter {
  +main()
}

class ExampleTradingApplicationListener {
  +channelClosed()
  +channelCreated()
  +peerUp()
  +peerDown()
}

class ExampleTradeChannelListener {
  +tradeClosed()
  +tradeCreated()
}

class ExampleTradeListener {
  +receiveEvent()
}

ExampleTradeChannelListener ..|> TradeChannelListener
ExampleTradingApplicationListener ..|> TradingApplicationListener
ExampleTradingApplicationListener ..> TradingProvider : instantiates >
DataSource --o TradingProvider
ExampleTradeListener ..|> TradeListener
TradingAdapter o-- ExampleTradingApplicationListener
TradingAdapter o-left- DataSource
ExampleTradingApplicationListener *-- ExampleTradeChannelListener
ExampleTradeChannelListener *-- ExampleTradeListener


@enduml
```

## Handle trade-channel messages

In this section of the tutorial, we will handle communication between your adapter and the client application.

On the Caplin Platform, trading is conducted via the exchange of messages on a trade channel. At a high-level, a channel is a subscription that supports the bi-directional exchange of private messages between a client and an adapter. For details of how channels are implemented at a low level (not required for this tutorial), see [Channels](../../caplin-platform/platform-architecture/channels.md).

The choreography of messages involved in a trade is managed by a trade model. Front end applications and trading adapters are configured with the same trade models. A change in the state of a trade is communicated by sending a message on the trade channel between a client and the adapter.

### Set the trade models recognised by the adapter

Trade models are state machines used to manage trading workflows in the [Java Trading API](https://docs.caplin.com/developer/api/trading_java/latest/), the [C Trading API](https://docs.caplin.com/developer/api/trading_c/latest/), and Caplin Trader’s [Trading API](../../caplin-trader/4/trading-api/index.md).

Trade models are defined in XML. Caplin’s front-end libraries (Caplin Trader) and back-end libraries use the same configuration file format, described here: [Trade Model XML Schema](../../caplin-platform/cis/cis-trade-model-schema.md).

A trading adapter can recognise more than one trade model. The trade model that applies to a trade is set by the `TradingProtocol` field in the first message of a workflow.

In this tutorial we will configure one trade model for the adapter, called "ESP". A state diagram for the model is shown below:

```plantuml
[*] --> Initial<<Terminator>>
Initial -[#ECAF28]-> Executing : Open
Executing --> TradeComplete<<Terminator>> : Confirm
TradeComplete --> [*]

legend left
**__Legend__**
Transitions initiated by the client are in <color:#ECAF28><b>yellow</b></color>.
Transitions initiated by the server are in <color:#003E67><b>blue</b></color>.
end legend
```

To define this trade model, open the file `blade/DataSource/etc/trademodels.xml` and replace the contents with the following:

**File: blade/DataSource/etc/trademodels.xml**

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<tradeModels>
  <tradeModel name="ESP" initialState="Initial">
    <state name="Initial">
      <transition target="Executing" trigger="Open" source="client" />
    </state>
    <state name="Executing">
      <transition target="TradeComplete" trigger="Confirm" source="server" />
    </state>
    <state name="TradeComplete" />
  </tradeModel>
</tradeModels>
```

This trade model is a much simplified version of the Caplin FX Suite’s  [ESP trade model](../../caplin-platform/cis/cis-trade-model-schema.md#example).

### Configure message fields

Field names in messages are encoded as numbers. In this section, we will map each field name to a number.

Add the following field names and codes to the file `blade/blade_config/fields.conf`:

**File: blade/blade_config/fields.conf**

```
add-field Price         -36003
add-field Message       -36004
add-field BaseCurrency  -36005
add-field TermCurrency  -36006
add-field BuySell       -36007
add-field Amount        -36008
```

### Receive trade messages from clients

Trading events are sent by messages on the trade channel between the client and the adapter. A trade begins when a client sends an "Open" event, taking a new trade from the "Initial" state to the "Executing" state and then waiting for the adapter to respond with a "Confirm" message.

The `ExampleTradeListener.receiveEvent` method is called whenever there is an incoming trade message on the /PRIVATE/TRADE/FX channel.

Follow the steps below:

1. Edit the `receiveEvent` method in your `ExampleTradeListener` class. Add the highlighted code below to handle "Open" event messages:

   **File: ExampleTradeListener.java**

   ```java
   @Override
   public void receiveEvent(TradeEvent event) throws TradeException
   {
       logger.log(Level.INFO, "receiveEvent");

       String transition = event.getType();
       if (transition.equals("Open")) {
           // Fields coming from the client
           Map<String, String> fields = event.getFields();
           String user = event.getTrade().getChannel().getUser();
           String requestID = fields.get("RequestID");
           String baseCurrency = fields.get("BaseCurrency");
           String termCurrency = fields.get("TermCurrency");
           String currencyPair = baseCurrency + "/" + termCurrency;
           double amount = Double.parseDouble(fields.get("Amount"));
           double price = Double.parseDouble(fields.get("Price"));
           String buySellString = fields.get("BuySell");
           System.out.println("Open message from user "
               + user + " to " + buySellString + " " + currencyPair);
       }
   }
   ```
2. Download and extract [testpage.zip](https://docs.caplin.com/developer/tutorial-resources/platform/testpage.zip) to Liberator’s `htdocs` folder: `<DeploymentFramework>\kits\Liberator\Liberator-<version>\htdocs`.
3. Run the following command from the root of your Deployment Framework to start all components:

   ```
   $ ./dfw start
   ```
4. In Google Chrome, navigate to the following URL: <span>http://</span>localhost:18080/testpage
5. Press F12 to bring up Chrome’s Developer Tools, then click the **Console** tab to view the log messages produced by the client application.
6. On the test page, click **Login**, then click **Trade**. You will now see that a trade message has been sent to the adapter in your browser’s console window: `Publish to /PRIVATE/TRADE/FX succeeded.`

   You will also notice from the Trading Adapter’s logs that the adapter receives the message: `Open message from user admin to BUY GBP/USD.`

<dl><dt><strong>📌 NOTE</strong></dt><dd>

Each time a trade is submitted from the test client page, your adapter will throw the following error:

```
com.caplin.management.jmx.MBeanServerManagerImpl notifyMBeanAttributeChanged, SEVERE: Error Notifying Bean Change, java.lang.Exception: Bean has not been registered
```

This error is thrown because we have not enabled JMX for the adapter. The error does not indicate that you have followed the tutorial incorrectly.
</dd></dl>

### Send trade messages to clients

[TradeEvent](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeEvent.html) objects passed to `ExampleTradeListener.receiveEvent` include a reference to the original [Trade](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/Trade.html) object with which `ExampleTradeListener` was registered as a [TradeListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeListener.html). You can use this [Trade](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/Trade.html) object to send a trade message back to the client.

The first trade event in the trade model is "Open", which is sent by the client when a trade is first opened. The [TradeEvent](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeEvent.html) object for the "Open" event includes the details of the trade. Later in this tutorial, we will modify `ExampleTradeListener.receiveEvent` to pass those details to a mock backend trading system. However, to keep things simple at this stage, we will pretend the trade has executed successfully and send back a "Confirm" trade event.

Follow the steps below:

1. In the file `ExampleTradeListener.receiveEvent`, add the highlighted code below to send a "Confirm" event message back to the client when you receive an "Open" event message:

   **File: ExampleTradeListener.java**

   ```java
   @Override
   public void receiveEvent(TradeEvent event) throws TradeException
   {
       logger.log(Level.INFO, "receiveEvent");

       String transition = event.getType();
       if (transition.equals("Open")) {
           // Fields coming from the client
           Map<String, String> fields = event.getFields();
           String user = event.getTrade().getChannel().getUser();
           String requestID = fields.get("RequestID");
           String baseCurrency = fields.get("BaseCurrency");
           String termCurrency = fields.get("TermCurrency");
           String currencyPair = baseCurrency + "/" + termCurrency;
           double amount = Double.parseDouble(fields.get("Amount"));
           double price = Double.parseDouble(fields.get("Price"));
           String buySellString = fields.get("BuySell");
           System.out.println("Open message from user "
               + user + " to " + buySellString + " " + currencyPair);

           // Send a "Confirm" event to the client
           TradeEvent tradeEvent = event.getTrade().createEvent("Confirm");
           event.getTrade().sendEvent(tradeEvent);
       }
   }
   ```
2. Restart the adapter.
3. Start a new trade from the test client page. You will notice in the browser console that a new message arrives. If you expand the message and then expand the `_fields` property, you will see that the incoming message contains the field `MsgType` with the value "Confirm". This indicates that the trade was completed successfully. In a real application you would of course render these incoming trade messages to the screen rather than inspect them in the browser console.

   ![tutorial-tradia-client_trade_confirmed](../../images/tutorial-tradia-client_trade_confirmed.JPG)

## Connect to a trade server

In the previous section, your code immediately confirmed a trade without executing it through a backend trading system. In production, you would establish a connection between the adapter and the bank trading system, then pass on any new trades to be processed by the bank system. You would only send a "Confirm" event when the bank system has completed the trade’s execution. In a more realistic scenario, the trade model would also have a failure transition in case the bank system rejected the trade request.

To complete this section, you will need the following two files from the [TrainingTradeProject](https://docs.caplin.com/developer/tutorial-resources/platform/TrainingTradeProject-0.0.0-254764.zip) zip file:

* `SimpleFXServer-<version>.jar`
* `SimpleFXMessenger-<version>.jar`

### Connect to the mock server

In this part of the tutorial you will implement a connection between the adapter and a mock trading server, just as we did in the [Pricing Integration Adapter 2](platbsc-pricing-integration-adapter-2.md) tutorial. We will also ensure that the trading adapter only establishes the connection to Liberator once it has successfully connected to the mock server.

Follow the steps below:

1. In the directory containing the mock server’s jar file (see [Pricing Integration Adapter 2](platbsc-pricing-integration-adapter-2.md) tutorial), type the following command to start the mock server:

   ```
   $ java -jar SimpleFXServer-<version>.jar
   ```

   The following console output indicates that the server is running:

   ```
   <timestamp> [main] INFO  quickfix.SocketAcceptor  - SessionTimer started
   <timestamp> [main] INFO  quickfix.mina.NetworkingOptions  - Socket option: SocketTcpNoDelay=true
   <timestamp> [main] INFO  quickfix.mina.NetworkingOptions  - Socket option: SocketSynchronousWrites=false
   <timestamp> [main] INFO  quickfix.mina.NetworkingOptions  - Socket option: SocketSynchronousWriteTimeout=30000
   <timestamp> [main] INFO  quickfix.SocketAcceptor  - Listening for connections at 0.0.0.0/0.0.0.0:14045
   ```
2. Copy the file `SimpleFXMessenger-<version>.jar` to the `lib` directory in your adapter project.
3. Edit the `build.gradle` file in the root directory of your adapter project, and add `SimpleFXMessenger` as a dependency in the `dependencies { }` stanza:

   **File: build.gradle**

   ```groovy
   implementation (name: 'SimpleFXMessenger', version: '0+') { transitive = false }
   ```
4. Reload the Gradle configuration for your project in your IDE.
5. In the file `ExampleTradingApplicationListener.java`, import the Simple FX Messenger classes:

   **File: ExampleTradingApplicationListener.java**

   ```java
   import messenger.*;
   ```
6. To communicate with the mock server, your `ExampleTradingApplicationListener` class will need to implement the `messenger.FXTradingListener` interface. This interface extends the `messenger.FXConnectionListener` interface and provides the methods `onConnect()`,  `onDisconnect()`, and `onTradeReport(FXTradeReport)`.

   **File: ExampleTradingApplicationListener.java**

   ```java
   public class ExampleTradingApplicationListener
           implements TradingApplicationListener, FXTradingListener
   {
       private final Logger logger;
       private ExampleTradeChannelListener tradeChannelListener;

       // ...

       @Override
       public void onConnect() {
           // ...
       }

       @Override
       public void onDisconnect() {
           // ...
       }

       @Override
       public void onTradeReport(FXTradeReport report) {
           // ...
       }

       // ...
   }
   ```
7. Define a new `FXTradingMessenger` field in your `ExampleTradingApplicationListener` class. Instantiate the field in the `ExampleTradingApplicationListener` constructor and call `FXTradingMessenger.connect()` to connect to the mock server.

   <dl><dt><strong>❗ IMPORTANT</strong></dt><dd>

   The session ID and the port used in the code below are deliberately different values to the ones used in the [Pricing Integration Adapter 2](platbsc-pricing-integration-adapter-2.md) tutorial, so don’t copy and paste the line from that project.
   </dd></dl>

   **File: ExampleTradingApplicationListener.java**

   ```java
   public class ExampleTradingApplicationListener
           implements TradingApplicationListener, FXTradingListener
   {
       // ...

       private final FXTradingMessenger messenger;

       public ExampleTradingApplicationListener (DataSource dataSource)
               throws IllegalArgumentException, IOException
       {
           this.logger = dataSource.getLogger();

           new TradingProvider(this, dataSource);

           this.messenger = new FXTradingMessenger(this,
               FXTradingMessenger.DEFAULT_SESSION_ID_2,
               FXTradingMessenger.DEFAULT_PORT_2);
           this.messenger.connect();
       }

       // ...
   }
   ```

The adapter connects to Liberator as soon as the call to `dataSource.start()` is made in the `main` method. We will update it to only initialise the connection to Liberator once the connection to the mock server is established, just as we did in the [Pricing Integration Adapter 2](platbsc-pricing-integration-adapter-2.md) tutorial.

1. Remove the `dataSource.start()` instruction from the main method of the `TradingAdapter` class.
2. In your `ExampleTradingApplicationListener` class, declare a new field, `datasource`, and in your constructor, assign it a reference to the `DataSource` object. This allows you to access the `DataSource` object from within all the methods in your class.

   Also declare a boolean field, `dataSourceIsStarted`, to keep track of whether the DataSource has been started or not, and initialise it to `false`.

   **File: ExampleTradingApplicationListener.java**

   ```java
   public class ExampleTradingApplicationListener
           implements TradingApplicationListener, FXTradingListener
   {
       // ...

       private final DataSource dataSource;

       private boolean dataSourceIsStarted = false;

       public ExampleTradingApplicationListener (DataSource dataSource)
               throws IllegalArgumentException, IOException
       {
           this.logger = dataSource.getLogger();

           this.dataSource = dataSource;

           new TradingProvider(this, dataSource);

           this.messenger = new FXTradingMessenger(this,
               FXTradingMessenger.DEFAULT_SESSION_ID_2,
               FXTradingMessenger.DEFAULT_PORT_2);
           this.messenger.connect();
       }

       // ...
   }
   ```
3. In the `ExampleTradingApplicationListener.onConnect()` method, start the DataSource if it has not yet been started, otherwise toggle the status to UP.

   **File: ExampleTradingApplicationListener.java**

   ```java
   @Override
   public void onConnect() {
       if (this.dataSourceIsStarted) {
           this.dataSource.setStatusUp();
       } else {
           this.dataSource.start();
           this.dataSourceIsStarted = true;
       }
       System.out.println("Connected to mock server");
   }
   ```
4. In the `ExampleTradingApplicationListener.onDisconnect()`, change the DataSource status to DOWN.

   **File: ExampleTradingApplicationListener.java**

   ```java
   @Override
   public void onDisconnect() {
       this.dataSource.setStatusDown();
   }
   ```
5. At this point you should be able to start your adapter and see it connect to your mock server:

   ```
   Connected to mock server
   ```

To test the effects of your changes, follow the steps below:

1. Stop the CMC if it is already running.
2. Update the CMC’s configuration:

   ```
   $ ./dfw mon
   ```
3. Start the CMC:

   ```
   $ ./dfw cmc
   ```
4. Right-click any available white space in the CMC canvas and click **Add new DataSource**.
5. In the **DataSource Properties** dialog, complete the fields according to the values below. Click **OK** when done.

   | Field | Value |
   | --- | --- |
   | Name | Trading Adapter |
   | Host | localhost |
   | Port | 11009 |
   | Username | admin |
   | Password | admin |

   **📌 NOTE**\
   We add the trading adapter to CMC manually because the Deployment Framework command `mon` cannot automatically detect the trading adapter while you run it in your IDE.
6. Stop the mock server (Ctrl-C).
7. Watch both the Pricing Adapter and Trading Adapter go from blue to red in the CMC.
8. Restart the mock server:

   ```
   $ java -jar SimpleFXServer-<version>.jar
   ```
9. Watch the Pricing Adapter and the Trading Adapter go from red to blue in the CMC.

### Make the FXTradingMessenger available to TradeListeners

Currently our `ExampleTradingApplicationListener` class is the only class that has a reference to the `FXTradingMessenger` object. To give the `ExampleTradeListener.receiveEvent` method access to the `messenger` object to submit trades, we will need to do a little bit of plumbing.

Follow the steps below:

1. In your `ExampleTradingApplicationListener` class, change the implementation of `TradingApplicationListener.channelCreated()` so that it passes the `messenger` object to `ExampleTradeChannelListener` as a new constructor argument.

   **File: ExampleTradingApplicationListener.java**

   ```java
   @Override
   public void channelCreated(TradeChannel tradeChannel) throws TradeException
   {
       logger.log(Level.INFO, "Trade channel created: " + tradeChannel.toString());
       this.tradeChannelListener =
           new ExampleTradeChannelListener(this.messenger, this.logger);
       tradeChannel.setTradeChannelListener(this.tradeChannelListener);
   }
   ```
2. In the `ExampleTradeChannelListener` class, import the Simple FX Messenger classes:

   **File: ExampleTradeChannelListener.java**

   ```java
   import messenger.*;
   ```
3. Update the `ExampleTradeChannelListener` constructor so that it expects an `FXTradingMessenger` instance as an extra argument and sets it as a field.

   **File: ExampleTradeChannelListener.java**

   ```java
   public class ExampleTradeChannelListener implements TradeChannelListener
   {
       private final Logger logger;
       private TradeListener tradeListener;
       private final FXTradingMessenger messenger;

       // ...

       public ExampleTradeChannelListener(FXTradingMessenger messenger, Logger logger)
       {
           this.logger = logger;
           this.messenger = messenger;
       }

       // ...
   }
   ```
4. Still in your `ExampleTradeChannelListener` class, change the `tradeCreated()` method so that it passes the `messenger` object to the `ExampleTradeListener` as a new constructor argument.

   **File: EXampleTradeChannelListener.java**

   ```java
   @Override
   public void tradeCreated(Trade trade) throws TradeException
   {
       this.logger.log(Level.INFO, "Trade created");
       this.tradeListener = new ExampleTradeListener(this.messenger, this.logger);
       trade.setTradeListener(this.tradeListener);
   }
   ```
5. In the file `ExampleTradeListener.java`, import the Simple FX Messenger classes:

   **File: ExampleTradeListener.java**

   ```java
   import messenger.*;
   ```
6. Update the `ExampleTradeListener` constructor so that it expects an `FXTradingMessenger` as a new constructor argument and sets it as a field.

   **File: ExampleTradeListener.java**

   ```java
   public class ExampleTradeListener implements TradeListener
   {
       private final Logger logger;
       private final FXTradingMessenger messenger;

       // ...

       public ExampleTradeListener (FXTradingMessenger messenger, Logger logger)
       {
           this.logger = logger;
           this.messenger = messenger;
       }

       // ...
   }
   ```

Instances of your `ExampleTradeListener` class now have access the `FXTradingMessenger` object and can use it to submit trades.

### Submit a trade to the mock server

Now we are going to change the implementation of the `TradeListener.receiveEvent()` method so that it uses the `FXTradingMessenger` to execute the trade _instead_ of immediately confirming the trade.

In a real system, there are always some field and formatting differences between how the client application submits a trade instruction and how the bank server expects to receive it, so you have to perform some transformations on the incoming data before you can submit it to the bank.

This example is no different: the `FXTradingMessenger.execute` method accepts the `char` constants `FXTradeReport.BUY` and `FXTradeReport.SELL`, but our `BuySell` field is a string ("BUY" or "SELL").

To send trade requests to the trading server, follow the steps below:

1. In the `ExampleTradeListener.receiveEvent` method, **remove** the code that sends a "Confirm" event to the client.
2. At the end of the `ExampleTradeListener.receiveEvent` method, add code to convert the "BuySell" field value and execute the trade.

   **File: ExampleTradeListener.java**

   ```java
   public void receiveEvent(TradeEvent event) throws TradeException
   {
       logger.log(Level.INFO, "receiveEvent");

       String transition = event.getType();
       if (transition.equals("Open")) {
           // Fields coming from the client
           Map<String, String> fields = event.getFields();
           String user = event.getTrade().getChannel().getUser();
           String requestID = fields.get("RequestID");
           String baseCurrency = fields.get("BaseCurrency");
           String termCurrency = fields.get("TermCurrency");
           String currencyPair = baseCurrency + "/" + termCurrency;
           double amount = Double.parseDouble(fields.get("Amount"));
           double price = Double.parseDouble(fields.get("Price"));
           String buySellString = fields.get("BuySell");

           System.out.println("Open message from user "
               + user + " to " + buySellString + " " + currencyPair);

           // Convert buySellString to an FXTradeReport constant
           char buySell;
           if (buySellString.equals("BUY")) {
               buySell = FXTradeReport.BUY;
           } else {
               buySell = FXTradeReport.SELL;
           }

           // Execute the trade
           messenger.executeTrade(user, requestID, currencyPair,
               amount, buySell, price);
       }
   }
   ```
3. Restart your Adapter.
4. Re-open the test page and execute a trade. Notice that as soon as this is done, the log message below appears in the mock server’s console output:

   ```
   <timestamp> INFO  server.GradFIXApplication  - fromApp: [Message Type = Trade Request (OrderSingle)]
   ```

   <dl><dt><strong>💡 TIP</strong></dt><dd>

   To locate this message quickly, right-click the console, click **find**, and search for 'OrderSingle'.
   </dd></dl>

   This is followed by the mock server sending back a trade report to the adapter, so the adapter knows that the trade was successful. However, the client is not yet aware that the trade was successful because we are no longer sending back a "Confirm" event. The next step is to listen for the confirmation from the mock server and send the "Confirm" trade event on to the client.

### Receive a trade confirmation from the mock server

The `FXTradingMessenger.execute` method is asynchronous. The response from the trade server is handled by the interface method `FXTradingListener.onTradeReport(FXTradeReport)`, which is implemented by your `ExampleTradingApplicationListener` class.

The `ExampleTradingApplicationListener` class receives the response from the server, but it’s the trade’s `ExampleTradeListener` instance that needs to be informed of the response. We will add code to implement this, working from `ExampleTradeListener` outwards to `ExampleTradingApplicationListener`.

To send "Confirm" event to the client when the trade server responds, follow the steps below:

1. In `ExampleTradeListener.receiveEvent`, assign the event’s Trade object to a new private instance variable, `trade`:

   **File: ExampleTradeListener.java**

   ```java
   public class ExampleTradeListener implements TradeListener
   {
       private Trade trade;

       // ...

       @Override
       public void receiveEvent(TradeEvent event) throws TradeException
       {
           logger.log(Level.INFO, "receiveEvent");
           this.trade = event.getTrade();

           // ...

       }

       // ...
   }
   ```

   **📌 NOTE**\
   Unlike the other instance fields, Java will not allow you to declare `trade` as `final`, because `final` fields must have their value set inline or in the constructor. We can’t set the value of `trade` until we get the `receiveEvent()` callback.
2. In `ExampleTradeListener`, add a new `onTradeReport` method:

   **File: ExampleTradeListener.java**

   ```java
   public class ExampleTradeListener implements TradeListener
   {
       // ...

       public void onTradeReport(FXTradeReport fxTradeReport)
       {
           try {
               TradeEvent event = trade.createEvent("Confirm");
               event.addField("Message", fxTradeReport.toString());
               this.trade.sendEvent(event);
           } catch (TradeException e) {
               logger.log(Level.SEVERE, e.getMessage());
           }
       }

       // ...
   }
   ```
3. In `ExampleTradeChannelListener`, add a new `onTradeReport` method and change the datatype of the `tradeListener` field from the interface `TradeListener` to the implementation class `ExampleTradeListener`:

   **File: ExampleTradeChannelListener.java**

   ```java
   public class ExampleTradeChannelListener implements TradeChannelListener
   {
       // ...

       private ExampleTradeListener tradeListener; ①

       // ...

       public void onTradeReport(FXTradeReport fxTradeReport)
       {
           this.tradeListener.onTradeReport(fxTradeReport); ②
       }

       // ...
   }
   ```
   1. Data type changed from `TradeListener` to `ExampleTradeListener`.
   2. The method `onTradeReport` is not part of the `TradeListener` interface.
4. Still in `ExampleTradeChannelListener`, update the data type of the `tradeListener` member variable to `ExampleTradeListener`. We need to do this because the `onTradeListener` method
5. In `ExampleTradingApplicationListener`, update the `onTradeReport` method so that it calls `onTradeReport` on the `ExampleTradeChannelListener` instance:

   **File: ExampleTradingApplicationListener.java**

   ```java
   @Override
   public void onTradeReport(FXTradeReport fxTradeReport)
   {
      this.tradeChannelListener.onTradeReport(fxTradeReport);
   }
   ```
6. Restart the adapter and execute a trade from the test page.
7. Open the browser console. You should see an incoming record message on your trade channel. If you expand this message and then expand the `_fields` property, you will see that you have received your confirmation message from the adapter.

   ![tutorial-tradia-client_trade_confirmed_2](../../images/tutorial-tradia-client_trade_confirmed_2.JPG)

+
Note that there are three fields on the message, and they were all set in different ways:

* `MsgType` -- the value of this field is the name of the transition in the trade model that this message represents. It has the value "Confirm" because you created the message in your adapter code by calling `trade.createEvent("Confirm")`.
* `Message` -- this is the field that you explicitly set on the message in your adapter code before sending it. You can set any number of these fields.
* `RequestID` -- this is a unique identifier set automatically by the trading library, to identify the trade that this message relates to. It will have been present on every message that relates to this trade.
  1. In your adapter’s console output, note that your `ExampleTradeChannelListener` received a `tradeClosed()` callback, because the trade has reached a final state in the model. In this tutorial we won’t do anything when we receive this callback, but in a real application you could use it as a trigger to do any clean up or post-trade logging required for your system.

## Extension question

To simplify this tutorial, the `ExampleTradingApplicationListener` class maintains a reference to only one `ExampleTradingChannelListener`. A production adapter, however, would have to handle multiple channels simultaneously.

What changes would you need to make so that the adapter can manage multiple trading channels?

When designing your solution, consider the following points:

* When the `ExampleTradingApplicationListener.onTradeReport` method receives a response from the mock trade server, how will the method determine _which_ trade channel the response relates to?
* What would happen if a user logged in from their mobile and from their desktop and then placed trades simultaneously on both clients?

## Review

This tutorial covered the basic aspects of the Trading Integration Adapter API and showed how to implement a basic adapter.

The first step is to design the trade model that models the sequence of events that pass between the client and the adapter. For more examples of trade models, see the trade models used to manage trading-state between Caplin FX Professional and the Caplin FX Integration API:

* [ESP trade model](../../fx-integration-api/fxapi-trade-model-esp.md)
* [RFS trade model](../../fx-integration-api/fxapi-trade-model-rfs.md)

The second step is to build your trading adapter around the following three classes:

* [TradingProvider](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradingProvider.html) establishes the connection to a backend trading server (we used a mock server in this tutorial). This class is informed by the Java Trading API when a user creates or closes a trade channel.
* [TradeChannelListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeChannelListener.html) is informed by the Java Trading API when a user creates a new trade.
* [TradeListener](https://docs.caplin.com/developer/api/trading_java/latest/com/caplin/trading/TradeListener.html) is informed by the Java Trading API when a trade event is received from the client.
