Franck | Granite Data Services

Cocomonio


Archive for Franck:

Granite Data Services 3.0.0.M1 and Apache Flex 4.8.0

By Franck November 28th, 2012 Flex, GraniteDS No Comments
Please, feature an image for this post.

The last 3.0.0.M1 release of GraniteDS (see announcement here) is compatible with the last 4.8.0 release of . The two GraniteDS SWCs compiled with Apache Flex 4.8.0 can be found here:

We didn’t have time to include those SWCs in our binary release, but we will include them in the next upcoming release (or milestone). Keep in mind that GraniteDS 3.0.0.M1 is still in a beta stage and that you can experience unexpected gitchs (report them in our ).

Build them yourself

If you want to build yourself GraniteDS SWCs against the Apache Flex release, proceed as follows:

1. Download Apache Flex(R) 4.8.0 and unzip/untar it somewhere (say “flex48″). 2. Spawn a command shell and type (Apache Ant must be installed):

cd flex48/framework
ant thirdparty-downloads

Answer yes to all questions.

3. Download GraniteDS 3.0.0.M1 sources and unzip it somewhere (say “gds30″). 4. Edit env.properties and env45.properties, and fix the FLEX_HOME variable (absolute path to flex48). 5. Then run:

cd gds30
ant -f build.xml
ant -f build-flex45.xml

The first build will fail after building granite-essentials.swc, when trying to compile granite.swc: just ignore that error and proceed with build-flex45.xml.

The two GraniteDS SWCs buit against Apache Flex 4.8.0 should be in the build directory (granite-essentials.swc and granite-flex45.swc): just rename them to granite-essentials-flex48.swc and granite-flex48.swc, you’re done.

Real-Time Messaging Tutorial with JavaFX 2.2

By Franck November 26th, 2012 GraniteDS, JavaFX 2 Comments

One of the key features of GraniteDS is its real-time messaging stack, relying on and long-polling. While GraniteDS 3.0.0.M1 introduces an experimental WebSocket support for JavaFX and Flex, this tutorial will focus on a sample JavaFX chat application based on a more conservative setup of Servlet 3.0 asynchronous processing.

For the sake of simplicity, this sample doesn’t require any server side setup: it connects to a Tomcat 7 server, located at the URL, where you will find an existing Flex 4 Chat application.

The architecture of this sample is straightforward: both JavaFX and Flex client applications connect to a GraniteDS asynchronous servlet, which simply dispatch user inputs to all connected users. Both applications rely on the binary AMF3 protocol for exchanging structured data, even if this basic sample only sends and receives Strings.

This tutorial will guide you through the key steps to setup, build and run a Chat JavaFX client application connected to a GraniteDS backend.

1. Requirements

  • (Java client librairies and dependencies)
  • (tested with Juno SR1 64bits, but it should work with prior versions)

2. Setting up the Chat / JavaFX Project

Start Eclipse and create a new Java project named “chat-javafx�? (accept all default settings).

Create a new folder in the project and name it “libs�?. From the granite 3.0.0.M1 distribution, add the following jars, located in the libraries/java-client directory:

  • granite-client.jar
  • granite-java-client.jar
  • commons-codec-1.6.jar
  • commons-logging-1.1.1.jar
  • httpasyncclient-4.0-beta3.jar
  • httpclient-4.2.1.jar
  • httpcore-4.2.2.jar
  • httpcore-nio-4.2.2.jar

Even if we are creating a GraniteDS / JavaFX project here, we don’t need to include granite-javafx-client.jar, which is only required for advanced data management. The last six librairies come from the project and are required for HTTP asynchronous calls to the GraniteDS backend.

Now, add those libraries to the build path of your project: select all height libraries, right click on them, then select “Build Path�? -> “Add to Build Path�?.

Finally, you need to complete the build path of your project by adding the jfxrt.jar library, which is not part of the JavaSE-1.7 installed JRE under Eclipse: right click on “Referenced Libraries�? in the project and select “Build Path�? -> “Configure Build Path…�?. Click on the “Add External JARs…�? button and locate the jfxrt.jar in your JavaSE-1.7 installation (under jre/lib). Select it and click on “Ok�?.

Your project is now fully configured for that basic GraniteDS / JavaFX Chat project and should look as follow:

Make sure the selected JRE System Library is JavaSE-1.7 and that jfxrt.jar is in your References Libraries (its location can of course differ from the one on the picture, depending on your platform).

3. Writing the Chat class

Create a new HelloWorld class in the “src�? source directory with its package set to “org.granite.client.examples.helloworld�?. Then, copy-paste the following code:

package org.granite.examples.javafx.chat;

import java.net.URI;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import org.granite.client.messaging.Consumer;
import org.granite.client.messaging.Producer;
import org.granite.client.messaging.TopicMessageListener;
import org.granite.client.messaging.channel.MessagingChannel;
import org.granite.client.messaging.channel.amf.AMFMessagingChannel;
import org.granite.client.messaging.events.TopicMessageEvent;
import org.granite.client.messaging.transport.HTTPTransport;
import org.granite.client.messaging.transport.apache.ApacheAsyncTransport;

public class Chat extends Application {

    private HTTPTransport transport;
    private MessagingChannel channel;
    private Consumer consumer;
    private Producer producer;

    private TextField input;
    private TextArea output;

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void init() throws Exception {
        super.init();

        transport = new ApacheAsyncTransport();
        transport.start();

        URI uri = new URI("http://demo.graniteds.org/chat/gravity/amf");
        channel = new AMFMessagingChannel(transport, "graniteamf", uri);

        consumer = new Consumer(channel, "gravity", "discussion");
        producer = new Producer(channel, "gravity", "discussion");
    }

    @Override
    public void start(Stage stage) {

        final String username = System.getProperty("user.name");

        stage.setTitle("Chat GraniteDS/JavaFX");
        stage.setResizable(false);

        Group root = new Group();
        stage.setScene(new Scene(root));

        VBox box = new VBox();
        box.setPadding(new Insets(8.0));
        box.setSpacing(8.0);
        root.getChildren().add(box);

        output = new TextArea();
        box.getChildren().add(output);
        output.setEditable(false);
        output.setStyle("-fx-border-style: none");
        output.setFocusTraversable(false);

        input = new TextField();
        box.getChildren().add(input);
        input.setOnKeyTyped(new EventHandler<KeyEvent>() {

            private int index = 1;

            @Override
            public void handle(KeyEvent event) {
                if ("\r".equals(event.getCharacter()) || "\n".equals(event.getCharacter())) {
                    producer.publish("[" + username + " #" + (index++) + "] " + input.getText().trim());
                    input.setText("");
                }
            }
        });

        stage.show();
        input.requestFocus();

        consumer.addMessageListener(new TopicMessageListener() {

            @Override
            public void onMessage(TopicMessageEvent event) {
                output.appendText((String)event.getData() + "\n");
            }
        });
        try {
            consumer.subscribe().get();
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            throw new RuntimeException(e);
        }

        producer.publish("[" + username + " has just connected]");
    }

    @Override
    public void stop() throws Exception {
        if (consumer != null && consumer.isSubscribed())
            consumer.unsubscribe().get();

        transport.stop();

        super.stop();
    }
}

The Chat project is now ready and should compile without any issues.

3. Running the Application

Right click on the “Chat.java�? class in your Eclipse Package Explorer and select “Run As�? -> “Java Application�?. The application should show up, saying that you are connected as “JavaFX�? and letting you entering some input, followed by the <enter> or <return> key:

Chatting with yourself isn’t very exiting so you had better to find a friend running the application at the same time. Note that the server being public you could end up chatting with other testers from different locations.

4. Understanding the Highlighted Code

After having (a lot) of fun with the application, it’s time to understand what is going on under the hood.

Let’s look at the first part of the highlighted code (lines 45-52):

transport = new ApacheAsyncTransport();
transport.start();

URI uri = new URI("http://demo.graniteds.org/chat/gravity/amf");
channel = new AMFMessagingChannel(transport, "graniteamf", uri);

consumer = new Consumer(channel, "gravity", "discussion");
producer = new Producer(channel, "gravity", "discussion");

This part of code is executed at initialization time and proceed as follow:

  1. A new ApacheAsyncTransport instance is created and stored into a class variable of the HttpTransport type (which is an interface). This transport is then started and ready to send asynchronous HTTP requests.
  2. A new AMFMessagingChannel instance is created and bound to the transport, a channel id (“graniteamf�?) and the URI of a GraniteDS servlet handling AMF3 asynchronous requests. You’ll need to have a closer look at the server-side to fully understand the meaning of these settings (see below).
  3. Then, a Consumer instance is created, bound to the channel, a destination id (“gravity�?) which identifies the real-time messaging service on the server-side and a topic (“discussion�?).
  4. Finally, a Producer is created, bound to the same channel, destination id and topic.

What we get at the end of this initialization is basically an object (producer) from which we can publish messages in the “discussion�? topic and another object (consumer) which will receive all messages published on that same topic.

The second part of the highlighted code is responsible of publishing the user input:

producer.publish("[" + username + " #" + (index++) + "] " + input.getText().trim());

For a given username (say “johndoe�?) and input (say “Bla bla�?), the producer will publish the message “[johndoe #1] Bla bla�?, the index (“#1″) being an incremental counter of the successive messages sent.

The third part of the highlighted code is setting up the consumer handler, subscription to the topic and publishing an initial message:

consumer.addMessageListener(new TopicMessageListener() {

    @Override
    public void onMessage(TopicMessageEvent event) {
        output.appendText((String)event.getData() + "\n");
    }
});
try {
    consumer.subscribe().get();
} catch (InterruptedException | ExecutionException | TimeoutException e) {
    throw new RuntimeException(e);
}

producer.publish("[" + username + " has just connected]");

A TopicMessageListener is attached to the consumer and displays received messages in the text area at the top of the application. Then, the consumer subscribes to the “discussion�? topic, waiting for the subscription completion (consumer.subscribe().get()): the subscribe method is asynchronous and returns a Future which can be used to wait for an acknowledgment message from the server.

Finally, a first message is published by the producer, announcing a new connection to the chat topic (eg. “[johndoe has just connected]“).

The final part of the highlighted code unsubscribes the consumer and stops the transport when the application is closed:

if (consumer != null && consumer.isSubscribed())
    consumer.unsubscribe().get();

transport.stop();

Again, the unsubscribe call is asynchronous and the get() call is blocking until the consumer receives an acknowledgment from the server.

All resources allocated by the transport are then released, in particular the underlying thread pool managing asynchronous requests: failing to call the transport stop method can lead to improper thread closing, leaving the application in a kind of daemon state.

4. A Look at the Server Code

In the “samples�? directory of the GraniteDS 3.0.0.M1 distribution, you will find a file named “sample_projects.zip�?. You can unzip it at location of your choice or import it as an existing projets archive under Eclipse.

Let’s look at the file that explains the above configuration of the Consumer and Producer (chat/war/WEB-INF/flex/services-config.xml):

<services-config>

    <services>
        <service id="messaging-service"
            class="flex.messaging.services.MessagingService"
            messageTypes="flex.messaging.messages.AsyncMessage">
            <adapters>
                <adapter-definition id="default" class="org.granite.gravity.adapters.SimpleServiceAdapter" default="true"/>
            </adapters>

            <destination id="gravity">
                <channels>
                    <channel ref="gravityamf"/>
                </channels>
            </destination>
        </service>
    </services>

    <channels>
        <channel-definition id="gravityamf" class="org.granite.gravity.channels.GravityChannel">
            <endpoint
                uri="http://{server.name}:{server.port}/{context.root}/gravity/amf"
                class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>

</services-config>

Let’s start with the channel definition: an asynchronous real-time channel identified by “gravityamf�? is bound to an uri which resolves to “http://demo.graniteds.org/chat/gravity/amf�?. If you look at the web.xml file, this is where the GraniteDS (Gravity) servlet is handling incoming AMF messages. The configuration of the AMFMessagingChannel in the JavaFX Chat class reflects these settings.

Then, jump to the beginning of the file and look at the service definition: a destination “gravity�? is declared, bound to the “gravityamf�? channel. This explains the configuration of our Consumer and Producer as well.

The last thing to understand is that we don’t need to declare any predefined topic on the server-side: Gravity, the real-time messaging engine of GraniteDS, has a built-in support for basic topic creation and handling. That’s why we can define the “discussion�? topic in the client code, without any further configuration on the server. You can change it to whatever you want (say “my-private-discussion�?) and initiate a private chat on this new topic.

Hello World Tutorial with JavaFX 2.2

By Franck November 26th, 2012 GraniteDS, JavaFX No Comments

Here is an over-classical and basic Hello World sample application that introduces the new support for Java and JavaFX in GraniteDS 3.0.0.M1. For the sake of simplicity, this sample doesn’t require any server side setup: it connects to a Tomcat 7 server, located at the URL, where you will find an existing Flex 4 sample, working with a very basic POJO service.

The architecture of this sample is straightforward: both JavaFx and Flex client applications connect to a GraniteDS POJO service, which simply echoes back your input, surrounded by “Hello �? and “!�?. Both applications rely on the binary AMF3 protocol for exchanging structured data, even if this basic sample only sends and receives Strings.

This tutorial will guide you through the key steps to setup, build and run a HelloWorld JavaFX client application connected to a GraniteDS backend.

1. Requirements

  • (Java client librairies and dependencies)
  • (tested with Juno SR1 64bits, but it should work with prior versions)

2. Setting up the HelloWorld / JavaFX Project

Start Eclipse and create a new Java project named “helloworld-javafx�? (accept all default settings).

Create a new folder in the project and name it “libs�?. From the granite 3.0.0.M1 distribution, add the following jars, located in the libraries/java-client directory:

  • granite-client.jar
  • granite-java-client.jar
  • commons-codec-1.6.jar
  • commons-logging-1.1.1.jar
  • httpasyncclient-4.0-beta3.jar
  • httpclient-4.2.1.jar
  • httpcore-4.2.2.jar
  • httpcore-nio-4.2.2.jar

Even if we are creating a GraniteDS / JavaFX project here, we don’t need to include granite-javafx-client.jar, which is only required for advanced data management. The last six librairies come from the project and are required for HTTP asynchronous calls to the GraniteDS backend.

Now, add those libraries to the build path of your project: select all height libraries, right click on them, then select “Build Path�? -> “Add to Build Path�?.

Finally, you need to complete the build path of your project by adding the jfxrt.jar library, which is not part of the JavaSE-1.7 installed JRE under Eclipse: right click on “Referenced Libraries�? in the project and select “Build Path�? -> “Configure Build Path…�?. Click on the “Add External JARs…�? button and locate the jfxrt.jar in your JavaSE-1.7 installation (under jre/lib). Select it and click on “Ok�?.

Your project is now fully configured for that basic GraniteDS / JavaFX Hello World project and should look as follow:

Make sure the selected JRE System Library is JavaSE-1.7 and that jfxrt.jar is in your References Libraries (its location can of course differ from the one on the picture, depending on your platform).

3. Writing the HelloWorld class

Create a new HelloWorld class in the “src�? source directory with its package set to “org.granite.client.examples.helloworld�?. Then, copy-paste the following code:

package org.granite.client.examples.helloworld;

import java.net.URI;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import org.granite.client.messaging.RemoteService;
import org.granite.client.messaging.ResponseListener;
import org.granite.client.messaging.ResultIssuesResponseListener;
import org.granite.client.messaging.channel.RemotingChannel;
import org.granite.client.messaging.channel.amf.AMFRemotingChannel;
import org.granite.client.messaging.events.IssueEvent;
import org.granite.client.messaging.events.ResultEvent;
import org.granite.client.messaging.transport.HTTPTransport;
import org.granite.client.messaging.transport.apache.ApacheAsyncTransport;

public class HelloWorld extends Application {

    private HTTPTransport transport;
    private RemoteService remoteService;

    private TextField input;
    private TextArea output;

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void init() throws Exception {
        super.init();

        transport = new ApacheAsyncTransport();
        transport.start();

        URI uri = new URI("http://demo.graniteds.org/helloworld/graniteamf/amf");
        RemotingChannel channel = new AMFRemotingChannel(transport, "graniteamf", uri);

        remoteService = new RemoteService(channel, "helloWorldService");
    }

    @Override
    public void start(Stage stage) {

        stage.setTitle("HelloWorld GraniteDS/JavaFX");
        stage.setResizable(false);

        Group root = new Group();
        stage.setScene(new Scene(root));

        VBox box = new VBox();
        root.getChildren().add(box);
        box.setPadding(new Insets(8.0));
        box.setSpacing(8.0);

        output = new TextArea();
        box.getChildren().add(output);
        output.setEditable(false);

        box.getChildren().add(new Label("Enter your name and type :"));

        input = new TextField();
        box.getChildren().add(input);
        input.setOnKeyTyped(new EventHandler() {

            private ResponseListener listener = new ResultIssuesResponseListener() {

                @Override
                public void onResult(ResultEvent event) {
                    output.appendText((String)event.getResult() + "\n");
                }

                @Override
                public void onIssue(IssueEvent event) {
                    output.appendText(event.toString() + "\n");
                }
            };

            @Override
            public void handle(KeyEvent event) {
                if (!event.getCharacter().isEmpty()) {
                    char c = event.getCharacter().charAt(0);
                    if (c == '\n' || c == '\r') {
                        remoteService.newInvocation("sayHello", input.getText()).addListener(listener).invoke();
                        input.setText("");
                    }
                }
            }
        });

        stage.show();

        input.requestFocus();
    }

    @Override
    public void stop() throws Exception {
        transport.stop();

        super.stop();
    }
}

The HelloWorld project is now ready and should compile without any issues.

3. Running the Application

Right click on the “HelloWorld.java�? class in your Eclipse Package Explorer and select “Run As�? -> “Java Application�?. The application should show up, letting you entering your name and saying in return, as expected, Hello:

As explained in the label above the text field, just enter some text and press the enter (or return) key on your keyboard.

4. Understanding the Highlighted Code

After having (a lot) of fun with the application, it’s time to understand what is going on under the hood.

Let’s look at the first part of the highlighted code (lines 43-49):

transport = new ApacheAsyncTransport();
transport.start();

URI uri = new URI("http://demo.graniteds.org/helloworld/graniteamf/amf");
RemotingChannel channel = new AMFRemotingChannel(transport, "graniteamf", uri);

remoteService = new RemoteService(channel, "helloWorldService");

This part of code is executed at initialization time and proceed as follow:

  1. A new ApacheAsyncTransport instance is created and stored into a class variable of the HttpTransport type (which is an interface). This transport is then started and ready to send asynchronous HTTP requests.
  2. A new AMFRemotingChannel instance is created and bound to the transport, a channel id (“graniteamf�?) and the URI of a GraniteDS servlet handling AMF3 requests. You’ll need to have a closer look at the server-side to fully understand the meaning of these settings (see below).
  3. Finally, a RemoteService instance is created, bound to the channel and a destination id (“helloWorldService�?) which identifies the Java POJO service on the server-side. Again, a closer look at the server code is required, see below.

What we get at the end of this initialization is basically an object (remoteService) from which we can call methods of a remote Java service (the helloWorldService).

The second part of the highlighted code is a handler for server responses:

private ResponseListener listener = new ResultIssuesResponseListener() {

    @Override
    public void onResult(ResultEvent event) {
        output.appendText((String)event.getResult() + "\n");
    }

    @Override
    public void onIssue(IssueEvent event) {
        output.appendText(event.toString() + "\n");
    }
};

The two methods of the ResultIssuesResponseListener interface deal respectively with successful answers (the server responds with “Hello �? + your input + “!�?) and issues (something went wrong). Both display their output in the text area of the application.

The third part of the highlighted code is the server request:

remoteService.newInvocation("sayHello", input.getText())
             .addListener(listener)
             .invoke();

The remoteService, bound to the hello world POJO service on the server, creates a new invocation of the method “sayHello�?, with the user input as parameter (newInvocation(“sayHello�?, input.getText())). Then, the just created handler (see above) is set as the listener of the server response (addListener(listener)) and the call is placed (invoke()). This happens each time the user input a new text.

The final part of the highlighted code stops the transport when the application is closed:

transport.stop();

All resources allocated by the transport are then released, in particular the underlying thread pool managing asynchronous requests: failing to call the transport stop method can lead to improper thread closing, leaving the application in a kind of daemon state.

4. A Look at the Server Code

In the “samples�? directory of the GraniteDS 3.0.0.M1 distribution, you will find a file named “sample_projects.zip�?. You can unzip it at location of your choice or import it as an existing projets archive under Eclipse.

Let’s look at the file that explains the configuration of the RemotingChannel and RemotingService (helloworld/war/WEB-INF/flex/services-config.xml):

<services-config>

    <services>
        <service id="granite-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="helloWorldService">
                <channels>
                    <channel ref="graniteamf"/>
                </channels>
                <properties>
                    <scope>application</scope>
                    <source>org.test.HelloWorldService</source>
                </properties>
            </destination>
        </service>
    </services>

    <channels>
        <channel-definition id="graniteamf" class="mx.messaging.channels.AMFChannel">
            <endpoint
                uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"
                class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>

</services-config>

Let’s start with the channel definition: a channel identified by “graniteamf�? is bound to an uri which resolves to “http://demo.graniteds.org/helloworld/graniteamf/amf�?. If you look at the web.xml file, this is where the main GraniteDS filter and servlet are handling incoming AMF requests. The configuration of the AMFRemotingChannel in the JavaFX HelloWorld class reflects these settings.

Then, jump to the beginning of the file and look at the service definition: the destination “helloWorldService�?, which uses the “graniteamf�? channel, is bound to the org.test.HelloWorldService POJO. This explains the configuration of our RemotingService as well.

Finally, let’s have a look at the HelloWorldService class (helloworld/java/org/test/HelloWorldService.java):

package org.test;

public class HelloWorldService {

    public String sayHello(String name) {
        return "Hello " + name + "!";
    }
}

The invocation of the service (ie: remoteService.newInvocation(“sayHello�?, input.getText())) is now all obvious: the method “sayHello�? is called with a parameter set to the current user input.

Granite Data Services 2.3.2 GA Released

By Franck May 24th, 2012 Annoucements, GraniteDS No Comments
Please, feature an image for this post.

Granite Data Services 2.3.2 GA is out and available for download . Maven artifacts are also available through Maven2 central repositories .

This new release comes with several bugfixes and improvements (see the complete changelog on Jira ). Here are some highlights of the most interesting new features in GraniteDS 2.3.2 GA:

  • Hibernate 4.1, JBoss 7 and Jetty 7 support.
  • The Eclipse builder, whenever you remove or rename a Java class which is in the scope of the generator, will rename (no deletion!) corresponding AS3 classes, appending the following suffix “<current_system_millis>.hid�? to them. You will then get useful Flex compilation errors if your project is referencing these deleted classes.
  • Bean validation is now working with DTOs and not only with JPA entities.

You can update Gas3 (together with the Wizard) through our Eclipse .

Flex, GraniteDS and the Future of RIA

By Franck December 6th, 2011 Flex, GraniteDS 4 Comments
Please, feature an image for this post.

After the recent announcements from Adobe regarding the future of the Flex framework (see, for example, this ) and, unofficially, from Microsoft about Silverlight (see ), the RIA world have been deeply shaken up and it is now time to look at the viable solutions left to the developers.

Before digging into what we, at GraniteDS, think about the Flex and RIA future and how it is influencing our platform roadmap, let’s see who are the different players in this area:

  • Flex (Adobe / Apache Foundation): one of best RIA solution right now, based on the Flash plugin.
  • Silverlight (Microsoft): another very good RIA solution, based on the plugin of the same name.
  • JavaFX (Sun / Oracle): emerging, based on the Java plugin, could be a good alternative if it comes on time.
  • GWT (Google), ExtJS (Sencha) and a plethora of others: good or emerging RIA solutions, no plugin required, targeted at HTML / JavaScript and the pending HTML5 specification.

Now let’s see what Flex brings to the table that makes it such a compelling solution for enterprise applications: a very good IDE and tooling, a strong language (ActionScript3), very good performance and cross-browser compatibility thanks to the Flash Player runtime, a great UI framework with plenty of advanced features (sophisticated component lifecycle, data binding, modularity, skinning, media capabilities, etc.), a good set of built-in, open source and for-pay components, and recently the ability to build cross-platform iOS / Android mobile applications from the same source code with the AIR runtime. All things that made possible for us to build our GraniteDS platform on a strong foundation.

All those capabilities are at worst inexistent, at best very partially matched by the existing alternatives. Without Flex and Silverlight, enterprise RIA developers are left with good but (while at different extents) emerging or less featured frameworks. There is not any doubt that it is possible to build enterprise applications with them, but the development will be much slower than with Flex or Silverlight, less maintainable, missing many advanced features and will require long and extensive testing on the various target browsers. Moreover the landscape of client technologies is evolving at an extremely fast pace with new frameworks, JavaScript evolutions or replacements such as Google Dart or ECMAScript 6 (Harmony), announced almost every day, and it’s very difficult to make a perennial choice right now.

You might have noticed that we only marginally mention HTML5 as an alternative. Indeed we think that HTML5 as it currently exists really is more an alternative to the Flash Player than to the Flex framework. You will always need complementary frameworks and component libraries to get a really usable development platform, and a big issue is that there is no common standard component model that ensures that all this stuff will work happily together. And while some of these HTML5-based frameworks will certainly become strong RIA platforms in the future, they are right now simply not as feature rich and stable as Flex and Silverlight can be, and most likely won’t be in the coming years. There is simply nothing that can replace Flex today.

What Future for the Flex Framework?

According to Adobe, the entire Flex framework will be soon given to the Apache Foundation. This is great news, from an openness and licensing point of vue, but it could also lead to a slow death of this great solution if nobody is truly committed into its development and maintenance. While Adobe seems to be willing to bind some of its own resources on the framework future, we think that a large part of the Flex community should be involved and we are very exited with the idea of participating to the Flex framework evolution.

While a participation as simple contributors is very likely, we wish to take a bigger part in the governance of the project. Of course this is subject to the choices of Adobe and the Apache Foundation concerning the people involved in this governance but, as a significant player in the Flex area, the GraniteDS team should be one of the natural choices in this community selection process.

If Flex as an Apache Foundation project is widely open to community contributors, we believe that it will remain the most powerful RIA platform in the future and may lead the industry for years to come until HTML5 or one of its next iterations can finally provide a credible solution. Flex is not going to disappear in the foreseeable future and is still the better choice for developing rich enterprise applications.

LCDS, BlazeDS and GraniteDS

GraniteDS has been the main alternative to LCDS (Livecycle Data Services) from the beginning and, after more than 5 years of polishing and improvements, it is a widely used, stable, production-ready, open-source and feature-rich solution for enterprise Flex / Java EE developments. It is also known as offering many strong advantages over BlazeDS and you will find a detailed comparison between GraniteDS and BlazeDS here, as well as a step-by-step migration guide.

According to another recent , Adobe is unlikely going to publish any new major release of LCDS, speaking only about supporting existing customers and applications. LCDS isn’t anymore bundled as a standalone product but is now sold as a module of a much larger platform, the . From its part, BlazeDS hasn’t really evolved during the last 1 or 2 years, and its maturation as an Apache Foundation project is at least questionable.

From an architectural point of vue, GraniteDS has always promoted a strong server-side approach, based on remote services that implement the most significant part of the business logic and a client application that is mostly a presentation layer. The main advantages of this approach are the independence of the server application from the client-side technology (Flex or any other) and the ability to leverage the full power of existing Java EE frameworks such as Spring, JBoss Seam, EJB3 and now CDI. This clearly differs from the classical client-server architecture promoted by LCDS, where almost all the business logic goes to the client-side, the server being not much more than a database frontend.

Another obvious advantage of this approach is the ability to migrate an existing Flex application to another RIA technology without having to change anything on the server application. The same applies when there is a need to create multi-headed client applications, targeted at different platforms (Flex, Android, iOS, HTML5, etc.). Using GraniteDS makes your application as future-proof as possible in this quickly evolving technology environment, while still benefiting from all its advanced enterprise features (lazy-loading, paging, real-time data push, etc.)

GraniteDS Roadmap

After the recent release of the 2.3.0.GA version of our platform (see details here) and a new Eclipse wizard plugin that dramatically simplifies GraniteDS’ projects creation (see here), we are moving to a major evolution of the framework. Among several other new features and improvements, the next 3.0 version will focus on the following areas:

  • Client libraries for iOS (Objective-C), Android (Java) and HTML5 (JavaScript): the purpose of these libraries is to implement the most salient features of the Flex / GraniteDS client framework in other technological contexts. Remoting, real-time messaging and data management will be available for each of these targeted platforms, without changing anything to the server-side implementation of current GraniteDS / Flex applications.
  • Code generation improvements (Gas3): generated code won’t be only targeted at ActionScript3, but also at Objective-C, Java and JavaScript.
  • Clean separation between data management and dependency injection features (Tide): this will allow an easier integration of Flex client framework (Spring ActionScript, Cairngorm, Parsley, Swiz, etc.) with GraniteDS’ data management module, and greatly simplify the implementation of data management for other client technologies.
  • An improved implementation of the real-time messaging system (Gravity): support of clustered and durable JMS subscriptions, reduced data transfers and WebSocket support.
  • Full OSGi / Java EE 6 compliance: GraniteDS conforms to standard and popular specifications, in order to be compatible with all application servers.
  • New distribution model (Community Platform): packaged as a ready-to-run test drive, it will greatly improve the getting started experience of the framework.

Overall, these new features are aiming to improve GraniteDS ease of use, enlarge its features and target platforms perimeter and help users in leveraging today’s and tomorrow’s best technical solutions.

Moving Forward

From all of the above, we believe that the GraniteDS platform, with its enterprise-grade features, uncompromised Java EE integration, professional support and openness to a wide range of client technologies can be considered as one of the best available platform for perennial RIA developments.

Through its continuous move toward new client technologies, GraniteDS will stay open to strong partnerships with IDE and graphical components providers, and committed to offer an open-source, comprehensive and powerful solution for Java EE developers willing to leverage the best of this renewed RIA world.

Announcing Granite Data Services 2.3.0 GA (final)!

By Franck November 9th, 2011 Annoucements, GraniteDS No Comments
Please, feature an image for this post.

Hi all,

Granite Data Services 2.3.0 GA (final) is out and available for download here: . Maven artifacts have been uploaded and should be shortly available as well.

This final release comes with fixes for the few issues that were discovered in the recent 2.3.0 RC1. The full change log can be found on .

Among many other things, GraniteDS 2.3.0 brings:

  • Client-side lazy-loading.
  • Clustering improvements.
  • JMS integration fixes.
  • Hibernate 4 / JBoss 7 / Flex 4.5 support.

See also this post about these new features / improvements: More details on the new features in GraniteDS 2.3.

Today’s Launch Of Our Enterprise Platform

By Franck July 18th, 2011 GraniteDS No Comments
Please, feature an image for this post.

Today, we are excited to announce the launch of the GraniteDS Enterprise Platform.

The Enterprise Platform of GraniteDS has been developed in response to the feedback we received in our many conversations with our users over the past weeks and months. Our team in Europe and the US conducted surveys, in depth interviews and spoke with as many GraniteDS users in person as possible. As a result, the release of the Enterprise Platform is the first step of many to come to make GraniteDS even more powerful and reliable for Flex / Java EE applications of any kind.

We are releasing the Enterprise Platform today as our recommended setup for projects using GraniteDS in production environments. The Enterprise Platform gives you:

  • An extensively QA tested and stable version of GraniteDS
  • Long term maintenance (5 years) with security updates and bugfixes
  • Flexible and affordable premium support or consulting with guaranteed quick response times

With the Enterprise Platform you will also get early access to new features that we plan to release soon like RTMP, extended mobile platform support, or out of the box clustering and integration with monitoring tools. For bundles and prices, check out our pricing page.

As a result, the GraniteDS Enterprise Platform enables developers and companies to leverage the full feature range of the open-source version of GraniteDS, along with a broad range of pre-packed enterprise-level services and full support for applications in development and production. This unique combination of features and services enables companies to leverage the full power of GraniteDS also in mission-critical applications through a highly stable, reliable and scalable distribution package.

Let us know what you think about this new offering! Please share your thoughts and comments with us at any time in the comments or via our ,  or our website.

Purchase the Enterprise Platform Now!

Review the pricing and choose your bundle here.

If you want to download and test a feature-reduced version of the Enterprise Platform (no clustering, no SSL, no technologies preview), check out the Community Platform that comes with pre-packaged real-time messaging native libraries (APR) and sample applications. Get it here.

Granite Data Services 2.2.1 GA Released

By Franck June 14th, 2011 GraniteDS No Comments
Please, feature an image for this post.

GraniteDS 2.2.1 GA is a bug and security fixes release with one major new feature: Gravity is now natively supported with WebLogic 9.1+ servers.

The security fix relies on a new configuration option and prevents arbitrary Java class instantiations through malicious AMF3 requests. (more…)

GraniteDS Wizard (technology preview)

By Franck March 1st, 2011 GraniteDS 1 Comment

The new GraniteDS Wizard Plugin is intended to facilitate the creation of new GraniteDS project under Eclipse.

1. Quick setup and usage:

In order to install and use it, you need at least an Eclipse 3.4+ bundle and, preferably, if you want to benefit from all of its features, the folowing plugins:

  • FlashBuilder 4.
  • GraniteDS Builder 2.2.
  • JBoss Tools 3 (with at least the archives tool, see is you don’t know what it is about).

You will also need a JBoss 5.1 distribution, as the default template that comes the wizard targets this application server.

Once you have setup this environment, donwload the new GraniteDS Wizard plugin on Github and unzip it into your eclipse/plugins directory. Restart Eclipse and you should now be able to see a “GraniteDS�? section in the “New Project�? dialog when you select “File�? -> “New�? -> “Project…�? in your Eclipse menu:

Select “GraniteDS Projects�?, click on the “Next�? button and select the first available template in the next dialog:

Click again on the “Next�? button and you should now see a standard project creation dialog with a specific “Template variables�? section at the bottom:

Enter a project name, change the “JBoss installation directory�? to your JBoss installation directory, accept all other default options (or change them if you want) and click on “Finish�?.

You should now see a new Flex / JavaEE project, configured for both FlashBuilder and GraniteDS builder, and with a “.package�? file that automatically deploy the project in the choosen JBoss deployment directory.

Tip: unfortunatly, you should also have an error when the project is first build… This is FlashBuilder error (actually a known bug), complaining that it hasn’t been able to create the html templates. Just right click on the error and ask it to recreate the template files.

2. Under the hood, modifying the template:

Project templates in this GraniteDS wizard tool are mostly made of Groovy scripts. Go to your “eclipse/plugin/org.granite.wizard_1.0.0.alpha1/resources�? directory. You should see two subdirectories, “libs�? and “templates�?.

The “libs�? directory contains GraniteDS libraries that are referenced by templates (see below).

The “templates�? directory contains actual templates. There is only one template at this time, in a directory called “jboss�?. If you open this directory, you will see two files and one directory:

  • template.properties: this file contains the name and description of the template, as they appear in the second screenshot above. The “title�? property is the title of the third screenshot above. The last property (“controller�?) is for advanced use only, don’t change it!
  • bindings.groovy: this file defines variables that are displayed in the “Template variables�? section of the third screenshot and that will be used later for the actual project creation. You may modify the values in this file in order to get default values that fit your environment (in particular, you should change the “jbossDir�? value so it will be set by default to your JBoss installation directory). The good thing is that you may do this change without restarting Eclipse: template files are reloaded each time you run the wizard.
  • project: this directory contains all files and directories that the template is made of. As you can see, some directory names are enclosed between ${} characters: this means that their names will be resolved against the actual values of templates variables, as defined in the bindings.groovy file and adjusted in the third dialog shown above. Some other files are ending with a “.gsp�? extension: these are Groovy templates, similar to GraniteDS builder templates. Finally, you will even see files named “@libs!…“: these files will be resolved by copying GDS libraries found in the “resources/lib�? directory.

As you may now understand, this GraniteDS Wizard is completely generic and could be used in order to make projects that have nothing to do with GraniteDS: it is simply a general mecanism for displaying and editing variables before copying template files and directories.

Some more informations before a future proper documentation:

  • Binding variables use Groovy closures with dependencies: the jbossDeployDir value is { new File(jbossDir.value, “server/default/deploy�?) }, a closure that uses the value of the jbossDir variable. If you change the “JBoss installation directory�? in the interface, you will see the JBoss deploy directory value changing accordingly. This is similar to Flex bindings, when you write something like text=�?The value is {bindableVariable}�?.
  • If a file shoudn’t be generated for some configuration, you may throw a CancelFileGenerationException to prevent its generation (see the .flexProperties.gsp file for an example).
  • There are currently 4 types of supported UI controls: text input, checkbox, combobox and directory selection. The type of the variable must be set accordingly to String, Boolean, String (again) or File.
  • Input validation is made on the fly: use the “validation�? and “errorMessage�? attributes in the bindings.groovy file to set it up.
  • If you omit the “label�? attribute, the variable won’t be shown in the UI intterface.
  • You may disabled by default a variable in the UI interface if you set the “disabled�? attribute to false: this may be done with the “false�? literal, by a call to a method that returns a boolean value or even by a closure that uses another variable value (see bindings.groovy for examples).
  • You may create other templates by copying the “jboss�? one and changing whatever you want. Again, you don’t need to restart Eclipse in order to see your new template: just rerun the wizard, the new template will be displayed in the list shown in the second screenshot.

Don’t forget this is an alpha work: we will i mprove this JBoss template and provide other ones for different environments.

At least you don’t need a psychiatrist ;-)

By Franck September 15th, 2010 GraniteDS 1 Comment
Please, feature an image for this post.

is somewhere beyond the final frontier: to get to GraniteDS into their decision trees, you first have to go with Java, which doesn’t even seem to be the most recommended option according to these guys. Then, you’ll have to follow this frustrating path:

Complete messaging? No.
Complete data management? No
Complete code generation? No.
A psychiatrist? No. (if you happen to choose Yes here, you get LCDS ;-)
Scale beyond one server? Yes.
J2EE-centric? Yes.
Here you are: GraniteDS.

So, after refusing all the good things, you, as a GraniteDS user, avoid at least the cost of a therapy!

But the most funny thing is at the end of their post:

We respectfully request that the developers of the other integration servers mentioned herein join us (…) 

You may guess that William and I are of course seriously studying this unexpected opportunity.

Page 1 / 2