суббота, марта 26, 2011

Собираем проект GWT 2.1.1+UIBinder+ Gxt-UIBinder 0.9 + Gxt 2.2.3 в IDEA

Эта заметка ориентирована на тех, кому хочется посмотреть на возможности связки GWT и ExtGWT с использованием UIBinder. Напомню, GWT это Google Web Toolkit, фреймворк, основная идея которого заключается в компиляции Java кода в оптимизированный клиентский Javascript, который будет исполняться на странице в браузере, формировать UI приложения и запросы к серверной стороне по протоколу GWT-RPC. Начиная со второй версии GWT из инкубатора вылез проект UIBinder - работа которого заключается в декларативном формировании дизайна UI - то есть не кодом, а разметкой. С UIBinder можно лаконичнее реализовывать обработчики событий, поскольку появились соответствующие аннотации. Это упростило работу с проектами, в которых имеет большое количество различных компоновок.
С другой стороны есть достаточно известные профессиональные библиотеки js-контролов ExtJS от sencha, среди которых предлагаются и интеграционные реализации с GWT - ExtGWT. Как обычно это бывает, костыль оказывается в отсутствии тесной интеграции - производители не поставляют варианты взаимодействия UIBinder и ExtGWT. Но нашелся умелец, который взялся за исправление ситуации и создал проект Gxt-UIBinder.
Попробуем с нуля создать GWT-проект в IDEA, подключить ExtGWT, Gxt-UIBinder и сделать простейшую компоновку.

Создаем GWT-проект в IDEA
1. File - New Project - Create Project from scratch
2. Назвали проект testextgwt
3. Указали что это Java модуль
4. Сказали сделать папку для сырцов
5. Выбрали фасет Google Web Toolkit. GWT SDK скачали именно версию2.1.1!!! С версией GWT 2.2.0 наша связка работать не будет!
6. Указали сделать пример с неймспейсом com.MySampleApplication
7. Запустили проект
8. Установили расширение GWT Developer Plugin к Google Chrome
9. Убедились что hello world, созданный средой работает

Далее подключаем ExtGWT
1. Идем на сайт http://www.sencha.com/, ExtGWT, Download Ext GWT 2.2.3. Распаковываем.
2. В нашем проекте в папке war создаем папку extgwt
3. Из папки /resource дистрибутива ExtGWT переносим все в папку /war/extgwt проекта
4. В основной html странице проекта testextgwt.html после подключения testextgwt.css подключаем стили extgwt <link rel="stylesheet" type="text/css" href="extgwt/css/gxt-all.css" />
5. В нашем проекте в папке war/WEB-INF создаем папку lib
6. Переносим файл gxt-2.2.3-gwt22.jar из корня дистрибутива ExtGWT в папку /war/WEB-INF/lib
7. В IDEA идем в меню File - Project Structure - Libraries. Там видим запись gwt-user.
8. Нажимаем кнопку "+" для добавления новых библиотек. Создаем с именем gxt.
9. Нажимаем кнопку "Attach Classes", выбираем web/WEB-INF/lib/gxt-2.2.3-gwt22.jar
10. В файле testextgwt.gwt.xml в секцию module после строки <inherits name='com.google.gwt.user.User'/> добавили строку <inherits name='com.extjs.gxt.ui.GXT'/>

Подключаем Gxt-UIBinder
1. Идем на http://code.google.com/p/gxt-uibinder/, скачиваем gxt-uibinder-0.9.jar
2. Положили библиотеку в war/WEB-INF/lib
3. Идем на http://code.google.com/p/gwt-customuibinder/, скачиваем gwt-customuibinder-0.1.jar
4. Положили библиотеку в war/WEB-INF/lib
5. Добавляем эти библиотеки в проект IDEA: идем меню File - Project Structure - Libraries. Ранее созданная gxt. Нажимаем кнопку "Attach Classes", выбираем web/WEB-INF/lib/xt-uibinder-0.9.jar и web/WEB-INF/lib/gwt-customuibinder-0.1.jar
6. В файле testextgwt.gwt.xml в секцию module после строки <inherits name='com.extjs.gxt.ui.GXT'/> добавили строку <inherits name="com.jhickman.web.gwt.gxtuibinder.GxtUiBinder" />

Декларируем компоновку MyDockLayoutPanel.ui.xml в com.mySampleApplication.client
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
             xmlns:g='urn:import:com.google.gwt.user.client.ui'
             xmlns:gxt='urn:import:com.extjs.gxt.ui.client.widget.button'
        >

 <ui:style>
        .eastPanel {
            background-color: #F60;
        }
        .westPanel {
            background-color: #EEE;
        }
        .northPanel {
            background-color: #39F;
        }
        .southPanel {
            background-color: #99C;
        }
        .centerPanel {
            background-color: #FFC;
        }
    </ui:style>
     <g:SplitLayoutPanel>
       <g:north size='60' unit='EM'>
         <g:FlowPanel styleName="{style.northPanel}">
           <g:Label>This is the NORTH panel</g:Label>
         </g:FlowPanel>
       </g:north>
       <g:west size='200' unit='EM'>
         <g:FlowPanel styleName="{style.westPanel}">
           <g:Label>This is the WEST panel</g:Label>
         </g:FlowPanel>
       </g:west>
       <g:center>
         <g:FlowPanel styleName="{style.centerPanel}">
           <g:Label>This is the CENTER panel</g:Label>
            <g:HTMLPanel>
               GWT Button: <g:Button ui:field="button">button</g:Button>
               ExtGWT Button: <gxt:Button text="submit" ui:field="extbtn" />
            </g:HTMLPanel>
         </g:FlowPanel>
       </g:center>
       <g:east size='200' unit='EM'>
         <g:FlowPanel styleName="{style.eastPanel}">
           <g:Label>This is the EAST panel</g:Label>
         </g:FlowPanel>
       </g:east>
        <g:south size="60" unit='EM'>
         <g:FlowPanel styleName="{style.southPanel}">
           <g:Label>This is the SOUTH panel</g:Label>
         </g:FlowPanel>
        </g:south>
     </g:SplitLayoutPanel>


</ui:UiBinder>



Помещаем реализацию панельки с контролами MyDockLayoutPanel.java в com.mySampleApplication.client

package com.mySampleApplication.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.jhickman.web.gwt.gxtuibinder.client.GxtEvent;
import com.jhickman.web.gwt.gxtuibinder.client.GxtUiHandler;

public class MyDockLayoutPanel extends Composite {
    interface MyDockLayoutPanelUiBinder extends UiBinder<DockLayoutPanel, MyDockLayoutPanel> {
    }



    private static MyDockLayoutPanelUiBinder ourUiBinder = GWT.create(MyDockLayoutPanelUiBinder.class);

    public MyDockLayoutPanel() {
        DockLayoutPanel rootElement = ourUiBinder.createAndBindUi(this);
        initWidget(rootElement);

    }

    @UiField com.google.gwt.user.client.ui.Button button;

    @UiHandler("button")
    void handleBtnClick(ClickEvent e) {
        Window.alert("Hello, AJAX");
    }
    
       
    
    @UiField com.extjs.gxt.ui.client.widget.button.Button extbtn;
    
    @GxtUiHandler(uiField="extbtn", eventType= GxtEvent.Select)
    public void submitForm(com.extjs.gxt.ui.client.event.ButtonEvent event) {
        MySampleApplicationService.App.getInstance().getMessage("Hello, World!", new MyAsyncCallback(extbtn));
    }




     private static class MyAsyncCallback implements AsyncCallback<String> {
        private com.extjs.gxt.ui.client.widget.button.Button btn;

        public MyAsyncCallback(com.extjs.gxt.ui.client.widget.button.Button btn) {
            this.btn = btn;
        }

        public void onSuccess(String result) {
            btn.setText(result);
        }

        public void onFailure(Throwable throwable) {
            btn.setText("Failed to receive answer from server!");
        }
    }



}


Реализуем EntryPoint.onModuleLoad() в mySampleApplication.java из com.mySampleApplication.client
public void onModuleLoad() {

          RootLayoutPanel.get().add(new MyDockLayoutPanel());
    }



Все. Что мы должны увидеть - кучу панелек, на центральной две кнопки - одна родная GWT, другая от ExtGWT. Как видно все по полочкам - представление отдельно, логика отдельно. Благодаря аннатациям UIBinder код вполне лаконичен.






PS: закончил писать заметку - вышла новыя версия gwt-customuibinder-0.2.jar, которая должна быть совместима с GWT 2.2.0. Пробуйте.

Комментариев нет:

Мой список блогов