Posted by : Bigyan Basnet on | Related Categories: BlazeDS, Flex, Hibernate, Spring

When I started my current job, I was asked to look into implementing data push using BlazeDS. To implement Data Push, I used the Spring BlazeDS Integration 1.0 integration just released last month. It integrates BlazeDS remoting and messaging facilities within the Spring IOC framework. Below is a quick proof of concept application I made using Spring, BlazeDS and Hibernate showing off some data push features with the aforementioned combination. If you open multiple windows or tabs on your browser, you’ll notice the changes are pushed to all clients.


I’ve included all the Flex, Java, XML config files, just click “View Source” and you can even get the project archive and play around with it locally. I’ll just go over some key points for and those interested.

  1. Since you’re reading this, I am assuming you are familiar and working with BlazeDS. You’ll also need to download and install the Spring BlazeDS integration jars from Spring Source: http://www.springsource.org/spring-flex
  2. Instead of the BlazeDS MessageBrokerServlet, configure you web.xml so that the Spring MVC Dispatcher Servlet handles all the communication for the “/messagebroker/*” AMF endpoint:
        <!-- Spring Flex Integration 1.0  -->
    	<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>/WEB-INF/applicationContext.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    
        <!-- Spring Flex Integration 1.0  -->
    	<!-- Map all /messagbroker requests to the DispatcherServlet for handling -->
    	<servlet-mapping>
    		<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    		<url-pattern>/messagebroker/*</url-pattern>
    	</servlet-mapping>
    
  3. The Spring ApplicationContext.xml looks like this:
    	<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
    
    	<flex:message-broker>
    		<flex:message-service
    	        default-channels="my-amf, my-polling-amf"/>
    	</flex:message-broker>	
    
    	<bean id="defaultMessageTemplate"
    		class="org.springframework.flex.messaging.MessageTemplate" />		
    
    	<bean id="dataSource"
    		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    		<property name="url" value="jdbc:mysql://localhost:3306/datapushtest"/>
    		<property name="username" value="XXXX"/>
    		<property name="password" value="XXXX"/>
    	</bean>
    
    	<bean id="sessionFactory"
    		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    
    		<property name="dataSource" ref="dataSource"/>
    
    		<property name="mappingResources">
    			<list>
    				<value>com/datapushtest/entities/Contact.hbm.xml</value>
    			</list>
    		</property>
    
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
    				<prop key="hibernate.show_sql">true</prop>
    				<prop key="hibernate.hbm2ddl.auto">update</prop>
    			</props>
    		</property>
    	</bean>
    
    	<bean id="contactsService"
    		class="com.datapushtest.dao.ContactDAO">
    		<property name="sessionFactory" ref="sessionFactory"/>
    		<flex:remoting-destination/>
    	</bean>
    
    	<flex:message-destination id="contactsMessaging"
    		channels="my-amf, my-polling-amf"/>
    

    Important here is that I am registering the MessageBroker in the Spring Container:

    	<flex:message-broker>
    		<flex:message-service
    	        default-channels="my-amf, my-polling-amf"/>
    	</flex:message-broker>
    

    Also I am registering the Spring MessageTemplate here. The MessageTemplate seems to wrap up the BlazeDS message broker and really simplifies adding messages to the queue from Java code and pushing these messages to all connected clients:

    	<bean id="defaultMessageTemplate"
    		class="org.springframework.flex.messaging.MessageTemplate" />
    

    Here I am registering the class for remoting instead of in remoting-config.xml. Spring is going to manage this and provide all the things it needs like connection to a database, the message template mentioned above, etc.

    	<bean id="contactsService"
    		class="com.datapushtest.dao.ContactDAO">
    		<property name="sessionFactory" ref="sessionFactory"/>
    		<flex:remoting-destination/>
    	</bean>
    

    I am also registering a AMF messaging destination with the Spring Container to handle incoming messages. Note above, I am calling remote methods of java classes mapped on the client, here I am setting a destination which is like a bus where messages are sent and pushed to clients:

    	<flex:message-destination id="contactsMessaging"
    		channels="my-amf, my-polling-amf"/>
    
  4. Now, whenever CRUD methods are called on the Hibernate DAOs, we want to push this to the message bus. I’ve implemented it like this. We have a class that implements this functionality and all hibernate DAOs that you want implementing this functionality can just extend this class.
    public class MessagingDAO {
    
    	private MessageTemplate template;
    
    	public MessageTemplate getTemplate() {
    		return template;
    	}
    
    	@Autowired
    	public void setTemplate(MessageTemplate template) {
    		this.template = template;
    	}
    
    	public void sendMessage(String destination, String headerName,
    			String headerValue, Object body) {
    		AsyncMessage message = template.createMessage();
            message.setDestination(destination);
            message.setBody(body);
            message.setHeader(headerName, headerValue);
            template.getMessageBroker().routeMessageToService(message, null);
    	}
    }
    

    Notice that Spring will (@autowired) inject the MessageTemplate we register and push the message with the sendMessage() method where you have args to specify the destination (we also registered this in the applicationContext), a header name, a header value, and a body (any object that is mapped over on the Flex client). Now a DAO will inherit the sendMessage() method and call it when doing a CRUD method:

    	@Override
    	public void remove(int contactId) {
    		Session session = sessionFactory.openSession();
    		Transaction tx = session.getTransaction();
    		try {
    			tx.begin();
    			Contact Contact = (Contact) session.get(Contact.class, contactId);
    			session.delete(Contact);
    			tx.commit();
    			super.sendMessage("contactsMessaging", "method", "delete", contactId);
    		}
    		catch (RuntimeException e) {
    			tx.rollback();
    			throw e;
    		}
    		finally {
    			session.close();
    		}
    	}
    
  5. Flex Client Side Now, I’ll just briefly highlight some of the main Flex client side code required to get things working. First you need to have remote objects somewhere pointing to the “contactsService” destination declared in the Spring applicationContext.xml and some event handlers to notify the user about successful or failure when calling the service:
        <mx:RemoteObject id="contactsService" destination="contactsService" fault="onFault(event)">
            <mx:method name="findAll" result="queryResult(event)" />
            <mx:method name="create" result="crudResult(event)"/>
            <mx:method name="remove" result="crudResult(event)"/>
            <mx:method name="update" result="crudResult(event)"/>
        </mx:RemoteObject>
    

    Next, the corresponding service is called based on a user action. We pass the data that is wrapped in the event and we also set some values to a asynchronous token when calling the service. Since the asynchronous token is a dynamic class, we set some of our own values like identifying the method that was called. This will help us know for what remote service call the a result event is returning for later.

                private function contactEventHandler(event:ContactEvent) : void {
                    var method : int = event.action;
                    switch (method) {
                        case (ContactEvent.CREATE_CONTACT):
                            asynToken = contactsService.create(event.contact);
                            asynToken.method = "add";
                            break;
                        case (ContactEvent.EDIT_CONTACT):
                            asynToken = contactsService.update(event.contact);
                            asynToken.method = "update";
                            break;
                        default:
                            break;
                    }
                }
    

    Now when the result returns, we can inform the user:

                private function crudResult(event:ResultEvent) : void {
    
                    var action:String = event.token.method;
                    switch (action) {
                        case "add":
                            Alert.show("New Contact added to database", "Contact Added");
                            break;
                        case "delete":
                            Alert.show("Contact deleted from database", "Contact Deleted");
                            break;
                        case "update":
                            Alert.show("Contact updated in database", "Contact Updated");
                            break;
                        default:
                            break;
                    }
                }
    

    Now the client side implementation of the data push part. Remember, on all CRUD operations on hibernate, using the Spring MessageTemplete, we were pushing the message to the message bus. Now on the client, we need to listen in on the channel. First we need a ChannelSet on the client pointing to a amfpolling endpoint on the server (the amf endpoints are defined in services-config.xml):

        <mx:ChannelSet id="cs">
            <mx:AMFChannel url="/DataPushTest/messagebroker/amfpolling"/>
        </mx:ChannelSet>
    

    Next you need to create a consumer that uses that ChannelSet and is connected to the contactsMessaging destination.

       <mx:Consumer id="contactsConsumer" destination="contactsMessaging" channelSet="{cs}"
            message="messageHandler(event)"/>
    

    This consumer will also have to explicitly subscribe to the messaging destination. In the sample app, I have done it in the init() method which is called after creationComplete():

                private function init() : void {
                    contactsConsumer.subscribe();
                    ............
                    ....................
                }
    

    FINALLY….some logic to mange the data that has been pushed through consumer. Remember the header name and head value set by the hibernate DAO, we use that to determine what action to take. The actual hibernate entity, the contact, comes back in the as the message body. We have an array collection of contacts and we either add a contact to it, update a contact in the collection by looping through it and finding it or delete it using the same logic. If you’ve declared your contacts arrayCollection using the [Binding] tag, databinding will ensure that the changes to the arrayCollection are seen by the user.

                private function messageHandler(event:MessageEvent) : void {
    
                    var action:String = event.message.headers.method;
                    var contact : Contact;
                    var i:int;
                    switch (action) {
                        case "create":
                            contact = event.message.body as Contact;
                            acContacts.addItem(contact);
                            break;
                        case "update":
                            contact = event.message.body as Contact;
                            for (i=0; i < acContacts.length; i++) {
                                if (acContacts[i].id == contact.id) {
                                    acContacts.setItemAt(contact, i);
                                }
                            }
                            break;
                        case "delete":
                            var id : int = event.message.body as int;
                            for (i =0; i < acContacts.length; i++) {
                                if (acContacts[i].id == id){
                                    acContacts.removeItemAt(i);
                                }
                            }
                            break;
                        defaut:
                            break;
                        }
                    }
    

    Note, you should have the ActionScript ContactVO mapped to the hibernate Contact:

        [RemoteClass(alias="com.datapushtest.entities.Contact")]
        [Bindable]
        public class Contact {
        .............
        ..................................
    




Tags: > > > > > > > > > > > > > >

Posted by : Bigyan Basnet on | Related Categories: Flex

I once had an interview with RoundArch, a consultancy that specializes in building RIAs with Flex/Flash. They were actually looking for a Flex developer who knew the Flex component life cycle really well and someone with enough of graphics background that they could skin photoshop PSD resources for these applications. So as a part of their interview process, they actually gave me a photoshop PSD file and pretty much said this is a toolbar, see what you can do with it. It was pretty open-ended. They wanted to see if I knew how to skin components and how much of the Flex Component life cycle I understood. Well, I am not a graphics artist but the rest of the post details what I came up with. I think it provides a solid example of the flex component life cycle including the invalidation/validation framework, overriding component life cycle methods, dispatching custom events, skinning and exposing custom styles for components.

First, here is GIF version of the PSD that was originally handed to me. I was supposed to make some sort of custom toolbar skinning this image:

Photoshop PSD file for custom component skin




I skinned the image the best I could with Fireworks and created a custom toolbar that exposed a lot of properties. The toolbar exposes a lot of properties of its child components, custom events are dispatched, and even styles of its children are exposed as custom styles for the component.

    <!-- Custom Component Toolbar with properties, event handlers and functions defined in client application -->
    <roundArch:SearchToolBar  id="searchToolbar"
        width="{widthSlider.value}"
        height="{heightSlider.value}"
        backgroundColor="#DADADA"
        criteriaLabel="{inputCriteriaLabel.text}"
        summaryButtonLabel="{inputSearchButton.text}"
        criteriaText="{inputCriteriaText.text}"
        summaryClicked="handleSummaryClicked(event)"
        resultsLabel="{inputResultsLabel.text}"
        resultsText="{inputResultsText.text}"
        comboSortDataProvider="{comboBoxData}"
        labelFunction="{myLabelFunction}"
        sideBarLabel="{inputSideBarLabel.text}"
        itemClick="handleSideBarClicked(event)"
        fontSize="{inputFontSize.value}"
        criteriaLabelFontSize="{criteriaLabelFontSize.value}"/>

I put the custom toolbar in client application that has bindings to all the exposed properties and events to allow the client to manipulate the toolbar. The following is the result:


How the Custom Component was built

When building custom components, there there 3 tenets of the Flex framework that every developer should understand:

  • Composition- Flex applications are built up of components that contain other components. Every component must be directly or indirectly attached to the root container in the display list in order to be visible to the user, interact with the user and dispatch and listen to events.
  • Invalidation/Validation – Flex runs on the Flash player which renders in frames. In order to optimize for how Flash player executes code, Flex uses the Invalidation/Validation framework. This means that changes to your component aren’t automatically rendered but rather the changes are flagged and the logic for dealing with those changes is executed right before rendering.
  • Event Handling – Flex components are ideally loosely coupled classes that communicate to each other using events. They use the observer pattern is registering for and being notified of events.
  1. Constructor() – The constructors in Flex UI components are pretty bare. You need a no args constructor for the class to be instantiated in MXML.
            public function SearchToolBar() {
                super();
            }
    
  2. CreateChildren() – The creatChildren method is where you create, initialize and add children to the parent component.
            protected override function createChildren() : void {
    
                super.createChildren();
    
                if (DividerIcon==null) {
                    DividerIcon = new DividerIcon();
                }
    
                //criteria label
                labelCriteria = new Label();
                labelCriteria.styleName = "AKBold";
                this.addChild(labelCriteria);
    
  3. commitProperties() – The commitProperties method is used to check for modifications to the properties to the component. It is a part of the invalidation/validation framework that was mentioned. For each property that might change, you check a dirty flag for it and if it has changed you assign the new value for it.
            override protected function commitProperties():void {
    
                super.commitProperties();
    
                if (labelCriteriaChanged) {
                    labelCriteria.text = _criteriaLabel;
                    labelCriteriaChanged = false;
                }
                if (summaryButtonLabelChanged) {
                    buttonSummary.label = _summaryButtonLabel;
                    summaryButtonLabelChanged = false;
                }
    

    The parent container has references to its children…

            //UI components
            private var labelCriteria : Label;
            private var labelCriteriaText : Label;
            private var buttonSummary : Button;
    

    …..and it keeps track of the sets of flags of properties that have changed and values of those properties…

            //dirty flags
            private var labelCriteriaChanged : Boolean;
            private var summaryButtonLabelChanged : Boolean;
            private var criteriaTextChanged : Boolean;
    
            //encapsulated
            private var _criteriaLabel : String;
            private var _criteriaText : String;
            private var _summaryButtonLabel : String;
    

    Now we use the actionscript “get/set” mechanism to actually access the property. In “get”, we return the corresponding private property, and in “set” we set the value of the corresponding private property and set the dirty flag for the property. We call invalidateProperties() to make sure that commitProperties() is triggered during the next render event. We might also trigger updateDisplayList() if the changes to the property affect the display. It’s important to take notice that during commitProperties() the dirty flag is set back to false after the new value has been assigned. Also, the [Bindable] tag on the “get/set” function marks the property for databinding and it will be available in code completion when creating the parent component in MXML.

            public function get summaryButtonLabel() : String {
                return _summaryButtonLabel;
            }    
    
            [Bindable]
            public function set criteriaText(value : String) : void {
                _criteriaText = value;
                criteriaTextChanged = true;
                invalidateProperties();
                invalidateDisplayList();
            }
    
  4. updateDisplayList() – The updateDisplayList method lays out the children components and draws graphics and skins based on the properties and styles of your components. This happens right before rendering so your components are not displayed before updateDisplayList is called. The updateDisplayList has unscaledWidth and unscaledHeight in its signature, these values are pixel width and height of the component determined by the parent component. So here we are calculating the size and positions of the children based on these values. Notice also that for classes that inherit from UI component we use the convenience methods move() to position the components instead of “.x” and “.y” and getExplicitOrMeasuredHeight() and getExplicitOrMeasuredWidth() instead of “.height” and “.width”.
            override protected function updateDisplayList(unscaledWidth : Number,
                unscaledHeight : Number) : void {
    
                super.updateDisplayList(unscaledWidth, unscaledHeight);
                labelCriteria.move(10, Math.round( (unscaledHeight -
                labelCriteria.getExplicitOrMeasuredHeight())/2) +2);
                labelCriteriaText.move(20+labelCriteria.getExplicitOrMeasuredWidth(),
                    Math.round( (unscaledHeight - labelCriteriaText.getExplicitOrMeasuredHeight())/2));
                buttonSummary.move((unscaledWidth/2)-buttonSummary.getExplicitOrMeasuredWidth()-10,
                    Math.round( (unscaledHeight - buttonSummary.getExplicitOrMeasuredHeight())/2) );
                labelCriteriaText.setActualSize((unscaledWidth/2)-labelCriteria.getExplicitOrMeasuredWidth()-
                    buttonSummary.getExplicitOrMeasuredWidth()-30,
                    labelCriteriaText.getExplicitOrMeasuredHeight());
                imageDivider1.move((unscaledWidth/2),  ((unscaledHeight
                -imageDivider1.getExplicitOrMeasuredHeight())/2));
                imageDivider1.height = unscaledHeight-4;
    
  5. Dispatching Custom Events – We dispatch custom events from the component by setting a unique event type identifer and dispatching the event but you also have to have a meta tag in the class declaring that this class is capable of dispatching this type of event. Client can can register and assign event handlers when these events are dispatched. Here we are registering a custom event type with the meta tag and dispatching that event when an itemClick() event occurs in a child component:
        [Event(name="summaryClicked", type="flash.events.Event")]
        public class SearchToolBar extends Canvas {
    
            private function summaryButtonClicked(event : Event) : void {
                dispatchEvent(new Event("summaryClicked"));
            }
    
  6. Exposing Custom Styles – We can expose custom styles in our custom component, they will then be available and can be set in MXML like the other default styles. First we have to declare that this component exposes a custom style with the style meta tag:
        [Style(name="criteriaLabelFontSize", type="Number", format="Length", inherit="no")]
        public class SearchToolBar extends Canvas {
    

    Next we need to override the styleChanged() method which passes in the name of the style that is being changed as an argument. If our custom style is the one being changed, we just flag it:

            override public function styleChanged(styleProp:String):void {
    
                super.styleChanged(styleProp);
    
                if(styleProp=="criteriaLabelFontSize")
                {
                    criteriaLabelFontSizeChanged = true;
                    invalidateProperties();
                    invalidateDisplayList();
                }
            }
    

    Now in the commitProperties, if we see a dirty flag that our style has been changed, we use the value:

                if(criteriaLabelFontSizeChanged)
                {
                    labelCriteria.setStyle("fontSize",calculatelabelFontSizeDefault);
                    criteriaLabelFontSizeChanged = false;
                }
    

    The helper function returns the “criteriaLabelFontSize” from the font manger or if it is undefined by the font manager it returns the default value of 10:

            private function get calculatelabelFontSizeDefault(): Number {
                return (getStyle("criteriaLabelFontSize") == undefined ? 10 :
                    getStyle("criteriaLabelFontSize"));
            }
    
  7. Skinning – Finally, in our CSS, we define the skins for each of the states of our controls downSkin, upSkin, overSkin, etc by assigning a subtly changed graphics files for each state.
    ButtonBar.ARCHsideBarFirstButton
    {
        disabledSkin: Embed(source="assets/skins/ARCHskins/ButtonBar_ARCHsideBarFirstButton_disabledSkin.png");
        selectedDisabledSkin: Embed(source="assets/skins/ARCHskins/ButtonBar_ARCHsideBarFirstButton_disabledSkin.png");
        downSkin: Embed(source="assets/skins/ARCHskins/ButtonBar_ARCHsideBarFirstButton_downSkin.png");
        overSkin: Embed(source="assets/skins/ARCHskins/ButtonBar_ARCHsideBarFirstButton_overSkin.png");
        upSkin: Embed(source="assets/skins/ARCHskins/ButtonBar_ARCHsideBarFirstButton_upSkin.png");
        selectedUpSkin: Embed(source="assets/skins/ARCHskins/ButtonBar_ARCHsideBarFirstButton_selectedUpSkin.png");
        selectedOverSkin: Embed(source="assets/skins/ARCHskins/ButtonBar_ARCHsideBarFirstButton_selectedUpSkin.png");
        selectedDownSkin: Embed(source="assets/skins/ARCHskins/ButtonBar_ARCHsideBarFirstButton_selectedUpSkin.png");
    }
    




Posted by : Bigyan Basnet on | Related Categories: Flex

I was looking for a more complete Flex class hierarchy diagram then the ones found in Flex books and really didn’t find anything out there. So I thought about making a small Flex application that shows the class hierarchy in Flex and googled to see if someone had already done this. It turns out, Jonathan Branam had done a simple but slick Class Browser as an AIR application and had the source available for download. I changed the AIR app into a Flex app, and shrunk down some of the graphics and displayed some of the most commonly used Flex classes by default. The following is the result and it’s a good reference to have. BTW, check out Jonathan Branam’s blog at http://jonathanbranam.net, he has some really good information about class hierarchy and component lifecycle in flex.






Tags: > > > > > > > >

October 8, 2007 at 3:19 am by Bigyan Basnet