Showing posts with label flex. Show all posts
Showing posts with label flex. Show all posts

Nov 23, 2009

Spring Flex Integration using SBI

Flex and Spring Integration Architecture

Many applications are implemented with a three-tier architecture wherein data is stored in the database. The web server runs Java services that access the database and retrieve the information. The Java classes are responsible for the business logic that receives a call from the client tier, assembles the information from the database, and returns the result.

The client tier utilizes browser technology that runs a Flash application to provide an interface to the user and calls the Java services for required information. The client workstations call the Tomcat server, which calls the database to gather data and executes the Spring services that contain the application’s business logic.

In this architecture, the compiled Flex and Spring code resides on the Tomcat server. The client workstations download the Flex SWF and associated files, which contain the hooks into the Spring services.

Sample Application

To demonstrate the Spring and Flex integration, I am presenting a sample application which is a web based application with the following architecture.

image

Spring

Spring addresses Java/Java EE development by organizing your middle-tier objects and takes care of the plumbing that is usually left up for you to create. Spring can also work in any architecture layer while running in any runtime environment.

Spring Bean Wiring

The IoC container, also called the core container, wires Spring beans together. It is also responsible

for the configuration and creation of objects in Spring.

In most cases, when an object needs references to data, it does a lookup or retrieval from an external data repository. IoC allows the component to not require information regarding the location of the data source, thus cleaning up the process of data retrieval through inverting the direction of the retrieval.

IoC helps to create layers of abstraction through your Spring applications. Spring’s core container provides a central location for accessing objects, called the application context. The application context can be configured as Java 5 annotations or as an XML file that contains the signatures of each bean that is created in a Spring application.

Building Spring Service

To demonstrate I will present a simple spring service that gets a list of objects from the database using Hibernate as the ORM technology.

Building a Simple Bean

The first item of interest is to build a bean for our service. This bean is part of the IoC container.

Beans defined in the IoC container are nothing more than a pool of components you have access to by referencing the service with which they are associated.

The MyService is a simple POJO with a method to print the project list. This bean does not have a constructor, as no arguments need to be passed to the bean at instantiation.

Bean Interface (MyService.java)

package com.sampleapp.services;

import java.util.List;
import com.sampleapp.domain.MyDomainObject;

public interface MyService {

List<MyDomainObject> getProjects();

}


Bean Implementation (MyServiceImpl.java)



package com.sampleapp.services;

import java.util.List;
import java.util.Map;
import com.sampleapp.domain.MyDomainObject;
import com.sampleapp.dao.MyDao;
import org.springframework.beans.factory.annotation.Autowired;

public class MyServiceImpl implements MyService {

MyDao myDao;

@Autowired(required = true)
public void setConsDbDao(MyDao myDao) {
this.myDao = myDao;
}

public List<MyDomainObject> getProjects() {
// TODO Auto-generated method stub
return myDao.getProjects();
}
}


Building Data Persistence





The Spring Framework provides a layer of abstraction for transaction management to allow you to consistently program across different transaction APIs, such as JDBC, Hibernate, JPA, and Java Data Objects (JDO). Spring provides support for both programmatic and declarative transaction management.



Spring Transaction Managers



Spring provides transaction managers that delegate work to platform-specific transaction implementations through either JTA or the transaction manager’s framework; Spring does not manage transactions directly. Spring provides transaction managers for J2EE Connector Architecture (JCA), JDBC, JMS, Hibernate, JDO, JPA, TopLink, and others.



Since here I am going to use Hibernate as ORM solution, so you will use the HibernateTransactionManager.



To demonstrate how to persist data with Spring, we need a database, so lets create a database table DOMAINOBJECT.



clip_image002



Once that is complete, you can go ahead and create a class to support the table.



Domain Object (MyDomainObject.java)



package com.sampleapp.domain;

import java.io.Serializable;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name="DOMAINOBJECT")
public class MyDomainObject implements Serializable {

static final long serialVersionUID = 1L;

private int id;
private String project;
private String ownerName;
private Date lastUpdated;

public MyDomainObject() {}

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="gen_id")
@SequenceGenerator(name="gen_id", sequenceName = "DOMAINOBJ_SEQ")
@Column(name="ID")
public int getId() {
return this.id;
}

public void setId(int id) {
this.id = id;
}

@Column(name = "PROJECT", nullable = false, length = 255)
public String getProject() {
return project;
}

public void setProject(String project) {
this.project = project;
}

@Column(name = "OWNERNAME", length = 255)
public String getOwnerName() {
return ownerName;
}

public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}

@Column(name = "LASTUPDATED")
public Date getLastUpdated() {
return lastUpdated;
}

public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
}


We will need to create a DAO to support database operations, each of which is carried out by a DAO method. Since we have only one operation here so will have one method defined in the interface.



These methods should be defined in the DAO interface to allow for different implementation technologies such as Hibernate and iBATIS.



Dao Interface (MyDao.java)



package com.sampleapp.dao;

import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Propagation;
import com.sampleapp.domain.MyDomainObject;

public interface MyDao {

@Transactional(readOnly=true, propagation=Propagation.SUPPORTS)
List<MyDomainObject> getProjects();

}


Since I am using Hibernate as the implementation technology so let’s create the Hibernate implementation of the above defined DAO interface.



Dao Implementation (MyDaoImpl.java)



package com.sampleapp.dao;

import java.util.List;
import com.sampleapp.domain.MyDomainObject;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class MyDaoImpl extends HibernateDaoSupport implements MyDao {

@SuppressWarnings({"unchecked"})
@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public List<MyDomainObject> getProjects() {
// TODO Auto-generated method stub
List<MyDomainObject> projects = getHibernateTemplate().find("from MyDomainObject");
return projects;
}
}


Once done we can now start registering the beans in the Spring ICO container called applicationContext.xml.



For simplicity, I am going to keep the database/hibernate related properties in a separate file called hibernate.properties. This has advantage that in future if the database needs to change I can change the settings in a file without touching rest of the application.



Hibernate SessionFactory Configuration (hibernate.properties)



# Hibernate 3 configuration
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.url=jdbc:oracle:thin:@servername:port:DB
hibernate.connection.username=username
hibernate.connection.password=password
hibernate.show_sql=true
hibernate.format_sql=false
hibernate.transaction.factory_class=org.hibernate.transaction.JDBCTransactionFactory
hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=5
hibernate.c3p0.max_statements=50
hibernate.c3p0.timeout=1800


Now lets start registering the various components in Spring IOC container.



1. Configure Hibernate Session Factory



<bean id="sessionFactory" 
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="annotatedClasses">
<list>
<!-- Add annotated domain objects here-->
<value>com.sampleapp.domain.MyDomainObj</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">${hibernate.show_sql}
</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}
</prop>
<prop key="hibernate.transaction.factory_class">${hibernate.transaction.factory_class}
</prop>
<prop
key="hibernate.dialect">${hibernate.dialect}
</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.c3p0.min_size}
</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">${hibernate.c3p0.timeout}</prop>
<prop key="hibernate.c3p0.max_statements">${hibernate.c3p0.max_statements}</prop>
<prop key="hibernate.connection.driver_class">${hibernate.connection.driver_class}</prop>
<prop key="hibernate.connection.url">${hibernate.connection.url}</prop>
<prop key="hibernate.connection.username">${hibernate.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.connection.password}</prop>
</props>
</property>
</bean>


2. Autowiring and Annotation Support



<!-- enable the configuration of transactional behavior based on annotations -->

<tx:annotation-driven transaction-manager="txManager"/>

<!-- enable autowiring -->
<context:annotation-config />

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>


3. Transaction Manager Registration



<bean id="txManager"  class="org.springframework.orm.hibernate3.HibernateTransactionManager">    
<property name="sessionFactory"><ref local="sessionFactory" />
</property>
</bean>


4. Dao Registration



<bean id="myDao" 
class="com.sampleapp.dao.MyDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


5. Registration of Services



<bean id="myService" 
class="com.sampleapp.services.MyServiceImpl"/>


That completes our Server side development of our sample application.



To expose the Spring services to the Flex, we need to have the BlazeDS integration done.



For this download the BlazeDS jars and Spring SBI jars and put it in your application classpath.



The SBI suite is designed as a best practice solution for integrating Flex and Spring. Its main goal is to simplify communication between Flex and Spring by providing Remoting and messaging capabilities in combination with BlazeDS.



Setting Up the BlazeDS MessageBroker



The MessageBroker is a the SBI component responsible for handling HTTP messages from the



Flex client. The MessageBroker is managed by Spring instead of BlazeDS. Messages are routed



to the Spring-managed MessageBroker via the Spring DispatcherServlet.



Lets modify the web.xml with the configuration required to handle the requests from Flex.



Web.xml



<?xml version="1.0" encoding="UTF-8"?>
<!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>

<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>/WEB-INF/app-config/applicationContext.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>/spring/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>

</web-app>


Since we are using the MessageBroker which is managed by Spring so we have to register it in the Spring IOC container applicationContext.xml



<bean 
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/*=springManagedMessageBroker
</value>
</property>
</bean>

<!-- Dispatches requests mapped to a MessageBroker -->
<bean
class="org.springframework.flex.servlet.MessageBrokerHandlerAdapter"/>

<!-- Bootstraps and exposes the BlazeDS MessageBroker -->
<bean id="springManagedMessageBroker"
class="org.springframework.flex.core.MessageBrokerFactoryBean" />


Also we need to expose our service beans to flex remoting



<bean id="myServiceRO" class="org.springframework.flex.remoting.RemotingDestinationExporter">
<property name="messageBroker"
ref="springManagedMessageBroker"/>
<property name="service" ref="consDbService"/>
<property name="destinationId" value="myService" />
<property name="channels" value="my-amf, my-secure-amf"/>
</bean>


Now lets register the channels my-amf in the BlazeDS configuration files (remoting-config.xml and services-config.xml)



remoting-config.xml



<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
class="flex.messaging.services.RemotingService">
<adapters>
<adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
</adapters>
<default-channels>
<channel ref="my-amf"/>
</default-channels>
</service>
services-config.xml
<channels>

<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/spring/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>false</polling-enabled>
</properties>
</channel-definition>
</channels>

image

Deploy the application on your favourite web server.



I am using Tomcat



Flex



In this application, Flex makes an RPC call to the BlazeDS server to consume the getProjects we created in Spring.



So lets create the flex application which will make RPC calls to the spring services we defined.



SampleApp.mxml



<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
pageTitle="Projects List"
layout="absolute"
width="100%"
height="100%"
initialize="initializeHandler()" borderColor="#009DFF"
creationComplete="initializeHandler()">

<mx:RemoteObject
id="ro"
destination="myService"
endpoint="http://localhost:8080/SampleApp/spring/messagebroker/amf"
result="resultHandler(event)"
fault="faultHandler(event)"
showBusyCursor="true"
/>

<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.utils.ObjectUtil;
import mx.controls.Alert;
import mx.utils.StringUtil;


[Bindable]
private var systemsData:ArrayCollection = new ArrayCollection();

private var selectedItem:Object;

private function initializeHandler():void
{
ro.getProjects();
}

private function resultHandler(event:ResultEvent):void
{
systemsData = ArrayCollection(event.result);
}

private function faultHandler(event:FaultEvent):void
{
Alert.show(ObjectUtil.toString(event.fault) );
}

]]>
</mx:Script>


<mx:VBox width="100%" height="100%" y="10" x="10">
<mx:ApplicationControlBar width="100%" height="81" borderColor="#F7FAFC" fillColors="[#009DFF, #009DFF]" fillAlphas="[0.53, 0.53]" autoLayout="true" themeColor="#F6F8F9">
<mx:Text text="Project List" fontSize="26" fontWeight="bold" fontStyle="italic" themeColor="#9E5814" alpha="0.52" color="#F4FAFB" width="310"/>
</mx:ApplicationControlBar>
<mx:HBox x="10" y="10" width="100%" height="100%" id="hbox1">

<mx:Panel id="systemStatus" width="100%" height="100%" layout="absolute" cornerRadius="0" borderColor="#009DFF" fontSize="13" backgroundAlpha="0.5" backgroundColor="#009DFF">
<mx:VBox label = 'Report' borderColor="#009DFF" borderStyle="solid" borderThickness="6" backgroundColor="#009DFF" x="33" y="9">
<mx:DataGrid
id="dgrid"
updateComplete=""
dataProvider="{systemsData}"
width="622" height="362"
bottom="0" right="0" alternatingItemColors="[#F7F7F7, #BDE7E8]" themeColor="#32C582" borderThickness="5" borderStyle="solid" borderColor="#009DFF">
<mx:columns>
<mx:DataGridColumn fontSize="9" headerText="Project Name" dataField="project" />
<mx:DataGridColumn fontSize="9" headerText="Last Updated" dataField="lastUpdated">
<mx:itemRenderer>
<mx:Component>
<mx:VBox>
<mx:DateFormatter id="formatDateTime" formatString="MM/DD/YY" />
<mx:Label text="{formatDateTime.format(data.lastUpdated)}"/>
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn fontSize="9" headerText="Owner Name" dataField="ownerName" />
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:Panel>
</mx:HBox>
</mx:VBox>
</mx:Application>


Once done copy the sampleApp.html, sampleApp.swf, AC_OETags.js and playerProductInstall.swf in your web application and you should be able to view the application deployed on tomcat as below:



clip_image002[5]



References



Spring Flex Integration using SBI

Flex and Spring Integration Architecture

Many applications are implemented with a three-tier architecture wherein data is stored in the database. The web server runs Java services that access the database and retrieve the information. The Java classes are responsible for the business logic that receives a call from the client tier, assembles the information from the database, and returns the result.

The client tier utilizes browser technology that runs a Flash application to provide an interface to the user and calls the Java services for required information. The client workstations call the Tomcat server, which calls the database to gather data and executes the Spring services that contain the application’s business logic.

In this architecture, the compiled Flex and Spring code resides on the Tomcat server. The client workstations download the Flex SWF and associated files, which contain the hooks into the Spring services.

Sample Application

To demonstrate the Spring and Flex integration, I am presenting a sample application which is a web based application with the following architecture.

image

Spring

Spring addresses Java/Java EE development by organizing your middle-tier objects and takes care of the plumbing that is usually left up for you to create. Spring can also work in any architecture layer while running in any runtime environment.

Spring Bean Wiring

The IoC container, also called the core container, wires Spring beans together. It is also responsible

for the configuration and creation of objects in Spring.

In most cases, when an object needs references to data, it does a lookup or retrieval from an external data repository. IoC allows the component to not require information regarding the location of the data source, thus cleaning up the process of data retrieval through inverting the direction of the retrieval.

IoC helps to create layers of abstraction through your Spring applications. Spring’s core container provides a central location for accessing objects, called the application context. The application context can be configured as Java 5 annotations or as an XML file that contains the signatures of each bean that is created in a Spring application.

Building Spring Service

To demonstrate I will present a simple spring service that gets a list of objects from the database using Hibernate as the ORM technology.

Building a Simple Bean

The first item of interest is to build a bean for our service. This bean is part of the IoC container.

Beans defined in the IoC container are nothing more than a pool of components you have access to by referencing the service with which they are associated.

The MyService is a simple POJO with a method to print the project list. This bean does not have a constructor, as no arguments need to be passed to the bean at instantiation.

Bean Interface (MyService.java)

package com.sampleapp.services;

import java.util.List;
import com.sampleapp.domain.MyDomainObject;

public interface MyService {

List<MyDomainObject> getProjects();

}


Bean Implementation (MyServiceImpl.java)



package com.sampleapp.services;

import java.util.List;
import java.util.Map;
import com.sampleapp.domain.MyDomainObject;
import com.sampleapp.dao.MyDao;
import org.springframework.beans.factory.annotation.Autowired;

public class MyServiceImpl implements MyService {

MyDao myDao;

@Autowired(required = true)
public void setConsDbDao(MyDao myDao) {
this.myDao = myDao;
}

public List<MyDomainObject> getProjects() {
// TODO Auto-generated method stub
return myDao.getProjects();
}
}


Building Data Persistence





The Spring Framework provides a layer of abstraction for transaction management to allow you to consistently program across different transaction APIs, such as JDBC, Hibernate, JPA, and Java Data Objects (JDO). Spring provides support for both programmatic and declarative transaction management.



Spring Transaction Managers



Spring provides transaction managers that delegate work to platform-specific transaction implementations through either JTA or the transaction manager’s framework; Spring does not manage transactions directly. Spring provides transaction managers for J2EE Connector Architecture (JCA), JDBC, JMS, Hibernate, JDO, JPA, TopLink, and others.



Since here I am going to use Hibernate as ORM solution, so you will use the HibernateTransactionManager.



To demonstrate how to persist data with Spring, we need a database, so lets create a database table DOMAINOBJECT.



clip_image002



Once that is complete, you can go ahead and create a class to support the table.



Domain Object (MyDomainObject.java)



package com.sampleapp.domain;

import java.io.Serializable;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name="DOMAINOBJECT")
public class MyDomainObject implements Serializable {

static final long serialVersionUID = 1L;

private int id;
private String project;
private String ownerName;
private Date lastUpdated;

public MyDomainObject() {}

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="gen_id")
@SequenceGenerator(name="gen_id", sequenceName = "DOMAINOBJ_SEQ")
@Column(name="ID")
public int getId() {
return this.id;
}

public void setId(int id) {
this.id = id;
}

@Column(name = "PROJECT", nullable = false, length = 255)
public String getProject() {
return project;
}

public void setProject(String project) {
this.project = project;
}

@Column(name = "OWNERNAME", length = 255)
public String getOwnerName() {
return ownerName;
}

public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}

@Column(name = "LASTUPDATED")
public Date getLastUpdated() {
return lastUpdated;
}

public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
}


We will need to create a DAO to support database operations, each of which is carried out by a DAO method. Since we have only one operation here so will have one method defined in the interface.



These methods should be defined in the DAO interface to allow for different implementation technologies such as Hibernate and iBATIS.



Dao Interface (MyDao.java)



package com.sampleapp.dao;

import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Propagation;
import com.sampleapp.domain.MyDomainObject;

public interface MyDao {

@Transactional(readOnly=true, propagation=Propagation.SUPPORTS)
List<MyDomainObject> getProjects();

}


Since I am using Hibernate as the implementation technology so let’s create the Hibernate implementation of the above defined DAO interface.



Dao Implementation (MyDaoImpl.java)



package com.sampleapp.dao;

import java.util.List;
import com.sampleapp.domain.MyDomainObject;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class MyDaoImpl extends HibernateDaoSupport implements MyDao {

@SuppressWarnings({"unchecked"})
@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public List<MyDomainObject> getProjects() {
// TODO Auto-generated method stub
List<MyDomainObject> projects = getHibernateTemplate().find("from MyDomainObject");
return projects;
}
}


Once done we can now start registering the beans in the Spring ICO container called applicationContext.xml.



For simplicity, I am going to keep the database/hibernate related properties in a separate file called hibernate.properties. This has advantage that in future if the database needs to change I can change the settings in a file without touching rest of the application.



Hibernate SessionFactory Configuration (hibernate.properties)



# Hibernate 3 configuration
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.url=jdbc:oracle:thin:@servername:port:DB
hibernate.connection.username=username
hibernate.connection.password=password
hibernate.show_sql=true
hibernate.format_sql=false
hibernate.transaction.factory_class=org.hibernate.transaction.JDBCTransactionFactory
hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=5
hibernate.c3p0.max_statements=50
hibernate.c3p0.timeout=1800


Now lets start registering the various components in Spring IOC container.



1. Configure Hibernate Session Factory



<bean id="sessionFactory" 
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="annotatedClasses">
<list>
<!-- Add annotated domain objects here-->
<value>com.sampleapp.domain.MyDomainObj</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">${hibernate.show_sql}
</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}
</prop>
<prop key="hibernate.transaction.factory_class">${hibernate.transaction.factory_class}
</prop>
<prop
key="hibernate.dialect">${hibernate.dialect}
</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.c3p0.min_size}
</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">${hibernate.c3p0.timeout}</prop>
<prop key="hibernate.c3p0.max_statements">${hibernate.c3p0.max_statements}</prop>
<prop key="hibernate.connection.driver_class">${hibernate.connection.driver_class}</prop>
<prop key="hibernate.connection.url">${hibernate.connection.url}</prop>
<prop key="hibernate.connection.username">${hibernate.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.connection.password}</prop>
</props>
</property>
</bean>


2. Autowiring and Annotation Support



<!-- enable the configuration of transactional behavior based on annotations -->

<tx:annotation-driven transaction-manager="txManager"/>

<!-- enable autowiring -->
<context:annotation-config />

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>


3. Transaction Manager Registration



<bean id="txManager"  class="org.springframework.orm.hibernate3.HibernateTransactionManager">    
<property name="sessionFactory"><ref local="sessionFactory" />
</property>
</bean>


4. Dao Registration



<bean id="myDao" 
class="com.sampleapp.dao.MyDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


5. Registration of Services



<bean id="myService" 
class="com.sampleapp.services.MyServiceImpl"/>


That completes our Server side development of our sample application.



To expose the Spring services to the Flex, we need to have the BlazeDS integration done.



For this download the BlazeDS jars and Spring SBI jars and put it in your application classpath.



The SBI suite is designed as a best practice solution for integrating Flex and Spring. Its main goal is to simplify communication between Flex and Spring by providing Remoting and messaging capabilities in combination with BlazeDS.



Setting Up the BlazeDS MessageBroker



The MessageBroker is a the SBI component responsible for handling HTTP messages from the



Flex client. The MessageBroker is managed by Spring instead of BlazeDS. Messages are routed



to the Spring-managed MessageBroker via the Spring DispatcherServlet.



Lets modify the web.xml with the configuration required to handle the requests from Flex.



Web.xml



<?xml version="1.0" encoding="UTF-8"?>
<!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>

<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>/WEB-INF/app-config/applicationContext.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>/spring/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>

</web-app>


Since we are using the MessageBroker which is managed by Spring so we have to register it in the Spring IOC container applicationContext.xml



<bean 
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/*=springManagedMessageBroker
</value>
</property>
</bean>

<!-- Dispatches requests mapped to a MessageBroker -->
<bean
class="org.springframework.flex.servlet.MessageBrokerHandlerAdapter"/>

<!-- Bootstraps and exposes the BlazeDS MessageBroker -->
<bean id="springManagedMessageBroker"
class="org.springframework.flex.core.MessageBrokerFactoryBean" />


Also we need to expose our service beans to flex remoting



<bean id="myServiceRO" class="org.springframework.flex.remoting.RemotingDestinationExporter">
<property name="messageBroker"
ref="springManagedMessageBroker"/>
<property name="service" ref="consDbService"/>
<property name="destinationId" value="myService" />
<property name="channels" value="my-amf, my-secure-amf"/>
</bean>


Now lets register the channels my-amf in the BlazeDS configuration files (remoting-config.xml and services-config.xml)



remoting-config.xml



<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
class="flex.messaging.services.RemotingService">
<adapters>
<adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
</adapters>
<default-channels>
<channel ref="my-amf"/>
</default-channels>
</service>
services-config.xml
<channels>

<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/spring/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>false</polling-enabled>
</properties>
</channel-definition>
</channels>

image

Deploy the application on your favourite web server.



I am using Tomcat



Flex



In this application, Flex makes an RPC call to the BlazeDS server to consume the getProjects we created in Spring.



So lets create the flex application which will make RPC calls to the spring services we defined.



SampleApp.mxml



<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
pageTitle="Projects List"
layout="absolute"
width="100%"
height="100%"
initialize="initializeHandler()" borderColor="#009DFF"
creationComplete="initializeHandler()">

<mx:RemoteObject
id="ro"
destination="myService"
endpoint="http://localhost:8080/SampleApp/spring/messagebroker/amf"
result="resultHandler(event)"
fault="faultHandler(event)"
showBusyCursor="true"
/>

<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.utils.ObjectUtil;
import mx.controls.Alert;
import mx.utils.StringUtil;


[Bindable]
private var systemsData:ArrayCollection = new ArrayCollection();

private var selectedItem:Object;

private function initializeHandler():void
{
ro.getProjects();
}

private function resultHandler(event:ResultEvent):void
{
systemsData = ArrayCollection(event.result);
}

private function faultHandler(event:FaultEvent):void
{
Alert.show(ObjectUtil.toString(event.fault) );
}

]]>
</mx:Script>


<mx:VBox width="100%" height="100%" y="10" x="10">
<mx:ApplicationControlBar width="100%" height="81" borderColor="#F7FAFC" fillColors="[#009DFF, #009DFF]" fillAlphas="[0.53, 0.53]" autoLayout="true" themeColor="#F6F8F9">
<mx:Text text="Project List" fontSize="26" fontWeight="bold" fontStyle="italic" themeColor="#9E5814" alpha="0.52" color="#F4FAFB" width="310"/>
</mx:ApplicationControlBar>
<mx:HBox x="10" y="10" width="100%" height="100%" id="hbox1">

<mx:Panel id="systemStatus" width="100%" height="100%" layout="absolute" cornerRadius="0" borderColor="#009DFF" fontSize="13" backgroundAlpha="0.5" backgroundColor="#009DFF">
<mx:VBox label = 'Report' borderColor="#009DFF" borderStyle="solid" borderThickness="6" backgroundColor="#009DFF" x="33" y="9">
<mx:DataGrid
id="dgrid"
updateComplete=""
dataProvider="{systemsData}"
width="622" height="362"
bottom="0" right="0" alternatingItemColors="[#F7F7F7, #BDE7E8]" themeColor="#32C582" borderThickness="5" borderStyle="solid" borderColor="#009DFF">
<mx:columns>
<mx:DataGridColumn fontSize="9" headerText="Project Name" dataField="project" />
<mx:DataGridColumn fontSize="9" headerText="Last Updated" dataField="lastUpdated">
<mx:itemRenderer>
<mx:Component>
<mx:VBox>
<mx:DateFormatter id="formatDateTime" formatString="MM/DD/YY" />
<mx:Label text="{formatDateTime.format(data.lastUpdated)}"/>
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn fontSize="9" headerText="Owner Name" dataField="ownerName" />
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:Panel>
</mx:HBox>
</mx:VBox>
</mx:Application>


Once done copy the sampleApp.html, sampleApp.swf, AC_OETags.js and playerProductInstall.swf in your web application and you should be able to view the application deployed on tomcat as below:



clip_image002[5]



References



Oct 10, 2009

Flex – Multi View Design Pattern

Problem

  • Need to develop a flex web application which is going to be deployed in different environment say in mobile and web.
  • Need to come up with different views for different devices and for different resolution. But the base view logic (event handling and state) should be same.

Solution

Follow the flex multi-view design pattern.

Multi - View Design Pattern

Multi-View design pattern uses passive design pattern and factory design pattern.

clip_image002

Passive View Design Pattern

The Passive View pattern is a derivative of the Model View Presenter (MVP), which is considered a derivative of the Model-view-controller. The Passive View pattern has some similarities to the “Code Behind” implementation, since both achieve a complete separation of Action Script logic and MXML or AS component tags. The passive presentation model allows us to easy test our application since we can create test cases just for the logic and if needed test cases for the view.

In passive view pattern we split our laundry to two piles, view and presenter:

View

  • View is passive and is not aware of the Presenter.

Presenter

  • Logic is in the Presenter.
  • Presenter observes view events.
  • Presenter updates the view data.
  • Presenter ‘knows’ about the components in the view.
  • Presenter holds the data or point to a data class.

By moving all the logic out of the view, the Passive View pattern can achieve the separation of designer and developer work and create a paradigm where it’s easy to change the view. The view class contains only the components and their states, no events, logic, changes or model.

Factory Design Pattern

Now throw in the mix the factory design pattern and you can actually create few views for each presenter.
The factory pattern is one of the most basic creational patterns that deal with the problem of creating different products without specifying the exact concrete class that will be created. This is done by creating a separate method for creating the product abstract class, whose subclasses can override to specify the derived type of product that will be created.

Sample Application

This sample application provides more clarity on multiple view design pattern. Basic view is to provide more granularities on design issues. Below are the screen snapshots.

  • The application will have multiple views of same screen.
  • ‘Submit’ button on both the screens will handle the same business logic at one point. There is no duplicate code to handle the same functionality in each screen.

Screen 1: To select different resolution.

clip_image004

Screen 2: User selects 400 X 300 screen size.

clip_image006

Screen 3: User selects 800 X 500 screen size.

clip_image008

Read the below steps for better understanding of the code. To implement multi view design pattern follow the below steps

  • Create an abstract action script view class. This class should extend mx.core.UIComponent. All user defined mxml should extend this class. In our example this class name is AbstractPassiveMainView.as. This abstract class should hold all the components that will be used by presenter.
  • Presenter knows the logic and has all control on view components. In our example ‘submit’ button event handling will be handled using the presenter class (Presenter.as).
  • Factory class is used to create instance for mxml or view classes.
  • Creator class is used to get the mxml object and passes through presenter for business handling.

Source Code Explanation

MultiViewApplication.mxml – This is the main application mxml file. This screen has a drop down which allows user to select different views. On value change loadView() action script method will be called. This loadView() method invokes the Creator object and adds the child to Canvas container.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#6797CE" backgroundGradientColors="[#ffffff,#6797CE]">
<mx:Script>
<![CDATA[
import mx.core.Container;
import view.Factory;
import view.AbstractPassiveMainView;
import mx.events.FlexEvent;
protected function loadView(event:Event):void
{
containerView.removeAllChildren();
var creator:Creator = new
Creator(event.currentTarget.selectedItem);
containerView.addChild(creator);
}
]]>
</mx:Script>
<mx:ComboBox x="139" y="29" change="loadView(event)">
<mx:ArrayCollection>
<mx:String>select</mx:String>
<mx:String>400 X 300</mx:String>
<mx:String>800 X 500</mx:String>
</mx:ArrayCollection>
</mx:ComboBox>
<mx:Canvas x="10" y="63" id="containerView"/>
<mx:Label x="10" y="31" text="Select Resolution:" fontSize="12"/>
</mx:Application>


Creator.as - This action script class decides which view to be loaded. Here we are getting the view instance using factory design pattern.



package
{
import mx.core.UIComponent;
import view.AbstractPassiveMainView;
import view.Factory;
import view.presenter.Presenter;
public class Creator extends UIComponent
{
private var mainView:AbstractPassiveMainView;
private var presenter:Presenter;
public function Creator(displayMode:String)
{
if(displayMode == "400 X 300")
{
mainView = Factory.createView(Factory.PASSIVE_MAIN_VIEW_1);
this.addChild(mainView);
presenter = new Presenter(mainView);
}
else if(displayMode == "800 X 500")
{
mainView = Factory.createView(Factory.PASSIVE_MAIN_VIEW_2);
this.addChild(mainView);
presenter = new Presenter(mainView);
}
}
}
}


Factory.as - This action script class is used to create view objects.



package view
{
import flash.errors.IllegalOperationError;
import view.mainview1.PassiveMainView1;
import view.mainview2.PassiveMainView2;
public final class Factory
{
public static const PASSIVE_MAIN_VIEW_1:int = 0;
public static const PASSIVE_MAIN_VIEW_2:int = 1;
public static function
createView(type:Number):AbstractPassiveMainView
{
var retVal:AbstractPassiveMainView;
switch (type)
{
case PASSIVE_MAIN_VIEW_1:
retVal = new PassiveMainView1();
break;
case PASSIVE_MAIN_VIEW_2:
retVal = new PassiveMainView2();
break;
throw new IllegalOperationError("The view type "
+ type + " is not recognized.");
}
return retVal;
}
}
}


PassiveMainView1.as – This is a view which includes our registartion1.mxml(400 X 300). I haven’t created this submit button in Registartion1.mxml because this button instance should be part of AbatractPassiveMainView.



package view.mainview1
{
import mx.controls.Button;
import view.AbstractPassiveMainView;
import view.subview.PassiveSubView1;
public class PassiveMainView1 extends AbstractPassiveMainView
{
public var registrationView:RegistrationView1;
public function PassiveMainView1()
{
registrationView = new RegistrationView1();
button = new Button();
button.label = "Submit";
button.x = 206;
button.y = 157;
registrationView.addChild(button);
this.addChild(registrationView);
passiveSubView = new PassiveSubView1();
this.addChild(passiveSubView);
}
}
}




RegistartionView1.mxml – plain mxml.



<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow title="New Registration" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" borderStyle="inset" xmlns:view="view.mainview1.*" width="400" height="300" showCloseButton="true" headerColors="[#000000,#000000]">
<mx:Label x="43" y="57" text="Name"/>
<mx:TextInput x="111" y="53"/>
<mx:Label x="43" y="85" text="Address 1"/>
<mx:TextInput x="111" y="83"/>
<mx:Label x="43" y="113" text="Address 2"/>
<mx:TextInput x="111" y="111"/>
</mx:TitleWindow>


PassiveMainView2.as - This is another view which includes our registartion2.mxml (800 X 500). I haven’t created this submit button in Registration1.mxml because this button instance should be part of AbatractPassiveMainView.



package view.mainview2
{
import mx.controls.Button;
import view.AbstractPassiveMainView;
import view.subview.PassiveSubView1;
public class PassiveMainView2 extends AbstractPassiveMainView
{
public var registrationView2:RegistrationView2;
public function PassiveMainView2()
{
registrationView2 = new RegistrationView2();
button = new Button();
button.label = "Submit";
button.x = 595;
button.y = 239;
button.width = 102;
registrationView2.addChild(button);
this.addChild(registrationView2);
passiveSubView = new PassiveSubView1();
this.addChild(passiveSubView);
}
}
}



RegistrationView2.mxml



<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow title="New Registration" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
borderStyle="inset" xmlns:view="view.mainview1.*" width="800" height="500" showCloseButton="true" headerColors="[#000000,#000000]">
<mx:Label x="43" y="57" text="Name"/>
<mx:TextInput x="43" y="83" width="654"/>
<mx:Label x="43" y="114" text="Address 1"/>
<mx:TextInput x="43" y="134" width="654"/>
<mx:Label x="43" y="164" text="Address 2"/>
<mx:TextInput x="43" y="190" width="654"/>
</mx:TitleWindow>


AbstractPassiveMainView.as - The abstract class holds all the components that will be used by presenter. This button object is nothing but the submit button that I have used in the above 2 mxml.



package view
{
import mx.controls.Button;
import mx.core.UIComponent;
public class AbstractPassiveMainView extends UIComponent
{
public var button:Button;
public var passiveSubView:AbstractPassiveSubView;
public function AbstractPassiveMainView()
{
}
}
}


AbstractPassiveSubView.as



package view
{
import mx.controls.Button;
import mx.core.UIComponent;
public class AbstractPassiveMainView extends UIComponent
{
public var button:Button;
public var passiveSubView:AbstractPassiveSubView;
public function AbstractPassiveMainView()
{
}
}
}


PassiveSubView1.as – This is the output view. Here on click of submit button I‘m displaying a message ‘Data Added Successfully’.



package view.subview
{
import mx.controls.Text;
import view.AbstractPassiveSubView;
public class PassiveSubView1 extends AbstractPassiveSubView
{
public function PassiveSubView1()
{
text = new Text();
text.y = 60;
text.x = 50;
text.width = 250;
text.height = 20;
text.setStyle("color", "0xfa0303");
text.text = "Data Added Successfully.";
text.visible = false;
this.addChild(text);
}
}
}


Presenter.as - The presenter handles the logic of the main application, as well as using sub presenter and sub view if needed. Here I have added the ‘Submit’ button event. Logic is in the presenter. Presenter ‘knows’ about the components in the view.



package view.presenter
{
import flash.events.MouseEvent;
import view.AbstractPassiveMainView;
public class Presenter
{
// Corresponding view
private var passiveMainView:AbstractPassiveMainView;
// Sub-presenters
private var subPresenter:SubPresenter;
public function
Presenter(passiveMainView:AbstractPassiveMainView)
{
this.passiveMainView = passiveMainView;
subPresenter = new
SubPresenter(passiveMainView.passiveSubView);
passiveMainView.button.addEventListener(
MouseEvent.CLICK, onButtonClick);
}
private function onButtonClick(event:MouseEvent):void
{
subPresenter.setTextLabelVisible(true);
}
}
}


SubPresenter.as 



package view.presenter
{
import view.AbstractPassiveSubView;
public class SubPresenter
{
private var passiveMainSubView:AbstractPassiveSubView;
public function
SubPresenter(passiveMainSubView:AbstractPassiveSubView)
{
this.passiveMainSubView = passiveMainSubView;
}
public function setTextLabelVisible(isVisible:Boolean):void
{
passiveMainSubView.text.visible = isVisible;
}
}
}


References





Text Widget

Copyright © Vinay's Blog | Powered by Blogger

Design by | Blogger Theme by