[null, {"document_url": "https://dzone.com/articles/enterprise-ria-spring-3-flex-4?fromrel=true", "unformatted_src": "/themes/dz20/images/DZone_MobileLogin2.png", "src": "https://dzone.com/themes/dz20/images/DZone_MobileLogin2.png", "formatted_filename": "DZone MobileLogin"}, null, null, null, {"document_url": "https://dzone.com/articles/enterprise-ria-spring-3-flex-4?fromrel=true", "unformatted_src": "/themes/dz20/images/ArticleImg_4.jpg", "src": "https://dzone.com/themes/dz20/images/ArticleImg_4.jpg", "formatted_filename": "ArticleImg", "rendered_width": 60}, null, null, null]
Comment (28)



Adobe Flex is one of the most widely used client technologies for building rich applications and Spring 3 is one of the most popular Java application frameworks. These two technologies make a great combination for building enterprise applications with a modern looking and rich user interface.

There are various options to integrate them, that each have their pros and cons, such as Web/REST services and the Spring-Flex project promoted by Adobe and SpringSource. There are lots of articles and resources about them, here I will focus on an alternative approach using the open source project GraniteDS.

GraniteDS is based on a cleanroom implementation of the AMF3 remoting and messaging protocols, and has been historically the first open source implementation of the AMF3 protocol in Java. It has been providing out-of-the-box integration with Spring very early and this integration has continually been improved with each new version of GraniteDS, following a few core principles :

These core design choices make GraniteDS very different from for example Adobe BlazeDS that has only a server-side part. In this article I will show this concept of RIA platform at work by building a simple application using the following features :

As a side note, GraniteDS still supports the classic Flex RemoteObject API and is thus a close drop-in replacement for BlazeDS with some useful enhancements, but provides an alternative Flex API called Tide that is easier to use and brings the full power of the platform.


We have to start somewhere, and the first step is to create the Spring application. This is no big deal, we could just start by a standard Spring MVC application, and just add a few GraniteDS elements in the Spring application context. To make things easier, I'm going to use a Maven archetype (Maven 3 recommended) :

This creates a basic project skeleton that includes persistence, security and real-time data push features. As a starting point you can simply build the project and run it with the Maven jetty plugin :

Then browse http://localhost:8080/gdsspringflex/gdsspringflex.swf, and log in with admin/admin or user/user.

The structure of the project is a classic multi-module Maven project with a Flex module, a Java module and a Web application module. It uses the very nice flexmojos plugin to build the Flex application with Maven.

If we forget about the default generated application sources in the Flex and Java modules, and focus only on configuration, the most interesting files are web.xml and the app*config.xml Spring configuration files.

web.xml basically includes Spring 3 listeners, a Spring MVC dispatcher servlet mapped on /graniteamf/* that will handle AMF requests, and a Gravity servlet for Jetty mapped on /gravityamf/* (Gravity is the name of the GraniteDS Comet-based messaging implementation).

The reason why there is a specific servlet for Gravity is that it is optimized to use the specific asynchronous capabilities of the underlying servlet container to get better scalability, and this can not be achieved with the default Spring MVC dispatcher servlet. That's also why this is necessary to configure different servlet implementations depending on the target container (Tomcat, JBossWeb...).

Next is the main Spring 3 configuration that is mostly basic Spring MVC stuff :

The main thing concerning GraniteDS is the flex-filter declaration. There is also an example messaging topic that is used by the default Hello World application. app-jpa-config.xml contains the JPA configuration and does not include anything about GraniteDS. Lastly Spring Security :

Once again mostly Spring stuff, we just find here the tide-identity bean that is used to integrate Spring Security with the Tide Identity Flex component.

We're done for the server-side setup. GraniteDS detects automatically most of the Spring configuration at startup and configures itself accordingly, so these 10 lines of XML are generally enough for most projects. If you have a look at the various Maven POMs, you will find the dependencies on the server-side GraniteDS jars and client-side GraniteDS swcs. You can also have a look at the Flex mxml code of the example application generated by the archetype, but for now I will start from scratch.

Remoting to Spring services

First the traditional Hello World and its incarnation as a Spring 3 service :

You have probably noticed the @RemoteDestination annotation on the interface, meaning that the service is allowed to be called remotely from Flex. Now the Flex application :

You can rebuild and restart the project with :

Well, that's not exactly the shortest Hello World application, but let's see the interesting bits :

Now that we got the basics working, we can improve this a little. The Flex project POM is configured to automatically generate (with the GraniteDS Gas3 generator embedded in flexmojos) typesafe AS3 proxies for all Java interfaces named *Service and annotated with @RemoteDestination. That means we could also simply write this :

This looks like a minor cosmetic change, but now you benefit from code completion in your IDE and from better error checking by the Flex compiler. Going even further, the whole injection can be made completely typesafe and not rely on the service name any more by using the annotation [Inject] instead of [In] (note that we can now give our injected variable any name) :

And as the injection in the client now uses the interface name, we don't have to give a name to the Spring service any more :

Now you can do any refactoring you want on the Java side, like changing method signatures, Gas3 will then regenerate the AS3 proxies and the Flex compiler will immediately tell you what's wrong. Another interesting thing is that the Flex mxml now looks like a Spring bean, making very easy for Spring developers to get started with Flex.

Persistence and integration with Hibernate/JPA

Let's go a bit further and see how to do simple CRUD with a couple of JPA entities :

Both entities extends AbstractEntity, but it is not mandatory at all, it's just a helper class provided by the Maven archetype.

Now we create a simple Spring service to handle basic CRUD for these entities (obviously a politically correct Spring service should use DAOs, but DAOs are awful and won't change anything here) :

And the Flex application :

This is a simple CRUD application using some very convenient Flex 4 features such as states and bidirectional data binding. Note how all boilerplate code to connect the client and the server has litterally disappeared while still keeping a clean separation between the two layers. In the real world we would probably want to apply some MVC pattern instead of a monolithic mxml but this would not change much. The important thing is that the Flex and Java parts do not contain useless or redundant code and are thus a lot easier to maintain. Even using model-driven code generators to build the Flex application automatically would be easier because there is basically much less code to generate.

Now rebuild and run the application on Jetty, and check that you can create, update and delete authors. There are two minor issues with this example that have not much interest in themselves but that I will use to show two interesting features of Tide.

First issue : when you start updating the name of an author, the change is propagated to the list by bidirectional binding but the previous value is not restored when you click on 'Cancel', leading to an inconsistent display. This is mainly a problem of Flex 4 bidirectional binding because it propagates all changes immediately but it is not able to rollback these changes. We would have three options to fix it : save the entity state somewhere before editing and restore it upon cancel, copy the original data and bind the input fields on the copy (but then the list would not be updated by binding), or avoid using bidirectional binding. None of these options is really appealing, fortunately Tide provides a very simple feature to deal with this and makes bidirectional binding really usable :

Managed.resetEntity() simply rolls back all changes done on the Flex side and restores the last stable state received from the server.

Second issue : clicking on refresh loses the current selected item. This is because we replace the dataProvider of the list each time we receive a new collection. This can easily be fixed by using the data merge functionality of Tide :

This relatively ugly remote call using a TideResponder indicates to Tide that it should merge the call result with the provided variable instead of completely replacing the collection with 'authors = event.result' in the result handler. Note that we don't even need a result handler any more, once again saving a few lines of codes.

This issue with item selection illustrates why keeping the same collection and entity instances accross remote calls is very important if you want to setup data-driven visual effects or animations (remember, the R of RIA). All visual features of Flex highly depend on the object instance that drives the effect and the events that it dispatches. This is where the Tide entity cache and merge helps a lot by ensuring that each entity instance will exist only once and dispatch only the necessary events when it is updated from the server.

I'll finish this part by showing how to display and update the collection of books. For now you have maybe noticed that the existence of this collection did not cause any problem at all, though it is marked lazy on the JPA entity. No LazyInitializationException, and no particular issue when merging the entity modified in Flex in the JPA persistence context. GraniteDS has transparently serialized and deserialized the Hibernate internal state of the collection back and forth, thus making the data coming from Flex appear exactly as if it came from a Java client.

So let's try to implement the editing of the list of books in the update form. We don't have to change anything in the service, Hibernate will take care of persisting the collection because of the cascading option we selected. On the Flex side, we can use an editable List (note that there is no built-in editable Spark List in Flex 4, so we use a custom ItemRenderer inspired from this blog post, see the full sources attached), and add this :

And the corresponding script actions :

The Tide framework automatically takes care of initializing the collection when needed, you just have to bind it to any Flex data component such as List. Once again all the usual boilerplate code necessary to deal with data and collections has completely disappeared.

Integration with Bean Validation

Our application is still missing a critical piece : data validation. As a first step, we can leverage the Hibernate integration with Bean Validation and simply annotate our entities to let the server handle validation :

Once you change this and redeploy, creating an invalid author has now become impossible but there is error message is a mess that cannot be understood by a real user. We could simply add a particular behaviour in the fault handler :

We now get the standard Flex validation error popup on the correct input field. It's definitely nicer, but it would be even better if we didn't have to call the server at all to check for text size. Of course we could manually add Flex validators to each field, but it would be very tedious and we would have to maintain consistency between the client-side and server-side validator rules.

Fortunately with GraniteDS 2.2 it can be a lot easier. If you have a look at the generated ActionScript 3 entity for Author (in fact its parent class AuthorBase.as found in flex/target/generated-sources), you will notice that annotations have been generated corresponding to the Java Bean Validation annotations.

The FormValidator component is able to use these annotations and automatically handle validation on the client side, but we first have to instruct the Flex compiler that it should keep these annotations in the compiled classes, which is not the case by default. In the Flex module pom.xml, you can find a section , just add the validation annotations that we are using here :

After a new clean build and restart, you can see that the GraniteDS validation engine now enforces the constraints on the client, which gives the user a much better feedback about its actions. We can also prevent any call to the server when something is wrong :

Integration with Spring Security

All is good, but anyone can modify anything on our ultra critical book database, so it's time to add a bit of security. The Maven archetype includes a simple Spring Security 3 setup with two users admin/admin and user/user that is obviously not suitable for any real application but that we can just use as an example. The first step is to add authentication, and we can for example reuse the simple login form Login.mxml provided by the archetype. We just need the logic to switch between the login form and the application, so we create a new main mxml by renaming the existing Main.mxml to Home.mxml and creating a new Main.mxml :

As you can see we have moved the Tide initialization to this new mxml, and added two main blocks to handle authentication :

Except removing the Tide initialization, we also need to do a small change to Home.mxml as it is not the main mxml any more :

The metadata [Name] indicates that this mxml has to be managed by Tide (i.e. injection, observers...). Without it, nothing will work any more.

Now we would like to prevent non-administrator users from deleting authors. As with did with validation, we can in a first step rely on server-side security and simply annotate the service method :

You can check that you cannot delete an author when logged in as user. The error message is handled by our fault handler and displayed as an alert. It's a bit tedious to handle this in each and every fault handler, so you can define a custom exception handler that will globally intercept such security errors that always have a faultCode 'Server.Security.AccessDenied' :

And register this handler in the main mxml with :

Now authorization errors will be properly handled and displayed for all remote calls.

That would be even better if we didn't even display the 'Delete' button to our user if he's not allowed to use it. It's very easy to hide or disable parts of the UI depending on user access rights by using the Identity component that has a few methods similar to the Spring Security jsp tags :

Finally if you manage to configure Spring Security ACL (I won't even try to show this here, it would require a complete article), you could use domain object security and secure each author instance separately (8 is the Spring Security ACL bit mask for 'delete') :

As with validation, you can see that most of the value of GraniteDS resides in the Flex libraries that it provides. This level of integration cannot be achieved with a server-only framework.

Data push

The last thing I will demonstrate is the ability to dispatch updates on an entity to all connected clients. This can be useful with frequently updated data, so every user has an up-to-date view without having to click on some 'Refresh' button. Enabling this involves a few steps :

The default ObserveAllPublishAll class comes from the archetype and defines a publishing policy where everyone receives everything. Alternative dispatching strategies can be defined if it's necessary to restrict the set of recipients depending on the data itself for security, functional or performance reasons.

Now you can rebuild and restart and connect from two different machines or two different browsers, and check that changes made on an author in one browser are propagated to the other.

New and deleted authors are not propagated automatically, we have to handle these two cases manually. This is not very hard, we just have to observe some built-in events dispatched by Tide :

Fine, the list is now correctly refreshed with new and deleted authors, but you will notice that new authors are added twice on the current user application. Indeed we add it from both the data observer and the result handler. We can safely keep only the global observer since it will always be called and remove the addItem from the handler. Such observers can be put in many views at the same time and all of them will be updated.


That was a long article, but at least I hope it gave you a good idea about the client+server RIA platform concept of GraniteDS. Applications can be written faster with a lot less code, and still have a clean architecture with clearly separated layers.
 Long Polling with Spring 3.2's DeferredResult Implementing REST Services with Apache Pivot An Introduction to Spring AOP 
java ,ria ,frameworks ,flex ,spring ,graniteds






