Skip navigation

Terracotta POJO Clustering Tutorial

Article Rating?


Table of Contents


Purpose

This tutorial shows how to create a plain and simple Swing application with Eclipse and then cluster it declaratively using Terracotta DSO Eclipse Plugin.

What You'll Need

  1. The Eclipse IDE
  2. Terracotta DSO Eclipse Plug-in Update Center

What You'll See

At the end of the tutorial, you will have multiple Sliders in different VMs that are all synchronously updated as any of them are modified. The code is simple Java with the cross-VM clustering capabilities added at runtime by Terracotta.

Getting Started

  1. Download, install, and start Eclipse
  2. Install the Terracotta DSO Eclipse Plugin by following the instructions at http://www.terracotta.org/eclipse.

Create a Java Project

  1. First create a standard Java project using the File → New → Project... menu
  2. Choose the Terracotta DSO Project project type.
  3. Name the project "DSO Tutorial" and accept the default location for the project within your workspace.

Create the Slider Class

  1. Create a new class using the File → New → Class menu.
  2. Specify the package name as "tutorial" and the class name as "Slider".
  3. Copy the following code and paste it into the Slider editor:
    Slider.java
    package tutorial;
    
    import javax.swing.DefaultBoundedRangeModel;
    import javax.swing.JFrame;
    import javax.swing.JSlider;
    
    public class Slider {
      private DefaultBoundedRangeModel rangeModel;
    
      public static void main(String[] args) {
        new Slider();
      }
    
      public Slider() {
        JFrame frame = new JFrame("Slider Test");
    
        rangeModel = new DefaultBoundedRangeModel();
        frame.getContentPane().add(new JSlider(rangeModel));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
      }
    }

    When you're done, Eclipse should look something like this:

The Slider Module

The Slider constructor creates a window (JFrame), sets the window so that closing it terminates the process, adds a slider to the window, packs the window to its preferred size, and makes the window visible. The static main() method is required to run the class as an application.

You might notice that we explicitly declared a DefaultBoundedRangeModel instance variable.

Normally you would not need to create a model for a slider but for the purposes of this tutorial we have since it is that model that we plan on sharing with DSO.

Running the Slider Application

  1. Invoke the context menu on the Slider by right-clicking it in the Package Explorer and choose Run As→Java Application.

    Note: If you don't have the Project → Build Automatically option enabled, compile the Slider class using the Project → Build Project menu.
  2. The window containing the slider should appear in the upper left corner of your display.
  3. Run another instance of the Slider application. Notice that if you move one Slider, the other Slider is unchanged. In the next section we will use Terracotta to cluster multiple Slider applications so that dragging one of the Sliders causes all of them to display the same value.

Clustering the Slider With Terracotta

The next step is to take the same code we've written and run it clustered with Terracotta. When this is done, all instances of the Slider application work together so dragging the slider on one instance will cause the other instances to slide in tandem.

The basic steps are:

  1. Configuring Terracotta
  2. Running the Terracotta Server
  3. Running the clustered slider applications

Configuring Terracotta

We will need to take several configuration steps:

  1. Declare the Slider instance variable rangeModel be a Shared Root
  2. Declare Named Locks on the mutator methods of DefaultBoundedRangeModel
  3. Declare any Distributed Methods defined by DefaultBoundedRangeModel
  4. Declare any Transient Fields belonging to DefaultBoundedRangeModel

In the following section each of these steps will be described in detail. Finally, we will run our newly configured DSO application.

There are multiple ways to accomplish the configuration steps listed above. The most direct way is to utilize the DSO Config view, which is part of the Terracotta Perspective. If the DSO Config view is not currently showing, use Window → Show View → Other..., browse to the Terracotta section, and select DSO Config.

It will also be convenient to use the Outline view, so be sure that it is showing at this time.

Declaring the Shared Root

To declare our shared slider model, select the rangeModel member in the Package Explorer or Outline view and drag&drop it on the Roots node of the DSO Config view:

As a side-effect of declaring rangeModel as a shared root, the rangeModel type, javax.swing.DefaultBoundedRangeModel, is declared as being a bootjar class as well as being listed as an instrumented class.

Note: DefaultBoundedRangeModel is a system type, but, since it is not pre-instrumented by Terracotta, it is also declared as an additional bootjar class. When you run the Slider application in Eclipse, the DSO plugin will ensure that a custom bootjar is created based on the configuration file we are in the process of creating. If you are not using the Eclipse plugin to run your application, you can manually create a custom bootjar from your configuration at any time by using the _Build BootJar... menu.

Because the Slider type defines a shared root, it will automatically be instrumented and therefor does not need to be explicitly listed as an instrumented class in the configuration file.

Select the javax.swing.DefaultBoundedRangeModel under the Additional Boot Classes node to display its structure in the Outline view.

Declare Locks for the Root Mutators

Since DefaultBoundedRangeModel was not written for multi-threaded operation, we will declare Named Locks on any methods that change the model state. Drag&drop the setRangeProperties method from the Outline view to the Named Locks node of the DSO Config view.

By default, the lock name will be the same as the method name and the lock-level will be WRITE. You can edit the lock attributes by using the context menu on the lock entry in the DSO Config view.

Alternative 1: You can also add named locks in the Instrumented Classes section of the DSO Config tab of the Configuration Editor. Use the Terracotta → Show Config Editor... menu to display the Configuration Editor.

Alternative 2: You can select the name of the setRangeProperties method in the Java Editor and use the Terracotta context menu to create a new NamedLock.

Declaring Distributed Methods

Drag&drop the DefaultBoundedRangeModel's fireStateChanged method onto the Distributed Methods node of the DSO Config view.

Note: Most non-Swing applications will not need Distributed Methods. Because Swing models implement a listener interface to inform other objects of changes to the model state, we must call the fireStateChanged() method on all instances of this application to inform the model listeners that the state has changed. This prompts the UI to repaint itself cluster-wide when the distributed model is updated.

Declaring Transient Fields

The list of listeners that the range model notifies upon change contains references to Swing objects that are display-specific. We don't want Terracotta to share these objects across the cluster, so we must declare this list as transient. It is held in an instance variable named listenerList:

javax.swing.DefaultBoundedRangeModel
...
  /** The listeners waiting for model changes. */
  protected EventListenerList listenerList = new EventListenerList();
  ...

To declare the listenerList as transient, drop the listenerList member onto the Transient Fields node of the DSO Config view.

Recreating Transient State

Note: There are three ways to re-initialize transient fields:

  1. Lazy initialization
  2. Specifying a method to be called at load-time
  3. Providing BeanShell script to be executed at load-time

Because we declared the listenerList as transient, we must also provide a way to initialize that object when it is shared in other instances of the application.

  1. In the DSO Config view, use the context menu on the javax.swing.DefaultBoundedRangeModel entry to select the Honor transient toggle:
  2. Select the Execute some code On Load option
  3. Copy the following text into the Code to execute field and click OK.
    self.listenerList = new EventListenerList();

Validating the Configuration

Now we're done configuring the application. Let's go through the configuration in the DSO Configuration Editor to make sure we haven't missed anything. Show the Configuration Editor by using the Terracotta → Show Config Editor menu.

  1. Go to the Roots page to validate that our shared root tutorial.Slider.rangeModel is listed.
  2. Go to the Locks page to be sure there is a Named write-lock on javax.swing.DefaultBoundedRangeModel.setRangeProperties().
  3. Go to the Transient Fields page to be sure javax.swing.DefaultBoundedRangeModel.listenerList is listed.
  4. Go to the Instrumented Classes page to be sure both tutorial.
    Slider and javax.swing.DefaultBoundedRangeModel are listed, and that DefaultBoundedRangeModel has Honor transients enabled and the proper BeanShell script to be executed On load.
  5. Go to the Distributed Methods page to be sure javax.swing.DefaultBoundedRangeModel.fireStateChanged() is listed.
  6. Go to the Boot Classes page to be sure javax.swing.DefaultBoundedRangeModel is listed.
  7. And finally, make sure you save the config.

Start the Server

  1. Start the Terracotta server by invoking the Terracotta → Start Terracotta Server → localhost menu.

Running the Slider Application Clustered

Now that our configuration is complete and the Terracotta server is running, we can run multiple instances of the Slider application clustered together.

  1. Run an instance of the Slider application---this time, run it as a Terracotta DSO Application using the Run As → Terracotta DSO Application context menu. (Make sure you have already started the Terracotta server as mentioned in the last section.)
  2. Now repeat this procedure to run a second instance of the Slider DSO application.
    Note: The window of the second Slider will appear directly atop the first window. Move the second window so that both windows can be viewed at once.
  3. Now drag one of the sliders and see how the second slider updates automatically to the same value.

Conclusions

In this tutorial, we created a simple Swing application. We then clustered that application by transparently sharing a simple data model among multiple instances of that same application. Hopefully this introduction to Terracotta DSO has made clear the potential power provided by a non-API, declarative approach to transparent data sharing.

Adaptavist Theme Builder Powered by Atlassian Confluence