9 minute read
Глава 11. Создание приложений на основе платформы Riena
ГЛАВА 11
Создание приложений на основе платформы Riena
Платформа Riena (http://www.eclipse.org/projects/project.php?id=rt.riena) позволяет создавать многоуровневые распределенные клиент-серверные приложения, основываясь на SOA-возможностях среды Equinox. На базе платформы Riena компоненты распределенного приложения разрабатываются для целевых платформ и затем разворачиваются на клиентской и серверной сторонах. Платформа Riena раздвигает рамки концепции Eclipse Rich Client Platform в сторону распределенных приложений, используя единую модель программирования для клиентской и серверной сторон, которая расширяет SOA-архитектуру OSGi/Equinox путем обеспечения единообразного доступа к локальным и удаленным сервисам. Кроме того, платформа Riena расширяет платформу Eclipse RCP собственной концепцией GUI-интерфейса, сервисом аутентификации-авторизации и др. Для использования платформы Riena в среде Eclipse необходимо назначить Rienaплатформу в качестве целевой платформы разработки и установить набор инструментов разработки Riena Toolbox. Платформа Riena доступна для скачивания на странице по адресу (http:// wiki.eclipse.org/Riena/Downloads). Скачав и распаковав дистрибутив платформы Riena, используя ссылку Download complete target platform, откроем среду Eclipse SDK и в меню Window выберем команду Preferences. В разделе Plug-in Development | Target Platform нажмем кнопку Add и, оставив выбранным переключатель Nothing: Start with an empty target definition, нажмем кнопку Next. В поле Name введем имя Riena, на вкладке Location нажмем кнопку Add, выберем пункт Directory и нажмем кнопку Next. Кнопкой Browse выберем расположение каталога скачанной платформы Riena и нажмем кнопки Next и Finish. Закроем диалоговое окно New Target Definition кнопкой Finish. В разделе Plug-in Development | Target Platform диалогового окна Preferences отметим флажок Riena (рис. 11.1) и нажмем кнопку OK. Для установки набора инструментов разработки Riena Toolbox в меню Help среды Eclipse выберем команду Install New Software и в поле Work with введем адрес ссылки Riena Toolbox страницы загрузки (http://wiki.eclipse.org/Riena/Downloads), отметим флажок Riena Toolbox и нажмем кнопку Next.
Рис. 11.1. Назначение платформы Riena в качестве целевой платформы разработки
После инсталляции набора Riena Toolbox в меню File среды Eclipse последовательно выберем команды New | Other | Plug-in Development | Plug-in Project и нажмем кнопку Next, введем имя проекта и нажмем кнопку Next, выберем переключатель Yes раздела Rich Client Application и нажмем кнопку Next. Откроется страница Templates мастера создания проекта с шаблонами Riena-приложений (рис. 11.2). Выберем шаблон Riena Hello World и нажмем кнопку Finish. В результате будет сгенерирована основа Riena-приложения. Запустить Riena-приложение из среды Eclipse можно, щелкнув правой кнопкой мыши в окне Package Explorer на узле проекта и в контекстном меню выбрав команды Run As | Eclipse Application. В результате откроется окно Rienaприложения (рис. 11.3). Рассмотрим отличие Riena-приложения "Hello World" от RCP-приложения "Hello". На вкладке Dependences PDE-редактора Riena-приложения добавляется зависимость от плагина org.eclipse.riena.client, обеспечивающего связь с платформой Riena.
Рис. 11.2. Страница Templates мастера создания проекта с шаблонами Riena-приложений
Рис. 11.4. Дерево компонентов GUI-интерфейса Riena-приложения
Расширение org.eclipse.riena.navigation.assemblies2 приложения как дерево компонентов (рис. 11.4). описывает GUI-интерфейс
Корневым узлом Riena Navigation-дерева GUI-интерфейса является узел приложения, экземпляр которого создается в главном классе Application приложения — точке входа в приложение (папка src Riena-проекта). В отличие от RCPприложений главный класс Riena-приложения расширяет класс org.eclipse.riena. navigation.ui.swt.application.SwtApplication с переопределением его метода createModel(), а не реализует интерфейс org.eclipse.equinox.app.IApplication, как главный класс RCP-приложения. Метод createModel() создает экземпляр узла приложения org.eclipse.riena.navigation.model.ApplicationNode, конструктор которого своим параметром определяет заголовок окна приложения. Идентификатор узла приложения совпадает с идентификатором расширения org.eclipse.core. runtime.applications, в котором указывается главный класс приложения (вкладка plugin.xml PDE-редактора Riena-приложения). Элемент assembly не имеет визуального представления и служит контейнером для компонентов Navigation-дерева, определяющим их сборку. Элемент assembly описывается тегом <assembly2> расширения org.eclipse.riena.navigation.assemblies2. Атрибут startOrder тега <assembly2> определяет порядок добавления assemblyконтейнера в Navigation-дерево. Атрибут parentNodeId указывает идентификатор узла приложения как корневого контейнера для assembly-контейнеров.
Элемент subApplication (тег <subApplication> расширения org.eclipse.riena. navigation.assemblies2) представляет отдельную часть Riena-приложения, визуально реализованную в виде вкладки окна приложения. В данном случае это вкладка с именем HelloWorldSubapplication (см. рис. 11.3). Каждое субприложение имеет Riena-перспективу, представленную классом org.eclipse.riena.navigation. ui.swt.views.SubApplicationView. Идентификатор перспективы указывается атрибутом perspectiveId тега <subApplication>. Riena-перспектива описывается тегом <perspective> расширения org.eclipse.ui.perspectives.
Субприложение Riena-приложения содержит модули, сгруппированные в группы модулей. Группа модулей описывается тегом <moduleGroup>, а модуль — тегом <module> расширения org.eclipse.riena.navigation.assemblies2. Визуально модули представлены узлами левой части окна Riena-приложения, имеющими кнопку закрытия. Заголовок модуля определяется атрибутом name тега <module>. Модуль субприложения Riena-приложения содержит субмодули, которые в левой части окна Riena-приложения визуально представлены дочерними элементами узла модуля, а в правой части окна — представлением View (рис. 11.5).
Рис. 11.5. Модули и субмодули субприложения Riena-приложения
Субмодуль описывается тегом <subModule> расширения org.eclipse.riena. navigation.assemblies2. Заголовок субмодуля определяется атрибутом name тега <subModule>. Атрибут viewId тега <subModule> указывает идентификатор расширения org.eclipse.ui.views, в котором с помощью атрибута class тега <view> определяется класс приложения, расширяющий класс org.eclipse.riena.navigation.ui. swt.views.SubModuleView и отвечающий за отображение View-представления с компонентами GUI-интерфейса. В данном случае это класс HelloWorldSubModuleView папки src Riena-проекта. Субмодули Riena-платформы реализуют архитектуру Model-View-Controller (MVC) — SubModuleView-класс приложения отвечает за визуальное представление данных, а сами данные связываются с SubModuleView-классом с помощью контроллера, определяемого атрибутом controller тега <subModule> и представленно- го классом, расширяющим класс org.eclipse.riena.navigation.ui.controllers. SubModuleController. В данном случае это класс HelloWorldSubModuleController папки src Riena-проекта. Widget-компоненты View-представления субмодуля представляются в контроллере как Ridget-компоненты, которые и связываются с моделью данных с помощью метода bindToModel(). Widget-компоненты конвертируются в Ridget-компоненты с помощью метода getRidget(), который в качестве аргумента принимает имя конвертируемого Widget-компонента. Для экспорта Riena-проекта в готовое для развертывания Riena-приложение необходимо в файл plugin.xml добавить расширение org.eclipse.core.runtime.products:
<extension id="product" point="org.eclipse.core.runtime.products"> <product application="RienaSample.application" name="Riena Product"> <property name="appName" value="Riena Product"> </property> </product> </extension>
Затем создать конфигурационный Product-файл, последовательно выбрав команды New | Other | Plug-in Development | Product Configuration. На вкладке Dependences редактора Product-файла отметить флажок Include optional dependences when computing required plug-ins и нажать кнопку Add Required Plug-ins, на вкладке Overview редактора Product-файла щелкнуть по ссылке Eclipse Product export wizard и произвести экспорт Riena-проекта в готовое для развертывания Riena-приложение. Для создания Riena-сервиса, работающего на стороне сервера, в первую очередь создадим OSGi-модуль, представляющий интерфейс сервиса, а затем OSGi-модуль, реализующий интерфейс сервиса и публикующий сервис. Чтобы создать OSGi-модуль, представляющий интерфейс сервиса, в меню File среды Eclipse последовательно выберем команды New | Other | Plug-in Development | Plug-in Project, нажмем кнопку Next, введем имя проекта RienaIService, выберем переключатель an OSGi framework и нажмем кнопку Next. Сбросим флажок Generate an activator, ... и нажмем кнопку Finish. В папке src проекта RienaIService создадим пакет reina.data.person с интерфейсом IPersonService:
package reina.data.person; public interface IPersonService {
String getFirstName();
String getLastName(); }
На вкладке Runtime PDE-редактора файла MANIFEST.MF проекта RienaIService кнопкой Add выполним экспорт пакета reina.data.person (рис. 11.6). На вкладке Dependences PDE-редактора файла MANIFEST.MF проекта кнопкой Add добавим зависимость от плагина org.eclipse.riena.communication.core (рис. 11.7). Чтобы создать OSGi-модуль, реализующий интерфейс сервиса и публикующий сервис, в меню File среды Eclipse последовательно выберем команды New | Other | Plug-in Development | Plug-in Project и нажмем кнопку Next. Введем имя проекта RienaServiceImp, выберем переключатель an OSGi framework и нажмем кнопки Next и Finish.
package rienaserviceimp; import reina.data.person.IPersonService; public class PersonServiceImp implements IPersonService { @Override public String getFirstName(){ return "Konrad"; } @Override public String getLastName(){ return "Zuse"; }}
Рис. 11.6. Экспорт пакета интерфейса сервиса
На вкладке Dependences PDE-редактора файла MANIFEST.MF проекта RienaServiceImp кнопкой Add добавим зависимость от плагина RienaIService, а также зависимость от плагина org.eclipse.riena.server. Для публикации сервиса изменим код класса Activator проекта RienaServiceImp:
package rienaserviceimp;
import java.util.Hashtable; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.eclipse.riena.communication.core.publisher.RSDPublisherProperties; import reina.data.person.IPersonService;
public class Activator implements BundleActivator { private static BundleContext context; private ServiceRegistration personservice; static BundleContext getContext() { return context; } public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
Hashtable<String, String> properties = new Hashtable<String, String>(3); properties.put(RSDPublisherProperties.PROP_IS_REMOTE, Boolean.TRUE.toString()); properties.put(RSDPublisherProperties.PROP_REMOTE_PROTOCOL, "hessian"); properties.put(RSDPublisherProperties.PROP_REMOTE_PATH, "/person"); personservice = context.registerService(IPersonService.class.getName(), new PersonServiceImp(), properties); } public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null; personservice.unregister(); personservice = null; }}
Для развертывания сервиса необходимо создать OSGi-конфигурацию запуска. Проще всего воспользоваться готовой конфигурацией примера riena.communication. sample.pingpong.*. В окне Plug-ins среды Eclipse выберем плагины riena.communication.sample. pingpong.* и, щелкнув правой кнопкой мыши, в контекстном меню выберем команды Import As | Source Project. В результате в Workspace-пространстве появится группа проектов riena.communication.sample.pingpong.*. В окне Package Explorer щелкнем правой кнопкой мыши на узле проекта RienaServiceImp и в контекстном меню выберем команды Run As | Run Configurations.
В разделе OSGi Framework мастера конфигурации запуска выберем конфигурацию Riena Sample PingPong Server, на вкладке Bundles которой в узле Workspace отметим только флажки RienaIService и RienaServiceImp и нажмем кнопку Add Required Bundles. Нажмем кнопки Apply и Run. В результате будет запущен удаленный Web-сервис RienaServiceImp, при этом в консоли, среди прочего, появится строка:
org.eclipse.riena.internal.communication.publisher.hessian.HessianRemoteService Publisher published web service. RemoteServiceDescription [serviceInterfaceClassName=reina.data.person.IPersonService, protocol=hessian, url=http://192.168.0.93:8080/hessian/person]
Для создания клиента удаленного Web-сервиса RienaServiceImp в качестве первого шага создадим OSGi-модуль, представляющий Proxy-сервис на стороне клиента, и зарегистрируем его как OSGi-сервис. В меню File среды Eclipse последовательно выберем команды New | Other | Plug-in Development | Plug-in Project и нажмем кнопку Next, введем имя проекта RienaClientConf, выберем переключатель an OSGi framework и нажмем кнопки Next и Finish. На вкладке Dependences PDE-редактора файла MANIFEST.MF проекта RienaClientConf кнопкой Add добавим зависимость от плагинов org.eclipse.riena. client.communication и RienaIService. Для публикации Proxy-сервиса изменим код класса Activator проекта RienaClientConf:
package rienaclientconf; import org.eclipse.riena.communication.core.IRemoteServiceRegistration; import org.eclipse.riena.communication.core.factory.Register; import org.eclipse.riena.communication.core.factory.RemoteServiceFactory; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import reina.data.person.IPersonService; public class Activator implements BundleActivator { private static BundleContext context; private IRemoteServiceRegistration personservice; static BundleContext getContext() { return context; } public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext; personservice = Register.remoteProxy(IPersonService.class).usingUrl("http://localhost:8080/hess ian/person").withProtocol("hessian").andStart(context); } public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null; if (personservice != null) { personservice.unregister(); personservice = null; }}}
Для создания клиента Proxy-сервиса в меню File среды Eclipse последовательно выберем команды New | Other | Plug-in Development | Plug-in Project и нажмем кнопку Next, введем имя проекта RienaClient, выберем переключатель an OSGi framework и нажмем кнопки Next и Finish. На вкладке Dependences PDE-редактора файла MANIFEST.MF проекта RienaClient кнопкой Add добавим зависимость от плагина RienaIService. Для вызова Web-сервиса изменим код класса Activator проекта RienaClient:
package rienaclient;
import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import reina.data.person.IPersonService;
public class Activator implements BundleActivator { private static BundleContext context; static BundleContext getContext() { return context; }
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
ServiceReference serviceRef = context.getServiceReference(IPersonService.class.getName()); if (serviceRef != null) { IPersonService personservice = (IPersonService)context.getService(serviceRef); System.out.println(personservice.getFirstName()); System.out.println(personservice.getLastName()); } else { context.addServiceListener(new PersonClient(), "(objectClass=" + IPersonService.class.getName() + ")"); }} class PersonClient implements ServiceListener { public void serviceChanged(ServiceEvent event) { ServiceReference serviceReference = event.getServiceReference(); IPersonService personservice = (IPersonService) context.getService(serviceReference); if (personservice == null) { return; }
System.out.println(personservice.getFirstName());
System.out.println(personservice.getLastName()); }}
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null; }}
Для запуска клиента Web-сервиса в окне Package Explorer щелкнем правой кнопкой мыши на узле проекта RienaClient и в контекстном меню выберем команды Run As | Run Configurations. В разделе OSGi Framework мастера конфигурации запуска выберем конфигурацию Riena Sample PingPong Client, на вкладке Bundles которой в узле Workspace отметим только флажки RienaIService, RienaClientConf и RienaClient и нажмем кнопку Add Required Bundles. Нажмем кнопки Apply и Run. В результате будет вызван Web-сервис с выводом предоставляемых им данных в консоль.