Advanced CMC Features

Liberator and Transformer expose several MBeans by default such as the Users, Peers and Objects. For Integration Adapters the MBeans exposed are only those common to all Integration Adapters. To expose values and operations specific to your particular adapter you need to add these to the 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.

Adding MBeans to your Adapter

We shall start by adding a very simple MBean to the PricingAdapter application - one which shows the status of the adapter's connection to the mock server and a list of the subscriptions which have been made. We also want to be able to toggle the adapter's conection with the mock server to add a "management" aspect to this MBean.

Steps

  1. Download the MBean interface ServerConnectionMBean and its implementation ServerConnection. Add them to your PricingAdapter.
  2. 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 for get/setSubscriptions() which sets or returns the list of subscriptions as a String. The connect and disconnect methods must actually start and stop the connection to the mock server. Take some time to look at how this is achieved in the implementation.
  3. 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 to be used:
    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();
    }
  4. 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.
  5. 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:

    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:

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. E.g. Liberator's detailed screen has views Overview, Licenses, DataServices etc . The views' functionality is defined by creating a Java Swing JPanel component that implements the View interface.     

Steps

  1. Open 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_ooverview.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 View is defined by creating a Java Swing JPanel component that implements the CMC's View interface.

Steps

  1. Download 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:
    <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:
 

Understand

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 retreive the ServerConnection MBean and its attributes and to invole its operations. The view polls to keep these values up to date.

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 CMC, Liberator and DataSourceJava/CIS versions 6.1 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
  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.