Skip to content

Lightstreamer/Lightstreamer-example-AMFHelloWorld-adapter-java

Repository files navigation

Lightstreamer - "Hello World" Tutorial - Java SE (AMF) Adapter

This demo, of the "Hello World with Lightstreamer" series, will focus on a new feature that was released with Lightstreamer Server since version 3.6: Action Message Format (AMF) support for Flex applications.

This project shows the Data Adapter and Metadata Adapters for the Hello World" Tutorial to show how to use AMF with the Lightstreamer Flex Client Library (docs).

As an example of a client using this adapter, you may refer to the "Hello World" Tutorial - Flex (AMF) Client.

Details

First, a quick recap of the previous installments:

Basically, Lightstreamer Server can be seen as a "technology hub" for data push, where you can mix different technologies on the client-side and on the server-side to exchange real-time messages.
Schema

We will delve into the "Flex on the client-side, Java on the server-side" scenario and, in this project, full details for the server-side will be provided.

As you may recall from the first installment Lightstreamer- "Hello World" Tutorial - HTTP Client, Lightstreamer data push model is based on items made up of fields. A client can subscribe to many items, each with its own schema (a set of fields). Each field is usually a text string with an arbitrary length (from a few characters to large data structures, perhaps based on XML, JSON, etc.). With this new Lightstreamer feature, you can now put a full AMF object into any field and have it pushed from the server to the client in real binary format (with no re-encodings).

The Flex Client library for Lightstreamer has been used for one of the major dealing platforms in the finance field and has undergone many cycles of improvements to make it completely production resilient. We were asked to add native support for AMF objects to improve the performance when streaming complex data structures. So now you can push both text-based items and object-based items to the same Flex application.

When approaching the Lightstreamer data model, it is important to choose the right trade-off between using fine-grained fields and coarse objects. You could map each individual atomic piece of information to a Lightstreamer field, thus using many fields and items, or you could map all your data to a single field of a single item. This applies to both text-based fields (where you can encode coarse objects via JSON, XML, etc.) and object-based fields (via AMF). Usually, going for fine-grained fields is better, because you let Lightstreamer know more about your data structure, so that it will be able to apply optimization mechanisms, like conflation and delta delivery. On the other hand, if you go for huge opaque objects, Lightstreamer will be used more as a blind pipe. But in both cases, you will still benefit from other features, like bandwidth allocation and dynamic throttling. All intermediate scenarios are possible, too.

In the sections below, it will be used a single field containing an AMF object derived from a JavaBean. To encode a JavaBean as an AMF object, several ready-made libraries exist. Here, we will leverage BlazeDS.

AMF Lightstreamer Tutorial

This project focuses on a simple "Hello World" example to show how to use AMF with our new Flex client library (docs). We will create a JavaBean on the server-side and then use it on the client-side.

For this tutorial, I'm assuming you have already read the "Hello World" Tutorial - Java Adapter and "Hello World" Tutorial - HTML Client basic examples, or that you are already familiar with Lightstreamer concepts.

On the client, the result of this tutorial will be quite similar to the one obtained with the original "Hello World" Tutorial - HTML Client, but in Flex: we'll get a string alternating some different values (Hello AMF World) and a timestamp. On the server-side, data will be encapsulated into a JavaBean containing a String and a Date instance. This bean will be translated into a byte array and then injected into the Lightstreamer kernel as a single field, instead of being spread over different fields as simple strings (as the original adapter does). Here lies the power of AMF, as you will be able to push even complex JavaBeans to your Flex clients with ease.

Dig the Code

This adapter reuses most of the code of the first Hello World. We add a static property and a static utility method to the class we've renamed into "AMFHelloWorld".

private static SerializationContext context = 
  SerializationContext.getSerializationContext();
 
public static byte[] toAMF(Object bean) { 
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  Amf3Output output = new Amf3Output(context);
  output.setOutputStream(baos);
  try {
    output.writeObject(bean);
    output.flush();
    output.close();
  } catch (IOException e1) {
    e1.printStackTrace();
  }
  return baos.toByteArray();
}

The conversion from Java beans to an AMF-compatible byte array is performed by a couple of the BlazeDS libraries. The toAMF method receives an Object instance and converts it into an AMF byte array using the Amf3Output class. You can find a list of the conversions performed to switch from Java to AMF in the [ActionMessageOutput class javadoc](http://livedocs.adobe.com/blazeds/1/javadoc/flex/messaging/io/amf/ActionMessageOutput.html#writeObject(java.lang.Object).

In this case, we're going to use a Java bean. Note that the AMF3Output class javadoc is currently not linked/listed on BlazeDS classes list (they forgot?). You can reach it anyway, at the logical directory.

Once the conversion method is in place, we can add the bean we want to send to the clients. We will prepare a simple bean containing only two properties, a String and a Date:

public class HelloBean implements java.io.Serializable {
 
  private static final long serialVersionUID = 7965747352089964767L;
  private String hello;
  private Date now;
 
  public HelloBean() {
  }
 
  public String getHello() {
    return hello;
  }
 
  public void setHello(String hello) {
    this.hello = hello;
  }
 
  public Date getNow() {
    return now;
  }
 
  public void setNow(Date now) {
    this.now = now;
  }
}

Finally, we replace the run method of the GreetingThread inner class with a different implementation that handles our bean:

public void run() {
  int c = 0;
  Random rand = new Random();
  HelloBean testBean = new HelloBean();
  while(go) {
    Map<String,byte[]> data = new HashMap<String,byte[]>();
 
    testBean.setHello(c % 3 == 0 ? "Hello" : c % 3 == 1 ? "AMF" : "World");
    testBean.setNow(new Date());
 
    data.put("AMF_field", toAMF(testBean));
 
    listener.smartUpdate(itemHandle, data, false);
    c++;
    try {
        Thread.sleep(1000 + rand.nextInt(2000));
    } catch (InterruptedException e) {
    }
  }
}

As you can see, there's nothing extremely complicated here, we just convert the instance of our bean through the toAMF method and inject it in a Map as if it was a simple String. Then, in turn, the Map is injected into the Lightstreamer kernel to make its way to the clients.

Please find the complete Java Adapter source in the "AMFHelloWorld.java" source file of this project.

In the adapters.xml configuration file, we use "AMFHELLOWORLD" as the adapter set name, as expected by the Lightstreamer - "Hello World Tutorial - Flex (AMF) Client", while we use the classic LiteralBasedProvider, already provided by Lightstreamer server, as our Metadata Adapter and our AMFHelloWorld class as our Data Adapter.
The adapters.xml file under the LS_HOME/adapters/AMFHelloWorld folder looks like:

<?xml version="1.0"?>
 
<adapters_conf id="AMFHELLOWORLD">
  <metadata_provider>
    <adapter_class>
      com.lightstreamer.adapters.metadata.LiteralBasedProvider
    </adapter_class>
  </metadata_provider>
  <data_provider>
    <adapter_class>AMFHelloWorld</adapter_class>
  </data_provider>
</adapters_conf>

NOTE: not all configuration options of an Adapter Set are exposed by the file suggested above. You can easily expand your configurations using the generic template, see the Java In-Process Adapter Interface Project for details.

Please refer here for more details about Lightstreamer Adapters.

Notes

You've seen how to push Objects instead of Strings from a Lightstreamer server to a Flex client. You can exploit this technique to push complex data structures, but obviously, in doing so, you'll lose some of the optimizations offered by Lightstreamer protocol. For example, the merging algorithm (of the MERGE mode) is applied to the entire bean, instead of being applied to each single field, so that every time a property within the bean changes, the entire bean is pushed to the client, not only the changed value. As with anything regarding engineering, you'll have to choose the trade-off that optimizes properly for your application.

Install

If you want to install a version of this demo in your local Lightstreamer Server, follow these steps:

  • Download Lightstreamer Server (Lightstreamer Server comes with a free non-expiring demo license for 20 connected users) from Lightstreamer Download page, and install it, as explained in the GETTING_STARTED.TXT file in the installation home directory.
  • Get the deploy.zip file of the latest release, unzip it, and copy the just unzipped AMFHelloWorld folder into the adapters folder of your Lightstreamer Server installation.
  • Launch Lightstreamer Server.
  • Launch a client like the "Hello World" Tutorial - Flex (AMF) Client.

Build

To build your own version of example-amfhelloworld-adapter-java-x.y.z.jar, instead of using the one provided in the deploy.zip file from the Install section above, you have two options: either use Maven (or other build tools) to take care of dependencies and building (recommended) or gather the necessary jars yourself and build it manually.

For the sake of simplicity only the Maven case is detailed here.

Maven

You can easily build and run this application using Maven through the pom.xml file located in the root folder of this project. As an alternative, you can use an alternative build tool (e.g. Gradle, Ivy, etc.) by converting the provided pom.xml file.

Assuming Maven is installed and available in your path you can build the demo by running

 mvn install dependency:copy-dependencies 

See Also

Clients Using This Adapter

Related Projects

Lightstreamer Compatibility Notes

  • Compatible with Lightstreamer Flex Client Library version 2.0 or newer.
  • Compatible with Lightstreamer SDK for Java In-Process Adapters since 7.3.
  • For a version of this example compatible with Lightstreamer SDK for Java Adapters version 6.0, please refer to this tag.
  • For a version of this example compatible with Lightstreamer SDK for Java Adapters version 5.1, please refer to this tag.

- Ensure that Flex Client API is supported by Lightstreamer Server license configuration.

About

AMF "Hello World" tutorial for Lightstreamer Java Adapter API

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages