Из архива Linux16.net: Java-практикум. Удаленные процедуры в GWT

(Опубликовано Mabel aka Yababay, 2009-04-18 )

Некоторое время назад я опубликовал на нашем ресурсе матераил о Google Web Toolkit — одном из замечательнейших творений команды Google. Напомню, что этот инструмент позволяет писать сайты не зная даже толком HTML. Не нужно заморачиваться тем, что разные браузеры по-разному интерпретируют интернет-странички, не нужно увязывать в единую систему кучу разнородных файлов. Правда, нужно знать Java. Но это, скорее достоинство, чем недостаток, потому что разве не прекрасно, когда клиент и сервер пишутся на одном и том же языке? Но достоинства GWT для Java-программиста на этом не заканчиваются. Из браузера можно обращаться к методам на удаленной машине почти так же просто, как к локальным. Об этом сегодняшний материал.


Вызов удаленных процедур (Remote Procedure Call или сокращенно RPC) — очень старая и, как оказалось, живучая концепция. Изобретена она была в недрах корпорации Sun еще в 80-х. Линуксоидам RPC хорошо знакомы по системе NFS, которая позволяет монтироваль удаленные файловые системы и пользоваться ими как локальными.

Смысл RPC вот в чем. Допустим, у вас есть мощный сервер, обрабатывающий большую базу данных. И есть слабое портативное устройство, запрашивающее у него информацию. Допустим с этого устройства обращаясь к серверу, нужно найти фамилию человека по номеру паспорта. Можно, конечно, организовать систему в виде базы данных и послать серверу соответствующий SQL-запрос. Но, во- первых, не всегда можно «светить» структуру базы данных. Во-вторых, на стороне сервера, помимо SQL-запроса, могут потребоваться дополнительные действия, в третьих, не смотря на то, что эту задачу можно решить кучей способов, самым изящным будет все-таки, вызов метода типа

Passrort passp = getPassport();
FIO fio = remote.getFIO(passp);

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

Концепция RPC развивалась бурно. Уже в ранних версиях Java появился пакет rmi, который позволял выполнять удаленные процедуры. Позднее возникли такие вещи, как SOAP, DCOM, CORBA. Всё это вариации на тему RPC. Особенно интересно использовать CORBA. Для нее вообще безразлично, на каком языке люди пишут. В свое время я реализовал проект, где клиент был написан на Visual Basic'e (царство ему небесное), сервер — на Java и они прекрасно и очень прозрачно общались посредством CORBA.

Было бы странно, если бы Google не включила в свой веб-инструментарий GWT накое мощное средство, как RPC. Действительно, допустим перед нами стоит задача создать нечто вроде гостевой книги. При реализации этой затеи обычными средствами нужно на стороне клиента городить форму, причем обязательно с методом post, а на стороне сервера вообще изрядно попотеть, разбирая присланные данные. В помощью RPC код на стороне клиента и на стороне сервера будет выглядеть примерно одинаково:

public void putMessage(String sender, String subj, String message);


Дальнейшее изложение базируется на одной одной англоязычной статье и собственном опыте.

Начало начал для любого удаленного вызова процедуры — создание интерфейса. Это такой особый абстрактный код, который нужен не для программирования конкретных действий, а для обозначения правил обмена данными между клиентом и сервером: как будут называться методы, какого типа будет возвращаемое значение и какие аргументы будут переданы. В GWT интерфейс должен расширять уже имеющимйся в API интерфейс com.google.gwt.user.client.rpc.RemoteService.

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

public interface MyService extends RemoteService  
{
   public String myMethod (String s);  
}


Поскольку передавать данные серверу мы будем не абы как, а через механизм HTTP, вообще-то не предназначенный для таких дел, Google вводит еще одно передаточное звено — асинхронный интерфейс. Его тоже нужно создать:

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

public interface MyServiceAsync  
{  
    public void myMethod(String s, AsyncCallback callback);  
}


Знатоки Java уже видят странную вещь: куда же делось возвращаемое значение типа String? И что это за AsyncCallback? А вот он-то как раз и отвечает за «выковыривание» возвращаемого значения из удаленной процедуры. Дело в том, что ответ по HTTP приходит с некоторой задержкой, измеряющейся иногда десятком секунд. Поскольку GWT — всего лишь надстройка над JavaScript, прямая реализация процедуры могла бы привести к зависанию браузера. Вот вызов удаленных процедур и организовали в форме отдельных тредов (ака «ниток») посредством асинхронных обработчиков. При этом такие обработчики еще и ошибки отлавливать умеют. AsyncCallback — абстрактный класс, в котором программист должен самостоятельно реализовать два метода: onSuccess(Object obj) и onFailure(Throwable thr). При этом obj — это и есть тот искомый объект, который доставляется от сервера. Вот как это реализуется:

MyServiceAsync svc = (MyServiceAsync) GWT.create(MyService.class);  

        ServiceDefTarget endpoint = (ServiceDefTarget) svc;  
        endpoint.setServiceEntryPoint("/myService");  
        AsyncCallback callback = new AsyncCallback()  

        {  
            public void onSuccess (Object result)  
            {  
                RootPanel.get().add(new HTML(result.toString()));  
            }  

            public void onFailure (Throwable ex)  
            {  
                RootPanel.get().add(new HTML(ex.toString()));  
            }  
        };  
  
        svc.myMethod("Do Stuff", callback);


Часть кода я сократил, чтобы сконцентрировать внимание на том, что имеет отношение к удаленным процедурам. Многие, кто еще не знаком с GWT и дочитал до этого места, может быть даже пришли к выводу, что всё это большой геморрой. Не торопитесь с выводами. Посмотрите зато как всё легко и просто делается на стороне сервера:

import org.hanson.gwt.client.MyService;  

import com.google.gwt.user.server.rpc.RemoteServiceServlet;    

public class MyServiceImpl extends RemoteServiceServlet implements MyService  
{  
    public String myMethod (String s)  

    {  
        return "You sent us '" + s + "'";  
    }  
}

Назовите мне другое средство, которое позволяет так прозрачно реализовывать код на стороне сервера и я признаю, что потратил напрасно несколько десятков минут на написание этой статьи.

Поскольку Java-код на стороне сервера — это всего лишь сервлет (хотя и существенно усовершенствованный Google'м), то путь к нему нужно прописать обычным для таких серверов как Tomcat или JBoss способом в файле web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"
         xmlns<img class="smile" src="/images/smilies/aggressive.gif" />si="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http:/java.sun.com/dtd/web-app_2_3.dtd">
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>MyServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/myService</url-pattern>
</servlet-mapping>
</web-app>
  • +1
  • 05 февраля 2010, 18:38
  • yababay

Комментарии (3)

RSS свернуть / развернуть
+
0
Бл-и-и-и-н! Вот филосовски мне все понятно, так как я писал 3-х уровневые
системы управления! НООО! Где время взять на практику.
Дьявол кроется в деталях…
Пора тебе книгу писать!
Кругом столько пурги, а здесь ОАЗИС !!!
avatar

Markony

  • 05 февраля 2010, 19:08
+
0
Это я Сергею_Т пищу для размышлений подкинул. Он как раз чем-то подобным занимается.
Книгу была мысль замутить. По вот такой технологии .
avatar

yababay

  • 05 февраля 2010, 19:15
+
0
Вот по такой технол. я читал инструкции по «Trace Mode» — «их издат»
-это чудо стоило 3000 руб.
Теория КЛАСС, только со СКАДА лучше не связываться...
avatar

Markony

  • 05 февраля 2010, 19:52

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.