Java 6 Web Services

Рубрика: Development, Java | 18 December 2007, 16:52 | juriy

Одно из существенных нововведений в Java 6 – поддержка Web сервисов в JDK Standard Edition. Я не буду разливаться мыслью по древу, и рассказывать, зачем нужны веб-сервисы: и без меня об этом написано много. Я просто покажу, как, используя Java 6, можно за 20 минут написать веб сервис, клиент для веб сервиса и запустить всю эту систему на локальной машине, не используя ничего кроме Java 6 SE.

Итак, начнем с бизнес-логики. Создадим простой класс Calculator, который умеет складывать два числа и возвращать результат.

public class Calculator {

	public int add(int a, int b) {
		return a + b;
	}
}

Теперь добавляем немного магии от Mustang: отмечаем класс Calculator аннотацией javax.jws.WebService:

import javax.jws.WebService;

@WebService
public class Calculator {
	...
}

Ну и, естественно, метод main, который опубликует веб сервис.

public static void main(String[] args) {
	Endpoint.publish(
			"http://localhost:8080/WS/calc", new Calculator());

}

Программирование сервера на этом закончено, но перед запуском необходимо сделать еще один шаг: сгенерировать обертку для сервиса – дополнительные классы, необходимые для публикации.

Предположим, что структура проекта такова, что скомпилированные классы лежат в папке bin а исходники – в папке src.

Выполним такую команду из корня проекта:

wsgen -cp bin -s src -d bin com.juriy.ws.srv.Calculator

Выполнение не должно занять больше пары секунд.

Все, сервис готов – можно его публиковать. Для этого просто запускаем java класс:

java -cp bin com.juriy.ws.srv.Calculator

Чтобы проверить, что сервис действительно работает, попробуйте открыть в окне браузера страничку http://localhost:8080/WS/calc?WSDL. Должно отобразиться WSDL-описание сервиса.

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

В новом проекте выполним команду:

wsimport -d bin -s src http://localhost:8080/WS/calc?WSDL

wsimport сгенерировал набор прокси-классов, которые теперь можно смело использовать для соединения с калькулятором (ведь он до сих пор запущен?).

Класс-клиент намного проще класса-сервера:

public class Main {
	public static void main(String[] args) {
		CalculatorService service = new CalculatorService();
		Calculator port = service.getCalculatorPort();
		System.out.println(port.add(1, 2));
	}
}

Классы CalculatorService и Calculator любезно предоставлены wsimport’ом.

Вот и все что нужно, чтобы создать собственный WebService. Теперь веб-сервисы – это стандартная Java. С нетерпением ждем, когда поддержка EJB тоже перекочует в обычный Desktop Java :-) .

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

52 Responses to “Java 6 Web Services”

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

  1. Vadim Voituk

    После того как неделями напролет, тратил время на разборы и отладку веб-сервисов, после написания “килотонн” кода интерфейсов и их имплементаций, после download-a мегабайтов библиотек увидеть ТАКОЕ!

    До этого момента для меня эталоном простоты работы с SOAP был пример связки Groovy+XFire.

  2. Olostan

    Неуж-то Sun пошли по пути Microsoft, у которых есть просто .NET, без разделения на enterprise и desktop.

    IMHO не всегда хорошее решение, лучше “мухи отдельно, котлеты отдельно”.

  3. Vadim Voituk

    Врядли, Sun больше ориентирует Java 6 Mustang на Desktop-приложения.
    Об этом говорит огромное количество улучшений (по сравнению с Java 5 Tiger) в GUI API а также наличие встраиваемой СУБД (Apache Derby) прямо в поставке.

  4. juriy

    Я думаю, это ориентация именно на Web сервисы. Ведь поддержка WS есть даже в MIDP 2.0 платформе (опционально) – http://jcp.org/en/jsr/detail?id=172 .

  5. Chabster

    Это вшитый JWSDP 2 или провайдер можно подложить?

  6. Агата

    вроде бы можно…у меня получилось по крайней мере

  7. Chabster

  8. juriy

    :-) Гм, сейчас попробую доказать, что я не тырил у индусов :-) На самом деле, отправная точка была тут: http://java.sun.com/developer/technicalArticles/J2SE/jax_ws_2/ а уж про калькулятор идея попалась вот тут: http://www.netbeans.org/kb/55/websvc-jax-ws.html

    В первой статье не было описания, как сделать клиент без NetBeans, так что решил исправить оплошность.

  9. Chabster

    Код 1:1 :) Ладно. “Позаимствовал”.

  10. ya

    А что означает, если Eclipse подчеркивает Endpoint?

  11. Juriy

    А какое предупреждение Eclipse выдает, когда подчеркивает?

  12. ya

    could be resolve.

    import javax.xml.ws.Endpoint; помог. Надеюсь он верен.

  13. victor

    Все хорошо, только запросы обрабатываются последовательно, пока одни обработается, все остальные ждут.

  14. Vadim Voituk

    Виктор,
    Это, насколько я понял, вы говорите об Endpoint.publish() ?
    Ну так для локального тестирования разве большее нужно?

  15. victor

    Пардон, запустил несколько экземпляров Endpoint.publish, после этого заработало.

  16. victor

    А разве нельзя этим воспользоваться хотя бы для полупромышленного использования?

  17. Vadim Voituk

    Честно говоря, я бы не рискнул использовать такой SOAP-сервер под мало-мальски реальной нагрузкой.
    Хотя возможно что и зря. Нужно будет исследовать этот вопрос детальнее.

  18. Владимир

    А в чём косяк и что надо делать по-другому для продакшна?

  19. Vadim Voituk

    Владимир,
    подозреваю что будут проблемы в производительности и многопоточности. Да и не верится мне что 5-6 аннотаций могут заменить какой-нить axis или аналог.
    Хотя опять же – надо проверять.

  20. victor

    Проверил на своем новом проекте, создал пул коннекторов к базе данных, создал несколько обработчиков запросов, все летает.
    Правда, вызов endpoint’а немного переделал:
    HttpServer server = null;
    int numConnections = 10;
    ExecutorService threads = Executors.newFixedThreadPool(numConnections);
    server = HttpServer.create(new InetSocketAddress(8080), numConnections);
    server.setExecutor(threads);
    server.start();
    Endpoint endpoint = Endpoint.create(new calculator(numConnections));
    HttpContext context = server.createContext(“/WS/calculator”);
    endpoint.publish(context);

  21. Olostan

    Да, всё упирается в тесты – “всё летает” для клиентов плохой критерий оценки производительности :)

    Если кто найдёт тесты этих вебсервисов по сравнению с конкурентами – скиньте ссылку. Возможно сам прокручу на досуге что-то.

  22. Burgen, Che

    Если попробовать сделать реальную нагрузку, сразу увидите тормоза веб-сервисов. В своем проекте решил эту проблему с помощью hessian, см http://hessian.caucho.com

  23. Gudvin

    А как, запустив такой сервер на одной машине, использовать клиент на другой

  24. ShadowX

    А как побороть ошибку: ” undefined simple or complex type ‘soapenc:Array’ “, – при генерации кода, ктото знает?

  25. Akopium

    повторю предыдущих авторов, что все летает

  26. Vadim Voituk

    @Akopium
    А ты делал через пул HTTP-worker-ов? Или в однопоточном режиме?
    Можно сниппетом кода поделиться?

  27. Maxim K.

    Господа, написал серверную часть, при попытке запустить:
    java -cp bin com.juriy.ws.srv.Calculator

    пишет ошибку: Exception in thread “main” java.lang.NoSuchMethodError: main

    эни айдиас?)

  28. Maxim K.

    Оу..сорри)) разобрался

  29. Swed

    ExecutorService threads = Executors.newFixedThreadPool(numConnections);
    server = HttpServer.create(new InetSocketAddress(8080), numConnections);
    server.setExecutor(threads);
    server.start();
    Endpoint endpoint = Endpoint.create(new calculator(numConnections));
    HttpContext context = server.createContext(“/WS/calculator”);
    endpoint.publish(context);

    во первых этого всего писать то и не надо
    достаточно:

    Endpoint endpoint = Endpoint.publish(“http://localhost:8080/WS/calculator”, new calculator());
    endpoint.setExecutor(threads);
    …..
    endpoint.stop() // Для остановки.

    во вторых на самом деле это все прикольно
    пока не понадобиться реализация сессий в веб сервисе
    вот тогда начинается веселуха.
    с Axis2 было вес проще.

  30. Vadim Voituk

    Судя по всему Swed невнимательно читал комментарии выше.
    В приведенном 2х-строчном примере весь web-сервис будет однопоточным, что врядли удовлетворит хоть какую-то мало-мальскую систему.
    Для того и создавется ThreadPool.

    Что же касается сессий – что-то вы делаете не так, потому как web-сервисы по природе своей stateless, следовательно удержание сессии между запросами к web-сервису – это уже задача приложения.
    Причем задача весьма примитивная.

  31. Swed

    во первых

    ThreadPoolExecutor threads = new ThreadPoolExecutor(10,20, 0,TimeUnit.MILLISECONDS,new ArrayBlockingQueue(QUEUE_CAPACITY))

    endpoint.setExecutor(threads);

    ужо дает вам много поточность!

    что касается сессий. я все делаю как надо! вот только немогу получить не только сессия но и реквест из пропертей месседжКонтекста.

    А при использовании @HttpSessionScope для сервиса он и вообще вываливается по причине того что не может найти тот самый реквест объект

  32. Vitaly

    А можно ли как то держать постоянное соединение с клиентом?
    Как реализовать передачу данных от вэб сервиса к клиенту? т.е. чтобы вэб сервис был инициатором?

  33. Олег

    Чувак, ты спас мне день ))

    Спасибо

  34. tam

    Бред, ничего неработает. Описали бы хоть поподробней где и что запускать:

    Выполним такую команду из корня проекта:
    wsgen -cp bin -s src -d bin com.juriy.ws.srv.Calculator

    да и воще выложите готовый пример, весит он не много.

  35. Juriy

    Правда, странно, что “ничего не работает” только у Вас? Попробуйте внимательнее почитать заметку и выполнить все шаги, которые там описаны? Даже если бы я выложил пример, это не освободило бы вас от выполнения команды в вашем комменте :-)

  36. tam

    1) что ето значит ? -> Теперь добавляем немного магии от Mustang.

    2)wsgen -cp bin -s src -d bin com.juriy.ws.srv.Calculator -> видно, что класс калькулятор находиться в определенных пакетах, а в коде этого нету.

    3)Выполним такую команду из корня проекта: -> выполним, я так понимаю, в консоли cmd ?

    имхо данный пример очень простой и посему публиковался для людей, каторые хотели бы попробывать написать свой первый веб сервис. С другой стороны он слишком коротко описан, что вртяли подходит к неопытным програмерам.

  37. IvanKa

    Juriy, спасибо, завелось сразу, даже блин удивило.
    Наверное, сюрпризы будут позже :)

  38. Armen

    Ja bi xotel posmotret na rabotajushi primer EJB3 facade + web services pod JBoss, i server i client.

  39. Apachi

    Возник такой вопрос, при генерации wsdl, входные параметры обзываются таким образом: arg0, arg1,… Может кто знает как задавать осмысленные имена самому?

  40. Sergio

    Juriy
    До этого все делал средой у вас все через командную строку
    зачем? ну написали калькулятор И что дальше ? каждый раз когда изменяеться сервис нужно заходить в OS и перезапускать ,
    и много вы так напрограмируете в реальной задаче ?

  41. Juriy

    Sergio,

    Сейчас на рынке есть как минимум 4 mainstream среды разработки и ещё дюжина сред “на любителя”. Поэтому моё мнение – программист, если он не Monkey Coder, должен иметь хорошее представление о том, как работает его инструментарий под “гламурными кнопочками”, чтобы не зависеть от своей среды. Это, собственно, цель заметки.

    Если развивать эту идею, то мало реальных проектов собираются полностью средствами IDE, используются билд скрипты вроде Ant или Gradle.

  42. Sergio

    Юра,
    Основных 2 Эклипс и NetBeans , возможно России из-за специфики менталитета их больше :IMHO
    У меня Эклипс прекрасно все собирает , счас работаю с NetBeans. При необходимости и коммандную строку запускаю, т,к, лучше ее пока ничего не придумали, но тем не менее смотреть как создавать что-то первый раз через соmmand line меня напрягает, осообенно если не настроены переменные окружения, и в наличии нет второго экрана,
    Что-бы выпить стакан молока мне предлагают целую корову,

  43. Vadim Voituk

    Sergio,
    Это с каких пор основными IDE стали NetBeans и Eclipse?
    Netbeans в сравнении с Idea & Eclipse – легковесный девелоперский блокнотик.

    А то, что вы хотите делать описанные в заметке задачи мышко-кликерством в IDE, вместо понимания что происходит на самом деле, чести вам, как разработчику не делает.
    Тем более как реализовать это же в вашей любимой IDE хорошо написано в справочной документации – даже monkey-coder раберется. Какой смысл заметки тогда?

    Плох тот разработчик, у которого не настроен терминал с текстовой консолью.

  44. Sergio

    Я прекрасно понимаю что происходит на самом деле, не первый код в профессии , и не один мега скриптов написал , среда для того и придумана что-бы не раниматься рутинной работой ,точнее не заниматься в стандартной ситуации ,
    есть такой принцип 10/90, или Keep it simple
    Смысл за метки какой ? Не знаю Я думаю что такиж же заметок еще пол-сотни в гугле имееться ? sorry сам напросился :lol?

  45. Vadim Voituk

    Если не знаешь зачем заметка – какой смысл ее комментировать?
    Если и так “прекрасно понимаешь” это – зачем ее читать еще раз?
    Что-то сильно сомневаюсь про “не первый год”,

  46. Sergio

    создаем за 20 минут и что дальше?, это как раз и написано для Monkey Coders. IMHO

  47. Juriy

    Sergio, честное слово, стараюсь не поддерживать такой бессмысленный и бесцельный флейм, но уж надоело. Напишите свою заметку и покажите “как надо”. Тогда обсудим. Беспредметная критика на этом блоге не приветствуется.

  48. Дима

    Здравствуйте. Понравилось ,кратко ,но не все понятно,точнее из статьи то все понятно ,однако я думаю здесь не все моменты раскрыты.
    Вы бы не могли написать более подробную статью ,разьясняющую “архитектуру” веб-сервисов ,типичные случаи применения и как организовать веб-сервис ,а потом подключится к нему удаленно… С уважением ,Дмитрий.

  49. XX

    Apachi
    > Возник такой вопрос, при генерации wsdl, входные параметры обзываются таким образом: arg0, arg1,… Может кто знает как задавать осмысленные имена самому?

    public int add(
    @WebParam(name = “a”)
    int a,
    @WebParam(name = “b”)
    int b) {
    return a + b;
    }

  50. Alex.Bar

    Спасибо огромное за статью. Пользуюсь этим материалом уже несколько лет.

  51. prsmax

    Почему-то возвращает 0 когда отрабатывает клиент с любыми параметрами.
    Где можно посмотреть сами запросы, которые бегут на веб-сервис и обратно?

  52. prsmax

    SOAPUI помогло

Leave a Reply