Friday, October 21, 2011

Создаем приложение с помощью Spring и GWT. Часть 3 - GWT RPC сервисы

Недавно я начал работу в проекте, в котором используется новая для меня технология - GWT. Решил написать небольшое приложение, использующее этот фреймворк и Spring.

Ранее мы интегрировали в нашем приложении Spring и GWT. В этой части мы рассмотрим, как обеспечить обмен данными между клиентской и серверной частями нашего приложения с помощью GWT RPC сервиса.

Для конфигурации бинов мы будем использовать аннотации Spring, а не XML. Для обеспечения этого добавим <context:component-scan/> в applicationContext.xml, указав пакет с бинами приложения:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.hellogwt"/>

</beans>

Согласно правилам GWT RPC, создадим в пакете com.hellogwt.client сервис GreetingService и снабдим его аннотацией @RemoteServiceRelativePath. Он будет содержать один метод greet(), принимающий и возвращающий строку:
package com.hellogwt.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("springGwtServices/greetingService")
public interface GreetingService extends RemoteService {

    String greet(String name);
}

Сервису GreetingService должен соответствовать асинхронный сервис GreetingServiceAsync. Создадим его в том же пакете:
package com.hellogwt.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface GreetingServiceAsync {

    void greet(String name, AsyncCallback<String> callback);
}

Перейдём к серверной части нашего приложения. Создадим класс, реализующий интерфейс GreetingService, в пакете com.hellogwt.server. Не забудем добавить аннотацию @Service. Класс GreetingServiceImpl содержит реализацию метода greet(). В нашем случае метод принимает одну строку, создаёт на её основе другую и возвращает полученное значение:
package com.hellogwt.server;

import com.hellogwt.client.GreetingService;
import org.springframework.stereotype.Service;

@Service("greetingService")
public class GreetingServiceImpl implements GreetingService {

    @Override
    public String greet(String name) {
        return "Hello, " + name + "!";
    }
}

Осталось только использовать наш сервис в приложении. Будем вызывать метод greet() сервиса GreetingService каждый раз, когда в текстовое поле вводится символ. Если метод greet() выполнится успешно, то текст метки изменится на строку, возвращаемую методом. Иначе текст метки будет говорить нам об ошибке:
package com.hellogwt.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;

public class HelloGWT implements EntryPoint {
    private GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
    private TextBox nameTextBox = new TextBox();
    private Label greetingLabel = new Label("Hello, GWT!");

    @Override
    public void onModuleLoad() {
        RootPanel.get().add(nameTextBox);
        RootPanel.get().add(greetingLabel);

        final AsyncCallback<String> callback = new AsyncCallback<String>() {
            @Override
            public void onFailure(Throwable caught) {
                greetingLabel.setText("ERROR!");
            }

            @Override
            public void onSuccess(String result) {
                greetingLabel.setText(result);
            }
        };

        nameTextBox.addKeyUpHandler(new KeyUpHandler() {
            @Override
            public void onKeyUp(KeyUpEvent keyUpEvent) {
                greetingService.greet(nameTextBox.getText(), callback);
            }
        });
    }
}

Соберем проект, выполнив команду "mvn clean install":
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building hellogwt 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ hellogwt ---
[INFO] Deleting d:\Dev\blog\hellogwt-3\target
[INFO] 
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ hellogwt ---
[debug] execute contextualize
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory d:\Dev\blog\hellogwt-3\src\main\resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ hellogwt ---
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 4 source files to d:\Dev\blog\hellogwt-3\target\classes
[INFO] 
[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ hellogwt ---
[debug] execute contextualize
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory d:\Dev\blog\hellogwt-3\src\test\resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ hellogwt ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ hellogwt ---
[INFO] No tests to run.
[INFO] Surefire report directory: d:\Dev\blog\hellogwt-3\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

[INFO] 
[INFO] --- gwt-maven-plugin:2.4.0:compile (default) @ hellogwt ---
[INFO] auto discovered modules [com.hellogwt.HelloGWT]
[INFO] Compiling module com.hellogwt.HelloGWT
[INFO]    Compiling 6 permutations
[INFO]       Compiling permutation 0...
[INFO]       Process output
[INFO]          Compiling
[INFO]             Compiling permutation 2...
[INFO]       Process output
[INFO]          Compiling
[INFO]             Compiling permutation 1...
[INFO]       Process output
[INFO]          Compiling
[INFO]             Compiling permutation 3...
[INFO]       Compiling permutation 4...
[INFO]          Compiling
[INFO]             Compiling permutation 5...
[INFO]    Compile of permutations succeeded
[INFO] Linking into d:\Dev\blog\hellogwt-3\target\hellogwt\hellogwt
[INFO]    Link succeeded
[INFO]    Compilation succeeded -- 41.300s
[INFO] 
[INFO] --- maven-war-plugin:2.1.1:war (default-war) @ hellogwt ---
[INFO] Packaging webapp
[INFO] Assembling webapp [hellogwt] in [d:\Dev\blog\hellogwt-3\target\hellogwt]
[INFO] Processing war project
[INFO] Copying webapp resources [d:\Dev\blog\hellogwt-3\src\main\webapp]
[INFO] Webapp assembled in [140 msecs]
[INFO] Building war: d:\Dev\blog\hellogwt-3\target\hellogwt.war
[WARNING] Warning: selected war files include a WEB-INF/web.xml which will be ignored 
(webxml attribute is missing from war task, or ignoreWebxml attribute is specified as 'true')
[INFO] 
[INFO] --- gwt-maven-plugin:2.4.0:test (default) @ hellogwt ---
[INFO] 
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ hellogwt ---
[INFO] Installing d:\Dev\blog\hellogwt-3\target\hellogwt.war to d:\Dev\.m2\repository\hellogwt\hellogwt\1.0\hellogwt-1.0.war
[INFO] Installing d:\Dev\blog\hellogwt-3\pom.xml to d:\Dev\.m2\repository\hellogwt\hellogwt\1.0\hellogwt-1.0.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 47.050s
[INFO] Finished at: Mon Apr 21 19:34:17 EEST 2014
[INFO] Final Memory: 15M/153M
[INFO] ------------------------------------------------------------------------

Скопируем полученный war-файл в директорию Tomcat'а webapps, запустим сервер и перейдем по ссылке http://localhost:8080/hellogwt/. При изменении текста поля должен меняться текст метки:











Структура проекта:

































Исходный код созданного приложения доступен по ссылке https://subversion.assembla.com/svn/hellogwt-3/trunk/.

В этой части мы добавили GWT RPC сервисы в наше приложение. На этом можно было бы и закончить, но это не наш вариант :) В следующей части мы рассмотрим, как добавить в наше приложение возможность работы с СУБД MySQL с помощью фреймворка MyBatis.


Рекомендуемые посты:

10 comments:

  1. Привет! Подскажи, пожалуйста, для чего нам вообще spring-то? можно ж и без него всё то же самое сделать: просто работать с RPC вызовами, в которых, например, hibernate реализацию доступа к данным делать (ну, я имею ввиду весь CRUD и т.д.). В чём +ы spring'а ???
    Я просто не особо знаком со spring'ом...

    ReplyDelete
    Replies
    1. Spring - один из самых популярных фреймворков для разработки Java EE приложений. Плюсов очень много - Dependency Injection, широкие возможности для организации безопасности приложения и гибкой интеграции различных фреймворков, поддержка AOP и транзакций. В общем, очень много полезного. Подробнее здесь.
      Конечно, можно бы было сделать все проще и без Spring, но я отталкивался от моего текущего проекта на работе - а там Spring, MyBatis и GWT.

      Delete
    2. Возникла проблема, при вводе символов в текстовое поле сообщение ERROR. В чем может быть проблема не подскажете?

      Delete
    3. Тяжело сказать, сравните свой код с кодом в SVN

      Delete
  2. Привет! У меня один вопрос - у меня ошибка в private GreetingServiceAsync greetingService = GWT.create(GreetingService.class); - написано, что GreetingService долщно быть классом ( [ERROR] Line 13: Rebind result 'com.westum.testproject.hellogwt.client.GreetingService' must be a class). У тебя есть идея, как разрешить эту проблему?

    ReplyDelete
    Replies
    1. Добрый день! Сравните, пожалуйста, свой код с кодом в SVN - возможно в нем есть ошибки

      Delete
  3. Извини, я нашёл решение - я забыл написать
    extends RemoteService..

    ReplyDelete
    Replies
    1. Спасибо, что указал в чем была проблема!

      Delete
  4. Может кому-то поможет данный пост. Сначала проект не работал(ошибку не помню) помогло комментирование строки ...... Проект запустил, но при вводе символом, выводил "Еррор". Раскоментировал я listner и получил я "Exception while dispatching incoming RPC call". **ался я долго(т.к. нюбЪ) и решил данную "проблемку" добавлением В котором указал путь к spring-context. Может кому и поможет этот пост.

    ReplyDelete
    Replies
    1. ps запускаю проект так: clean install tomcat7:run-war

      Delete