# Monitoring custom MBeans with the CMC

Liberator and Transformer expose several MBeans by default such as Users, Peers and Objects. Integration Adapters, by default, expose only the default MBeans of the Java DataSource API. To expose values and operations specific to your adapter, you need to add new MBeans to your implementation. This is what we will do in this tutorial, and also add a custom view to the CMC to enable you to monitor and manage the adapter via a custom interface.

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

## Adding MBeans to your Adapter

We start by adding a very simple MBean to the PricingAdapter application. The MBean will provide the access to the following data and functionality:

* expose the status of the adapter’s connection to the mock server and a list of the subscriptions that have been made.
* expose an operation that toggles the adapter’s connection with the mock server.

Follow the steps below:

1. Download the MBean interface [ServerConnectionMBean](https://docs.caplin.com/developer/tutorial-resources/platform-adv/ServerConnectionMBean.java) and its implementation [ServerConnection](https://docs.caplin.com/developer/tutorial-resources/platform-adv/ServerConnection.java). Add them to your PricingAdapter.

   ```java
   public interface ServerConnectionMBean {
       boolean getConnected();
       void setConnected( boolean connected );
       void connect();
       void disconnect();

       void setSubscriptions(String subscriptions);
       String getSubscriptions();
   }
   ```

   The `getConnected()` and `setConnected()` methods manipulate a boolean value which reflects the connection status. Similarly, `setSubscriptions()` and `getSubscriptions()` methods set and return the list of subscriptions as a `String`. The `connect` and `disconnect` methods start and stop the connection to the mock server. Take some time to look at how this is achieved in the implementation.
2. It is necessary to register this MBean on the MBean server of the application. Create a new instance of the MBean and pass it to the PricingAdapter:

   ```java
   public static void main( String[] args ) throws Exception {
     DataSource dataSource = DataSourceFactory.createDataSource(args);
     ServerConnection serverConnection = new ServerConnection();
     ObjectName name =
       new ObjectName("PricingAdapter.server.custom:type=ServerConnectionMBean");
     dataSource.getMBeanServer().registerMBean(serverConnection, name);

     new PricingAdapter(dataSource, serverConnection);
     dataSource.start();
   }
   ```
3. Change the `PricingAdapterPricingProvider` to:
   1. call `setMessenger()` on the `ServerConnection` when the `FXPricingMessenger` is created
   2. call `addSubscription()` when a new request is received for an instrument
   3. call `removeSubscription()` when an instrument is discarded
   4. call `setConnected(true/false)` upon `onConnect()` and `onDisconnect()` callbacks from the messenger.
4. When you re-run the PricingAdapter, you will now notice the new MBean in the Explorer tab of your PricingAdapter’s detailed view in the CMC:

   ![tutorial-adv-mbean-explorer](../../images/tutorial-adv-mbean-explorer.jpg)

+
When you make a subscription the value in subscriptions will change.
+
Notice that you can already control the adapter’s connection to the mock server by double-clicking on the "connect" or "disconnect" operations and then clicking the **Execute** button:
+
image::tutorial-adv-mbean-explorer-operation.jpg[width=400,height=340]

## Modifying the CMC View Configuration

The configuration defining how your CMC overview screen appears and the tabs in the components' detail screens is stored in xml configuration files in directory `tools\CMC\conf`.

The configuration files are grouped as consoles and views. A console defines which views are visible for a component. For example, Liberator’s detailed screen has views Overview, Licenses, DataServices, ... The views' functionality is defined by creating a Java Swing `JPanel` component that implements the [com.caplin.view.View](https://docs.caplin.com/developer/api/cmc/latest/com/caplin/view/View.html) interface.

Follow the steps below:

1. Open the file `console_javadatasrc.conf`. Add a new view: `<View Id="server"/>`.
2. Now you need to create a new file which corresponds to this view. Name this `view_server.xml`.
3. The next step will be to develop the view’s implementation. For now simply copy the configuration from another view (such as `view_datasource_overview.xml`) and change the Name and Long Description to "Server Connection". You should now see a new tab called "Server Connection" in the PricingAdapter’s detailed view.

## Creating a View Implementation

The functionality of the [com.caplin.view.View](https://docs.caplin.com/developer/api/cmc/latest/com/caplin/view/View.html) is defined by creating a Java Swing `JPanel` component that implements the CMC’s [com.caplin.view.View](https://docs.caplin.com/developer/api/cmc/latest/com/caplin/view/View.html) interface.

Follow the steps below:

1. Download [extension.jar](https://docs.caplin.com/developer/tutorial-resources/platform-adv/extension.jar) which to the `tools\CMC` directory. This file contains the custom view’s implementation. (All custom views must be packaged in a file called `extension.jar`)
2. You can now replace the view in `view-server.xml`:

   ```xml
   <Class>com.mycompany.ServerConnectionView</Class>
   ```
3. When you relaunch the CMC the Server Connection tab will use this custom view allowing you to see and change the connection status and monitor the subscriptions made to the mock server:

   ![tutorial-adv-custom-cmc-view](../../images/tutorial-adv-custom-cmc-view.jpg)

The Server Connection’s custom view (below) creates two labels and a button. The `init()` method is called by the CMC console. At this point the view can use the console’s JMX connection to retrieve the `ServerConnection` MBean and its attributes and to invoke its operations. The view polls to keep these values up to date.

```java
import com.caplin.console.Console;
import com.caplin.view.View;

public class ServerConnectionView extends JPanel implements View {

  private Console console;
  private MBeanServerConnection jmxConnection;
  private ObjectName mbean;
  private JLabel connectedLabel;
  private JButton connectButton;
  private JLabel subscriptionsLabel;
  ActionListener viewReloader;

  public ServerConnectionView() {
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

    subscriptionsLabel = new JLabel("Subscriptions: ...waiting");
    add(subscriptionsLabel);

    connectButton = new JButton("...waiting");
    connectButton.setEnabled(false);
    add(connectButton);

    connectedLabel = new JLabel("Connection Status: ...waiting");
    add(connectedLabel);

    viewReloader = new ViewUpdater();
  }

  ...

  @Override
  public void init(Console console, Properties properties) {
    this.console = console;

    this.jmxConnection = console.getJMXConnection();
    try {
        this.mbean =
          new ObjectName("PricingAdapter.server.custom:type=ServerConnectionMBean");
        new Timer(2000, viewReloader).start();
    } catch (MalformedObjectNameException e) {
        e.printStackTrace();
    }
  }

  ...

  class ViewUpdater implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent evt) {
      Object connectedAttribute;
      Object subscriptionsAttribute;

      try {
        subscriptionsAttribute =
          jmxConnection.getAttribute(mbean, "Subscriptions");
        subscriptionsLabel.setText("Subscriptions: "
          + subscriptionsAttribute.toString());

        connectedAttribute = jmxConnection.getAttribute(mbean, "Connected");
        boolean connected = (boolean)connectedAttribute;

        connectButton.setEnabled(true);
        if (connected) {
          connectButton.setText("disconnect");
          connectedLabel.setText("Connection Status: connected");
        } else {
            connectButton.setText("connect");
            connectedLabel.setText("Connection Status: disconnected");
        }
        connectButton.addActionListener(new ActionListener()
        {
          public void actionPerformed( ActionEvent a )
          {
            connectButton.setEnabled(false);
            try {
              Object rtn =
                jmxConnection.invoke(mbean, a.getActionCommand(), null, null);
            } catch (InstanceNotFoundException | MBeanException
                | ReflectionException | IOException e) {
              e.printStackTrace();
            }
          }
        });
      } catch (Exception e) {
          e.printStackTrace();
      }
    }

  }
}
```

## Configuring Read-Only Users

So far you have been using the credentials admin/admin to monitor the Caplin Platform via the CMC. You can add further configuration to allow more users to be able to monitor and manage via the CMC or another JMX client. If you are using Caplin Platform 6.1 components or later, you can also provide different monitoring and management permissions for different users.

### Try this yourself

1. Read the guide to [Configuring DataSource Monitoring](../../caplin-platform/datasource/datasource-configure-datasource-monitoring.md).
2. Create two new monitoring users: user1/pass1 and user2/pass2.
3. Configure permissions so that user1 is able to use the CMC to connect and disconnect the PricingAdapter from the mock server, but user2 can only connect them.
