07.11.2011

Веб-сервис на Java с использованием Apache CXF.

Напишем простой веб-сервис на Java, используя фреймворк Apache CXF, JAXB, и JUnit для тестирования. Используемая среда разработки - Eclipse (Java EE IDE for Web Developers). Последнюю версию Apache CXF можно скачать здесь. В Eclipse нужно создать обычный Java проект, в свойствах проекта добавить библиотеки CXF и JUnit (Project > Properties > Java Build Path > Add Library). Это все что нужно, можно приступать к написанию кода.
1. Классы запроса и ответа.
Первым делом определим типы данных запроса и ответа, с которыми будет иметь дело наш веб-сервис. В запросе будет содержаться имя и фамилия, в ответе - приветствие с этим именем и фамилией. Для преобразования Java объектов в XML данные и обратно используется JAXB  (Java Architecture for XML Binding). Вот так выглядит класс данных запроса:
package servicetest;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class RequestType {
 private String firstName;
 private String lastName;

 @XmlElement(required = true, name="frist-name")
 public String getFirstName(){
  return firstName;
 }

 public void setFirstName(String value){
  firstName = value;
 }

 @XmlElement(required = true, name="last-name")
 public String getLastName(){
  return lastName;
 }

 public void setLastName(String value){
  lastName = value;
 }
}

JAXB является частью платформы Java SE и, как видно, для преобразования данных используются аннотации. Обычно подобные классы автоматически генерируются на основе XSD схемы.  Класс ответа у нас будет таким:

package servicetest;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class ResponseType {
 private String greeting;

 @XmlElement(required = true)
 public String getGreeting(){
  return greeting;
 }

 public void setGreeting(String value){
  greeting = value;
 }
}

2. Реализация веб-сервиса. Теперь напишем интерфейс, в котором объявлен единственный метод веб-сервиса.

package servicetest;
import javax.jws.WebService;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@WebService
public interface HelloServiceResource {
 @POST
 @Path("sayHello")
 @Produces("application/xml")
 @Consumes("application/xml")
 ResponseType sayHello (RequestType quote);
}

И соответственно, его реализация, собственно "ядро" веб-сервиса:

package servicetest;
import javax.jws.WebService;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@WebService (serviceName
 = "HelloService", targetNamespace = "http://servicetest")
public class HelloService implements HelloServiceResource {

 @POST
 @Path("sayHello")
 @Produces("application/xml")
 @Consumes("application/xml")
 public ResponseType sayHello (RequestType request) {
  ResponseType response = new ResponseType();
  response.setGreeting("Hello " +
  request.getFirstName() + " " + request.getLastName()+"!");
  return response;
 }
}

Как видно, здесь тоже используются аннотации, которые описывают веб-сервис и его метод sayHello. Теперь осталось только запустить сервис, в данном случае будем делать это в методе main:

package servicetest;
import javax.xml.ws.Endpoint;

public class Main {
 public static void main(String[] args){
  HelloService webService = new HelloService();
  String address = "http://localhost:8080/helloService";
  Endpoint.publish(address, webService);
 }
}

3. Тестовый клиент. Веб-сервис готов к работе, осталось только протестировать. Для этого можно написать тестовый клиент - создадим класс HelloClient, с методом, который будем запускать как JUnit тест. Для этого нужно только добавить аннотацию @Test перед определением метода  (для запуска теста в Eclipse на панели Outlie, в контекстном меню соответствующего метода выбрать Debug As > JUnit Test).

package servicetest;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.junit.Test;

public class HelloClient {

@Test
public void runTest() {

   JaxWsProxyFactoryBean factory =
   new JaxWsProxyFactoryBean();

   LoggingInInterceptor i = new LoggingInInterceptor();
   factory.getInInterceptors().add(i);
   LoggingOutInterceptor o = new LoggingOutInterceptor();
   factory.getOutInterceptors().add(o);
   factory.setServiceClass(HelloServiceResource.class);
  
   factory.setAddress("http://localhost:8080/helloService");
   HelloServiceResource client =
               (HelloServiceResource) factory.create();
   RequestType request = new RequestType();
  
   request.setFirstName("Alex");
   request.setLastName("Dl");
  
   ResponseType reply = client.sayHello(request);
   System.out.println("Response: "+ reply.getGreeting());
   System.exit(0);
  }
}

В результате запуска теста должен получиться вывод, похожий на этот:

ID: 1
Address: http://localhost:8080/helloService
Encoding: UTF-8
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload:
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org
/soap/envelope/">
  <soap:body>
   <ns2:sayhello xmlns:ns2="http://servicetest/">
    <arg0>
     <frist-name>Alex</frist-name>
     <last-name>Dl</last-name>
    </arg0>
   </ns2:sayhello>
  </soap:body>
 </soap:envelope>
--------------------------------------
ноя 07, 2011 1:36:10 AM
org.apache.cxf.services.HelloServiceResourceService.
HelloServiceResourcePort.HelloServiceResource
INFO: Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {Content-Length=[238],
content-type=[text/xml;charset=UTF-8],
Server=[Jetty(7.5.3.v20111011)]}
Payload:
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org
/soap/envelope/">
  <soap:body>
   <ns2:sayhelloresponse xmlns:ns2="http://servicetest/">
    <return>
     <greeting>Hello Alex Dl!</greeting>
    </return>
   </ns2:sayhelloresponse>
  </soap:body>
 </soap:envelope>
--------------------------------------
Response: Hello Alex Dl!

Все, веб-сервис работает! В Payload видно, какие данные были переданы веб-сервису в POST запросе и что получено в ответе. Конечно, можно обойтись и без тестового клиента, просто создав POST запрос с помощью curl или утилиты наподобие wfetch. Структура XML данных запроса и ответа (корневой элемент и т.п.) может быть изменена с помощью множества настроек, которые были опущены для упрощения примера.

Скачать исходники примера.



Теги: programming webservice java

comments powered by Disqus