Rapid Server Side Development for Flex RIA using SpringFuse and BlazeDS

flex-loginRapid Flex RIA development using Spring-BlazeDS and SpringFuse for Spring/Hibernate Dummies
Last March, I decided to develop a new product after a friend talked to me about an opportunity for a new SaaS product in the video post-production market. Flex was a perfect candidate for the UI but I did not know what back-end to use. Even If I have a long experience in Java and Flex, I am mainly a UI designer and developer and I needed to learn the back-end side.
Eventually, I found a very good solution built around Spring Framework and a code generation tool (SpringFuse) which I want to share. So this article is mainly for people that want to implement a Spring back-end for a Flex web application but don’t want/have no time to be a specialist in this area, but still want a solid back-end (especially for security)
Working example is available for download at the end of the article, there is an eclipse flex project and a maven project for the web server.
note: To understand this article you must have Flex and Java experience
So I was looking for a back-end technology,preferably Java-based because I know Java very well. I had no experience in setting such a thing and I was getting ready for a long road to learn a new framework, fight with configuration files, build an automatic process, write all the DB accesses, etc. I was looking at Spring and its very nice integration with BlazeDS to allow remote object invocation, when a friend of mine told me about his latest SaaS product: SpringFuse. I jumped into it, and 6 month later I can say that it saves me months of work and that I have a solid back-end that follows best practices.
So what is SpringFuse ? Basically, it is a code generation tool, you give a database schema as input and you get in return a complete Spring-based project for you back-end. When I say complete it is really complete:
Maven2 build process (that provide you with a ready to use Web server -jetty to name it)
Spring configuration (including security that uses the DB)
Hibernate-based classes to access your DB efficiently
Jsp-based web interface to access you DB (if you want to use it, but it is also usefull as examples)
It is important to note that all the generated files (java and configuration files) are well commented and uses best practices which allow you to learn by examples. You may also be interested by the price: if you database schema has no more than 10 tables it is free, else it is $249 for 1 month pass.
Ok, I stop my marketing speech for SpringFuse…Let’s jump into the subject of this article.
So the goal of this article is to show you how to use a SpringFuse generated project with a Flex app to speed up your RIA development. It was a little bit tricky to do for me at first, especially because I did not know Spring and Maven. So I gonna share with you how I did that through a simple example.
I use the “quickstartdb” exampleprovided by SpringFuse and adapt it to be able to use it via a Flex app. The project is very simple: users can logged in and create,delete and update text documents. You can have a look at it (especially the DB shema) in this SpringFuse page http://www.springfuse.com/documentation/getting-started-tutorial.action
To illustrate with images, the Flex UI looks like this.
Adding Spring-BlazeDS support to Spring Fuse generated project
The first thing is to add support for BlazeDS. As stated on the BlazeDS web site, “BlazeDS is the server-based Java remoting and web messaging technology that enables developers to easily connect to back-end distributed data and push data in real-time to Adobe® Flex® and Adobe AIR™ applications”.”
Spring provides a nice integration of BlazeDS, Spring-BlazeDS (or sometimes called Flex-Spring), with a very good support and nice examples and tutorials (thanks Jeremy!)
So here are the steps you need to do to add BlazeDS support. Note that if you look into the configuration of the provided project , I’ve added a comment with the string “Spring-BlazeDS” above all changes I made so that you can find them easily.
—Maven Configuration file (build process)
location: quickstardb/pom.xml.
add the Spring-BlazeDS dependency to your files
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><dependency></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><groupId>org.springframework.flex</groupId></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><artifactId>spring-flex</artifactId></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><version>1.0.1.RELEASE</version></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></dependency></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
disable the Hibernate optimization (cache level 2 and query cache). This is not because of BlazeDS but because in the example I use the minimal code to access the DB via hibernate.
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><hibernate.use.second.level.cache>false</hibernate.use.second.level.cache></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><hibernate.use.query.cache>false</hibernate.use.query.cache></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
———–Adobe BlazeDS configuration files
location: BlazeDS_SpringFuse/src/main/webapp/WEB-INF/flex/ folder
BlazeDS needs some configuration files especially to configure the channel that will be used by Flex client and BlazeDS to communicate (which URL is messagebroker/amf in our example).You must create this folder and add the needed configuration files.
If you want to know more about these configuration files, check the Spring-Blaze DS and BlazeDS documentation.
———-web.xml configuration
location: BlazeDS_SpringFuse/src/main/webapp/WEB-INF/web.xml
in web.xml you must add support for requests that the Flex clients will post to the server. The URL of the requests has been defined in the BlazeDS configuration files: it is messagebroker/amf.
add servlet mapping for the Flex requests so that these requests are handled by Spring
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><servlet-mapping></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><servlet-name>springmvc</servlet-name></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><url-pattern>/messagebroker/*</url-pattern></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></servlet-mapping></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
add filter mapping to support security since we want to authenticate users
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><filter-mapping></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><filter-name>springSecurityFilterChain</filter-name></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><url-pattern>/messagebroker/*</url-pattern></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><dispatcher>FORWARD</dispatcher></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><dispatcher>REQUEST</dispatcher></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></filter-mapping></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
add filter mapping to support hibernate sessions ?? to check with nicolas
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><filter-mapping></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><filter-name>openEntityManagerInViewFilter</filter-name></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><url-pattern>/messagebroker/*</url-pattern></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><dispatcher>FORWARD</dispatcher></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><dispatcher>REQUEST</dispatcher></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></filter-mapping></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
———-Spring Configuration Files
location: BlazeDS_SpringFuse/src/resources/spring/ folder
SpringFuse uses several files to configure Spring.
—in applicationcontext.xml, you must:
add specific namespaces for Spring-BlazeDS (check the header of the file)
add the Spring-Blazeds message broker bean with a secured channel (because we want to allow access to BlazeDS only to authenticated users), and disable default mapping (because we want also the springfuse jsp based to be functionnal)
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><flex:message-broker disable-default-mapping="true" ></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><flex:secured ></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><flex:secured-channel channel="my-amf" access="ROLE_ADMIN,ROLE_USER"  /></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></flex:secured><span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></flex:message-broker></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
add a Spring bean (a java class) and set it as a BlazeDS remote object. In others words, the java methods of this class will be available to authentifcated Flex clients.
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><bean id="DocumentManagerRO"/></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><flex:remoting-destination ref="DocumentManagerRO" /></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
in spring-mvc.xml
add an url mapping to route the request to Spring-BlazeDS bean (aka the messageBroker)
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><bean></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><description></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Maps request paths to BlazeDS</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></description></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><property name="order" value="0" /></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><property name="mappings"></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><value></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>amf=_messageBroker</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></value></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></property></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><property name="interceptors" ref="interceptorChain"/></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"></bean></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
One More Thing
SpringFuse uses Hibernate filtering to allow an account to only access its data. This create a problem when one tries to log using BlazeDS because there is no account in the session yet, and thus Spring Security cannot see any account and fails. To handle this, one must modify a SpringFuse generated java class to disable filtering when nobody is logged and the request is for BlazeDS (don’t worry it does not mean that you can access the remote object when you are not logged since the channel is secured, it is only to support the logging process of BlazeDS)
so in you must add a little bit of code in /BlazeDS_SpringFuse/src/main/java/com/contextuel/springblazeds/web/interceptor/HibernateFilterInterceptor.java
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>// Spring-BlazeDS integration</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>// if the authentification is not done yet, we must disable the hibernate filters so that hibernate</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>//can access to all accounts to verify the credentials   <span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if (request.getRequestURI().contains("messagebroker/amf") &&</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>SpringSecurityContext.getUserDetails() == null) <span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>return true;<span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>hibernateFilterContext.enableFilters();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>return true;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
======Flex and Java Implementation
Now that the SpringFuse generated project support Spring-BlazeDS, let’s have a look a the Flex client and Java server implementation.
Communication between Flex Client and Java Server via BlazeDS Basics
Basically, once Flex client is authenticated, Flex is able to call methods on the java class we have declared as remote object (DocumentManagerRO.java) previously. BlazeDS converts automatically java objects to actionscript objects (and vice-versa) to allow smooth communications. The mapping of is relatively straightforward (check the BlazeDS documentation for more details on this). When you want BlazeDS to map a specific business object, it is also relatively easy to do.
In our example, we use one business object which represent a document.
you can find the java class at
/BlazeDS_SpringFuse/src/main/java/com/contextuel/springblazeds/blazeds/Document.java (in the springfuse generated project),
and the actionscript class is src/com/contextuel/springfuseflex/Document.as (in the flex project)
For the mapping to be done, you have to tell BlazeDS which class to use for the mapping. You do this by including a tag in the actionscript file to specify the java class. In our example it is:
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">[RemoteClass(alias="com.contextuel.springblazeds.blazeds.Document")]</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Java Remote Object (Server Side)
I only implemented two java classes on the server side (located in the package com/contextuel/springblazeds/blazeds)
The first one is the business object Document.java that we have seen before
The second one is the the remote object that can be called from Flex Client : DocumentManagerRO.java
As you will see the implementation of the remote object is straightforward. It is because it uses the SpringFuse generated classes. Basically, we use the SpringFuse data model and managers and then when we need to send documents to the Flex clients, we convert the SpringFuse document (DocumentModel.java) to our own Document object (Document.java) which is understood and optimized for BlazeDS.
Note that one don’t want to use the SpringFuse data model to communicate with Flex client because it is not a lightweight object and we cannot control it as we want.
For example look at the code that allow to save a document
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">/**</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">* Create a new document for the account of the current session.<BR></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">* Flex client calls this method and in return receives the newly created</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">* document in the DB</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">*</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">* @return a new document created for the account of the current session</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">*/</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">public Document newDocument() throws Exception {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>try {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>//first we create a SpringFuse DocumentModel and assign account and default values</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>DocumentModel document = new DocumentModel();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>document.setAccount(getAccount());</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>document.setDocumentFileName("New Document");</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>document.setDocumentContentType("not used");</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>String str = "Enter your text";</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>document.setDocumentSize(str.getBytes().length);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>document.setDocumentBinary(str.getBytes());</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>// save the document into the DB to get an id immediatly</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>//we use the DocumentManager created by SpringFuse, it handles all the hibernate stuff</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>getDocumentManager().save(document);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>//eventually convert the DocumentModel object to a Document object that can be handled by BlazeDS</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>return createDocumentForBlazeDSFromModel(document);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>} catch (Exception e) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>logger.debug("Exception while creation a new document for account id="</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>+ getAccount().getAccountId(), e);</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>throw e;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">/**</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">* Convert a DocumentModel (which is the class generated by SpringFuse) to</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">* an Document (which is the java class that BlazeDS know how to translate to an actionscript class)<BR></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">*</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">*</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">* @param p_documentModel the document model</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">* @return a Document that correspond to the DocumentModel</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">*/</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">private Document createDocumentForBlazeDSFromModel(DocumentModel p_documentModel) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>Document bo = new Document();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>bo.setId(p_documentModel.getDocumentId());</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>bo.setName(p_documentModel.getDocumentFileName());</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>byte[] documentBinary = p_documentModel.getDocumentBinary();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if (documentBinary != null)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>bo.setContent(new String(documentBinary));</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>else</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>bo.setContent("");</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>return bo;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
The remote object class is located at /BlazeDS_SpringFuse/src/main/java/com/contextuel/springblazeds/blazeds/DocumentManagerRO.java
To make it easier to understand I’ve put a lot of comments in the class. So have a look at it to understand how it works.
Flex Client
There’s is not a lof thing to tell about the Flex client, a lot of good examples are coming with the Spring-BlazeDS distribution (testdrive examples).
I just describe the 3 files and highlight important things about the communication with BlazeDS.All files are in the com/contextuel/springfuseflex/ package.
Document.as : we have seen this one above. The important thing is the declaration of the remote java class used ( [RemoteClass(alias="com.contextuel.springblazeds.blazeds.Document")])
MainComponent.xml: it is the Flex UI but it also contains the declaration of the remote object on the client side.
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><!-- The remote object that we use to communicate with the server via BlazeDS</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span> Note that the destination property value (DocumentManagerRO) corresponds to the flex remoting destination that is defined on server side</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span> in the the BlazeDS_SpringFuse/src/resources/spring/applicationcontext.xml --></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span><mx:RemoteObject id="DocumentManagerRO" destination="DocumentManagerRO" fault="faultHandler(event)" showBusyCursor="true"/></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
Main.as : it is the actionscript code that is included in mainComponent.xml. It contains all calls to the server which are done via the RemoteObject declared above. The channel is initialized once the application is loaded, and then we wait the user to logged in.
-Next
This is a small example of how you can obtain a RIA with authentication based around Flex and Spring thanks to SpringFuse without having a good knowledge of Spring (and no knowledge at all about hibernate). Of course, you will need to learn some Spring stuff to do an advanced project, but for me using SpringFuse was really a nice starting point for me and save me a lot of work.
Note that I tried to keep the example simple as possible and thus the design of the client server is not ideal (for example you may want to prevent to download the document content for not yet opened document…). Also I recommend you to use the Mate framework for you Flex client which is very nice and useful (here you can find a tutorial to use Mate with BlazeDS).
If you don’t have checked yet the wonderful examples that comes with the Spring BlazeDS releases. You must have a look. You can find this on the Spring-BlazeDS web page.
Link:
Spring-BlazeDS
BlazeDS
SpringFuse
=====Download the projects
Eclipse Flex Project
you must have Flex Builder 3 installed
SpringFuse Project with support for BlazeDS
It is Maven based but you can import it in eclipse using the http://m2eclipse.sonatype.org/ plugin
launch the project using the following command: mvn -Ph2 jetty:run

Earlier this year, I decided to develop a new product after a friend talked to me about an opportunity for a new SaaS product in the video post-production market. Flex was a perfect candidate for the UI but I did not know what back-end to use. Even If I have a long experience in Java and Flex, I am mainly a UI designer and developer and I needed to learn the back-end side.

I found a very good solution built around Spring Framework using a code generation tool (SpringFuse) which I want to share because I found it very handy. So this article is mainly

  • For people that want to implement a java based back-end for a Flex web application with authentication but are novice to Spring and Hibernate
  • Since a full project is also provided with this article, some people may also be interested by this (you can find download links at the end of the article)

Note: in this article, I assume that you have some Flex and Java experience (since Spring is Java based)

So I was looking for a back-end technology,preferably Java-based because I know Java very well. I had no experience in setting such a thing and I was getting ready for a long road to learn a new framework, fight with configuration files, build an automatic process, write all the DB stuff, etc. I was looking at Spring and its very nice integration with BlazeDS to allow remote object invocation from Flex, when a friend of mine told me about his latest SaaS product: SpringFuse. I jumped into it, and 6 month later I can say that it saves me months of work and that I have a solid and secure back-end that follows best practices.

So what is SpringFuse ? Basically, it is a code generation tool, you give a DB schema as input and you get in return a complete Spring-based project for you back-end . When I say complete it is really complete:

  • Maven2 build process (that is also configured with a ready to use Web server – Jetty to name it)
  • Spring configuration (including Security configuration that uses the DB)
  • Hibernate-based classes to access your DB efficiently (but you don’t need to know Hibernate since some high-level managers are generated)
  • Jsp-based web interface to access your DB (if you want to use it, but it is also very usefull as example)

It is important to note that all the generated files (java and configuration files) are well commented and uses best practices which allow you to learn by example . You may also be interested by the price: if you database schema has no more than 10 tables it is free, else it is $249 for 6 month pass (so you’ve got the time to regenerate the project when you need to add some DB tables).

So the goal of this article is to explains  how to use a SpringFuse generated project with a Flex application to speed up your RIA development. It was a little bit tricky to do for me at first, especially because I did not know Spring and Maven. So I gonna share with you how I did that through a simple example.

As project example, I use the “quickstartdb” example provided by SpringFuse . Originally this example only provides a jsp based web interface to access the DB with authenfication, in this article I show how to add a simple Flex interface to do the same thing. The example is very simple: users can logged in, and then create,delete and update text documents. You can have a look at the page that describe this example -without Flex support – in this SpringFuse page.

To illustrate with images, the Flex UI of the example looks like this:

flex-login

flex-logged

Adding BlazeDS support to SpringFuse generated project

The first thing is to add support for BlazeDS. As stated on the BlazeDS web site, “BlazeDS is the server-based Java remoting and web messaging technology that enables developers to easily connect to back-end distributed data and push data in real-time to Adobe® Flex® and Adobe AIR™ applications”.

Spring provides a nice integration of BlazeDS, Spring-BlazeDS (sometimes called Spring-Flex), with a very good forum support and nice examples and tutorials coming with the release.

So here are the steps you need to do to add Spring-BlazeDS support. Note that if you look into the configuration of the provided project , I’ve added a comment with the string “Spring-BlazeDS” above all changes I made so that you can find them easily.

Maven Configuration file (build process)

Location (in the project attached to this article) : BlazeDS_SpringFuse/pom.xml.

Add the Spring-BlazeDS dependency to your files

<dependency>
	<groupId>org.springframework.flex</groupId>
	<artifactId>spring-flex</artifactId>
	<version>1.0.1.RELEASE</version>
</dependency>

Disable the Hibernate optimization (cache level 2 and query cache). This is not because of BlazeDS but because in the example I use minimal code to access the DB via hibernate (if you use cache level 2 you need more code, you can check in the SpringFuse jsp example how to do it).

<hibernate.use.second.level.cache>false</hibernate.use.second.level.cache>
<hibernate.use.query.cache>false</hibernate.use.query.cache>

Adobe BlazeDS configuration files

Location: BlazeDS_SpringFuse/src/main/webapp/WEB-INF/flex/ folder

BlazeDS needs some configuration files especially to configure the channel that will be used by Flex client and BlazeDS to communicate (which URL is messagebroker/amf in our example).You must create this folder and add the needed configuration files.

If you want to know more about these configuration files, check the Spring-Blaze DS and BlazeDS documentation.

web.xml configuration

Location: BlazeDS_SpringFuse/src/main/webapp/WEB-INF/web.xml

In web.xml you must add support for requests that the Flex clients will post to the server. The URL of the requests have been defined in the BlazeDS configuration files: it is messagebroker/amf.

Add servlet mapping for the Flex requests so that these requests are handled by Spring

<servlet-mapping>
	<servlet-name>springmvc</servlet-name>
	<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

Add filter mapping to support security since we want to authenticate users

<filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/messagebroker/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
</filter-mapping>

Add filter mapping that automatically open hibernate sessions for requests

<filter-mapping>
        <filter-name>openEntityManagerInViewFilter</filter-name>
        <url-pattern>/messagebroker/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
</filter-mapping>

Spring Configuration Files

Location: BlazeDS_SpringFuse/src/resources/spring/ folder

SpringFuse uses several files to configure Spring.

  • in applicationcontext.xml:

Add specific namespaces for Spring-BlazeDS (check the header of the file)

Add the Spring-Blazeds message broker bean with a secured channel (because we want to allow access to BlazeDS only to authenticated users), and disable default mapping (because we want also the springfuse jsp based interface to be functionnal)



<flex:message-broker disable-default-mapping="true" >
	<flex:secured >
		<flex:secured-channel channel="my-amf" access="ROLE_ADMIN,ROLE_USER"/>
	</flex:secured>
</flex:message-broker>

Add a Spring bean (a java class) and set it as a BlazeDS remote object. In others words, the java methods of this class will be available to authentifcated Flex clients.


<bean id="DocumentManagerRO"
	class="com.contextuel.springblazeds.blazeds.DocumentManagerRO"/>

<flex:remoting-destination ref="DocumentManagerRO" />
  • in spring-mvc.xml

Add an url mapping to route the request to Spring-BlazeDS bean (aka the messageBroker)


<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	<description>
            Maps request paths to BlazeDS
	</description>
	<property name="order" value="0" />
	<property name="mappings">
		<value>
		amf=_messageBroker
		</value>
	</property>
	<property name="interceptors" ref="interceptorChain"/>
</bean>

One More Thing

SpringFuse uses Hibernate filtering to prevent an account to access others accounts data. This create a problem when one tries to log using BlazeDS because there is no account in the session yet, and thus Spring Security cannot see any account in the DB and fails. To handle this, one must modify a SpringFuse generated java class to disable filtering when nobody is logged and the request is for BlazeDS (don’t worry it does not mean that you can access the remote object when you are not logged in since the channel is secured, it is only to support the logging process of BlazeDS)

So  you must add a little bit of code in the “prehandle” method of HibernateFilterInterceptor.java (in package java/com/contextuel/springblazeds/web/interceptor)


public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
	 Object handler) throws ServletException {

	// Spring-BlazeDS integration
	// if the authentification is not done yet,
	// we must disable the hibernate filters so that hibernate
	//can access to all accounts to verify the credentials
	if (request.getRequestURI().contains("messagebroker/amf") &&
			SpringSecurityContext.getUserDetails() == null)
		return true;

	hibernateFilterContext.enableFilters();

	return true;
    }

Flex and Java Implementation

Now that the SpringFuse generated project support BlazeDS, let’s have a look a the Flex client and Java server implementation.

Communication between Flex Client and Java Server via BlazeDS Basics

Basically, once Flex client is authenticated, Flex is able to call methods on the java class we have declared as remote object previously (DocumentManagerRO.java). BlazeDS converts automatically java objects to actionscript objects (and vice-versa) to allow smooth communications. The mapping used to do the mapping is relatively straightforward (check the BlazeDS documentation for more details on this).

When you want BlazeDS to map a specific actionscript object to a specific java object, it is also relatively easy to do. In our example, we use one business object which represent a document.

you can find the java class at

java/com/contextuel/springblazeds/blazeds/Document.java (in the springfuse generated project),

and the actionscript class at

src/com/contextuel/springfuseflex/Document.as (in the flex project)

For the mapping to be done, you have to tell BlazeDS which class to use for the mapping. You do this by including a tag in the actionscript file to specify the java class. In our example it is:


[RemoteClass(alias="com.contextuel.springblazeds.blazeds.Document")]

Java Remote Object (Server Side)

I only implemented two java classes on the server side (located in the package com/contextuel/springblazeds/blazeds)

The first one is the business object Document.java that we have seen above.

The second one is the the remote object that can be called from Flex Client : DocumentManagerRO.java

As you will see the implementation of the remote object is straightforward. It is because it leverages the SpringFuse generated classes. Basically, we use the SpringFuse data model and managers and when we need to send documents to the Flex clients, we convert the SpringFuse document (DocumentModel.java) to our own Document object (Document.java) which is understood and optimized for BlazeDS.

Note that one doesn’t want to use the SpringFuse data model to communicate with Flex client because it is not a lightweight object and we cannot control it as we want.

For example look at the code that allow to create  a document


/**
* Create a new document for the account of the current session.<BR>
* Flex client calls this method and in return receives the newly created
* document in the DB
*
* @return a new document created for the account of the current session
*/
public Document newDocument() throws Exception {

	try {
		//first we create a SpringFuse DocumentModel
		//and assign account and default values
		DocumentModel document = new DocumentModel();
		document.setAccount(getAccount());
		document.setDocumentFileName("New Document");
		document.setDocumentContentType("not used");
		String str = "Enter your text";
		document.setDocumentSize(str.getBytes().length);
		document.setDocumentBinary(str.getBytes());

		// save the document into the DB to get an id immediatly
		//we use the DocumentManager created by SpringFuse,
		//it handles all the hibernate stuff
		getDocumentManager().save(document);

		//eventually convert the DocumentModel object to
		//a Document object that can be handled by BlazeDS
		return createDocumentForBlazeDSFromModel(document);
		} catch (Exception e) {
			logger.debug("Exception while creation a new document for account id="
			+ getAccount().getAccountId(), e);
			throw e;
	}
}

/**
* Convert a DocumentModel (which is the class generated by SpringFuse) to
* an Document (which is the java class that BlazeDS know how to translate to
* an actionscript class)<BR>
*
*
* @param p_documentModel the document model
* @return a Document that correspond to the DocumentModel
*/
private Document createDocumentForBlazeDSFromModel(DocumentModel p_documentModel) {

	Document bo = new Document();
	bo.setId(p_documentModel.getDocumentId());
	bo.setName(p_documentModel.getDocumentFileName());

	byte[] documentBinary = p_documentModel.getDocumentBinary();
	if (documentBinary != null)
		bo.setContent(new String(documentBinary));
	else
		bo.setContent("");

		return bo;
}
The remote object class is located at /java/com/contextuel/springblazeds/blazeds/DocumentManagerRO.java

To make it easier to understand I’ve put a lot of comments in the class. So have a look at it to understand how it works.

Flex Client

There’s is not a lof thing to tell about the Flex client, a lot of good examples are coming with the Spring-BlazeDS distribution (testdrive examples).

I just describe the 3 files and highlight important things about the communication with BlazeDS. All files are in the com/contextuel/springfuseflex/ package.

Document.as : we have seen this one above. The important thing is the declaration of the remote java class used ( [RemoteClass(alias="com.contextuel.springblazeds.blazeds.Document")])

MainComponent.xml: it is the Flex UI but it also contains the declaration of the remote object on the client side.


<!--
The remote object that we use to communicate with the server via BlazeDS
Note that the destination property value (DocumentManagerRO) corresponds
to the flex remoting destination that is defined on server side
in the the BlazeDS_SpringFuse/src/resources/spring/applicationcontext.xml
-->
<mx:RemoteObject id="DocumentManagerRO" destination="DocumentManagerRO"
	fault="faultHandler(event)" showBusyCursor="true"/>

Main.as : it is the actionscript code that is included in mainComponent.xml. It contains all calls to the server which are done via the RemoteObject declared above. The channel is initialized once the application is loaded, and then we wait for the user to logged in.

Next

This is a small example of how you can obtain a RIA with authentication based around Flex and Spring thanks to SpringFuse without having a good knowledge of Spring (and no knowledge at all about hibernate). Of course, you will need to learn some Spring stuff to do an advanced project, but for me using SpringFuse was really a nice starting point for me and save me a lot of work.

Note that I tried to keep the example simple as possible and thus the design of the client server is not ideal (for example you may want to prevent to download the document content for not yet opened document…). Also I recommend you to use the Mate framework for you Flex client which is very nice and useful (here you can find a tutorial to use Mate with BlazeDS).

If you don’t have checked yet the examples that comes with the Spring BlazeDS releases, you must have a look since there is a lot of interesting things.

Links:

Spring-BlazeDS

BlazeDS

SpringFuse

Download the Projects

To import the Flex project into Flex Builder, use File/Import/Flex Project and select the appropriate folder. You may need to change the Flex Server/Root Folder settings (via Project/Properties/Flex Server/Root Folder), it must point to the webapp folder location of your SpringFuse project (i.e. …./BlazeDS_SpringFuse/src/main/webapp)

This is the SpringFuse generated project modified for our example. The project uses Maven2 to be built. if Maven2 is not configured on your computer, check the SpringFuse tutorial in this SpringFuse page which explain how install Maven2 (For mac users , you may install MacPorts and then use the following command from Terminal “sudo port install maven2″ to install Maven2 )

Launch the Maven build process using the following command when you are in the root folder of the project (the folder that contains the pom.xml file)

mvn -Ph2  jetty:run

Once Maven has built everything and has launched the Jetty Web Server, connect to the Flex application at

http://localhost:8090/FlexSpringFuse/FlexSpringFuse.html

then use the server/server account or demo/demo account (these are the default accounts, other accounts can be created in the DB). The project already contains the compiled Flex app (swf file) so it will work even if you have not compiled the Flex project.

Note that if want to check the code, you can import the Maven project in Eclipse using the following plugin http://m2eclipse.sonatype.org/

Update: there are some interesting comments on the related article I wrote on Adobe Cookbook

This entry was posted in Articles and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>