Опубликован: 10.10.2010 | Доступ: свободный | Студентов: 3217 / 301 | Оценка: 4.14 / 3.32 | Длительность: 13:16:00
ISBN: 978-5-9963-0444-8
Специальности: Системный архитектор
Лекция 12:

Web-сервисы. Примеры

< Лекция 11 || Лекция 12: 1234 || Лекция 13 >

Клиентский класс BillingClient

При реализации клиента первая проблема состоит в том, что вызываемые методы Web -сервиса принимают аргументы - объекты. Вторая проблема состоит в том, что некоторые из этих методов принимают массивы объектов.

Первая проблема возникает из-за того, что на самом деле клиентское приложение не получает доступа к "настоящим" классам сервера - т.е. клиент не имеет доступа к классам com.asw.ws.ex1.endpoint.Card или com.asw.ws.ex1.endpoint.CardOperation,рассмотренным в предыдущем разделе и реализованным на сервере. Вместо этого утилитой wsimport на основании анализа WSDL файла генерируются другие классы. Они тоже располагаются в пакете com.asw.ws.ex1.endpoint (но клиента) и называются так же - Card и CardOperation.Но предназначены они только для того, чтобы служить оберткой для передаваемых данных. В этих сгенерированных классах будут содержаться все поля классов исходных, но в них не будет содержаться методов, которые определены в "настоящих" классах, располагающихся на сервере. Все, что они будут содержать, - методы установки и получения соответствующих полей. По большому счету, это даже не классы, а структуры, предназначенные для передачи параметров. Ниже для иллюстрации приведен один такой сгенерированный класс для Card.

Вторая проблема возникает из-за того, что при генерации структура вида "массив объектов" (Т[]) преобразуется в "список объектов" (List<T>).Поэтому в соответствующие методы нужно передавать не массивы, а классы, производные от List,- например, Vector.

1  package com.asw.ws.ex1.client;
2  
3  import javax.xml.ws.WebServiceRef;
4  import com.asw.ws.ex1.endpoint.BillingService;
5  import com.asw.ws.ex1.endpoint.Billing;
6  import com.asw.ws.ex1.endpoint.Card;
7  import com.asw.ws.ex1.endpoint.CardOperation;
8  import javax.xml.datatype.XMLGregorianCalendar;
9  import java.util.*;
10  
11  public class BillingClient {
12      @WebServiceRef(wsdlLocation="http://localhost:8080/billingservice/billing?wsdl")
13      static BillingService service;
14  
15      public static void main(String[] args) {
16          try {
17              BillingClient client = new BillingClient();
18              client.startTest();
19          } catch(Exception e) {
20              e.printStackTrace();
21          }
22      }
23      
24      public void startTest() {
25          try {
26            Billing port = service.getBillingPort();
27  
28      Vector<Card> vc = new Vector<Card>();
29      Card c = new Card();
30      c.setPerson("Piter");
31      XMLGregorianCalendar dat = javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar();
32      dat.setYear(2006);
33      dat.setMonth(11);
34      dat.setDay(5);
35      c.setCreateDate( dat );
36      c.setCardNumber("1");
37      c.setBalance(0.0);
38      vc.add(c);
39  
40      c = new Card();
41      c.setPerson("Stefan");
42      c.setCreateDate( dat );
43      c.setCardNumber("2");
44      c.setBalance(0.0);
45      vc.add(c);
46  
47      c = new Card();
48      c.setPerson("Nataly");
49      c.setCreateDate( dat );
50      c.setCardNumber("3");
51      c.setBalance(0.0);
52      vc.add(c);
53  
54  
55      port.addNewCard(vc);
56      
57  
58      int cnt = 30000;
59      Vector<CardOperation> vco = new Vector<CardOperation>();
60      CardOperation co;
61      for (int i = 0; i < cnt; i++) {
62        co = new CardOperation();
63        switch (i%3){
64        case 0:  co.setCard("1"); co.setAmount(1);            co.setOperationDate(dat);vco.add(co);break;
65      case 1:  co.setCard("2"); co.setAmount(2);   co.setOperationDate(dat);vco.add(co);break;
66    case 2: co.setCard("3"); co.setAmount(3);   co.setOperationDate(dat);vco.add(co);break;
67        }
68      }
69  
70      port.processOperation(vco);
71      
72      printCard(port.getCard("1"));  
73      printCard(port.getCard("2"));
74      printCard(port.getCard("3"));
75  
76  
77      
78          } catch(Exception e) {
79              e.printStackTrace();
80          }
81      }
82      public void printCard(Card card){
83    System.out.println(card.getCardNumber()+"\t"+card.getPerson()+"\t"+
84  card.getCreateDate()+"\t"+card.getBalance());
85      }
86  }
Листинг 12.4. Клиентский класс BillingClient

Сначала подключается соответствующая аннотация (пример 12.4). Именно с ее помощью (строка 12) мы указываем месторасположения WSDL -файла интересующего нас Web -сервиса, на основании анализа которого генерируются все вспомогательные классы. Затем подключаются классы пакета com.asw.ws.ex1.endpoint - все эти классы сгенерированы автоматически утилитой wsimport (еще раз повторимся: это не те классы, что мы написали при реализации Web -сервиса).

В main создается экземпляр нашего класса BillingClient и запускается его метод startTest (строка 18). Метод startTest первым делом создает клиентскую заглушку (строка 26), или proxy -класс, - класс, который реализует такие же методы, как и нужный нам Web -сервис, и который все их вызовы пересылает Web -серверу. И этот класс, и класс BillingService,который, собственно и создает клиентский proxy, созданы автоматически.

После того как клиентская заглушка создана, мы можем вызывать ее методы. Поскольку первый метод, который нам нужно вызвать - метод addNewCard,а он принимает в качестве параметра массив, для его вызова предстоит выполнить некоторые подготовительные действия. Сначала создается вектор, который мы будем передавать в качестве параметра (строка 28 )1В данном случае используется относительно новая возможность, появившаяся в версии 1.5. Это очень похоже на применение шаблона в C++ (производимый эффект - строгая типизация при работе с соответствующей структурой данных), за исключением того, что ответственность за проверку типов целиком лежит на компиляторе и не поддерживается на уровне виртуальной машины (по крайней мере, так обстоят дела на момент написания этих строк) . Затем последовательно создаются три экземпляра Card,поля которых заполняются нужными значениями. Эти карты добавляются в вектор. Вызов addNewCard (строка 55) передает созданные карты Web -сервису и заставляет его создать эти карты.

Похожим образом создаются 30000 операций с картами - по 10000 на каждую из созданных нами трех карт. Вызов processOperation (строка 70) передает созданный массив Web -серверу, а тот, в свою очередь, обработав их, изменяет балансы карт.

И наконец, вызовы метода getCard (строки 72-74) возвращают на клиента карты, которые распечатываются.

Компиляция и выполнение клиента

Так же как и для компиляции сервера, для компиляции клиента воспользуемся ant'ом. Соответствующая строка компиляции выглядит следующим образом (компиляция является целью по умолчанию):

asant

Вывод получим следующий

Buildfile: build.xml clean:

javaee-home-test:

init:

prepare:
[echo] Creating the required directories.... 
[mkdir] Created dir: H:\Java\jwstutorial20_new\examples\ 
jaxws\simpleclient\build

generate-client: [wsimport] command line: wsimport 
H:\Java\AppServer\jdk\jre\bin\java.exe -classpath 
H:\Java\AppServer\lib\activation.jar;
H:\Java\AppServer\lib\admin-cli.jar;
H:\Java\AppServer\lib\appserv-admin.jar;
H:\Java\AppServer\lib\appserv-ext.jar;
H:\Java\AppServer\lib\jmxremote_optional.jar;
H:\Java\AppServer\lib\appserv-cmp.jar; 
H:\Java\AppServer\lib\appserv-deployment-client.jar;
H:\Java\AppServer\lib\appserv-jstl.jar;
H:\Java\AppServer\lib\appserv-jwsacc.jar;
H:\Java\AppServer\lib\appserv-launch.jar; 
H:\Java\AppServer\lib\appserv-rt.jar;
H:\Java\AppServer\lib\appserv-tags.jar;
H:\Java\AppServer\lib\appserv-upgrade.jar; 
H:\Java\AppServer\lib\appserv-ws.jar;
H:\Java\AppServer\lib\com-sun-commons-launcher.jar;
H:\Java\AppServer\lib\com-sun-commons-logging.jar;
H:\Java\AppServer\lib\dbschema.jar; 
H:\Java\AppServer\lib\j2ee-svc.jar;
H:\Java\AppServer\lib\j2ee.jar;
H:\Java\AppServer\lib\javaee.jar;
H:\Java\AppServer\lib\jhall.jar;
H:\Java\AppServer\lib\jsf-impl.jar; 
H:\Java\AppServer\lib\mail.jar;
H:\Java\AppServer\lib\sun-appserv-ant.jar;
H:\Java\AppServer\lib\toplink-essentials-agent.jar;
H:\Java\AppServer\lib\toplink-essentials.jar;
H:\Java\AppServer\jdk\lib\tools.jar com.sun.tools.ws.WsImport -d 
H:\Java\jwstutorial20_new\examples\ 
  jaxws\simpleclient\build -g -keep -s 
H:\Java\jwstutorial20_new\examples\jaxws\simpleclient\src -verbose
http://localhost:8080/billingservice/billing?wsdl -p com.asw.ws.ex1.endpoint
[wsimport]  com\asw\ws\ex1\endpoint\AddMoney.java
[wsimport]  com\asw\ws\ex1\endpoint\AddMoneyResponse.java
[wsimport]  com\asw\ws\ex1\endpoint\AddNewCard.java
[wsimport]  com\asw\ws\ex1\endpoint\AddNewCardResponse.java
[wsimport]  com\asw\ws\ex1\endpoint\Billing.java
[wsimport]  com\asw\ws\ex1\endpoint\BillingService.java
[wsimport]  com\asw\ws\ex1\endpoint\Card.java
[wsimport]  com\asw\ws\ex1\endpoint\CardOperation.java
[wsimport]  com\asw\ws\ex1\endpoint\GetCard.java
[wsimport]  com\asw\ws\ex1\endpoint\GetCardResponse.java
[wsimport]  com\asw\ws\ex1\endpoint\ObjectFactory.java
[wsimport]  com\asw\ws\ex1\endpoint\ProcessOperation.java
[wsimport]  com\asw\ws\ex1\endpoint\ProcessOperationResponse.java
[wsimport]  com\asw\ws\ex1\endpoint\package-info.java
[wsimport]  com\asw\ws\ex1\endpoint\AddMoney.java
[wsimport]  com\asw\ws\ex1\endpoint\AddMoneyResponse.java
[wsimport]  com\asw\ws\ex1\endpoint\AddNewCard.java
[wsimport]  com\asw\ws\ex1\endpoint\AddNewCardResponse.java
[wsimport]  com\asw\ws\ex1\endpoint\Billing.java
[wsimport]  com\asw\ws\ex1\endpoint\BillingService.java
[wsimport]  com\asw\ws\ex1\endpoint\Card.java
[wsimport]  com\asw\ws\ex1\endpoint\CardOperation.java
[wsimport]  com\asw\ws\ex1\endpoint\GetCard.java
[wsimport]  com\asw\ws\ex1\endpoint\GetCardResponse.java
[wsimport]  com\asw\ws\ex1\endpoint\ObjectFactory.java
[wsimport]  com\asw\ws\ex1\endpoint\ProcessOperation.java
[wsimport]  com\asw\ws\ex1\endpoint\ProcessOperationResponse.java
[wsimport]  com\asw\ws\ex1\endpoint\package-info.java

compile-client:
[echo] Compiling the client source code ...
[javac] Compiling 1 source file to 
H:\Java\ jwstutorial20_new\examples\jaxws\simpleclient\build

prepare-dist:
[echo] Creating the required directories ...
[mkdir] Created dir: 
H:\Java\jwstutorial20_new\ examples\jaxws\simpleclient\dist

package-client:
 
[echo] Building the client JAR   file ...
[jar] Building jar: 
H:\Java\jwstutorial20_new\examples\jaxws\simpleclient\dist\client.jar

build-client:

build:

BUILD SUCCESSFUL 
Total time: 16 seconds

В приведенном выводе можно увидеть работу утилиты wsimport по созданию вспомогательных файлов по WSDL Web -сервиса. Запустив клиента командой

asant run

видим, что все необходимые операции на Web -сервисе - создание карт, изменение балансов и запрос информации по картам - успешно выполнены:

Buildfile: build.xml

run:

appclient-command-common:
[exec] 1       Piter  2006-11-05T00:00:00+03:00  10000.0
[exec] 2      Stefan  2006-11-05T00:00:00+03:00  20000.0
[exec] 3      Nataly  2006-11-05T00:00:00+03:00  30000.0

BUILD SUCCESSFUL
Total time: 23 seconds
< Лекция 11 || Лекция 12: 1234 || Лекция 13 >
Алмаз Мурзабеков
Алмаз Мурзабеков
Прохожу курс "Построение распределенных систем на Java" в третьей лекции где описывается TCPServer вылетает эта ошибка
"Connection cannot be resolved to a type"


Java version 1.7.0_05