Навигация
Главная »  Xml 

Интеграция XForms и Google Web Toolkit: Часть 3. Используем GWT для создания элементов XForms (исходники)


Источник: IBM developerWorks Россия
Майкл Галпин

Введение

В данной статье, мы немного переделаем приложение, созданное в предыдущей части. Как вы помните, приложение позволяет управлять списком исполнителей и их альбомами, и в смысле функциональности, мы ничего менять не будем. Мы лишь поменяем реализацию путем смешивания GWT и XForms на одной странице. Вы увидите насколько просто начать использовать GWT на уже существующей Web-странице. Вы сможете динамически загружать данные на страницу, используя вызовы Ajax через GWT, а затем также динамически создавать модель XForms через интерфейс JSNI, поддерживаемый GWT. Все это позволит упростить нашу страницу. Более того, в целях дальнейшего упрощения даже элементы управления XForms можно будет создать через GWT JSNI. Кроме этого, дополнительным преимуществом использования GWT на страницах XForms является уменьшение размера страниц, что ускоряет их загрузку и отображение в браузере.

Предварительные требования

В данной статье используется GWT версии 1.4 и подключаемый модуль Mozilla XForms версии 0.8. Модуль Mozilla XForms работает с любым браузером на основе Mozilla, например, Firefox или Seamonkey. Использование GWT предполагает определенные знания Java, а так же Web-технологий, таких как HTML и CSS. Кроме этого, в статье широко используется JavaScript. Наконец, поскольку технология XForms разработана в соответствии с парадигмой MVC (Model-View-Control), желательно понимание принципов MVC. В то же время опыт использования GWT или XForms хотя и будет полезным, но не является обязательным.

Динамические страницы XForms?

До этого момента мы использовали XForms для отображения данных, хранящихся в модели внутри страницы. Модель загружалась динамически через скриптлет на JSP, который запрашивал и фильтровал данные, а также записывал их на страницу в виде XML. Теперь же мы сделаем саму XForms-страницу еще более динамической, а именно: вместо записи экземпляров данных внутрь страницы, мы будем асинхронно запрашивать их с сервера, а затем добавлять внутрь существующей модели на странице. Ajax-вызовы будут делаться с помощью GWT, а последующее изменение модели XForms - через JSNI.

Использование GWT на странице XForms

Теперь мы возьмем нашу страницу, отображающую альбомы с помощью XForms, и начнем использовать на ней GWT. Первый вопрос заключается в том, как применить GWT к уже существующей странице. На самом деле, это очень просто. Все, что требуется - это добавить на страницу ссылку на JavaScript-библиотеку, созданную компилятором GWT при преобразовании вашего кода на Java в JavaScript. Подобная библиотека создается одна на каждый модуль. Иными словами, надо просто добавить строчку, как показано в листинге 1.

Листинг 1. Использование GWT на странице для показа альбомов.
  

Зачастую разработчики удивляются простоте добавления GWT к существующим страницам. Эта легкость была одной из задач при создании GWT. Несмотря на то, что большинство примеров использования GWT демонстрируют "свежие" приложения, т.е. изначально написанные на GWT, унаследованные (legacy) проекты встречаются на практике ничуть не реже, и от GWT изначально требовалось быть полезной в обоих случаях. Не забывайте, что весь код на GWT - это по сути JavaScript, так что интеграция и должна быть простой. Теперь, после добавления GWT к странице, можно начинать писать GWT-код, а точнее - Java-код, который будет скомпилирован в JavaScript.

Загрузка альбомов через Ajax: используем JSNI для управления данными XForms

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

Создание удаленного сервиса

Для начала создадим интерфейс сервиса, как показано в листинге 2.

Листинг 2. Интерфейс AlbumService
 package org.developerworks.rockstar.client;  import com.google.gwt.user.client.rpc.RemoteService;  public interface AlbumService extends RemoteService{ public Album[] getAlbumsForArtist(int artistId); public void addAlbum(Album newAlbum); } 

Этот сервис очень похож на тот, что мы разработали во второй части серии. Как и в том случае, нам понадобится асинхронная версия интерфейса, показанная в листинге 3.

Listing 3. Асинхронная версия интерфейса сервиса
 package org.developerworks.rockstar.client;  import com.google.gwt.user.client.rpc.AsyncCallback;  public interface AlbumServiceAsync { public void getAlbumsForArtist(int artistId, AsyncCallback callback); public void addAlbum(Album newAlbum, AsyncCallback callback); } 

И наконец, надо создать серверную реализацию сервиса для обработки клиентских вызовов через HTTP. Реализация должна наследовать стандартный GWT-класс RemoteServiceServlet, как показано в листинге 4.

Листинг 4. Реализация AlbumService
 package org.developerworks.rockstar.server;  import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;  import org.developerworks.rockstar.client.Album; import org.developerworks.rockstar.client.AlbumService;  import com.google.gwt.user.server.rpc.RemoteServiceServlet;  public class AlbumServiceImpl extends RemoteServiceServlet implements AlbumService {  private static final long serialVersionUID = -2706402745094297460L; private Map> albumCache; private AlbumDao dao;       public AlbumServiceImpl(){ this.dao = new AlbumFileDao(); List allAlbums = this.dao.getAllAlbums(); // initialize cache int size = allAlbums.size(); this.albumCache = new HashMap>(size); for (Album album : allAlbums){ int artistId = album.getArtistId(); List albums = this.albumCache.get(artistId); if (albums == null){ albums = new ArrayList(); this.albumCache.put(artistId, albums); } albums.add(album); } }  public void addAlbum(Album newAlbum) { int artistId = newAlbum.getArtistId(); List albums = this.albumCache.get(artistId); if (albums == null){ albums = new ArrayList(); this.albumCache.put(artistId, albums); } albums.add(newAlbum); List all = this.getAllAlbums(); this.dao.saveAlbums(all); }  public Album[] getAlbumsForArtist(int artistId) { List albums = this.albumCache.get(artistId); if (albums == null){ return null; } Album[] array = new Album[albums.size()]; array = albums.toArray(array); return array; }       private List getAllAlbums(){ List allAlbums = new ArrayList(); for (int artistId : this.albumCache.keySet()){ List albums = this.albumCache.get(artistId); allAlbums.addAll(albums); } return allAlbums; }  } 

Как и ранее, мы использовали объект доступа к данным (Data Access Object - DAO) для абстрагирования от особенностей физической организации данных, таких, как доступ к файловой системе, разбор XML и т.д. В будущем это позволит легко заменить нашу упрощенную реализацию, работающую с файлами XML, на более распространенный вариант, использующий базу данных. Теперь можно начинать вызывать новый сервис через GWT.

Вызов удаленного сервиса через GWT

Весь код, находящийся в пакете org.developerworks.rockstar.client, будет скомпилирован в JavaScript и доступен на любой странице, как показано в листинге 1. Таким образом, надо просто создать Java-класс для дальнейшего использования на странице альбомов. Исходный код класса показан в листинге 5.

Листинг 5. Класс AlbumLib
 package org.developerworks.rockstar.client;  import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget;  public class AlbumLib { public void loadAlbums(int artistId){ AlbumServiceAsync albumService = this.getAlbumService(); AsyncCallback callback = new AsyncCallback(){  public void onFailure(Throwable caught) { // TODO Auto-generated method stub                      }  public void onSuccess(Object result) { Album[] albums = (Album[]) result; for (int i=0;i

В этом классе много интересного. Во-первых, он предоставляет два метода для удаленного вызова ранее созданного сервиса AlbumService, аналогично тому, как в предыдущей части вызывался сервис ArtistService. Как и ранее, для обработки ответов сервиса на асинхронные запросы, используются функции обратного вызова. В данном случае, они вызывают два других метода - addAlbumToModel() и refreshXformsModel().

Последние являются собственными (native) методами JavaScript, как и те, что вы видели в примерах в первой части серии.

Метод addAlbumToModel() работает непосредственно c объектами в JavaScript, представляющими модель XForms, позволяя таким образом получить доступ к экземплярам данных в XML. В первой статье мы делали похожие вещи, но через JavaScript, используя методы вроде document.getElementById(...). Теперь же мы работаем через GWT, поэтому необходимо использовать переменную $doc для обращения к объекту документа, который неявно определен в JavaScript. Получив ссылку на этот объект, можно вызывать стандартные методы DOM для добавления элементов типа Album в XML-документ. Таким образом, метод addAlbumToModel() вызывается в цикле, по разу на каждый добавляемый альбом, полученный с сервера. После добавления всех альбомов вызывается метод refreshXformsModel(). Аналогично предыдущему, это собственный метод, имеющий доступ к модели данных XForms и использующий ее API для обновления элементов управления, привязанных к модели.

Все что осталось сделать - это убедиться, что метод loadAlbums вызывается при загрузке страницы. Для этого надо чуть изменить страницу Albums.jsp, как показано в листинге 6.

Листинг 6. Вызов GWT JavaScript из JSP
    Albums       )">     Title:   Year:       

Как видите, достаточно просто вызвать GWT-метод после окончания загрузки страницы. К тому же этот метод позволил нам избавиться от большей части ранее использовавшегося скриптлета, оставив только крошечный фрагмент для передачи параметра artistId. Большая часть оставшегося на странице кода служит исключительно для создания элементов интерфейса. Далее посмотрим, как и их можно создавать программно через GWT.

Создание элементов управления XForms через интерфейс JSNI в GWT

Вы уже видели, как получить доступ к модели XForms и ее данным, используя GWT и JSNI. Теперь мы сделаем следующий шаг и начнем использовать GWT и JSNI для динамического создания элементов управления XForms. Первым делом заменим элемент xforms:repeat на фрагмент кода на JavaScript, показанный в листинге 7.

Листинг 7. Динамическое создание элементов управления XForms через интерфейс JSNI в GWT
 private native void createControls()/*-{ var xfNs = "http://www.w3.org/2002/xforms"; // get the container div var container = $doc.getElementById("albumList");      var repeater = $doc.createElementNS(xfNs,"xforms:repeat"); repeater.setAttribute("id", "repeatItem"); repeater.setAttribute("nodeset", "instance('albumData')/Data/Album");           var titleOut = $doc.createElementNS(xfNs, "xforms:output"); titleOut.setAttribute("ref", "Title"); var titleLabel = $doc.createElementNS(xfNs, "xforms:label"); titleLabel.appendChild($doc.createTextNode("Title:")); titleOut.appendChild(titleLabel); repeater.appendChild(titleOut);           var yearOut = $doc.createElementNS(xfNs, "xforms:output"); yearOut.setAttribute("ref", "Year"); var yearLabel = $doc.createElementNS(xfNs, "xforms:label"); yearLabel.appendChild($doc.createTextNode("Year:")); yearOut.appendChild(yearLabel); repeater.appendChild(yearOut);      container.appendChild(repeater); }-*/; 

Как и ранее, создание элементов управления XForms сводится к простой работе с DOM через собственные методы JavaScript. Теперь мы можем просто добавить код создания элементов UI в метод loadAlbums(), вызываемый при загрузке страницы. Таким образом, сначала будут созданы элементы интерфейса, а затем вызван метод для загрузки альбомов. После этого будут созданы экземпляры данных XForms на основе полученных альбомов, и, наконец, модель XForms будет обновлена для показа новых данных пользователю. В листинге 8 показано насколько простой стала наша JSP.

Листинг 8. Упрощенный вариант JSP (без элементов управления XForms)
 )">    

Теперь JSP-страница на XForms выглядит практически так же, как и страница для показа списка исполнителей, которая была написана ранее с использованием GWT. Весь пользовательский интерфейс создается программно через собственные методы JavaScript в Java-классах, а данные по-прежнему запрашиваются через Ajax.

Заключение

В третьей части мы взяли нашу JSP-страницу, использующую скриптлет для размещения данных, и упростили ее, избавившись от скриптлета и используя GWT. Сами данные асинхронно запрашиваются с сервера через Ajax. Экземпляры данных в модели XForms создаются динамически с помощью интерфейса JSNI в GWT. И, наконец, даже элементы управления XForms для показа данных об альбомах теперь генерируются динамически через JSNI. В четвертой части серии мы покажем, как использовать элементы XForms для асинхронных Ajax-запросов к GWT-сервисам по требованию пользователя.



 

 Интеграция XForms и Google Web Toolkit: Часть 3. Используем GWT для создания элементов XForms (исходники).
 Используйте динамические языки динамично : Часть 2. Оперативный поиск, выполнение и изменение скриптов (исходники).
 Стоит ли искать ИТ-специалистам новую работу в январе?.
 Как зарегистрировать схему XML в БД и как этим воспользоваться.
 IBM Rational Insight.


Главная »  Xml 

© 2017 Team.Furia.Ru.
Частичное копирование материалов разрешено.