вторник, 4 мая 2010 г.

CXF: Шаг 1 - Описание интерфейса средствами Java

Шаг 1. Описание интерфейса средствами Java.
На мой взгляд, работая с CXF лучше использовать именно 'Java first' схему объявления интерфейса. В основном потому, что манипулируя аннотациями легче получить желаемый WSDL.
Итак, процесс описания интерфейса веб сервиса предельно прост и довольно подробно описан на сайте CXF. Но встречаются мелкие моменты, которые не описаны толком, но при этом не дают спать спокойно.


Имена параметров и возвращаемых значений

Собственно говоря это не хитрость, а просто 'не приятное наблюдение' – все параметры методов пройдется проаннотировать с помощью @WebParam (если хочется получить удобочитаемый интерфейс). Так что если интерфейс объемный, то пройдется запастись терпением :)

Указание главного targetNamespace для WSDL

По умолчанию targetNamespace для тега 'wsdl:definitions ' берется с имени пакета. Т.е. если SEI находится в org.test.ws то результирующий WSDL будет начинаться примерно вот так:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://ws.test.org/">
Есть возможность явно указать targetNamespace для всего WSDL (параметр параметр 'targetNamespace' для аннотации @WebService). И если @WebService присутствует и в SEI (интерфейсе) и в реализации (классе) (или SEI и реализация находятся в разных пакетах), то лучше проследить, чтобы значения 'targetNamespace' совпадали. Иначе в результирующем WSDL появится тег 'wsdl:import' (и некоторые неудобства, связанные с этим).

Исключения (wsdl:fault)

Довольно 'интересной' задачей оказалось корректное объявление исключений. Полное описание как это сделать присутствует только в спецификации JAX-WS. Вот пример:
@WebFault
public class MyException extends Exception {

  private MyFaultInfo faultInfo = null;

  public MyException(String message, MyFaultInfo faultInfo) {
    super(message);
    this.faultInfo = faultInfo;
  }
  public MyException(String message, MyFaultInfo faultInfo, Throwable cause) {
    super(message, cause);
    this.faultInfo = faultInfo;
  }
  public MyFaultInfo getFaultInfo() {
    return faultInfo;
  }
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "my-fault-info-type", propOrder = { "description" })
@XmlRootElement(name = "my-fault-info")
public class MyFaultInfo {
  private String description = null;
  public String getDescription() {
    return description;
  }
  public void setDescription(String description) {
    this.description = description;
  }
}
Что необходимо соблюсти:
  • Наше исключение унаследовано от java.lang.Exception (или его потомка)
  • Присутствует два обязательных конструктора (с параметрами 'String, MyFaultInfo' и 'String, MyFaultInfo, Throwable')
  • Присутствует метод getFaultInfo()
  • Класс-носитель дополнительной информации (в нашем случае это MyFaultInfo) мапится по всем правилам JAXB

Параметры типа Map, бинарные данные и прочие

В отличии от XFire, CXF 'не понимает' параметры типа Map, DataSource и т.д.
Для преодоления этих неудобств приходится прибегать к помощи класса XmlAdapter и аннотации @XmlJavaTypeAdapter.

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

Отправить комментарий