Построение клиент-серверного приложения с помощью Macromedia Flash Data Connection Wizard и ColdFusion



Для изучения материалов этой статьи вы должны обладать хорошим практическим опытом в ColdFusion MX, а именно, в работе с ColdFusion Компонентами. Также, нам понадобится установить последнюю версию Flash MX Professional 2004.

 

Что мы создадим?

Самым лучшим способом понять интеграцию Flash и ColdFusion - это создать некое приложение. В этой статье говорится не о всех возможностях и опциях Flash, а только о некоторых их них. Впрочем, статья расскажет, как создать полное приложение. Приложение будет отображать данные на стороне клиента. Его возможности:

И все будет работать без перезагрузки экрана браузера!

 

Требования

Для изучения этой статьи нам понадобится установить следующее программное обеспечение и файлы:

 

Установка и настройка

Чтобы убедиться, что дополнительные модули установлены, откройте любой Flash документ в Flash MX Professional 2004. Откройте меню Commands. Если они установлены, то вы увидите меню Data Connection Wizard. Дополнение DataGrid Column editor будет использовано через Data Connection Wizard, поэтому в меню Commands его не видно.

После установки всего программного обеспечения проделайте следующее:

 

Веб служба на стороне ColdFusion

Для получения списка пользователей и списка отделов, создадим в CFC два метода: ListDepts и ListByDept. Скопируйте и вставьте в employees.cfc следующий код:

Потом мы добавим в компоненту еще методы, но пока нам нужны только эти два.

Обратите внимание, что в обоих методах указано ACCESS="remote". Этот атрибут следует использовать для того, чтобы определить компоненту как веб службу и Flash на стороне клиента сможет вызывать эти методы.

 

Тестируем код на стороне сервера

Перед тем, как идти дальше, убедимся, что ColdFusion компонента работает правильно. Отладка проблем в CFML из среды Flash сложно; как правило, всегда первым делом лучше независимо тестировать серверную часть.

Следующий CFML код вызывает компоненту employees.cfc, чтобы отобразить список отделов и позволяет пользователям щелкать на название отдела, чтобы посмотреть его сотрудников.
Сохраним этот код в новом файле emplist.cfm в папке cfflash и запустим его (результат будет как на рисунке 1). Теперь мы готовы создавать Flash клиента.

HTML версия приложения
Рисунок 1. HTML версия приложения "сотрудники по отделам"

 

Подготавливаем Flash

Чтобы подготовиться к работе с Flash, выполним следующие шаги:

  1. Запускаем Flash MX Professional 2004. Создаем Flash Form Application выбрав File > New > Flash Form Application.
  2. Сохраняем файл как employees.fla в папке cfflash.
  3. Flash Form Applications включает несколько окон, которые можно показывать и срывать. Экраны (формы) отображаются в окне Screens слева от сцены. По-умолчанию, Flash называет верхний уровень формы application и создает дочернюю форму с именем form1. Двойным щелчком мыши выделим форму form1, а затем переименуем ее в data, т.к. эта форма будет содержать наборы данных. Наш экран будет выглядеть как показано на рисунке 2.
  4. Сохраним изменения.

Flash Forms Applications состоит из множества экранов (форм), организованных в виде иерархии
Figure 2. Flash Forms Applications состоит из множества экранов (форм), организованных в виде иерархии

Перед тем как использовать компоненту ColdFusion, Flash должен знать о ней (имя CFC, ссылка, методы и т.д.). Чтобы зарегистрировать ColdFusion компоненту в Flash, выполним следующее:

 

Создаем таблицу для отделов

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

Создание таблицы с данными требует использования трех Flash компонент: сетка (grid); компонента WebServiceConnector, которая соединяется с компонентой ColdFusion; DataSet, которая связывает две эти компоненты и код путем доступа к полученным данным. Нам следует вручную перетащить все три компоненты на сцену из панели Flash Components, указать требуемые свойства и связать их вместе. Или же мы можем использовать Data Connection Wizard, который создаст большинство работы за нас. Выполняем следующее:
  1. Выберем Commands > Data Connection Wizard. В результате запустится окно (Рисунок 5).

    Data Connection Wizard упрощает соединение веб служб и XML данных
    Рисунок 5. Data Connection Wizard упрощает соединение веб служб и XML данных

  2. Диалоговое окно запрашивает указать источник данных, выбираем Web Service из выпадающего меню и нам будет показан список всех зарегистрированных вею служб (включая и ту, которую мы только что создали).
  3. Раскроем ветку employeesService, чтобы открыть ее методы.
  4. Раскроем метод ListDepts, чтобы открыть его атрибуты и результаты.
  5. Нажимаем на Results. (Для заполнения таблицы мы используем результаты метода ListDepts.)
  6. Нажимаем Next.
  7. На этом этапе, возможно, вы ожидали увидеть список полей данных, доступных в результате, но если вы используете ColdFusion, то этого не происходит. Нам следует вручную указать список полей.
  8. Нажимаем Next.
  9. Тут мы можем добавлять, обновлять и удалять поля. Нажимаем кнопку Add Field и добавляем поле с именем DEPARTMENTID с типом данных String (колонки запроса ColdFusion должны быть в верхнем регистре).
  10. Давим второе поле DEPARTMENTNAME с типом данных String (Рисунок 6).

    При использовании ColdFusion компонент, имена полей должны быть указаны вручную
    Рисунок 6. При использовании ColdFusion компонент, имена полей должны быть указаны вручную

  11. Нажимаем Next, чтобы перейти к заключительному окну диалога.
  12. Здесь мы должны дать компоненте имя. Укажем dept как Label for Generated Components. Две галочки оставляем нажатыми (первая говорит о том, что диалоговое окно создаст таблицу данных, а вторая вставит кнопку, которую пользователь может нажать и выполнить запрос веб службы) как на Рисунке 7.

    Модуль по желанию может создать Таблицу с данными (DataSets) и кнопку для вызова данных
    Рисунок 7. Модуль по желанию может создать Таблицу с данными (DataSets) и кнопку для вызова данных.

  13. Нажимаем Finish.
Теперь на сцене должны появиться четыре компоненты: WebServiceConnector, DataSet, DataGrid и Button. Нажмите на лубую из первых трех и посмотрите на вкладки панели Component Inspector. Здесь есть параметры, которых не было в Data Connection Wizard, но мы должны их указать. (Нам придется воспользоваться панелью Component Inspector позже). Теперь тестируем приложение:
  1. Сохраним наши изменения с помощью File > Save.
  2. Выбираем Control > Test Movie и запускаем приложение.
  3. Появилась пустая таблица данных. Чтобы вызвать данные, нажмем на кнопку Get Data; Flash соединится с ColdFusion через WebServiceConnector, получит данные из метода ListDepts ColdFusion компоненты, и использует результат, чтобы заполнить DataSet, который заполняет DataGrid (Рисунок 8).

    Работа DataGrid без использования кода
    Рисунок 8. Работа DataGrid без использования кода

  4. Чтобы прекратить тест приложения, закройте файл, щелкнув по кнопке (X).

 

Заканчиваем создание таблицы для отделов

По-умолчанию таблица слишком большая и у нас нет места для добавления еще одной, поэтому мы отрегулируем ее местоположение и размер:

  1. Перемещение таблицы может перекрыть иконки компонент WebServiceConnector и DataSet, поэтому мы переместим их все за сцену. (У них нет визуального интерфейса, поэтому нет разницы, где им находится.)
  2. Выбираем deptDataGrid.
  3. Если панель Properties не открыта, то откройте ее (Рисунок 9).

    Управление позицией и размером в инспекторе свойств
    Рисунок 9. Управление позицией и размером в инспекторе свойств.

  4. Установим позицию и размер такими: W=510, H=150, X=20, Y=20.
  5. Закрываем инспектор Property, если нужно больше свободного места на экране.
Перед тем, как перейти к следующей таблице, сделаем изменения с таблице отделов; сейчас интерфейс отображает name и id отделов, а нам нужно только name. В дополнение к этому, наша таблица должна наполнятся данными сразу, а не после нажатия кнопки.

Сперва займемся отображение колонок. По-умолчанию таблица отображает в своих наборах данных все колонки; чтобы изменить это, используем ActionScript код. К счастью, модуль может сделать это за нас. Выполним следующее:

  1. Выбираем deptDataGrid.
  2. Если панель Component Inspector не открыта, открываем ее.
  3. Нажимаем кнопку вызова модуля (иконка желтой звезды) в верхней правой стороне панели, и выбираем DataGrid Column Editor, чтобы запустить модуль (Рисунок 10).

    Модуль DataGrid Column Editor создает код для формирования таблицы данных
    Figure 10. Модуль DataGrid Column Editor создает код для формирования таблицы данных.

  4. Этот модуль следует использовать для обозначения тех колонок, которые мы хотим видеть в таблице данных, а также свойств каждой колонки. Нажав на Плюс (+), мы можем указать имена колонок вручную, или же мы можем импортировать их из DataSet. Нажимаем кнопку Import Columns, чтобы импортировать колонки DataSet; мы увидим колонки DEPARTMENTID и DEPARTMENTNAME.
  5. Чтобы исключить DEPARTMENTID, выбираем ее и нажимаем кнопку Минус (-).
  6. DEPARTMENTNAME (все заглавными буквами) не создает идеальную колонку, поэтому в поле Column Label наберем Department. Убираем галочку с параметра Editable и укажем setWidth в 500. (Колонка растянется по всей ширине таблицы.)
  7. Нажимаем OK. Модуль создаст около 20 линий ActionScript кода, который определяет свойства колонки таблицы. Снова нажимаем OK.
  8. Сохраняем изменения и запускаем приложение, выбрав Control > Test Movie (Рисунок 11).

    Для добавления, удаления или форматирования колонок таблицы, используем ActionScript код
    Рисунок 11. Для добавления, удаления или форматирования колонок таблицы, используем ActionScript код.

Далее мы удалим кнопку Get Data и напишем код, который будет сразу наполнять таблицу данными:
  1. Выделяем кнопку Get Data.
  2. Удаляем кнопку Get Data, нажав на клавиатуре Delete.
  3. Код, который будет сразу наполнять таблицу данными, должен быть вставлен в панели Actions. При этом ни один элемент на сцене не должен быть выделен, а в нижней части панели Actions имя фрейма должно быть data.
  4. Набираем в панели Actions следующий код:
    // Populate grid on startup
    on (reveal) {
       deptReceiveWebServiceConnector.trigger();
    }
  5. Сохраняем изменения и запускаем приложение, выбрав Control > Test Movie. Теперь таблица заполняется данными без нажатия на кнопку.
Набранный нами код нуждается в объяснении. Flash поддерживает события и при наступлении определенного события исполняет ассоциированный с этим событием код. В нашем случае, событие on(reveal) дает понять, что следует исполнить код, когда отображена текущая форма (форма data). Событие deptReceiveWebServiceConnector.trigger() просто переключает или исполняет службу deptReceiveWebServiceConnector. Это то, что выполняет кнопка Get Data.

 

Создаем таблицу для сотрудников

Далее, мы создадим таблицу сотрудников, которая будет показывать список сотрудников выбранного отдела. Снова начинаем с запуска модуля:

  1. Выделяем форму data.
  2. Запускаем Commands > Data Connection Wizard.
  3. Выбираем Web Service как тип источника данных.
  4. Выбираем веб службу employeesService и открываем ее метод ListByDept.
  5. Нажимаем на Results (т.к. для заполнения таблицы мы будем использовать результаты метода ListByDept). Нажимаем кнопку Next.
  6. Появится предупреждение о том, что метод требует передачи в него параметра, который мы пока еще не указали. (Мы должны передать в метод отдел, чтобы получить список сотрудников.) Пока нажимаем OK; укажем эти данные позже.
  7. Снова поля данных не отображены и нажимаем Next.
  8. Добавляем следующие поля:
    1. FIRSTNAME с типом данных string
    2. LASTNAME с типом данных string
    3. TITLE с типом данных string
    4. EMAIL с типом данных string
    5. STARTDATE с типом данных date, исходный формат даты у нас YYYY MM DD (формат даты, возвращаемой из ColdFusion), а отобразим его в виде MM-DD-YYYY
    6. EMPLOYEEID с типом данных string
    7. DEPTIDFK с типом данных string
  9. Нажимаем Next.
  10. Укажем emp как имя в Label for Generated Components. Первую галочку оставим выделенной, а вторую уберем. (Нам не нужно создавать кнопку.)
  11. Нажимаем Finish.
Далее подправим размер и позицию таблицы:
  1. Перетащим новые иконки WebServiceConnector и DataSet за сцену.
  2. Выделяем таблицу empDataGrid и панели Property укажем свойства: W=510, H=175, X=20, Y=180 (Рисунок 12).

    Управление позицией и размером в инспекторе свойств
    Рисунок 12. Управление позицией и размером в инспекторе свойств.

  3. Сохраняем изменения и запускаем приложение, выбрав Control > Test Movie.
Запустится приложение и покажет новую таблицу. Но таблица пуста, т.к. вторая веб служба не исполняется. Чтобы запустить веб службу, мы должны передать в метод id отдела:
  1. Выделяем иконку empReceiveWebServiceConnector.
  2. Открываем панель Component Inspector.
  3. Выбираем вкладку Bindings.
  4. Нажимаем кнопку Плюс (+), чтобы добавить binding. Появится диалоговое окно Add Binding.
  5. Доступные биндинги сгруппированы в params, посылаемые данные веб слуюбе; и results, возвращаемые веб службой данные. Нам нужно передать id тдела в метод; выделяем параметр DepartmentID и нажимаем OK.
  6. В панели Bindings появился новый биндинг, но он пока еще ни с чем не связан. Чтобы связать его, выделяем его и нажимаем на ряд bound to внизу.
  7. Нажимаем на иконку увеличительного стекла, чтобы вызвать список доступных параметров.
  8. Опции в диалоговом окне Bound To отображены иерархически. Привяжем значение к текущему выделенному id отдела, выбрав deptDataSet; затем выделяем DEPARTMENTID из списка справа (Рисунок 13).

    Диалоговое окно Bound To используется для выбора связующих данных
    Figure 13. Диалоговое окно Bound To используется для выбора связующих данных

  9. Нажимаем OK и новая связь появится в панели Component Inspector. Теперь, когда SWF исполняет метод, он также передает ему выбранный id отдела.
Нам нужно выполнять ListByDept каждый раз, когда меняется выделение в deptDataSet:
  1. На сцене выделяем deptDataSet. Имя компоненты мы можем смотреть либо в испекторе Property, либо внизу панели Actions.
  2. Набираем следующий код в панели Actions:
    // Get employees when department is selected
    on (iteratorScrolled) {
       _parent.empReceiveWebServiceConnector.trigger();
    }
  3. Сохраняем изменения и запускаем приложение, выбрав Control > Test Movie. Приложение загрузится как раньше, но на этот раз в нижней таблице показаны сотрудники выделенного отдела.
Каждый раз, когда меняется выделение в DataSet, выполняется событие iteratorScrolled. Здесь код выполняет веб службу empReceiveWebServiceConnector. _parent необходим, потому что все ссылки относительны. DataSet и WebServiceConnector вложены в форму data, поэтому _parent обращается к форме, а empReceiveWebServiceConnector затем обращается к коннектору внутри себя. Следует отметить, что следующий код также будет работать:
// Get employees when department is selected
on (iteratorScrolled) {
   _root.application.data.empReceiveWebServiceConnector.trigger();
}
_root ссылается к верхней ветви приложения; application - это форма верхнего уровня; data - это вложенный элемент application, а empReceiveWebServiceConnector - это вложенный элемент data. Результат тот же, но разница в том, что этот код использует абсолютный путь, а предыдущий - относительный. Как и в верхней таблице, мы можем использовать DataGrid Column Editor, чтобы подправить свойства колонок нижней таблицы. Сделайте это по своему усмотрению.

 

Создаем окно авторизации На данном этапе у нас есть рабочее приложение, которое демонстрирует вид master/detail, без обновлений экрана браузера. Это впечатляет само по себе. Но еще более впечатляющим будет добавление возможности добавлять, редактировать и удалять записи прямо в таблице.

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

Для начала создадим окно авторизации:
  1. Добавим новую форму в application, нажав кнопку Плюс (+) в управлении деревом формы.
  2. Эта новая форма будет содержать окно авторизации. щелчком мыши выделим форму form1, а затем переименуем ее в login (Рисунок 14).

    Каждая форма в форме application должна иметь уникальное имя
    Рисунок 14. Каждая форма в форме application должна иметь уникальное имя.

  3. Теперь в окно авторизации добавим некоторые компоненты формы. Перетащим компоненту Label из панели Components на сцену. Открываем панель Property (выбираем вкладку Parameters) и установим W=100, H=22, X=30, Y=20. Затем выделим поле text (на вкладке Parameters в панели Property) и укажем текст "Логин:".
  4. Поместим еще одну компоненту Label на сцену. Укажем W=100, H=22, X=30, Y=50 и текст "Пароль:".
  5. Перетащим компоненту TextInput на сцену. В панели Property назовем ее loginName и установим W=100, H=22, X=145, Y=20.
  6. Поместим еще одну компоненту TextInput на сцену. В панели Property назовем ее loginPassword и установим W=100, H=22, X=145, Y=50. Щелкнем на поле password и установим и его значение в true. Так пользователь, вводя пароль будет видеть только звездочки.
  7. Перетащим компоненту Button на сцену. В панели Property inspector назовем ее loginButton и установим W=100, H=22, X=35, Y=85. Щелкнем на поле label и укажем значение "Войти".
  8. Перетащим на сцену еще одну компоненту Button. В панеле Property назовем ее cancelButton и установим W=100, H=22, X=140, Y=85. Щелкаем на поле label и укажем здесь Отмена. Наша форма будет выглядеть как на рисунке 15.
  9. Теперь у нас есть полная форма. Сохраняем изменения и тестируем приложение.

    Форма авторизации содержит две компоненты Label, две компоненты TextInput и две кнопки
    Рисунок 15. Форма авторизации содержит две компоненты Label, две компоненты TextInput и две кнопки.

Flash формы по-умолчанию прозрачны
Рисунок 16. Flash формы по-умолчанию "прозрачны".

Рисунок 16 показывает, что форма автоматически показывается при старте приложения и перекрывает таблицу; очевидно, это не совсем правильно. По-умолчанию, все новые формы отображаются при старте приложения. Чтобы убрать это, проделаем следующее:
  1. Щелкнем на форму login в дереве форм.
  2. Открываем панель Property, а в ней вкладку Parameters.
  3. Выделяем параметр visible и установим его в false.
  4. Сохраняем и тестируем приложение. Теперь при старте приложения форма авторизации не видна.
Работая с множеством форм, есть полезная штука: Правой кнопкой мыши щелкните по любой форме и выберите Hide Screen, чтобы данная форма не показывалась, пока мы работаем с другими формами. Это не влияет на производительность.

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

  1. Добавим еще одну форму в application и назовем ее navLogin. Если нужно, чтобы кнопка появлялась при запуске приложения, укажите ее параметр visible в true.
  2. Выделим форму navLogin и добавим в нее компоненту Button. В панели Property назовем ее buttonLogin и укажем W=75, H=22, X=440, Y=370. В поле label укажем "Авторизация".
  3. Сохраним изменения и запустим приложение; мы увидим новую кнопку Авторизация. Щелчок по этой кнопке пока ничего не дает.
  4. Выделим кнопку Авторизация и откроем панель Actions. Панель Actions должна показывать buttonLogin на закладке ActionScript.
  5. Наберем в панели Actions следующий код (Рисунок 17):
    // Display login form
    on (click) {
      _root.application.login.visible=true;
    }

    Flash ассоциирует код с текущей выделенной формой или компонентой
    Рисунок 17. Flash ассоциирует код с текущей выделенной формой или компонентой

  6. Сохраняем изменения и запускаем приложение. Когда пользователь нажмет кнопку Авторизация, наше приложение покажет форму авторизации.
Интерфейс пользователя все еще неуклюжий. Таблицы видны сквозь окно авторизации и пользователи могут использовать их во время отображения формы авторизации. Нам нужно сделать так, чтобы окно авторизации появлялось как всплывающее (pop-up) окно. Это возможно и требует вручную добавить немного кода:
  1. Вернемся в панель Actions для кнопки buttonLogin, удалим весь код и укажет следующее:
  2. Этот код использует компоненту Window, чтобы создать всплывающее окно. Если мы запустим приложение как есть, то всплывающее окно не будет появляться, т.к. компоненты Window не будет в конечном откомпилированном SWF файле. Добавим компоненту в SWF, перетащив компоненту Window из панели Components на сцену.
  3. Конечно, в действительности компонента Window на сцене нам не нужна, поэтому удаляем ее. Это звучит странно, но откройте панель Library и обратите внимание, что компонента Window осталась здесь (Рисунок 18).

    Используем панель Library, чтобы видеть, какие компоненты используются в приложении
    Рисунок 18. Используем панель Library, чтобы видеть, какие компоненты используются в приложении.

  4. Сохраняем изменения и тестируем приложение. Теперь после нажатия кнопки Авторизация появляется форма в всплывающем окне.
Так что же делает только что вставленный нами код ActionScript? Событие on(click) перехватывает щелчки по кнопке, поэтому код исполняется только после нажатия на кнопку Авторизация. Первые две линии кода определяют две переменные: x и y - которые указывают позицию всплывающего окна (высота и ширина приложения минус высота и ширина всплывающего окна и все делим на два). Следующая линия кода использует класс PopUpManager, чтобы создать всплывающее окно, указываем login как имя формы, которую нужно загрузить в окне, Авторизация как заголовок окна, и передаем переменные x и y для определения позиции. Далее, код устанавливает размер окна и сохраняет ссылку на шаблон окна, таким образом, что SWF сможет позже закрыть окно.

Теперь добавим действие для кнопки Отмена:

  1. Выделяем форму login.
  2. Выделяем кнопку Отмена.
  3. Открываем панель Actions и набираем следующий код:
    // Close login window
    on (click) {
      _root.application.login.loginInstance.deletePopUp();
    }
  4. Сохраняем изменения и тестируем приложение. Теперь мы можем вызвать окно авторизации, нажав кнопку Login и закрыть его, нажав кнопку Отмена (Рисунок 19).

    Используем компоненту Window и класс PopUpManager, чтобы создавать интуитивные всплывающие меню
    Рисунок 19. Используем компоненту Window и класс PopUpManager, чтобы создавать интуитивные всплывающие меню.

 

Обрабатываем авторизацию

Теперь у нас есть форма авторизации, которую можно только передвигать и закрыть. Далее мы обработаем авторизацию. Проверка авторизации требует добавления нового метода в ColdFusion компоненту. Вставим следующий код в компоненту employees.cfc.

Метод Authenticate берет имя и пароль и возвращает true, если авторизация успешна, или false, если нет. Этот метод очень сильно упрощен, но в реальном приложении вам понадобится добавить в него проверку имени и пароля в соответствии с потребностями приложения. Сейчас проверяется только наличие пароля, равного password.

Нужно сделать так, чтобы Flash узнал о новом методе:
  1. Открываем Window > Development Panels > Web Services.
  2. Нажимаем кнопку Refresh (иконка с синей круговой стрелкой). Flash обновит список веб служб и отобразит новый метод Authenticate().
Перейдем к окну авторизации:
  1. Выделяем экран login.
  2. Перетаскиваем компоненту WebServiceConnector из панели Components в форму login. You might want to place it in the middle so it doesn't interfere with pop-up window placement.
  3. Выделяем новый WebServiceConnector, открываем панель Property и указываем ей имя authService.
  4. В отличие от предыдущих двух запросов к веб службе, этот запрос нужно сконфигурировать вручную. Открываем панель Component Inspector, предварительно выделив на сцене authService.
  5. Выбираем вкладку Parameters. В поле WSDLURL указываем URL веб службы employees.cfc. Если у вас все настроено по-умолчанию, то адрес может быть http://localhost:8500/cfflash/employees.cfc?wsdl. В поле operation выбираем Authenticate (Рисунок 20).


    Рисунок 20. Вручную определяем свойства веб службы в панели Components Inspector.

  6. Веб служба Authenticate требует передать ей два параметра: имя и пароль. Следовательно, нам нужно связать два поля формы авторизации с атрибутами веб службы. Выбираем вкладку Bindings, щелкаем по кнопке Плюс (+), чтобы вызвать диалоговое окно Add Binding, выделяем LoginName и нажимаем OK.
  7. Снова нажимаем кнопку Плюс (+) и добавляем параметр LoginPassword.
  8. Выделяем связь LoginName, щелкаем по полю bound to, а затем по иконке увеличительного стекла, чтобы открыть диалоговое окно Bound To.
  9. Находим форму login, выделяем loginName TextInput, щелкаем по полю text справа (Рисунок 22) и нажимаем на OK, чтобы связать поле loginName с аргументом LoginName в веб службе.


    Figure 21. Во время использования диалогового окна Bound To внимательнее выбирайте компоненты.

  10. Повторим последние два шага, чтобы связать поле loginPassword TextInput с аргументом LoginPassword в веб службе.
Теперь, когда исполняется веб служба authService, в ColdFusion на обработку будут переданы значения двух полей формы. Единственная проблема в том, что веб служба не исполняется сама по себе. Нам нужно добавить код в кнопке Войти так, что она будет запускать выполнение веб службы. Это можно сделать вручную или использовав простой визард:
  1. Выделяем форму login.
  2. Выделяем кнопку Войти.
  3. Открываем панель Behaviors.
  4. Нажимаем кнопку Плюс (+). Выбираем Data > Trigger Data Source, чтобы открыть диалоговое окно Trigger Data Source.
  5. Раскрываем root > application > login > authService (Рисунок 22).


    Рисунок 22. Окно Trigger Data Source позволяет выбирать веб службы.

  6. Выбираем authService и нажимаем OK. Flash создаст несколько линий кода, который будет выполнять запрос к веб службе authService, когда пользователь щелкает по кнопке Войти.
Теперь, когда пользователь запускает приложение, нажатие кнопки Авторизация вызывает всплывающее окно, которое запрашивает ввести имя и пароль и проводит авторизацию. Но мы пока еще не сказали Flash, что делать, когда метод Authenticate возвращает true или false. Для этого добавляем код:
  1. Выделяем форму login.
  2. Выделяем компоненту WebServiceConnector authService.
  3. Открываем панель Actions и вставляем следующий код:
    // Process authentication results
    on (result) {
      if (results) {
        // If returned true
        // Make employee data editable
        _root.application.data.empDataGrid.editable=true;
        // Close login popup
        _root.application.login.loginInstance.deletePopUp();
      }
      else {
        // Returned false, show error message
        mx.controls.Alert.show("Неправильно указаны имя или пароль!","Авторизация");
      }
    }
  4. Сохраняем приложение и тестируем его. Теперь мы можем авторизироваться, используя любое имя и пароль password. После успешной авторизации мы можем редактировать поля в таблице сотрудников (Рисунок 23).


    Рисунок 23. Flash DataGrid поддерживает встроенное редактирование.

 

Завершение авторизации

Далее мы создадим кнопку Выйти. Чтобы легче переключаться между кнопками Войти и Выйти, а также кнопками для добавления, удаления и сохранения, мы разместим кнопки Выйти в отдельной форме:

  1. Добавляем форму в application и зазываем ее navLogout.
  2. Выделяем форму navLogout в дереве форм и переходим в панель Property. Устанавливаем параметр visible в значение false. Мы не хотим, чтобы кнопки Добавить, Удалить, Сохранить и Выйти были видимы при запуске программы (до авторизации пользователя).
  3. Выделяем форму navLogout и добавляем в нее компоненту Button. В панели Property называем ее buttonLogout и устанавливаем W=75, H=22, X=440, Y=370. В поле label укажем Выйти.
  4. Щелкнем по новой кнопке Выйти в форме navLogout и открываем панель Actions.
  5. В Панели Actions набираем следующий код:
    // Process logout
    on (click) {
       // Hide logout buttons
       _root.application.navLogout.visible=false;
       // Show login button
       _root.application.navLogin.visible=true;
       // No more editable
       _root.application.data.empDataGrid.editable=false;
    }
  6. Этот код гарантирует, что до авторизации SWF скрывает кнопку Выйти и показывает кнопку Авторизация. Противоположное происходит после авторизации, поэтому выделяем форму login и компоненту authService, вставляем следующий код перед комментарием // Close login popup:
    // Hide login buttons
    _root.application.navLogin.visible=false;
    // Show logout button
    _root.application.navLogout.visible=true;
  7. Сохраняем изменения и запускаем приложение. По желанию мы можем авторизироваться и завершить авторизацию. После авторизации код разрешает редактировать таблицу сотрудников и показывать кнопку Выйти; после завершения авторизации код запрещает редактировать таблицу сотрудников и снова показывает кнопку Авторизация.

 

Разрешаем добавлять и удалять

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

  1. Выбираем форму navLogout.
  2. Перетаскиваем на сцену компоненту Button из панели Components. В панели Property называем ее buttonInsert и устанавливаем W=75, H=22, X=20, Y=370. В поле label указываем Добавить.
  3. Перетаскиваем на сцену еще одну компоненту Button. В панели Property называем ее buttonDelete и устанавливаем W=75, H=22, X=130, Y=370. В поле label указываем Удалить. Наш экран должен выглядеть как на рисунке 24.


    Рисунок 24. Размещаем кнопки на отдельной форме.

  4. Выделяем кнопку buttonInsert и в панели Actions вставляем следующий код:
    // Process insert button
    on (click) {
       // Insert a row into the data set
       _root.application.data.empDataSet.addItem(
          {
             STARTDATE:new Date().getTime(),
             DEPTIDFK:_root.application.data.deptDataSet.DEPARTMENTID
          });
    }
  5. Выделяем кнопку buttonDelete и в панели Actions вставляем следующий код:
    // Process delete button
    on (click) {
       // Remove current item from data set
       _root.application.data.empDataSet.removeItem();
    }
  6. Сохраняем изменения и тестируем приложение. Пользователь после авторизации может использовать кнопки Добавить и Удалить.
Код, который добавляет сотрудника, использует метод addItem() в DataSet; он использует текущий выбранный id отдела для DEPTIDFK и сегодняшнюю дату для STARTDATE. Код, который удаляет сотрудника, использует метод removeItem() в DataSet, чтобы просто удалить текущий выделенный ряд.

Обратите внимание, что добавить или удалить информацию мы можем только после того, как CFC создаст или удалит запись в базе данных на сервере.

 

Управление изменениями

Созданное нами приложение позволяет делать изменения внутри Flash, но не отправляет их обратно на сервер; поэтому, приложение не обновляет изменения в самой базе данных. Управление обновлениями требует использования специальной компоненты Resolver. Работа Resolver заключается в отслеживании изменений и принимать соответствующие решения; она хранит список изменений, внесенных пользователем, и передает их еще одной веб службе.

Сперва, нам нужен еще один метод для веб службы. Вот код действитеьно простого метода, который на самом деле ничего не обновляет. Он только перехватывает обновления, посылаемые серверу, и сохраняет их в файл. Такой способ удобен тем, что позволяет быть уверенным в том, что клиентская сторона (Flash) работает правильно и независимо от серверной части. Эта функция сохраняет изменения в файл c:\test.xml, который получает обновления в виде XML пакетов. По желанию мы можем изменить путь.

Теперь добавим следующий метод в employees.cfc.

Нам также понадобится обновить окно зарегистрированных веб служб - Window > Development Panels > Web Services. Щелкаем по иконке Refresh. Обратите внимание, что нам не нужно регистрировать CFC и ее функции каждый раз, когда вносим в них какие либо изменения; это нужно делать только после добавления или удаления функций в ColdFusion компоненте.

Обновив employees.cfc, настраиваем Resolver:

  1. Выделяем форму data. Сюда мы добавим две компоненты. Они не имеют визуального интерфейса, поэтому расположить их можно где-угодно.
  2. Resolver собирает изменения в XML пакет. Перетащите компоненту RDBMSResolver на форму data (Рисунок 25).


    Рисунок 25. Resolver не имеет визуального интерфейса, поэтому ее можно расположить в любом месте сцены.

  3. На панели Property назовем ее userResolver.
  4. Выделив ResolverЮ открываем панель Components Inspector, вкладку Parameters.
  5. Чтобы правильно собрать изменения, мы должны указать имя колонки таблицы, которая является первичным ключом данных в Resolver. Первичным ключом для данных о сотрудниках является EMPLOYEEID. Щелкаем по полю fieldInfo и нажимаем на иконку увеличительного стекла, чтобы открыть диалоговое окно Values. Щелкаем по кнопке Плюс (+), чтобы добавить поле.
  6. Укажем значение поля как EMPLOYEEID, а isKey как true (Рисунок 26).


    Рисунок 26. Resolver'у нужно знать имя первичного ключа, чтобы эффективно собирать измененные данные.

  7. Выбираем вкладку Bindings в панели Component Inspector.
  8. Щелкаем по кнопке Плюс (+), чтобы открыть диалоговое окно Add Binding.
  9. Выбираем deltaPacket и нажимаем OK.
  10. Связываем deltaPacket в empDataSet с deltaPacket в userResolver. Убедитесь в том, что выбрали правильный DataSet, т.к. их там несколько (Рисунок 27). Нажимаем OK.


    Рисунок 27. deltaPacket содержит изменения данных, пока они не отправлены на обработку серверу.

Мы настроили Resolver, чтобы обновлять deltaPacket, когда пользователь меняет empDataSet. Далее нам нужно сказать Flash, что делать с этими изменениями. Это требует еще один WebServiceConnector:
  1. Выделяем форму data.
  2. Перетаскиваем кмопоненту WebServiceConnector из панели Components на сцену.
  3. Открываем панель Property и называем новый шаблон WebServiceConnector как userUpdateService. Открываем панель Components Inspector и выбираем вкладку Parameters.
  4. В поле WSDLURL указываем URL для веб службы employees.cfc. он может быть примерно таким http://localhost:8500/cfflash/employees.cfc?wsdl. В поле operation выбираем Update.
  5. Метод Update требует, чтобы мы передали параметр в deltaPacket; вместо использования связки мы передадим его вручную. Это даст нам больше контроля над передаваемыми данными. Щелкните по шаблону компоненты userResolver на сцене и укажите в панели Actions следующий код:
    // Process updates
    on (beforeApplyUpdates) {
       // Pass delta packet to the Web Service
       _parent.userUpdateService.params = { deltaData:this.updatePacket };
       // Fire Web Service
       _parent.userUpdateService.trigger();
    }
Теперь у нас есть Resolver, которые следит за изменениями, и WebServiceConnector, который отправляет изменения на обработку в ColdFusion. Теперь на нужна кнопка Сохранить, чтобы мы могли сохранять изменения:
  1. Выделяем форму navLogout.
  2. Перетаскиваем компоненту Button из панели Components на сцену. В панели Property назовем ее buttonSave и укажем W=75, H=22, X=240, Y=370. В поле label укажем Сохранить.
  3. Открываем панель Actions и набираем следующий код:
    // Process save button
    on (click) {
       _root.application.data.empDataSet.applyUpdates();
    }
  4. Сохраняем изменения и тестируем приложение. Теперь мы можем авторизироваться, редактировать и просматривать отредактированные изменения в созданном в ColdFusion XML файле по адресу c:\test.xml.
Перед тем как закончить с Flash, проделаем последние настройки:
  1. Во время завершения авторизации, возможно, нам понадобится сохранить все не сохраненные изменения. Выбираем форму navLogout, кнопку Выйти и вставляем в нее следующий код в блок on (click):
    // Are there any unsaved changes?
    if (_root.application.data.empDataSet.changesPending()) {
      // Yes, save them
      _root.application.data.empDataSet.applyUpdates();
    }
  2. Следуя тому же принципу, если пользователь отредактировал данные в одном отделе, но потом выбрал другой отдел, то нам понадобится сохранить изменения. Чтобы сделать это, заменим код в панели Actions для deptDataSet в форме data на следующий:
    // Each time there is a department change
    on (iteratorScrolled) {
      // If there are unsaved changes
      if (_parent.empDataSet.changesPending()) {
        // Save them
        _parent.empDataSet.applyUpdates();
      }
      // Get employees
      _parent.empReceiveWebServiceConnector.trigger();
    }
  3. При первом запуске приложения нижняя таблица не заполняется данными пока не будет выбран отдел. Это значит, что первый отдел выделен, но его сотрудники не отображаются пока мы не выберем этот отдел снова. Чтобы исправить это, добавим следующий код в панели Actions для deptDataSet в форме data:
    // After department load get employees
    on (afterLoaded) {
      _parent.empReceiveWebServiceConnector.trigger();
    }
В действительности, произвольно записывать данные в файл на сервере - не очень хорошо. В обоих примерах выше, вероятно, потребуется выводить окно alert, запрашивающее сохранять изменения или нет, но это будет оставлено на ваше усмотрение.

 

Обрабатываем обновления

Flash сторона приложения закончена, но как насчет серверной части? Сейчас приложение сохраняет изменения в XML файл, но нам нужен ColdFusion код, чтобы обработать данные и обновить базу данных.

Окончательная версия метода Update обновляет таблицы:
Рассмотрим основные части метода Update.

Метод получает дельта пакет из Flash как аргумент:

<cfargument name="deltaData" type="string" required="true">
Затем код анализирует дельта пакет и использует XPath, чтобы получить массив ветвей. Каждая опреазия добавления, удаления и обновления находится в отдельной ветке:
<!--- Parse received XML packet --->
<cfset deltaXML=XMLParse(deltaData)>

<!--- Extract all nodes (each operation is a node) --->
<cfset deltaNodes=XmlSearch(deltaXML, "update_packet/*")>

<!--- How many operations? --->
<cfset nodeCount=ArrayLen(deltaNodes)>
Затем код циклически проходит от единицы до количества ветвей (nodeCount), чтобы обработать каждое дейтсвие. Следующий код только первая строка внутри цикла, обнаруживающий действие по имени ветки:
<!--- Get action (INSERT UPDATE or DELETE) --->
<cfset action=deltaNodes[i].XmlName>
Если action равно UPDATE или DELETE, то коду понадобится первичный ключ. Используется еще один XPath, чтобы найти все поля с ключом равным true (это основано на поле, ранее указанном в Resolver). Обработав, переменная pkid будет содержать значение первичного ключа, которое мы сможем использовать в SQL выражениях:
<!--- Get primary key if update or delete --->
<cfif (action IS "update") OR (action IS "delete")>
<!--- Get node with key field --->
<cfset keyFldNodes=XmlSearch(deltaXML, "update_packet/*[#i#]/field[@key='true']")>
<!--- Get primary key (in "OldValue") --->
<cfset pkid=keyFldNodes[1].XmlAttributes.oldValue>
</cfif>
Далее приложение использует XPath в каждом циклическом проходе, чтобы получить все не ключевые поля, где key равен false:
<!--- Now get all non-key fields --->
<cfset modFldNodes=XmlSearch(deltaXML, "update_packet/*[#i#]/field[@key='false']")>
Вооружившись всей этой информацией, код может построить SQL выражения: В конце цикла добавляем новое SQL выражение в массив SQL выражений:
<!--- Add this statement to the array of SQL statements --->
<cfset ArrayAppend(sqlStatements, sql)>
Затем создаем блок тегов CFTRANSACTION, который содержит тег CFLOOP, проходящий по массиву и выполняет SQL запросы:
<!--- And run the query --->
<cfquery datasource="exampleapps">
#PreserveSingleQuotes(sql)#
</cfquery>
Метод, вызываемый из Resolver ожидает пакет результата. (Тут могут быть сообщения об ошибке, если SQL выражения не будут выполнены, или другая информация, которая может быть использована в Flash на стороне клиента.) Для простоты примера, метод CFC у нас возвращает пустой пакет:
<!--- Return result packet (this one is empty) --->
<cfreturn "<result_packet />">
Теперь ColdFusion может обрабатывать дельта пакет и обновлять базу данных в одной транзакции.

 

Заключение

И вот у нас получилось полное клиент-серверное приложение: клиент - Flash, сервер - ColdFusion. Общий объем приложения - меньше 150 кб! Создаваемые вами собственные ColdFusion/Flash приложения будут очень похожи на то, чему вы научились в этой статье.


Источник: Building a Client-Server Application with Flash Data Connection Wizard and ColdFusion

 


Hosted by uCoz