Spring BlazeDS Integration Test Drive

In this Test Drive, you run a series of short sample applications that demonstrate the key features of Spring BlazeDS Integration. This Test Drive is a continual work in progress and will be updated with each release of the project. Please submit your feedback to the Spring BlazeDS Integration team via the project forum.

These samples have been developed in collaboration between Adobe and SpringSource, with contributions from:


Spring Architecture

This version of the Test Drive uses a layered Spring configuration, with the core domain services and supporting infrastructure loaded in a root application context via the ContextLoaderListener, and the Flex integration configured separately via the DispatcherServlet's child application context. This layered approach with explicit separation of concerns is by no means required, but it does have some benefits over a non-layered approach such as opening up the option of writing out-of-container integration tests for the core domain services without having to load the BlazeDS infrastructure.

Samples Index

Remoting

Messaging

Security

Source code:

This guide assumes you have built and imported all of the Eclipse projects from {Spring BlazeDS Integration Distribution Root}/projects/spring-flex-samples/spring-flex-testdrive (See the reference docs for instructions on building and running the samples)

Remoting Samples

Spring BlazeDS Integration 101

Run the sample:

  1. Click here to run the application
  2. Click "Get Data": The DataGrid is populated with data returned by the findAll() method of the ProductDAO Java class.

Code walkthrough:

Open main.mxml in the spring-blazeds-101/src/main/flex directory to look at the source code of the client.

Open the following files to look at the source code for the server side of the application:

Note that in this first sample, we use a simplistic DAO implementation with low level JDBC code and no real abstraction. This was done intentionally to provide a bare-bones example that focuses exclusively on the Spring/BlazeDS Integration plumbing. In all the other examples of this Test Drive, we use the JdbcTemplate abstraction of the Spring framework to build the data access objects.

Using RemoteObject, you can directly invoke methods of Java objects deployed in your application server, and consume the return value. The return value can be a value of a primitive data type, an object, a collection of objects, an object graph, etc.

Using Spring BlazeDS Integration, Spring beans are exposed using the <flex:remoting-destination /> configuration tag. See the "product" bean definition in app-config.xml and the remoting destination that references it in flex-servlet.xml

Java objects returned by server-side methods are deserialized into either dynamic or typed ActionScript objects. In this example, we don't have an explicit ActionScript version of the Product Java class. Product objects are therefore deserialized into dynamic objects. In InSync03 below, we start working with strongly typed model objects.


InSync01: Searching Contacts

Run the sample:

  1. Click here to run the application
  2. Click the Search button to retrieve all the contacts in the database
  3. Enter a few characters in the Search input field before clicking the Search button in order to search by name

Code walkthrough:

Open insync01.mxml in the insync01/src/main/flex directory to look at the source code of the application.

Open the following files to look at the source code for the server side of the application:


InSync02: Using the RemoteObject Events

Run the sample:

Click here to run the application

Code walkthrough:

Open insync02.mxml in the insync02/src/main/flex directory to look at the source code of the application.

This version is similar to InSync01, but demonstrates how to use the ResultEvent and FaultEvent to have a finer control over RemoteObject calls.


InSync03: Strong Typing

Run the sample:

  1. Click here to run the application
  2. Click the Search button to retrieve all the contacts in the database
  3. Enter a few characters in the Search input field before clicking the Search button to search by name
  4. Select a contact in the DataGrid
  5. Edit the contact in the Contact form and click "Save" to persist your changes

Code walkthrough:

Open insync03.mxml, Contact.as, and ContactForm.mxml in the insync03/src/main/flex directory to look at the source code of the application.

In this version, we work with strongly typed contact objects. The Contact.as class is the ActionScript representation of org.springframework.flex.samples.contact.Contact.java. The [RemoteClass(alias="org.springframework.flex.samples.contact.Contact")] annotation in Contact.as is used to indicate that instances of Contact.as sent to the server should be deserialized as instances of org.springframework.flex.samples.contact.Contact at the server side, and that similarly, instances of org.springframework.flex.samples.contact.Contact retrieved from the server should be deserialized as instances of Contact.as.


InSync04: Opening Multiple Contacts

Run the sample:

  1. Click here to run the application
  2. Click the Search button to retrieve all the contacts in the database
  3. Enter a few characters in the Search input field before clicking the Search button to search by name
  4. Double-click a contact in the DataGrid to open it in a separate Tab
  5. Edit the contact in the Contact form and click "Save" to persist your changes

Code walkthrough:

Open insync04.mxml in the insync04/src/main/flex directory to look at the source code of the application.


InSync05: Adding New Contacts

Run the sample:

  1. Click here to run the application
  2. Click the Search button to retrieve all the contacts in the database
  3. Click the New Contact button
  4. Edit the new contact in the Contact form and click "Save" to create the contact

Code walkthrough:

Open insync05.mxml and ContactForm.mxml in the insync05/src/main/flex directory to look at the source code of the application.

This version enables the user of the application to add contacts. In ContactForm, we remotely invoke the create() method of ContactDAO when dealing with a new contact, and the update() method when updating an existing contact.


InSync06: Adding Event Notification for "Loosely Coupled" UI Synchronization

Run the sample:

  1. Click here to run the application
  2. Click the Search button to retrieve all the contacts in the database
  3. Enter a few characters in the Search input field before clicking the Search button to search by name
  4. Double-click a contact in the DataGrid to open it in a separate Tab
  5. Modify the first name or last name of the contact and click "Save". Notice that the DataGrid is updated to reflect your changes.
  6. Add a new contact and click "Save" to create the contact. Notice that the contact appears in the DataGrid.
  7. Delete a contact and notice that the contact is removed from the DataGrid.

Code walkthrough:

Open insync06.mxml, ContactForm.mxml, and ContactEvent.as in the insync06/src/main/flex directory to look at the source code of the application.

In this version, ContactForm dispatches events when a contact has been created, updated, or deleted. Other components of the application can register as listeners to these events to perform a specific task when a contact is created, updated or deleted. In this case, the main application registers as a listener to these events and refreshes the contact DataGrid to make sure it reflects the changes made in ContactForm.


InSync07: Styling the Application

Run the sample:

  1. Click here to run the application
  2. Click the Search button to retrieve all the contacts in the database
  3. Enter a few characters in the Search input field before clicking the Search button to search by name

Code walkthrough:

Open insync07.mxml and styles.css in the insync07/src/main/flex directory to look at the source code of the application.


inSync AIR: Desktop Version and the Client-Side Channel API

Run the sample:

  1. Click here to install the application
  2. Click the Search button to retrieve all the contacts in the database
  3. Enter a few characters in the Search input field before clicking the Search button to search by name

Code walkthrough:

Open main.mxml in the insync-air-spring/src/main/flex directory to look at the source code of the application.

In this version we also use the client-side Channel API to programmatically provide the endpoint of the AMF channel. By default, the endpoint is read from services-config.xml at compile time. This means that the compiled application includes a hardcoded value for the AMF endpoint URL, which is not appropriate for real life applications. The client-side Channel API allows you to provide the endpoint URL at runtime. In this version, the URL is now hardcoded in the client code which is not a good solution either. The key, in a real life application, is to obtain that URL dynamically. One approach is to read a configuration file using the HTTPService. Another option is to encapsulate such configuration with a client-side DI framework like Spring ActionScript.


Company Manager

Run the sample:

  1. Click here to run the application
  2. Click the Search button to retrieve all the contacts in the database
  3. Enter a few characters in the Search input field before clicking the Search button to search by name

Code walkthrough:

Open companymgr.mxml, Company.as, Industry.as, and CompanyForm.mxml in the companymgr/src/main/flex directory to look at the source code of the application.

Open the following files to look at the source code for the server side of the application:

Note that the CompanyDAO and IndustryDAO beans are not defined in web-application-config.xml but are configured using annotations (@Service, @RemotingDestination, @Autowired, @RemotingInclude, and @RemotingExclude). This application is similar to inSync, but demonstrates object associations: the Company class has a property of type Industry.


Messaging Samples

Chat

Run the sample:

  1. Click here to run the application
  2. Access the same URL in another browser window to open a second instance of the chat application
  3. Type a message in one of the chat clients and click "Send": the message appears in the two chat clients

Code walkthrough:

Open chat.mxml in the chat/src/main/flex directory to look at the source code of the application. The Message Service manages a set of destinations that Flex clients can publish and subscribe to. Flex provides two components, Producer and Consumer, that you use to publish and subscribe to a destination. To subscribe to a destination, you use the subscribe() method of the Consumer class. When a message is published to a destination that you subscribed to, the message event is triggered on the Consumer.

Open testdrive/src/main/webapp/WEB-INF/flex-servlet.xml to look at the message service configuration. The message service is configured using <flex:message-service /> inside <flex:message-broker />. The "chat" destination is configured using <flex:message-destination id="chat" />


Simple Data Push

Run the sample

This example demonstrates how to use the message service to push data from the server to the client. At the server-side, a Java component publishes simulated real time values to a message destination. The Flex client subscribes to that destination and displays the values in real time.

  1. To start the feed at the server-side, run the Feed Starter application and start the "Simple Feed".
  2. Click here to run the client application.
  3. Click the Subscribe button. Pushed values appear in the text field. You can click the Unsubscribe button to unsubscribe from the destination.
  4. To stop the feed when you are done experimenting with the application, access the Feed Starter application and stop the "Simple Feed".

Code walk through

Open simplepush.mxml in the simplepush/src/main/flex directory to look at the source code of the application.

Open the following files in a text editor to look at the source code for the server side of the application:

In SimpleFeed.java, the MessageTemplate class is used to publish messages to the "simple-feed" destination.


Traderdesktop

Run the sample

Traderdesktop is a more sophisticated data push example showing how to use subtopics to selectively subscribe to specific messages. In this case, the user can subscribe to updates for specific stocks only. At the server side, a Java component publishes simulated market data to a messaging destination.

  1. To start the feed at the server-side, run the Feed Starter application and start the "Market Feed".
  2. Click here to run the client application.
  3. To stop the feed when you are done experimenting with the application, access the Feed Starter application and stop the "Market Feed".

Code walk through

Open traderdesktop.mxml in the traderdesktop/src/main/flex directory to look at the source code of the application.

Open the following files in a text editor to look at the source code for the server side of the application:


JMS Chat

Run the sample:

This application is identical to the regular chat application above. The only difference is the destination: "jms-chat". At the server-side, the "jms-chat" destination is mapped to a JMS topic.

  1. Click here to run the application
  2. Access the same URL in another browser window to open a second instance of the chat application
  3. Type a message in one of the chat clients and click "Send": the message appears in the two chat clients
  4. You can also start the Java (Swing) client: Import and execute the Eclipse launch configuration from testdrive/jmschat.launch. This is an axample of how you can exchange messages between Flex and Java apps through JMS topics.

Code walkthrough:

Open jmschat.mxml in the jmschat/src/main/flex directory to look at the source code of the application.

Open testdrive/src/main/webapp/WEB-INF/flex-servlet.xml to look at the message service configuration. Note that the "jms-chat" destination is mapped to the "chatTopic" (sampletopic.flex.jms.chat) JMS topic that is configured in testdrive/src/main/webapp/WEB-INF/spring/infrastructure-config.xml. In this application, we use an embedded ActiveMQ message broker configured by the connectionFactory bean. You don't have to start ActiveMQ in a separate process.


POJO Messaging

Run the sample:

This application uses the same frontend as the two chat applications. However, in this case messages are sent between the client and a server-side POJO. There are separate inbound and outbound destinations, and these are mapped to Spring Integration channels.

  1. Click here to run the application
  2. Type "start" in the text field and click "Send"
  3. Incremental values should display in the upper text area every 5 seconds
  4. You can send a "stop" message as well or any integer value to set the counter
  5. Any other message text will trigger log output in the console

Code walkthrough:

Open messaging.mxml in the spring-messaging/src/main/flex directory to look at the source code of the client.

Open testdrive/src/main/webapp/WEB-INF/flex-servlet.xml to look at the message service configuration. Note that the "si-receive" and "si-send" destinations are mapped to the "toFlex" and "fromFlex" Message Channels respectively. Those are configured in testdrive/src/main/webapp/WEB-INF/spring/integration-config.xml. Also, in that configuration file you will see the "inbound-channel-adapter" and "service-activator" Spring Integration components and the "counter" bean definition they reference. The Counter source code is located within testdrive/src/main/java in the "org.springframework.flex.samples.integration" package.

Collaboration

Run the sample:

  1. Click here to run the application
  2. Access the same URL in another browser window to open a second instance of the chat application
  3. Enter some data in one browser and notice that the data appears in the other browser as well.
  4. Select another tab in the accordion in one broswer, and notice that the other client's user interface is synchronized accordingly.

Code walkthrough:

Open collaboration.mxml in the collaboration/src/main/flex directory to look at the source code of the application.

Open testdrive/src/main/webapp/WEB-INF/flex-servlet.xml to look at the message service configuration.


Security Samples

Security Integration 101

Run the sample and login as various users to see the effect of the security settings:

  1. Click here to run the application
  2. Log in (use UserId: john / Password: john), and click "Get Data" again: you should now get the data
  3. Expand the "Chat" panel and enter a message. You should see the message published to the main chat window.
  4. Log out and then log in as the admin user (use UserId: admin / Password: admin). You should now see an additional column in the table that is conditionally displayed based on the user's permissions.
  5. Log out and then log in as the guest user (use UserId: guest / Password: guest). If you click "Get Data" an "Access Denied" error will be displayed as this user does not have sufficient permissions.
  6. As the "guest" user, again expand the "Chat" panel and attempt to enter a message. You should receive an error due to not having sufficient permissions.
  7. The sample also demonstrates detection of a user that's already been authenticated, and the loading of that user's information. For example, log out and then access http://localhost:8080/testdrive/login.jsp, and logon using john / john. You will then be redirected into the secured sample. Notice that the user information has been populated and you can access data as if you'd logged in through the Flex UI.

Code walkthrough:

Open secured.mxml in the secured/src/main/flex directory to look at the source code of the application.

Open the following files in a text editor to look at the the server side configuration:

Note that the "find*" methods of securedProductService are secured in app-config.xml. A basic authentication provider is defined in security-config.xml, and the BlazeDS support is enabled by the <flex:secured> tag in flex-servlet.xml.