Integrating Parsley into a Basic Flex Application
I have recently started working with Lab49 and will be assisting one of their clients with some Parsley integration on a legacy Cairngorm application. This means I have to learn Parsley, so the following is a brain dump / example of what I have picked up so far.
Please keep in mind that this article is primarily an explanation of a client side Flex framework named Parsley and it assumes that the reader has some knowledge of BlazeDS/AMF/Java/Maven and that they are primarily concerned with learning something about Parsley and it's integration points with regards to Flex.
I started by reading the documentation here. This was a great primer but I felt as though I needed to try to use some of it to actually feel like I know it well. My colleague at Lab49 Marcin Staszyszyn helped ensure that the steps below actually work, thanks to him for checking my work.
Please also note that the examples below are based on the directory structure in this image. It may be confusing to read without noting that the article is specifically focused on the "commons-user-flex-client" module in the project. There are more modules in this project that are not discussed in the article or examples.

Afterwards I identified a few items that appeared to be necessary when implementing a Parsley based application and those items are the following:
- Dependency Injection
- Managed Events
- Dynamic Commands
- Messaging
The application I am using to extend is a simple grid application for managing contacts. It really has no practical use whatsoever but is a full stack application in that it talks to a Java based AMF service layer hooked into Hibernate / SQLLite backed persistence layer.
To build the application it is required that you have Maven 2.2.0 installed on your machine and in your path. Please follow instructions below to make sure that is done to satisfaction: http://maven.apache.org/download.html please notice the directions all the way at the bottom of the screen.
Unzip the tar ball with
tar –zxvf parsley-integration.tar.gz
Copy the parsley-integration/settings.xml into your your ~/.m2/ directory for Mac OS or for Windows it is your C:\Documents and Settings\username\.m2 directory or C:\Users\username\.m2 directory
To build the application:
1 2 3 4 | cd parsley-integration mvn clean install –DskipTests=true cd commons-user-webapp mvn cargo:start |
This should build the application, ignore test cases, and then start tomcat
You should now be able to browse to the application via this URL:
http://localhost:8080/commons-user-webapp/
You should see something like this:

Dependency Injection
To leverage the dependency injection features of parsley one must follow a few steps:
- Define a spring-like application context via one of the three methods available via parsley’s API: http://www.spicefactory.org/parsley/docs/2.2/manual/config.php#mxml
- Define dependencies on each object that needs them
- Ensure that each object is managed by using the Configure tag
Step one
Step one was extremely clear in that all that is required is to define an application context, mine looks like this: (ApplicationContext.xml)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?xml version="1.0"?> <mx:Object xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:service="com.neosavvy.user.service.*" xmlns:parsley="http://www.spicefactory.org/parsley" xmlns:controller="com.neosavvy.user.controller.*" xmlns:model="com.neosavvy.user.model.*" > <model:UserModel/> <parsley:DynamicCommand type="com.neosavvy.user.controller.GetUsersCommand" selector="get"/> <parsley:DynamicCommand type="com.neosavvy.user.controller.SaveUserCommand" selector="save"/> <parsley:DynamicCommand type="com.neosavvy.user.controller.DeleteUserCommand" selector="delete"/> <mx:RemoteObject id="userService" destination="userService" showBusyCursor="true"> <mx:channelSet> <mx:ChannelSet> <mx:channels> <mx:AMFChannel url="http://localhost:8080/commons-user-webapp/messagebroker/amf"/> </mx:channels> </mx:ChannelSet> </mx:channelSet> </mx:RemoteObject> </mx:Object> |
It defines a model object to bind the presentation layer to, three commands for asynchronous activity, and a remote object to delegate to the Java layer for data requests.
Step two
I had to identify what objects needed to have dependencies and right now given the simplicity of the application the view components depend on the model and the context.
MainView.mxml is the best example of this as it can be seen in the
1 2 3 4 5 6 | [Inject] public var context:Context; [Bindable] [Inject] public var userModel:UserModel; |
My initial impression was that simply leveraging the [Inject] tag would be enough to configure / autowire the application. That is not the case, any time something is to be “managed” by Parsley it is left up to the developer to add step 3 to the mix.
Step three
Add the parsley namespace and call configure:
Add this to the top of the file in the namespaces
1 | xmlns:parsley=http://www.spicefactory.org/parsley |
Ensure that this appears in the MXML somewhere
1 | <parsley:Configure/> |
Managed Events / Dynamic Commands
Why would someone want to use this feature? I have to assume that in my case I am going to be replacing a heavy Event/Command pair driven architecture and this is the closest pattern to that in Parsley and I believe the DynamicCommand was inspired by Cairngorm 3.
These features caused me a bit of headache as the documentation indicated how they are to work, but after attempting to use this feature I was unable to easily make it work in the first two of three use cases I attempted initially.
Use cases:
- Dispatch an event from the creationComplete() method and have it be managed and responded to by a GetUsersCommand
- Dispatch an event from a modal popup and have it be responded to by a SaveUserCommand
- Dispatch an event from an item renderer and have it be responded to by a DeleteUserCommand
Use Case 1:
Dispatching a managed event from creationComplete() does not work! One must use the [Init] tag instead.
MainView.mxml contains the logic to dispatch this managed event. There are three steps required to enable this use case:
- Define the DynamicCommand as seen above in the Application context with the selector of type “get” (see ApplicationContext.xml)
1
<parsley:DynamicCommand type="com.neosavvy.user.controller.GetUsersCommand" selector="get"/> - Define the UserEvent and type as seen in UserEvent.TYPE_GET (see /com/neosavvy/user/event/UserEvent.as)
- Define the GetUsersCommand
- Define UserModel to ensure you have a place to store the result from the server call
- Add the metadata to the MainView.mxml to ensure that they are registered with Parsley’s internal message system
1 2 3 4
<mx:Metadata> [Event(name="get",type="com.neosavvy.user.event.UserEvent")] [Event(name="userModelChanged",type="com.neosavvy.user.event.UserEvent")] [ManagedEvents("get,userModelChanged")] </mx:Metadata>
It may be wise to also attempt to run the application to understand the flow of data.
Use Case 2
I needed to be able to inject dependencies into the popup window and this actually requires a bit of extra voodoo that I had to dig around in the documentation for. Specifically this code from MainView.mxml did the trick
1 2 3 4 5 6 | protected function showRegistrationLoginWindow():void { var regAndLoginWindow:RegistrationAndLoginWindow = new RegistrationAndLoginWindow(); context.viewManager.addViewRoot(regAndLoginWindow); PopUpManager.addPopUp(regAndLoginWindow as IFlexDisplayObject, this, true); PopUpManager.centerPopUp(regAndLoginWindow); } |
The third line above where the context.viewManager.addViewRoot() call occurs is the magic that makes it happen.
After doing this all of the injections and managed events began to work as they were part of the context and Parsley was aware of their existence, but without this Parsley has no knowledge of them and Commands will not respond to Managed Events as they are dispatched.
Use Case 3:
Dispatching events from item renderers was effectively very easy, but could be refactored a bit. I had the managed event declared on the renderer and then it was responded to by the command as expected. No extra configuration required.
Initial Impression
Public everywhere???? It seems like there is no way to declare private message handlers, which may seem obvious, but simply declaring something public allows for the lack of encapsulation since now anyone can call those methods without having to invoke a message. Also it is required that all dependencies are declared public otherwise they are going to be null when the application context is done wiring itself. This is not a requirement in spring which is what I was under the impression would be the basis for a framework like this.
Dependency Injection requires the manual intervention of the developer to make it work ie
Getting RIA Test / Maven / Flex Mojos to play nice
What is RIA Test
This tool is a for pay click test tool that records and plays back automated click tests. It can help streamline the testing process and reduce testing costs via automation and reduced numbers of QA team members.
Why should you read this article?
This article is relevant to you if you are using Flex Mojos to build your code and are interested in automated click testing. When I first attempted to setup RIA Test I noticed that the instructions lacked information about how to make it work for users who use ANT or Maven to build their code, likely because they don’t know that it is common practice to do so.
Assumptions
- You have a build process in Maven for your flex applications
- You are using Flex Mojos for the actual compilation process
- RIA Test is your desired agent for testing
- You are using a repository manager like Nexus for the Maven repository
- You are using Flex 3.4 or 3.5
Step 1 – Add necessary dependencies to Nexus
The automation libraries are required to embed and run the agent to record and playback the test scripts. You can find them on Adobe’s site here:
Flex 3.5: http://download.macromedia.com/pub/flex/sdk/automation_sdk3.5.zip
Flex 3.4: http://download.macromedia.com/pub/flex/sdk/automation_sdk3.4.zip
I was unable to locate any older libraries.
Unzip the files so that the folder structure looks like this:

All of these files except the ja_JP files need to be uploaded to your nexus repository. I will not cover that here but I have pasted the POM entries for how I uploaded my 3.5 libraries.
<dependency> <groupId>com.riatest</groupId> <artifactId>riatestagent</artifactId> <version>3</version> <type>swc</type> <scope>test</scope> </dependency> <dependency> <groupId>com.adobe.flex.framework</groupId> <artifactId>automation_rb</artifactId> <version>${flex.version}</version> <type>swc</type> <scope>test</scope> </dependency> <dependency> <groupId>com.adobe.flex.framework</groupId> <artifactId>automation_agent_rb</artifactId> <version>${flex.version}</version> <type>swc</type> <scope>test</scope> </dependency> <dependency> <groupId>com.adobe.flex.framework</groupId> <artifactId>automation</artifactId> <version>${flex.version}</version> <type>swc</type> <scope>test</scope> </dependency> <dependency> <groupId>com.adobe.flex.framework</groupId> <artifactId>automation_agent</artifactId> <version>${flex.version}</version> <type>swc</type> <scope>test</scope> </dependency> <dependency> <groupId>com.adobe.flex.framework</groupId> <artifactId>automation_dmv</artifactId> <version>${flex.version}</version> <type>swc</type> <scope>test</scope> </dependency> <dependency> <groupId>com.adobe.flex.framework</groupId> <artifactId>qtp</artifactId> <version>${flex.version}</version> <type>swc</type> <scope>test</scope> </dependency>
Step 2 – Add the dependencies to your pom.xml
Great now assuming you have them added to your repository, you can reuse that pom.xml section from above and place it in your top level pom file for your flex projects in the dependencyManagement section to ensure all children inherit the dependency.
Step 3 – Upgrade to Flex Mojos 3.6.1
This step could be problematic but it is relatively simple to test. First you will just need to locate your plugin configuration or the variable that controls what version of Flex Mojos you are using. You then need to change it from 3.4.0 to 3.6.1.
When I made this change I was using custom gas3 code generation and depended on graniteds1. I found some help here: https://docs.sonatype.org/display/FLEXMOJOS/Generator+Mojo#GeneratorMojo-flexmojos36
The main gist of it is that you need to have a separate plugin used for generation so you can override the default graniteds dependencies in 3.6.1. If you don’t use graniteds generation, then you won’t have to worry about this problem, but you could run into others. Please post in the comments if you have an issue as it would be great for others to benefit from your fix.
Step 4 – Compile the test swc
After the dependencies are set you should be able to run
mvn clean install flexmojos:test-swfon the project that you would like to create record playback scripts in. You will see a new artifact in the target directory with the word “test” as the classifier and you can then run that to connect to the RIA Test IDE.
Thanks for reading, I hope this short how-to is helpful and saves time for someone as I spent a few extra hours making this work in my scenario.
Cheers!
Continuous Integration with Jetty/Cargo/Maven/Bamboo
Recently I have had the pleasure of helping migrate a client to a maven build process where they wanted to also migrate to a Jetty container from a full blown JBoss application server. The decision to move to Jetty is probably wise as they don’t need all of the extras provided by JBoss as they aren’t really using all of them.
Regardless this move presented an interesting hurdle. One of the requirements that dictated success of the migration was successful remote deployment from a Bamboo continuous integration build environment on a windows server to a remotely deployed Jetty instance. The main crux of this setup is that Jetty does not support remote deployment natively. Also I chose to configure cargo’s remote deployer to handle the deployment in a push fashion. Luckily a kind person at Redhat has written a cargo remote deployer that can be deployed as a war file to the Jetty server. This deployer then allows the cargo maven plugin to push a file. The cargo hook however does not support the removal of the previously deployed artifact, so in a continuous integration environment trying to support a push button deploy won’t work – one has to cleanup after themselves.
Out solution was to use some functionality from JCSH to make a java client that can call a script on the Jetty server to delete the old artifact and restart the application server. The code to handle the remote call can be seen below and is admittedly hackish but definitely solved my problem in a few hours where I wasn’t necessarily granted the permission of infinite time to solve this problem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | import com.jcraft.jsch.Channel; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import com.jcraft.jsch.UserInfo; import java.io.*; public class RebootJetty { private static String DISC_STRING = "###### SERVER CLEANED #####"; private static String TEST_QA = "10.0.0.1"; private static String TEST_QA_PASSWORD = "password!"; private static String APP_QA_1 = "10.0.0.2"; private static String APP_QA_1_PASSWORD = "password2"; public static void main(String[] args) throws Exception { com.jcraft.jsch.JSch jsh = new JSch(); Session testSession = jsh.getSession("root", APP_QA_1 , 22); testSession.setConfig("StrictHostKeyChecking", "no"); testSession.setUserInfo(new MyUserInfo()); testSession.connect(10000); Channel channel = testSession.openChannel("shell"); channel.setInputStream(new StringBufferInputStream("/root/cleanupJetty.sh\n")); channel.connect(); PipedOutputStream pos = new PipedOutputStream(); channel.setOutputStream(pos); PipedInputStream pis = new PipedInputStream(pos); BufferedReader r = new BufferedReader(new InputStreamReader(pis)); String s = ""; while (s != null) { s = r.readLine(); System.out.println(s); if (s != null && s.indexOf(DISC_STRING) > -1) { channel.disconnect(); System.exit(0); } } System.exit(1); } public static class MyUserInfo implements UserInfo { public String getPassphrase() { return APP_QA_1_PASSWORD; } public String getPassword() { return APP_QA_1_PASSWORD; } public boolean promptPassphrase(String arg0) { return false; } public boolean promptPassword(String arg0) { return true; } public boolean promptYesNo(String arg0) { return false; } public void showMessage(String arg0) { } } } |
The Maven Cargo Plugin however was extremely helpful and was not extremely hard to configure however it doesn’t support all features equivalently in all application servers. Make sure to check your application server on their feature matrix for the scenario you are attempting to see if it even works out of the box. In my case they even advertise that it works, but after reading their Jira issues I noticed it is fixed in an alpha release of their plugin but advertised as working in their latest release…frustrating…
Cargo Feature Matrix for Jetty 6.x: http://cargo.codehaus.org/Jetty+6.x
You will need to make sure to download and build the war file to deploy to your target Jetty to support remote deployment. I found it here: http://svn.codehaus.org/cargo/resources/trunk/jetty-deployer/
To make the code above work I downloaded their entire trunk and built it locally, then I modified their war file to remove security settings so I wouldn’t have to setup a security realm in Jetty. Not sure how hard that really is, but given this is an internal continuous integration server I didn’t really care about deployment security as Bamboo would only allow secure uses to click the button to cause the deployment to occur. Other than that one of the 8 developers on the team would have to execute the maven profile to cause a deployment, and likely if one of them does it, then it probably needed to happen. Specifically the code I commented out was in here: http://svn.codehaus.org/cargo/resources/trunk/jetty-deployer/src/main/webapp/WEB-INF/web.xml I removed the login-constraint and the security-constraint.
Here is the code required to push a release to a remote running server instance. Just throw this in a profile in your pom or add the plugin to your build section if you prefer it run in your pom. I opted to use a profile so that I can enable it as necessary and others can use this same pom to build the WAR for normal use. There is another profile in use for a local deployment to Jetty which is way easier with cargo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <profile> <id>deploy-to-qa</id> <build> <plugins> <plugin> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <version>1.0.1-alpha-1</version> <configuration> <container> <containerId>jetty6x</containerId> <type>remote</type> <timeout>120000</timeout> </container> <configuration> <type>runtime</type> <properties> <cargo.hostname>172.1.0.1</cargo.hostname> <cargo.servlet.port>80</cargo.servlet.port> <cargo.remote.username>user</cargo.remote.username> <cargo.remote.password>pass</cargo.remote.password> </properties> </configuration> <deployer> <type>remote</type> <deployables> <deployable> <groupId>${project.groupId}</groupId> <artifactId>${project.artifactId}</artifactId> <type>war</type> </deployable> </deployables> </deployer> </configuration> </plugin> </plugins> </build> </profile> |
The final piece to the puzzle is likely the cleanupJetty.sh script that resides on the target server. This script simply stops jetty, deletes the war file deployed by cargo, then starts jetty again. It is called via a call into the JSCH program above from the windows box via command line (in Bamboo) and then after it completes it kicks off the maven build. Here is the contents of the script:
1 2 3 4 5 6 | #!/bin/bash /opt/jetty/bin/jetty.sh stop rm -rf /opt/jetty/webapps/NAME_OF_WAR /opt/jetty/bin/jetty.sh start sleep 20s echo "###### SERVER CLEANED #####" |
I sure hope this little tidbit helps someone out there as I did a lot of reading on forums and Jira bugs to figure out how to make this all work. If you have a similar setup please let me know as I am happy to help you out. Also please note that I will openly admit that the JCSH hook from a windows box into the bash script could arguably be considered a hack, but sometimes it just has to work.
Auto Filtering Grid and the Neosavvy Open Source Contribution
I have recently open sourced a very useful component that I have applied to a variety of problems over the past year. I have attempted to make this component as reusable as possible and as well encapsulated as I can. The use case is that one may need to filter down a large data set that is in a grid via a dropdown driven menu based approach. The component heavily leverages the functionality behind ArrayCollection's filterFunction.
I have published an example of the component here and the source code is available on google code
I will attempt to update the wiki on google code with examples of how to use it and also will add features as necessary.
High Level Features:
1) Support for groupedColumns and columns set as AdvancedDataGrid supports
2) Support to add and remove columns via a popup driven menu
3) Ability to define a super-set of columns in MXML and set some of them as default with a flag
4) Ability to filter data via menu driven drop downs
5) Externalized events to handle external reactions to internal grid events (like dependencies on column filters)
6) Ability to attach a search text control from an external location so that it can be placed anywhere on the screen and used to augment the filterFunction
7) Much more....
I plan to also expose a PickFilterGrid for community reuse which uses an auto-proxy method of wrapping all the objects in a dataprovider to expose a checkbox. Once those items are selected the non-proxied items are returned if necessary. This is useful when a use case for selecting items from a large data set is required to populate some smaller data set.
Enjoy!
Spring 3.0 Supports Spring Flex and Spring Security 3.0
This isn't a huge post but I just received notification from a JIRA issue I have been watching that Spring 3.0 and Spring Flex should place together now with Spring Security 3.0
https://jira.springsource.org/browse/FLEX-6
For those that were interested and sent in questions about how to make all this work it appears that the Spring guys should have it all packaged and released very soon.
Automating SVN Backups
Today I read a post on coding horror about catastrophic disk failure and thought to myself that I should wake up every day and think of some way to automate a piece of infrastructure to prevent myself from reaching a point of failure on losing important data.
So today I wrote a simple backup script for my svn repository and exposed the dumps via HTTPD in a directory alias.
1) The backup script:
#!/bin/bash startRepositoryRevision=0 latestRepositoryRevision=`svn info http://www.neosavvy.com/svn/neosavvy/ | grep Revision | cut -d " " -f 2| tr -d '\r'` /usr/bin/svnadmin dump /home/svn/neosavvy > /svndump/neosavvy.svn.dump.$startRepositoryRevision-$latestRepositoryRevision.$(date +%Y.%m.%d)
2) Crontab Entry: (crontab -e)
0 */4 * * * /root/bin/dumpNeosavvySvn.sh
3) Apache Directory Alias to expose it to some other automagic script that will download the files to another location
Alias /svndump /svndump <Directory /svndump> Options Indexes Order allow,deny Allow from all </Directory>
The dumps are available here: http://www.neosavvy.com/svndump/
That's it a short useful documentation of something I think will improve the infrastructure of things I work on every day. As I add to the script I will document the process in this post.
Thanks for reading.
Building a Simple Login Mechanism in Flex – Part 2 (Enabling Spring Security)
This guide is an extension to the previous post http://blog.neosavvy.com/wordpress/?p=18 that described how to build a simple Flex project with Maven and also create the necessary base to start securing simple features in an application with BlazeDS integrations provided by Spring-Flex.
Please note that all SVN Links are temporarily locked down - I apologize for the inconvenience but please find the source here: http://www.neosavvy.com/commons-user-blog-post.tar.gz
In this article we will address the following topics:
- Adding spring-security 2.0.5 as a dependency
- Adding spring-flex 1.0.1.RELEASE as a dependency
- Defining security with annotations on UserService with one role
- Making Login calls from Flex to secured services
- Making Logout calls from Flex to secured services
- Accessing user and authority information after a successful login call
Adding spring-security 2.0.5 and spring-flex 1.0.1.RELEASE is simple if your application uses Maven
Add the following dependencies to your top level pom.xml and also add them without versions to your WAR and JAR pom.xml files.
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <artifactId>com.springsource.javax.validation</artifactId> <groupId>javax.validation</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.flex</groupId> <artifactId>spring-flex</artifactId> <version>1.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${spring.security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core-tiger</artifactId> <version>${spring.security.version}</version> </dependency>
Spring-webmvc is used for its DispatcherServlet in the servlet.xml file and the javax.validation artifacts caused a ClassLoader issue when starting the WAR so it is excluded as a transitive dependency. The latest release of spring-flex is 1.0.1.RELEASE and is included as that version. The base spring-security classes are part of spring-security-core and the Java 1.5 compliant classes are part of spring-security-core-tiger. Without that library the @Secured() annotations will not work.
After the necessary dependencies are included securing the service is as simple as adding some annotations to the interface of the message broker exposed service that necessitates security.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | package com.neosavvy.user.service; import com.neosavvy.user.dto.UserDTO; import org.springframework.security.annotation.Secured; import java.util.List; public interface UserService { @Secured("ROLE_ADMIN") public List<UserDTO> getUsers(); public void saveUser(UserDTO user); @Secured("ROLE_ADMIN") public UserDTO findUserById(int id); @Secured("ROLE_ADMIN") public List<UserDTO> findUsers(UserDTO user); @Secured("ROLE_ADMIN") public void deleteUser(UserDTO user); public Boolean login(UserDTO user); public Boolean logout(UserDTO user); } |
Notice in the above class that all @Secured annotations at this time have a value of “ROLE_ADMIN” which means that the “ROLE_ADMIN” privilege is required when a user is looked up from the security DAO. More on this later.
The WAR configuration needs some modification to expose the services as secured services. This requires the use of DispatcherServlet instead of ContextLoaderListener to initialize spring in the web.xml.
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>COMMONS-USER-SERVICE</display-name> <listener> <listener-class>flex.messaging.HttpFlexSession</listener-class> </listener> <servlet> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:applicationContext.xml classpath:flexContext.xml classpath:securityContext.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <url-pattern>/messagebroker/*</url-pattern> </servlet-mapping> </web-app>
Note that the additional securityContext.xml that is included. This file is used to configure Spring to use spring security. The flexContext.xml also needed a one line adjustment to enable security in the message broker servlet configuration.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flex="http://www.springframework.org/schema/flex" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd"> <flex:message-broker> <flex:remoting-service default-channels="user-amf"/> <flex:secured/> </flex:message-broker> <flex:remoting-destination ref="userService"/> </beans>
Notice the inclusion of
Using the following securityContext.xml will enable security and associate the existing UserDTO objects with the login requests when users try to authenticate.
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"> <http entry-point-ref="preAuthenticatedEntryPoint"/> <beans:bean id="preAuthenticatedEntryPoint" class="org.springframework.security.ui.preauth.PreAuthenticatedProcessingFilterEntryPoint"/> <authentication-provider user-service-ref="authenticationDao"/> <beans:bean id="authenticationDao" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl"> <beans:property name="dataSource" ref="dataSource"/> <beans:property name="usersByUsernameQuery"> <beans:value> SELECT USERNAME, PASSWORD, true as enabled FROM USER WHERE USERNAME=? </beans:value> </beans:property> <beans:property name="authoritiesByUsernameQuery"> <beans:value> SELECT USERNAME, 'ROLE_ADMIN' AS PRIVILEGE FROM USER WHERE USERNAME=? </beans:value> </beans:property> </beans:bean> <global-method-security secured-annotations="enabled" jsr250-annotations="enabled"/> </beans:beans>
The authoritiesByUsernameQuery is currently a hack that allows all users to have the ROLE_ADMIN but in a later article the differentiation between ROLE_USER and ROLE_ADMIN will be established. The other item of note in this file is that the global-method-security tag enables secured annotations which ensures that the @Secured annotations on the UserService interface are honored.
Flex Cient configuration:
Making a login call is relatively simple and to ensure simplicity the remoteobject is not separated from the view in the example. To perform a login a user will simply type in the username/password and click login. If they do not have a login, they can register a user (saveUser) as that is not restricted by security.
Here is the login functionality in the Login.mxml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | protected function login():void { errorLbl.text = null; var userService:RemoteObject = new RemoteObject(); var channel:AMFChannel = new AMFChannel("user-amf", "http://localhost:8080/commons-user-webapp/messagebroker/amf"); var channelSet:ChannelSet = new ChannelSet(); channelSet.addChannel(channel); userService.channelSet = channelSet; userService.destination = "userService"; channelSet.login(username.text, password.text); channelSet.addEventListener(ResultEvent.RESULT, resultHandler); channelSet.addEventListener(FaultEvent.FAULT, faultHandler); } protected function resultHandler( result:ResultEvent ):void { if (result.result.authorities.indexOf("ROLE_ADMIN") >= 0) { trace("User logged in as admin"); } else { trace("User logged in as user"); } FlexGlobals.topLevelApplication.hideRegistrationLoginWindow(result.result); } protected function faultHandler( fault:FaultEvent ):void { trace("Login Failed: " + fault.fault.faultString); errorLbl.text = "login invalid"; } |
Here is a snippet used in another function to retrieve the user from the object that is returned from the service after a successful call to login:
1 2 3 4 5 6 7 8 | public function hideRegistrationLoginWindow(security:Object):void { PopUpManager.removePopUp(regAndLoginWindow); if(security.hasOwnProperty("name")) { usernameLbl.text = security.name; } initializeService(); } |
Logging out is rather simple as well and requires no parameters. The assumption in this code is that the logout is successful and no error occurs. This may be an unsafe assumption, but for now this will suffice.
public function logout() { var userService:RemoteObject = new RemoteObject(); var channel:AMFChannel = new AMFChannel("user-amf", "http://localhost:8080/commons-user-webapp/messagebroker/amf"); var channelSet:ChannelSet = new ChannelSet(); channelSet.addChannel(channel); userService.channelSet = channelSet; userService.destination = "userService"; channelSet.logout(); showRegistrationLoginWindow(); usernameLbl.text = "Not Logged In"; }
Some additional polish was added to this feature in that a getUsers call occurs on initial application startup. Since the user is not logged in yet on initial load of the application a fault occurs and a dialog is displayed to login or register. Additionally the logged in user should display at the top right of the main dialog window.
This is essentially all it takes to secure a flex application in a basic way. Next time the addition of some more ROLE_* information and a better explanation of how the privilege tables works will be included / created. Some new features like enabling and disabling users will also be added. If anyone has a feature request as well posting it on the blog in comments is hugely appreciated and if it seems like a good idea I am happy to try and add it.
Thanks for reading and please contact me at aparrish@neosavvy.com if you have any questions or want to use the code as it is open source and totally free to use in any application for profit or not.
Building a Simple Login Mechanism with Flex, Spring-Flex, and Spring-Security
Introduction
This guide is a step by step architecture walkthrough of a simple Flex application I have constructed to help depict how to build a Flex application with BlazeDS/Java/Hibernate and an in memory database. The attempt will be to use the newest features of Spring to integrate security and BlazeDS integrations since they are relatively new and undocumented at this point.
You can find the code at the time of this writing tagged here: http://www.neosavvy.com/svn/neosavvy/projects/commons-user/tags/initial-integration-of-user-registration-with-blazeds/
Please note that all SVN Links are temporarily locked down - I apologize for the inconvenience but please find the source here: http://www.neosavvy.com/commons-user-blog-post.tar.gz
The following requirements are attempted to be met with this project:
- Provide a Registration dialog that allows new users to supply Username, Name, Email, and password information
- Provide a login dialog that allows a user to authenticate
- Provide a basic user management system that can be used by administrative users and will serve as the user management system for other applications
- Provide a secured UI and a non-secured UI
- Non Secured features are Login / Registration screens
- Secured features are User Management screens (Some admin – some all users)
Now that the rudimentary requirements are out of the way I will explain how the application was specified. I used the application Balsamiq Mockups to design the login and registration screens and they should accurately depict what was attempted to be built.
Simple Design / Wireframes
This first screen that a new user will be prompted to click a button to initialize the user registration process.
Once the new user has clicked the new user button the next screen will be rendered to prompt for necessary input to create a user. This is standard user information and could be extended depending on the scenario needing it.
This screen shows a few simple validation errors that will be integrated to ensure valid user creation.
After a user successfully registers a simple confirmation will be displayed and the users account will be active. For the intent of simplicity no confirmation is required in the code to authorize email addresses or integrate captcha at this time. A similar screen to the one below will be implemented for server side errors when creating a user such as uniqueness constraint violations on user creation.

If you would like to open the BMML files or the PNGs they are checked in here:
http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/doc
They were created with Balsamiq Mockups http://www.balsamiq.com/products/mockups which is a great inexpensive way to create simple mockups of screens before you spend hours trying to make them work.
Architecture
The chosen architecture for this application is going to be my standard architecture for applications produced by Neosavvy for Open Source initiatives. The following technologies are used
- Maven – Build and Configuration Management
- Nexus – Dependency management Repository
- HSQLDB – In Memory RDBMS
- JUnit 4 – Unit / Integration Testing for Java
- Java 1.5 (I know it is EOL but this ensures maximum support in the Field at this time as I know of multiple production apps that have not and can not upgrade to 1.6)
- Tomcat 5.5 for Maven based deployment testing via Cargo Maven plugin
- Spring 2.5.6 – At the time of writing this is the minimum version to support Spring’s Flex Libraries
- Spring Flex 1.0.1.RELEASE
- Hibernate 3.0.GA
- Flex 4.0.0 – At the time of this writing Flex 4 is in Beta and the Sparc packages are in Flux. The 4.0 version of the Flex SDK is used to build but the MX packages are used for the interface. A conversion to the Sparc packages will occur in a later post to help understand what that entails
The application is organized into separate projects as Maven projects and has the following structure

I have made an attempt to show the dependencies of the projects to depict the build order when maven executes. The top level project is not depicted but the project structure can also be seen by opening the top level pom in IntelliJ.

The intent of each of these project is my standard approach to developing a RIA and is as follows:
Commons-user-java-lib
- All of the Unit / Integration testing lives in this project for Java
- All of the Spring configuration specific to wiring the JAR together lives here
- All of the Value Objects, Service Architecture, and DAOs are defined in this project
Commons-user-flex-model-lib
- This project encapsulates generated DTOs for the frontend consumption
- Autogeneration is accomplished via Flex Mojo’s generator plugin
Commons-user-config
- To configure a BlazeDS application some files are required and can be shared with the flex client and the webapplication configuration
- Extracting them into a separate project allows for the Flex code and Java code to share the configuration rather than duplicate it
Commons-user-webapp
- This project outputs a WAR and assembles the Flex and Java code into a working web application
- Theoretically Java Integration tests more appropriately belong here, but there are some problems making eclipse easily build/test/code/repeat so they were moved to the Jar. IntelliJ handles this fine, but Eclipse is the defacto standard so I moved them.
Commons-user-top-level (not depicted in above diagram)
- This project is the top level project and assembles the modules via multi-module configuration in Maven.
- This also manages dependencies across projects to maintain a uniform set of dependencies
- Properties to share amongst projects are also declared at this level
- Project information related to developers and documentation are also at this level
Java Implementation
Now that the overall architecture is explained let’s explain how the Java implementation was accomplished. I attempted to use a test driven development approach and also leveraged Spring’s test architecture to load Application Context and set database state (by deleting existing values in a transaction).
Test Classes
BaseSpringAwareTestCase ( http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/commons-user-java-lib/src/test/java/com/neosavvy/user/BaseSpringAwareTestCase.java )
This is a good place to start because this class will load your application context for you and allow you to extend it and write good test cases. It’s UML structure is depicted below:

The important part to notice is that it extends from AbstractTransactionalJUnit4SpringContextTests, verything else if for free.
The next class of note is the test suite that verifies all the functionality that is being attempted in this feature.
As you can see all of the test cases that support the basic registration functionality and login functionality are stubbed in and at the time of writing have been completely fleshed and and work. (see http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/commons-user-java-lib/src/test/java/com/neosavvy/user/TestUserDAO.java )
Model Classes
The next step usually for me is to define the model classes as can be seen in the diagram below. Source here: http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/commons-user-java-lib/src/main/java/com/neosavvy/user/dto/UserDTO.java
DAO Interface
The next step is to define some basic DAO interface operations. The following were implemented to support the features depicted in the requirements. At this point you will notice none of these will support “login” as this will be a feature of implementing Spring Security later. Source is here: http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/commons-user-java-lib/src/main/java/com/neosavvy/user/dao/UserDAO.java
DAO Interface Implementation
Now it is time to write some actual working code. This is done by implementing the DAO interface. Usually it is best to wire the interface’s implementation to your test case before actually coding the functionality. For brevity I will just show the full working class, but you can assume I wrote it that way. It is worth noting that the Implementing class extends HibernateDaoSupport and implements UserDAO. This helps with wiring Spring to datasources and provides transaction support out of the box so you don’t have to think about it.
Spring Configuration
After all this is complete it is time to wire all this together with Spring. This can be done with the applicationContext.xml and some extras are thrown in for JOTM transaction management for deployment to containers like Tomcat that do not have a PlatformTransactionManager. Here is a diagram that depicts the beans that are configured.
At this point the Jar definition is complete. The test case runs to completion with no errors and the HSQLDB starts up when Maven executes. The HSQLDB configuration uses an in memory configuration to allow the startup sequence to always have a predictable state.
Configuring the Spring services via BlazeDS / Spring-Flex
Note that this is a great step by step guide to follow: http://static.springsource.org/spring-flex/docs/1.0.x/reference/html/ch01.html
In the commons-user-webapp there is some configuration to Spring that exposes all of the services via BlazeDS.
To start make sure that you are using DispatcherServlet to configure Spring instead of ContextLoaderListener.
Notice the following from the web.xml (http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/commons-user-webapp/src/main/webapp/WEB-INF/web.xml
<servlet> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:applicationContext.xml classpath:flexContext.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <url-pattern>/messagebroker/*</url-pattern> </servlet-mapping>
Notice that the flexContext.xml is included without the *. The reason for this is because the * tells Spring to load a resource from any dependent Jar file. The applicationContext.xml lives in commons-user.jar so it has to use the * operator, while the flexContext.xml is in the WEB-INF/classes directory.
About the flexContext.xml file:
All that had to be done to expose the UserService was to point the flexContext.xml at this bean with the following configuration
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flex="http://www.springframework.org/schema/flex" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd"> <flex:message-broker> <flex:remoting-service default-channels="user-amf" /> </flex:message-broker> <flex:remoting-destination ref="userService" /> </beans>
It is also required that you ensure you have the services-config.xml defined in the commons-user-config project. Take a look at the following file: http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/commons-user-config/src/main/resources/services-config.xml
The most important part to ensure that you include is:
<?xml version="1.0" encoding="UTF-8"?> <services-config> <channels> <channel-definition id="user-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> <properties> <polling-enabled>false</polling-enabled> </properties> </channel-definition> </channels> </services-config>
At this point all that is required to test and ensure that the BlazeDS integration is complete.
Flex Implementation
The next step is to get those model objects proxied on the Flex side as actionscript. I leveraged Marvin Froeder’s Flex Mojo’s plugin that hooks into the GAS3 groovy based actionscript generation tools. This generates all the classes specified in the POM file for maven and places a Base class in the target/generated-classes/flex directory before compiling a SWC. All the extended versions of the classes end up in src/main/flex/com/neosavvy/dto/ and allow a developer to put custom logic there.
Take a look at the following to understand how code generation works:
<build> <plugins> <plugin> <groupId>org.sonatype.flexmojos</groupId> <artifactId>flexmojos-maven-plugin</artifactId> <version>${flex.mojos.maven.version}</version> <executions> <execution> <goals> <goal>generate</goal> </goals> <configuration> <includeJavaClasses> <includeClass>com.neosavvy.user.dto.*</includeClass> </includeJavaClasses> <beanTemplate> <template>${basedir}/src/main/template/beanBase.gsp</template> <template>${basedir}/src/main/template/bean.gsp </template> </beanTemplate> </configuration> </execution> </executions> <configuration> <configurationReport>true</configurationReport> <debug>true</debug> <locales> <param>en_US</param> </locales> <targetPlayer>10.0.0</targetPlayer> </configuration> </plugin> </plugins> </build>
It is also necessary to add a dependency to the Jar project as a provided scope to allow the generator plugin to find the Java classes it is supposed to generate.
<dependency> <groupId>com.neosavvy.commons.user</groupId> <artifactId>commons-user-java-lib</artifactId> <version>1.0-SNAPSHOT</version> <scope>provided</scope> </dependency>
Executing the maven build on this project will cause the classes to get regenerated.
Now in the interest of not using complicated frameworks but focusing on the integration points of Flex I have used some not-so-best practices when developing the Flex client. There are frequent examples of RemoteObjects defined in the mx:Script section of some of these components. I plan to use this as a starting point for new Flex developers as it is likely that they would attempt to develop in this way if they are just starting out.
The RegistrationAndLoginWindow.mxml is the top level MXML document that handles transitioning between the error screens and the registration screens. The actual code to implement the service calls is in the UserRegistration.mxml file. The two error handling files are UserFailed.mxml and UserConfirmed.mxml. The NewUserRegistration.mxml is what starts the registration process.
To see those classes take a look at the source here: http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/commons-user-flex-client/src/main/flex/com/neosavvy/user/registration/
Testing and Verification
Now that the Flex Client is defined you can test to see if the code is working. To explore my example follow the instructions below. Hopefully the guide above and the code samples will be enough to help you get going with a similar setup.
- Place the settings.xml from my SVN location into your ~/.m2/ directory from here: http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/settings.xml
- Checkout the source code with the following command:
svn co http://www.neosavvy.com/svn/neosavvy/projects/commons-user/trunk/ commons-user - Change directory into your commons-user directory and run a maven clean install
mvn clean install - Wait until the code compiles and test cases complete. The build should be successful.
- Change directories into the commons-user-webapp and start the application served
cd commons-user-webapp ; mvn cargo:start - The server should start then you can open your browser and navigate to http://localhost:8080/commons-user-webapp/
- Click the button at the top of the Application
- Notice that you can being the registration flow and create a user
- After completing the registration you should notice that your user has been added to the grid.
This concludes the simple BlazeDS integration with Spring Flex. In a future post I will explore the hooks into Spring Security for Spring Flex. Also will explore the restriction of some of the administrative features such as deleting a user and viewing/searching users.
Thanks for reading! Please email me at aparrish@neosavvy.com if you have any questions. Also please feel free to comment on this post and ask questions.
If you are interested in seeing part two of this post please click here
Neosavvy’s Neverending Quest to Improve Code Quality
My name is Adam Parrish and I have been spending a large portion of my free time working on a project called SVN Analytics or SVN Spy. The goal of my extracurricular effort is to create an open source alternative for the Fisheye toolset and potentially answer some of the questions that Fisheye helps developers answer. As a result of this effort another goal has emerged in search of a method of creating greater code quality.
In search of greater code quality, it is important to factor in the following concepts:
1) Version control
2) Continuous Integration
3) Judicious and constant refactoring
4) Proper organization in project management
The above concepts may seem obvious, but in an attempt to grow personal knowledge and share with others this blog will become a log of a journey exploring software engineering and forming good habits that improve the lives of software craftsman.
Neosavvy is a company that will be built around the desire to grow good habits in software engineering process and share this "modern knowledge" with other like minded software craftsman.








