Советы и приемы работы с инструментарием разработки Web-сервисов IBM Rational Application Developer: Часть 2. Проверка классов Java на соответствие JAX-RPC

Генри Кви & группа технической поддержки, IBM Toronto Lab

При создании Web-сервисов на основе существующих приложений вы можете столкнуться с проблемами, связанными с генерированием кода. Основной причиной возникновения подобных проблем является несоответствие исходного приложения спецификации Java API для RPC, основанного на XML (JAX-RPC). В данной статье перечислены основные ошибки, вызванные этим несоответствием, и приведены советы по использованию Rational Application Developer для их предотвращения.

Введение

Данная статья, вторая в цикле, посвящена проблемам генерирования кода при разработке на основе существующего кода Web-сервисов, использующих Java™ API для RPC, основанного на XML (JAX-RPC) . В спецификации JAX-RPC определены стандартные способы преобразования типов Java в типы XML и обратно. Тем не менее разработчики должны иметь в виду, что в Web-сервисе, использующем JAX-RPC, не каждый класс Java может быть типом параметра метода или возвращаемого методом значения.

Если в процессе генерирования кода вы столкнулись с проблемами, то, скорее всего, их источником является несоответствие исходного класса спецификации JAX-RPC. Чтобы найти причину придется проверить исходные классы на предмет наличия в них несовместимых типов Java. Для этой цели в состав IBM® Rational® Application Developer 7 включен новый инструмент, анализирующий исходный Java-класс сервиса и используемые в нем типы и выполняющий проверку их соответствия ключевым требованиям спецификации JAX-RPC.

Научиться управлять процессом генерирования кода с помощью страницы настройки параметров Web-сервисов можно, прочитав первую статью цикла.

Разработка Web-сервисов на основе существующих приложений

При разработке Web-сервисов используются два подхода: "снизу вверх" - на основе существующих компонентов и "сверху вниз" - разработка компонентов исходя из общей концепции Web-сервиса.

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

При подходе "снизу вверх" Web-сервис создается на основе бизнес-логики, содержащейся в существующих bean- или EJB-компонентах (Enterprise Java™Beans), после чего генерируется WSDL-код, описывающий интерфейс получившегося Web-сервиса. Подход "снизу вверх" часто используется для превращения в Web-сервис существующего приложения.

При реализации подхода "снизу вверх" с помощью мастера Web-сервисов Rational Application Developer используются средства генерирования кода IBM® WebSphere® (Java2WSDL и WSDL2Java). Сначала мастер генерирует WSDL-файл из Java-кода существующего приложения с помощью Java2WSDL. Затем на основе полученного WSDL-файла мастер с помощью WSDL2Java создает составляющие Web-сервиса (вспомогательные классы Java, механизмы сериализации и десериализации, дескриптор развертывания и прочее).

Как уже было сказано, в процессе генерирования кода Web-сервиса создаются механизмы сериализации Java-объектов в XML (и их десериализации из XML), при этом бизнес-логика, реализованная в коде существующего приложения, остается нетронутой. Соответственно, возникновение ошибок при генерировании кода говорит о том, что не удалось создать механизм сериализации какого-либо типа параметра метода или возвращаемого значения, используемого в классе сервиса.

Типы Java, использование которых допускается в Web-сервисах, использующих JAX-RPC

Сервер приложений IBM WebSphere 6.0 и последующих версий поддерживает спецификацию JAX-RPC 1.1. Спецификация JAX-RPC обеспечивает функциональную совместимость и переносимость разработанных в соответствии с ней Web-сервисов и клиентов. К числу типов Java, поддерживаемых JAX-RPC, относятся:

  • Отдельные примитивные типы (boolean, byte, short, int, long, float и double)
  • Отдельные стандартные классы (String, Date, Calendar, BigInteger, BigDecimal, QName и URI)
  • Массивы, элементами которых являются объекты поддерживаемых типов
  • Исключения, наследующие от java.lang.Exception
  • Типы значений JAX-RPC

Первые четыре типа не требуют особых пояснений. Разобраться с типами значений JAX-RPC несколько сложнее.

Чтобы быть совместимым с JAX-RPC типом значения, класс Java должен отвечать приведенным ниже требованиям:

  • Он должен иметь конструктор с уровнем доступа public.
  • Он не должен реализовывать (прямо или косвенно) интерфейс java.rmi.Remote.
  • Он может реализовывать любой интерфейс (за исключением java.rmi.Remote) и наследовать от любого класса.
  • Он может иметь поля, имеющие уровень доступа public, private, protected или по умолчанию (package-level). Все атрибуты должны иметь тип, поддерживаемый JAX-RPC.
  • Если тип значения JAX-RPC оформлен как класс bean-компонента, каждое свойство этого компонента должно иметь соответствующие setter и getter методы и иметь тип, поддерживаемый JAX-RPC.

Концепцию типов значений легко объяснить на примерах. Person.java (листинг 1) и Employee.java (листинг 2) являются примерами корректных типов значений JAX-RPC, поскольку отвечают приведенным выше требованиям.

Листинг 1. Person.java

                 
public class Person {
	private String name;
	private Calendar dateOfBirth;
	public Person() {
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	public void setDateOfBrith(Calendar dateOfBirth) {
		this.dateOfBirth = dateOfBirth;
	}
	public Calendar getDateOfBirth() {
		return dateOfBirth;
	}
}

Листинг 2. Employee.java

                 
public class Employee extends Person {
	private BigDecimal salary;
	private String[] ProjectNames;
	public Employee() {}
	public String[] getProjectNames() {
		return ProjectNames;
	}
	public void setProjectNames(String[] projectNames) {
		ProjectNames = projectNames;
	}
	public BigDecimal getSalary() {
		return salary;
	}
	public void setSalary(BigDecimal salary) {
		this.salary = salary;
	}
}

Типы Java, которых стоит избегать в Web-сервисах, использующих JAX-RPC

Ответы на приведенные ниже вопросы покажут, какие классы не следует применять в Web-сервисах, использующих JAX-RPC.

Разрешены ли коллекции?

Использовать коллекции в Web-сервисах не рекомендуется. Это связано с тем, что они могут содержать элементы различных типов. При отсутствии исчерпывающей информации от пользователя коллекцию невозможно преобразовать в четко определенный элемент XML-схемы, имеющий однозначные правила сериализации и десериализации элементов.

Платформа Web-сервисов WebSphere поддерживает перечисленные ниже типы коллекций (с помощью унаследованных механизмов преобразования Axis), причем исключительно в среде WebSphere:

  • java.util.Vector
  • java.util.Hashtable
  • java.util.HashMap

Перечисленные типы Java преобразуются в нестандартные типы XML Schema и реального документа (instance document) и не могут использоваться при взаимодействии с другими платформами Web-сервисов.

Поскольку функциональная совместимость является основной целью технологии Web-сервисов, не стоит предполагать, что Web-сервис и его клиенты будут всегда использовать исключительно платформу WebSphere. Принимая во внимание вышесказанное, рекомендуется избегать использования этих трех типов коллекций при разработке Web-сервисов, использующих JAX-RPC. Проще всего избежать проблем с коллекциями если использовать вместо них массивы Java. Если исходный API использует коллекции и изменить его никак нельзя, можно написать код-обертку, преобразующий коллекции в массивы.

Разрешены ли интерфейсы?

Нет. Интерфейсы не поддерживаются JAX-RPC. Из-за этого вам следует избегать использования интерфейсов, таких, как, например, org.w3c.dom.Element.

Разрешены ли типы java.sql.Date и java.sql.Timestamp?

Нет. Эти типы не поддерживаются JAX-RPC. Вместо них нужно использовать java.util.Calendar. Если исходный API использует эти типы и его нельзя изменить, можно написать код-обертку, преобразующий их в java.util.Calendar.

Разрешен ли тип java.util.Date?

Рекомендуется отказаться от использования этого типа в пользу java.util.Calendar по следующей причине. При преобразовании данных Java в XML в Web-сервисах, использующих JAX-RPC, тип java.util.Date преобразуется в xsd:datetime. Тип xsd:dateTime, в свою очередь, соответствует типу java.util.Calendar при обратном преобразовании. Это означает, что Web-сервис и его клиент будут воспринимать объекты типа java.util.Date по-разному.

Дополнительные требования

Исключения

JAX-RPC предписывает наличие в каждом исключении, используемом в Web-сервисе, конструктора, имеющего соответствующий параметр для каждого свойства, снабженного getter-методом. В листинге 3 приведен пример неподдерживаемого класса исключения.

Листинг 3. UserDoesNotExistException.java (не соответствует требованиям JAX-RPC)

                 
public class UserDoesNotExistException extends Exception {
	private String userId;
	private String userName;
	private Throwable throwable;

	public UserDoesNotExistException(String userId, Throwable throwable) {
		this.userId = userId;
		this.throwable = throwable;
	}

	public String getUserId() {
		return userId;
	}

	public String getUserName() {
		return userName;
	}

	public Throwable getThrowable() {
		return throwable;
	}
}

Код, приведенный в листинге 3 содержит два несоответствия спецификации. Во-первых, свойство throwable имеет тип, не поддерживающийся JAX-RPC. Во-вторых, конструктор не имеет параметра, соответствующего свойству userName. Пример класса исключения, соответствующего спецификации приведен в листинге 4.

Листинг 4. UserDoesNotExistException.java (соответствует требованиям JAX-RPC)

                 
public class UserDoesNotExistException extends Exception {
	private String userId;
	private String userName;

	public UserDoesNotExistException(String userId, String userName) {
		this.userId = userId;
	}

	public String getUserId() {
		return userId;
	}

	public String getUserName() {
		return userName;
	}
}

Свойства userId и username входят в число параметров конструктора класса UserDoesNotExistException, приведенного в листинге 4. Кроме того, эти свойства снабжены соответствующими getter-методами. Следовательно, этот класс соответствует спецификации JAX-RPC.

Средство проверки соответствия JAX-RPC

В состав Rational Application Developer 7 входит инструмент, производящий проверку классов Java на соответствие требованиям JAX-RPC перед генерированием на их основе кода Web-сервисов. Опцию Validate Java classes for compliance (Проверять классы Java на соответствие) можно включить в окне (рисунок 1), отображаемом по команде Window > Preferences > Web Services > WebSphere > JAX-RPC Code Generation.

Рисунок 1. Опция Validate Java classes for compliance option (Проверять классы Java на соответствие)
Окно настройки параметров, опция обведена красным прямоугольником

По умолчанию эта опция включена. Перед генерированием кода Web-сервиса из кода существующего приложения данное средство выполнит проверку класса сервиса и используемых типов на соответствие спецификации JAX-RPC и, в случае выявления несоответствий, выдаст предупреждения.

Пример класса сервиса, не соответствующего JAX-RPC, приведен в листинге 5.

Листинг 5. NoncomplianceTest.java

                 
public class NoncomplianceTest {
	//ArrayList is a Java collection types
	public void test1(ArrayList al) {
	}
	
	//java.lang.Object is not a supported JAX-RPC type.
	public void test2(Object obj) {
	}
	
	//Primitive type char is not a supported JAX-RPC type.
	public void test3(char c) {
	}
	
	//Person is an interface
	public void test4(Person p) {
	}

	//java.sql.Timestamp is not a supported JAX-RPC type.
	public void test5(java.sql.Timestamp timeStamp) {
	}
}

public interface Person {
	   public void setName(String n);
	   public String getName();
}

При генерировании кода Web-сервиса из кода существующего приложения с помощью мастера Web-сервисов (для этого нажмите на NoncomplianceTest.java правой кнопкой мыши, затем выполните команду контекстного меню Web Services > Create Web service и нажмите Next) мастер выдаст предупреждение, как показано на рисунке 2.

Рисунок 2. Предупреждение о несоответствии JAX-RPC
Окно сообщения об ошибке

Сообщение в диалоговом окне содержит детальную информацию об обнаруженном несоответствии в типах данных. Вы можете проигнорировать это предупреждение и продолжить генерирование кода. В этом случае при развертывании полученного Web-сервиса или в ходе его работы могут возникнуть сбои.

Что делать, если не удается избавиться от ошибок при генерировании кода?

Если этих советов оказалось недостаточно для того, чтобы избавиться от ошибок при генерировании кода, то перед тем, как обратиться в службу поддержки IBM, попробуйте выполнить следующие действия:

Установите последние обновления для Rational Application Developer

IBM выпускает обновления для Rational Application Developer в среднем каждые три месяца. При этом каждое обновление содержит значительное количество исправлений. Возможно, проблема, с которой вы столкнулись, уже решена, достаточно лишь установить последнее обновление. Для установки обновлений используйте менеджер инсталляции.

Обновите тестовую среду сервера приложений WebSphere

Если установка последних обновлений для Rational Application Developer не помогла справиться с ошибками, обновите тестовую среду сервера приложений WebSphere.

Если у вас установлена тестовая среда сервера приложений WebSphere 6.1 и разрабатываемый проект предназначен для WebSphere 6.1, то Rational Application Developer 7 использует для генерирования кода Web-сервисов файл com.ibm.ws.webservices.thinclient_6.1.0.jar file в каталоге < Каталог установки Rational Application Developer>/runtimes/base_v61/runtimes.

Если установлена тестовая среда WebSphere 6.0 и разрабатываемый проект предназначен для WebSphere 6.0, то Rational Application Developer 7 использует файл webservices.jar в каталоге < Каталог установки Rational Application Developer>/runtimes/base_v6/lib/.

IBM регулярно выпускает обновления для сервера приложений WebSphere. Рекомендуется установить эти обновления и использовать последнюю версию сервера приложений WebSphere.

Обратитесь в службу поддержки IBM

Если ни один из советов, приведенных в статье, не помог, и при генерировании кода Web-сервисов из кода существующего приложения все еще возникают ошибки, это может быть вызвано дефектом ПО. Вы можете обратиться в службу поддержки IBM Rational и сделать сообщение об ошибке (Problem Management Report (PMR)).

Соответствие JAX-RPC

В этой статье я рассказал вам о требованиях, которым должен соответствовать исходный класс для создания Web-сервиса, использующего JAX-RPC. Кроме того, вы узнали о том, что средство проверки соответствия JAX-RPC, входящее в состав Rational Application Developer, может помочь выявить несовместимые классы. Теперь у вас намного больше шансов избежать проблем при генерировании кода Web-сервисов из кода существующих приложений.


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=17079