Статьи

Ввод данных в приложения Flex — Введение

В этой статье будут описаны наиболее распространенные способы переноса данных в приложение Flex, а также будут представлены преимущества и недостатки каждого подхода. Предполагается, что читатель имеет базовое понимание языка Flex.

В отличие от классического веб-приложения (под классическим я имею в виду pre AJAX), где страницы генерируются на сервере, приложение Flex загружается при запуске и выполняет вызовы для загрузки или сохранения данных. Конечно, приложение Flex также может отправлять запросы для загрузки других модулей Flex таким же образом, как приложение Java может динамически загружать библиотеки JAR, но это тема другой статьи.

Некоторые из представленных решений не зависят от сервера — вы можете использовать все что угодно на сервере — другие предполагают, что вы установили сервер приложений Java, на котором вы можете развертывать различные решения, включая BlazeDS, Livecycle Data Services, GraniteDS, WebORB и т. Д.

а) Открытие сокетного соединения между приложением Flex и серверной частью.

Гнездовое соединение Это наиболее низкоуровневое и в то же время наиболее гибкое решение. Вам нужно будет определить собственный протокол и порядок сериализации данных (или использовать протоколы AMF / Hessian). В большинстве случаев вам следует использовать это решение только в том случае, если у вас есть очень специфические потребности бизнеса и существующие решения не соответствуют вашим требованиям).

Вы можете использовать Apache MINA, если вы собираетесь это сделать. Например, сервер Red5 Flash был написан с использованием инфраструктуры MINA.

Ниже приведен простой фрагмент кода, который показывает, как создать сокет и как читать или записывать данные:

public function initConnection():void{
    CursorManager.setBusyCursor();
    Security.loadPolicyFile(“xmlsocket://localhost:24?);
	socket = new Socket();
	socket.addEventListener( Event.CONNECT, onConnect );  
	socket.addEventListener(ProgressEvent.SOCKET_DATA, socketRead);    
	socket.addEventListener(ErrorEvent.ERROR, errorHandler);    
	socket.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);    
	socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler);    
	socket.connect(“localhost”, 23);}
	
	public function socketWrite(event:Event){    
	socket.writeUTF(inputName.text);    
	socket.flush();}
	public function socketRead(event:ProgressEvent){  
	while ( socket.bytesAvailable ) {        
	var data:String = socket.readUTF();        
	Alert.show(data);  }}

Вы, вероятно, заметили строку Security.loadPolicyFile (”xmlsocket: // localhost: 24 ″); По умолчанию приложение Flex может открывать подключения только к тому же домену, откуда оно было загружено, и к тому же порту. Чтобы иметь возможность инициировать подключения к другому домену, на этом сервере должен существовать файл с именем crossdomain.xml. Этот файл указывает, какие ресурсы доступны и для каких доменов. В нашем случае файл политики позволит всем подключенным SWF-файлам, загруженным из любого домена, подключиться к порту 23.

<cross-domain-policy>    
<allow-access-from domain=“*” to-ports=“23″ />
</cross-domain-policy>

 Дополнительные сведения о файлах политики и безопасности Flash см. В этой документации.

б) Использование сервисов REST и SOAP (через компоненты HTTPService и WebServices)

Службы REST и SOAP работают с любыми типами серверных технологий — эти технологии также являются стандартными, и большинство крупнейших поставщиков услуг (Yahoo, Amazon, Google, Flickr, eBay) предоставляют свои API через них обоих. Существует бесконечная дискуссия о том, когда использовать REST и когда использовать SOAP, но это выходит за рамки этой статьи. Вместо этого я представлю несколько примеров того, как их использовать.

Как и в примере с сокетами, поскольку приложение Flex может инициировать запросы только в тот же домен, откуда он был загружен, вам потребуется файл crossdomain.xml на сервере, где расположены службы. Очевидно, что вы не можете разместить файлы политики на каждом сервере, поэтому используйте следующий подход: подключитесь к внутреннему серверу, с которого было загружено приложение Flex, и используйте этот сервер для выполнения запроса — после этого отправьте результат обратно в приложение Flex. Для этого вы можете использовать существующий продукт — BlazeDS или другое решение.

Ниже приведен пример кода, показывающий два тега mxml, используемые для вызова служб REST и SOAP:

<mx:HTTPService id=“resultHttpService”
     url=“http://www.sampledomain.com/query.jsp?quote=ADBE” />
<mx:WebService id=“resultWebService”
     wsdl=“http://www.sampledomain.com/quotes?wsdl” />

 

В этом случае я подключаюсь напрямую к домену sampledomain, поэтому в первый раз Flash Player проверит наличие файла crossdomain.xml, чтобы узнать, разрешает ли сервер запрос.

Чтобы использовать прокси-подход (используйте сервер для выполнения запроса), я изменю код:

<mx:HTTPService id=“resultHttpService” destination=“HTTPDestination” useProxy=“true” />
<mx:WebService id=“resultWebServive” destination=“WebServiceDestination” useProxy=“true” />

 

и в proxy-config.xml я добавлю определение назначения:

<destination id=“resultHttpService”>
    <properties>
	<url>http://www.domain.com/query.jsp?quote=ADBE</url>
    </properties>
</destination>
<destination id=“ws-catalog”>
    <properties>
	<wsdl>http://www.domain.com/quotes.wsdl</wsdl>
	<soap>*</soap>
    </properties>
    <adapter ref=“soap-proxy”/>
</destination>

 

В примере REST очень важно отметить, что из-за ограничений Flash Player вам разрешено использовать только методы GET и POST, и любой код возврата, отличный от 200, вызовет ошибку. Чтобы преодолеть эти ограничения, вы можете написать свой собственный прокси-сервер или, что еще лучше, использовать уже написанный (например, BlazeDS).

в) Использование удаленного взаимодействия

Технология удаленного взаимодействия позволяет разработчикам напрямую вызывать методы на внутреннем сервере. Первоначально это было возможно только с Java и Coldfusion, но после этого появились различные реализации для PHP, Python, Ruby и .Net. Также есть несколько других реализаций, которые используют протокол Hessian. Ниже я приведу несколько примеров для языка Java, используя BlazeDS.

Тег mxml из приложения Flex выглядит так же, как те, что используются для вызова веб-сервисов — основными атрибутами являются идентификатор и место назначения

<mx:RemoteObject id=“productService” destination=“ProductService”/>

Место назначения настраивается в файле remoting-config.xml:

<destination id=“productService”>
    <properties>
	<source>
	com.test.services.ProductService
	</source>
    </properties>    
	<adapter ref=“java-object” />
</destination>

 

Удаленный объект позволяет вам вызывать методы объекта Java, связанного с соответствующим назначением. Все остальное прозрачно с точки зрения пользователя (включая преобразование между ActionScript и объектами Java и механизм сериализации, который может обрабатывать граф сложных объектов). Вам нужно только объявить сопоставление между ActionScript и объектами Java с помощью метаданных [RemoteClass]:

package com.test.model{
    [RemoteClass(alias="com.test.model.Product")]
    public class Product{
        public var id:int;
        public var name:String;
    }}

 

Перед тем, как начать использовать удаленное взаимодействие, рекомендуется прочитать эту ссылку, описывающую преобразование типов данных между Java и ActionScript.

Важно отметить, что при каждой операции ввода-вывода удаленный метод также вызывается асинхронно, поэтому вам необходимо зарегистрировать обработчики для событий результата и сбоя.

г) Использование сообщений

В настоящее время на рынке имеется несколько решений для обмена сообщениями для приложений Flex: BlazeDS (и коммерческая версия Livecycle Data Services), Granite Data Services и WebORB. Все они также имеют интеграцию с JMS-серверами.

С помощью обмена сообщениями приложение Flex может подключаться к месту назначения сообщений на сервере (указанному в messaging-config.xml) и может обмениваться сообщениями с сервером или другими клиентами (используя сервер в качестве прокси-сервера). Вы можете использовать обмен сообщениями, чтобы сервер отправлял сообщения клиентам (например, в приложении, которое отображает последние цены на акции), и вы можете использовать его для совместной работы между клиентами (например, приложение чата).

Одна из самых важных вещей при работе с сообщениями — это выбор правильного канала связи для получения сообщений в реальном времени. Сервер BlazeDS поддерживает потоковую передачу HTTP и опрос (короткий и длинный) по каналам AMF и HTTP. Потоковая передача по протоколу HTTP — лучший способ получения данных в режиме реального времени, но из-за ограничений модели сервлета он поддерживает один открытый поток на каждое соединение. Коммерческая версия (Livecycle Data Services ES) преодолевает это ограничение с помощью каналов NIO (RTMP и NIO HTTP).

Ниже приведен пример кода, который показывает основные теги, используемые для обмена сообщениями:

<mx:Producer id=“producer” destination=“chat”/>
<mx:Consumer id=“consumer” destination=“chat”/>

 

Целевой чат определяется ниже:

<default-channels>
    <channel ref=“my-rtmp”/>
    <channel ref=“my-streaming-amf”/>
</default-channels>
<destination id=“chat”>
    <properties>
	<network>
	<!--The session timeout for inactive HTTP sessions–>           
	<session-timeout>0</session-timeout>
	</network>
    </properties>
</destination>

 

Подробную информацию об обмене сообщениями можно найти в главе « Служба сообщений» руководства разработчика BlazeDS.

д) Использование службы управления данными

Служба управления данными — это функция, предоставляемая (на момент написания этой статьи) как в Livecycle Data Services ES, так и в WebORB. Оба продукта предлагают структуру, называемую «Управление данными», однако архитектуры различаются — в этой статье я расскажу только о структуре управления данными, предоставляемой Livecycle Data Services. Он работает на гораздо более высоком уровне, чем службы обмена сообщениями и RPC. Хотя он может использоваться для различных типов приложений, он обеспечивает наибольшую ценность для приложений, интенсивно использующих данные (особенно там, где совместная работа очень важна). Он предназначен для решения нескольких важных задач:

  • синхронизация данных о клиентах с сервером без необходимости писать методы CRUD
  • автоматическая или ручная синхронизация данных между клиентами
  • обработка конфликтов, наборы данных подкачки, работа с автономными приложениями и синхронизация данных при повторном подключении приложения

Можно провести сравнение между Data Management и Hibernate — обе платформы позволяют разработчикам сконцентрироваться на определении модели домена и работе с ней, не тратя слишком много времени на такие проблемы, как сохранение, загрузка, версия и синхронизация данных. Hibernate имеет дело с сохранением данных в базе данных, управление данными с сохранением данных и синхронизацией между клиентскими приложениями и сервером. Существует также интеграция между этими двумя фреймворками, и я приложил полностью рабочий пример, демонстрирующий это.

Как и в случае с сообщениями, очень важно выбрать правильные каналы связи (особенно для функции автоматической синхронизации). Те же варианты, которые описаны в примере обмена сообщениями, применяются и здесь

Вот простой пример, который показывает, как легко создать приложение для редактирования таблицы:

Код Flex:

<?xml version=“1.0? encoding=”utf-8?><mx:Application xmlns:mx=“http://www.adobe.com/2006/mxml” layout=“absolute” initialize=“init();” >
    <mx:Script>
	<![CDATA[
	import test.*;
	import mx.collections.ArrayCollection;
	import mx.data.events.*;
	import mx.events.*;
	import mx.data.*;
	var    companyDataService = new DataService("test.Company");
	[Bindable]
	var companyArray:ArrayCollection = new ArrayCollection();
	function addCompany():void{
	var company:Company = new Company();
	company.name=“<new company>”;
	companyArray.addItem(company);
	}
	function deleteCompany():void{
	var company:Company = companyGrid.selectedItem as Company;
	if (company==null)
	return;
	companyDataService.deleteItem(companyGrid.selectedItem);
	}
	function save():void{
	companyDataService.commit();
	}
	function revert():void{
	companyDataService.revertChanges();
	}
	function init():void{
	companyDataService.fill(companyArray,“mainFill”,[]);               
	companyDataService.autoCommit=false;
	}
	]]>
    </mx:Script>
    <mx:VBox width=“100%” height=“100%” horizontalAlign=“center” > 
	<mx:DataGrid  id=“companyGrid” width=“40%” height=“40%” dataProvider=“{companyArray}” 
	editable=“true” textAlign=“center”>
	<mx:columns> 
	<mx:DataGridColumn dataField=“id”  headerText=“Id” editable=“false”/>
	<mx:DataGridColumn dataField=“name”  headerText=“Company”/>
	</mx:columns>
	</mx:DataGrid> 
	<mx:HBox horizontalAlign=“center” width=“100%”>
	<mx:Button label=“+” click=“addCompany();”/> 
	<mx:Button label=“-” click=“deleteCompany();”/>
	</mx:HBox>
	<mx:HBox width=“100%” horizontalAlign=“center”>
	<mx:Button label=“Save changes” click=“save();”/>
	<mx:Button label=“Revert modifications” click=“revert();”/> 
	</mx:HBox>
    </mx:VBox>
	</mx:Application>

 

Определение объекта DataService находится в файле конфигурации data-management-config.xml.

<destination id=“test.Company” channels=“my-rtmp”>
    <properties>
        <source>flex.data.assemblers.HibernateAnnotationsAssembler</source>
        <scope>application</scope>
        <item-class>test.Company</item-class>
        <metadata>
            <identity property=“id” />
        </metadata>
        <server>
            <hibernate-entity>test.Company</hibernate-entity>
        </server>
    </properties>
</destination>

 

Как видите, вызовов удаленного взаимодействия нет — после того, как коллекция companyArray заполнена данными, вы можете манипулировать данными, добавляя новые элементы, удаляя или обновляя элементы. У вас есть возможность вызвать сохранение, если вы хотите сохранить изменения или отменить их, если решите отказаться от них.

Можно работать с более сложными моделями доменов (ассоциациями между объектами), и вы можете найти один пример этого.

Data Management is the most appealing approach for bringing data into a Flex application, but like Hibernate case it has a steep learning curve. Documentation related to it can be found in LCDS developer guide.

The following table summarizes the advantages and disadvantages for each solution:

Pros Cons
Socket communication The most flexible approach. Allows you to write your own server using whatever technology do you want obtaining the best performance. It takes a lot of time and money to define your protocol and write your server. It can be useful if you intend to communicate with an already written server or for cases in which you need extremely high performance
REST/SOAP services Well established standards, you can wrote them once and consume them from most of the systems, not just Flex applications. Also most of the companies expose their api through REST and SOAP services The overhead of parsing data (especially for SOAP) can be substantial
Remoting Little overhead compared with web services. Automatic conversion between Action Script and the Java objects (or another language) Sometimes the data exposed through services needs to be consumed by a variety of applications – this is possible using web services but not with remoting
Messaging Ability to implement collaboration features. Integration with JMS There are relatively few solutions that implements messaging. As the writing of this article only BlazeDS and LCDS from Adobe (if your backend is Java) and WebORB (if your backend is Java, PHP, .NET)
Data Management (LCDS) The time needed to implement a data driven application is reduced. It offers solutions for collaboration, conflict detection, dealing with complex domain objects, pagination and lazy loading. It also offers integration with Hibernate and Spring There is only one commercial product for this solution – LCDS from Adobe. It has a relatively steep learning curve

I have also attached an archive containing one Flex Builder project showing the data transfer using sockets and also a more advanced case of data management use. For the rest of the cases I recommend that you download the most recent version of BlazeDS (look in samples folder) or LCDS (look in the lcds-samples folder). If you want to use non Adobe products you can try WebORB (look in examples/flex folder) or GraniteDS (I was not able to find a folder with samples in this product).

From http://cornelcreanga.com/