Flex is rapidly becoming the preferred technology for building groundbreaking internet applications delivered in the browser and on the desktop (using the AIR runtime). For several years, Spring has been one of the most popular frameworks for building the Java back-end of internet applications. In this post is described how to use BlazeDS Remoting to seamlessly integrate the two technologies and build state-of-the-art internet applications made of a Flex front-end and a Spring back-end. To leverage the examples therein, download and install BlazeDS, the Spring framework and the Adobe Flex 3 Sample files.
Whether you are a Flex developer with limited knowledge of Spring, or a Spring developer with limited knowledge of Flex, you can benefit from the powerful integration of these products. This post describes how BlazeDS enables a tight integration between Flex and Spring, and provides background information on the technologies at play.
Spring is one of the most popular Java frameworks. The foundation of the Spring framework is a lightweight component container that implements the Inversion of Control (IoC) pattern. Using an IoC container, components don't instantiate or even look up their dependencies (the objects they work with). The container is responsible for injecting those dependencies when it creates the components (hence the term "Dependency Injection" also used to describe this pattern). The result is looser coupling between components. The Spring IoC container has proven to be a solid foundation for building robust enterprise applications. The components managed by the Spring IoC container are called Spring beans. The Spring framework includes several other modules in addition to its core IoC container. These modules are not covered in this document even though we will be using the Spring JDBC abstraction framework in the second sample application below. More information on the Spring framework can be found at http://www.springframework.org.
Flex is an environment for building Rich Internet Applications. The Flex programming model is made of:
- ActionScript, an ECMAScript compliant, object-oriented programming model. With some syntactical differences, ActionScript looks and feels similar to Java, and supports the same object-oriented constructs: packages, classes, inheritance, interfaces, strong (but also dynamic) typing etc.
- MXML: an XML-based language that provides an abstraction on top of ActionScript, and allows parts of an application (typically the View) to be built declaratively with an extensive set of class libraries.
The Flex source code (.mxml and .as files) is compiled into Flash bytecode (.swf) that is executed at the client-side by the Flash virtual machine using a Just-In-Time compiler. The Flex SDK is an open source project. It includes the Flex component library, the compiler, the debugger, and the documentation. A complete discussion of Flex is beyond the scope of this document. You can find more information and download the Flex SDK at http://opensource.adobe.com.
BlazeDS is a set of data services that give your Flex applications additional options for data connectivity. Without BlazeDS (or, without deploying any Flex-specific component at the server-side), Flex applications can access back-end data using either the HTTPService or the WebService: You use the HTTPService component to send HTTP requests to a server, and consume the response. Although the HTTPService is often used to consume XML, it can be used to consume other types of responses. The Flex HTTPService is similar to the XMLHttpRequest component available in Ajax. You use the WebService component to invoke SOAP-based web services. BlazeDS adds the following services: The Remoting Service allows your Flex application to directly invoke methods of Java objects deployed in your application server. The Message Service provides a publish/subscribe infrastructure that enables your Flex application to publish messages and subscribe to a messaging destination, enabling the development of real-time data push and collaborative applications. The Proxy Service allows your Flex application to make cross-domain service requests in a secure and controlled manner. In other words, it allows your Flex application to access a service available on a different domain than the domain from where the application was downloaded (without having to deploy a crossdomain.xml policy file on the target domain). BlazeDS is deployed as a set of JAR files as part of your web application. Like the Flex SDK, BlazeDS is an open-source project. More information is available at http://opensource.adobe.com.
In this post, I focus on the Remoting service. The Remoting Service provides a tight and natural integration with Spring. There is no need to transform data, or to expose services in a certain way: the Flex application can directly access the beans registered in the Spring IoC container. How does Flex use BlazeDS to access Spring beans? So, if Flex clients can remotely access Java objects, and if Spring beans are Java objects, aren't we all set and ready to start accessing Spring beans from Flex clients? Almost… There is one simple element to configure. The whole idea behind Spring IoC is to let the container instantiate components (and inject their dependencies). By default, however, components accessed remotely by a Flex client are instantiated by BlazeDS on the server. The key to the Flex/Spring integration, therefore, is to configure BlazeDS to let the Spring container take care of instantiating Spring beans. BlazeDS supports the concept of a factory to enable this type of custom component instantiation. The role of a factory is simply to provide ready-to-use instances of components to BlazeDS (instead of letting BlazeDS instantiate these components). The supporting files available with this article include a factory class (SpringFactory) that provides BlazeDS with fully initialized (dependency-injected) instances of Spring beans. Note: The SpringFactory was developed by Jeff Vroom (Flex Data Services architect) and is also available on Adobe Exchange. The remainder of this post describes how to configure your web application to use BlazeDS and Spring, how to configure the Spring Factory, and how to put the pieces together and start invoking Spring beans from Flex applications.
Environment: Configuring your web application is simple and merely requires installing and registering the necessary components.
- Step 1: Install the BlazeDS turnkey server The BlazeDS turnkey server is a ready-to-use version of Apache Tomcat in which the Blaze data services have already been deployed along with sample applications. The goal of the turnkey server is to give developers an easy way to run samples and tutorials out of the box. To install the BlazeDS turnkey server: Make sure that you have the JDK 1.5 or higher installed, and that you have a JAVA_HOME environment variable pointing to your Java Development Kit installation. Download blazeds-turnkey-.zip. Unzip blazeds-turnkey-.zip in /blazeds. Note.You can unzip blazeds-turnkey-.zip anywhere else. Just make sure you adjust the path in the instructions provided in this document accordingly. Start the samples database. Open a command prompt. Navigate to /blazeds/sampledb. Execute startdb.bat (Windows) or startdb.sh (Unix-based systems) Start Tomcat. Open a command prompt. Navigate to /blazeds/tomcat/bin. Execute the following command: catalina run Access http://localhost:8400/samples to make sure the installation is successful: you should see the BlazeDS samples home page. As an alternative to using the turnkey server, you could use one of the following options: Download blazeds-.war and deploy it in your own application server. Blazeds-.war is a blank web application configured to use the BlazeDS data services. Note: samples-.war includes everything included in blazeds.war, plus a series of samples. Download blazeds-.war and merge its content in your own web application. The instructions in this document assume that you use the BlazeDS turnkey server. If you are using one of the alternative options, you will have to adjust the instructions accordingly.
- Step 2: Install the Flex SDK You need the Flex compiler to compile the client-side (Flex-side) of the sample applications discussed in this document. The Flex compiler is part of the Flex SDK. As a convenience, the Flex SDK is available as part of the BlazeDS installation in blazeds/resources/flex_sdk/flex_sdk_3.zip. Note: The Flex SDK can also be downloaded at http://opensource.adobe.com. It is also available as part of Flex Builder. To install the Flex SDK: You can skip this step if Flex Builder 3 is installed on your system. Unzip /blazeds/resources/flex_sdk/flex_sdk_3.zip in /flex_sdk_3. Note: You can unzip flex_sdk_3.zip anywhere else. Just make sure you adjust the path in the instructions provided in this document accordingly.
- Step 3: Install Spring Note: A complete discussion of the Spring installation process is beyond the scope of this article. Refer to http://www.springframework.org for more information. The steps below describe a basic configuration that is sufficient for the purpose of this article. Download the Spring framework at http://www.springframework.org/download (the version without dependencies is sufficient to complete the examples in this article). Note: The examples below have been developed and tested using Spring 2.x. However the integration approach described in this document (and the SpringFactory class) should work fine using Spring 1.2.8 (some of the examples might not work because they use Spring 2.x features). Unzip the downloaded file. Locate spring.jar in the dist directory and copy the file to /blazeds/tomcat/webapps/blazeds/WEB-INF/lib Open /blazeds/tomcat/webapps/blazeds/WEB-INF/web.xml and add the context-param and listener definitions as follows: contextConfigLocation /WEB-INF/applicationContext.xml org.springframework.web.context.ContextLoaderListener
- Step 4: Install the supporting files Download flex-spring.zip here Unzip flex-spring.zip in /flex-spring Flex-spring.zip includes the Spring factory as well as the supporting files for the examples below.
- Step 5: Register the Spring factory Copy SpringFactory.class and SpringFactory$SpringFactoryInstance.class from /flex-spring/factory/bin/flex/samples/factories to /blazeds/tomcat/webapps/blazeds/WEB-INF/classes/flex/samples/factories. Register the Spring factory in /blazeds/tomcat/webapps/blazeds/WEB-INF/flex/services-config.xml:
- Step 1: Examine the application source code Examine the Flex source code: Open MortgageCalc.mxml located in /flex-spring/samples/mortgage/flex in a code editor to familiarize yourself with the application. The application enables the user to enter a mortgage amount. When the user clicks the "Calculate" button, the application obtains the value of the monthly payment for that mortgage by invoking the calculate() method of the remote object identified by a logical name: "mortgageService". "mortgageService" is mapped to a fully qualified Java class name in the remoting-config.xml file (see Step 3 below). Examine the Java source code: Open RateFinder.java, SimpleRateFinder.java and Mortgage.java located in /flex-spring/samples/mortgage/java in a code editor. Notice that Mortgage has a dependency to a RateFinder object. Mortgage doesn't instantiate a RateFinder object itself, doesn't lookup up for a RateFinder object, and doesn't even know the exact type of the object it will be dealing with (RateFinder is an inteface). An instance of a class implementing the RateFinder interface will be injected by the container (using the setRateFinder method) when it instantiates the component (see step 2 below).
- Step 2: Register Spring beans If it doesn't already exist, create a file named applicationContext.xml in /blazeds/tomcat/webapps/blazeds/WEB-INF. Register the rateFinderBean and mortgageBean beans in applicationContext.xml as follows: Notice that in the mortgageBean definition, we tell the container how to inject the rateFinder dependency: the rateFinder property is mapped to rateFinderBean, which defines an instance of the SimpleRateFinder class.
- Step 3: Configure the Flex Remoting destination Open remoting-config.xml in /blazeds/tomcat/webapps/blazeds/WEB-INF/flex. Add a mortgageService destination as follows: spring mortgageBean Notice that we use the Spring factory defined above (see "Register the Spring Factory"), and we provide the name of the Spring bean as defined in applicationContext.xml as the source.
- Step 4: Build the project The Flex SDK includes ANT tasks that make it easy to compile Flex applications and create HTML pages to host them as part of a build process. The support files include build scripts to compile and deploy each sample application. Note: You need the Apache Ant build tool to build and deploy your applications as described in this document. If Apache Ant is not installed on your system, visit http://ant.apache.org and follow the download and installation instructions. To build the Mortgage Calculator project: Edit /flex-spring/samples/mortgage/build.xml: Make sure the FLEX_HOME property points to the location of the Flex SDK on your system. Make sure the CONTEXT_ROOT property matches the context root of your web application. Open a command prompt. Navigate to /flex-spring/samples/mortgage. Execute the following command to compile and deploy the client and server of the application: ant The build process deploys the client side of the application (the compiled flex application) in /blazeds/tomcat/webapps/blazeds/mortgage and the server side (the compiled Java classes) in /blazeds/tomcat/webapps/blazeds/WEB-INF/classes/flex/samples/spring/mortgage.
- Step 5: Run the client application Restart Tomcat. Open a browser, access http://localhost:8400/blazeds/mortgage/index.html, and test the application: Enter a loan amount and click "Calculate" to get the monthly payment for a 30-year mortgage.
Example 2: Inventory Management Using Flex Remoting: This second example is more sophisticated and includes database connectivity. To keep the application simple and avoid dependencies on other products or frameworks, the Spring JDBC abstraction framework is used to access the database. You could use the Spring support for ORM data access (using Hibernate, JDO, Oracle TopLink, iBATIS, or JPA) as an alternative: the specific Spring data access strategy you choose has no impact on the Flex/Spring integration. This sample application has two modules: a database maintenance module (storeadmin) and a customer-facing product catalog with filtering capabilities (store).
- Step 1: Examine the application source code Examine the Flex source code: Open store.mxml located in /flex-spring/samples/store/flex in a code editor to familiarize yourself with the store application. Notice the RemoteObject declaration pointing to the "productService" destination. "productService" is mapped to a Spring bean in Step 3 below. When the application starts, it invokes the findAll() method on the remote bean to retrieve the list of products (see the createComplete event on the Application tag). Open storeadmin.mxml and ProductForm.mxml located in /flex-spring/samples/store/flex in a code editor to familiarize yourself with the storeadmin application. Notice that the storeadmin application uses the same remote Spring bean (productService) as the store application to retrieve the list of products using the findAll() method, and update changes using the updateProduct() method. Examine the Java source code: Open ProductDAO.java, SimpleProductDAO.java and Product.java located in /flex-spring/samples/store/java in a code editor. Notice that SimpleProductDAO extends org.springframework.jdbc.core.support.JdbcDaoSupport. JdbcDaoSupport has a dependency to a javax.sql.DataSource object (javax.sql.DataSource is an interface).
- Step 2: Register Spring beans Register the dataSource and productDAOBean beans in applicationContext.xml as follows: Copy hsqldb.jar from blazeds/tomcat/webapps/samples/WEB-INF/lib to /blazeds/tomcat/webapps/blazeds/WEB-INF/lib.
- Step 3: Configure the Flex Remoting destination Open remoting-config.xml in /blazeds/tomcat/webapps/blazeds/WEB-INF/flex. Add the productService destination as follows: spring productDAOBean
- Step 4: Build the project Edit /flex-spring/samples/store/build.xml: Make sure the FLEX_HOME property points to the location of the Flex SDK on your system. Make sure the CONTEXT_ROOT property matches the context root of your web application. Open a command prompt. Navigate to /flex-spring/samples/store. Execute the following command to compile and deploy the client-side and the server side of the application: ant The build process deploys the client-side of the store and storeadmin applications in /blazeds/tomcat/webapps/blazeds/store and /blazeds/tomcat/webapps/blazeds/storeadmin respectively, and the server-side (the compiled Java classes) in /blazeds/tomcat/webapps/blazeds/WEB-INF/classes/flex/samples/spring/store.
- Step 5: Run the client application Restart Tomcat Open a browser, access http://localhost:8400/blazeds/storeadmin/index.html, and test the storeadmin application. Open a browser, access http://localhost:8400/blazeds/store/index.html, and test the store application.
If you're a maven user, you may eliminate the ramp-up time by using my Spring Hibernate Maven Archetype (and have a sample app running in 3 command lines)
see : http://www.jroller.com/francoisledroff/entry/a_blazeds_xdoclet_spring_hibernate
Posted by: François | 26 May 2008 at 10:45
Add hibernate into the mix, and you'll definitely have my attention :)
Posted by: John | 16 June 2008 at 21:36
Thanks man, it was really usefull for me. Specially because when I readed it, I understand that you know what you are writing, and it helps me to understand some concepts of BlazeDS and Spring Container (I'm a newbie in java and flex, i'm coming from c#... yes... ioc is pretty new for me).
Posted by: Gualivchenko | 20 June 2008 at 14:47
Hi,
I developed a chat application using the following.
- Blaze DS turnkey 3-0-0-544
- the embedded Tomcat server with Blaze DS turnkey.
While sending message I am getting the following error.
Channel.Security.Error error Error #2048:
Security sandbox violation:
http://servername/apache2-default/chat.swf
cannot load data from
http://sez-ws-19:8400/blazeds/messagebroker/amfpolling. url: 'http://sez-ws-19:8400/blazeds/messagebroker/amfpolling'
I am compiling the application using the following xml file.
-services "C:\blazeds_turnkey_3-0-0-544\tomcat\webapps\blazeds\WEB-INF\flex\services-config.xml" -locale en_US
In the services-config.xml, the Channel definition is given as
false
true
4
The Application path is D:\Projects\Glasnost\chat
The Root URL of the application "http://sez-ws-19/".
Can you please provide a suggestion how to compile the application in the local and make it run in the linux server.
Anil
Posted by: Anil(aK) | 19 September 2008 at 07:09