У нас есть 2 отдельных продукта, которые должны взаимодействовать друг с другом через веб-сервисы. Как лучше всего поддерживать управление версиями API?
У меня есть эта статья от 2004 года, в которой утверждается, что настоящего стандарта не существует, и только лучшие практики. Любые лучшие решения? Как вы решаете проблемы с версиями WS?
описание проблемы
Система А
Клиент
class SystemAClient{
SystemBServiceStub systemB;
public void consumeFromB(){
SystemBObject bObject = systemB.getSomethingFromB(new SomethingFromBRequest("someKey"));
}
}
Оказание услуг
class SystemAService{
public SystemAObject getSomethingFromA(SomethingFromARequest req){
return new SystemAObjectFactory.getObject(req);
}
}
Передаваемый объект
Версия 1
class SystemAObject{
Integer id;
String name;
... // getters and setters etc;
}
Версия 2
class SystemAObject{
Long id;
String name;
String description;
... // getters and setters etc;
}
Объект запроса
Версия 1
class SomethingFromARequest {
Integer requestedId;
... // getters and setters etc;
}
Версия 2
class SomethingFromARequest {
Long requestedId;
... // getters and setters etc;
}
Система Б
Клиент
class SystemBClient{
SystemAServiceStub systemA;
public void consumeFromA(){
SystemAObject aObject = systemA.getSomethingFromA(new SomethingFromARequest(1));
aObject.getDescription() // fail point
// do something with it...
}
}
Оказание услуг
class SystemBService{
public SystemBObject getSomethingFromB(SomethingFromBRequest req){
return new SystemBObjectFactory.getObject(req);
}
}
Передаваемый объект
Версия 1
class SystemBObject{
String key;
Integer year;
Integer month;
Integer day;
... // getters and setters etc;
}
Версия 2
class SystemBObject{
String key;
BDate date;
... // getters and setters etc;
}
class BDate{
Integer year;
Integer month;
Integer day;
... // getters and setters etc;
}
Объект запроса
Версия 1
class SomethingFromBRequest {
String key;
... // getters and setters etc;
}
Версия 2
class SomethingFromBRequest {
String key;
BDate afterDate;
BDate beforeDate;
... // getters and setters etc;
}
Сценарии неудач
Если система A клиент версии 1 вызывает систему B службу < strong>версия 2 может дать сбой:
- отсутствующие методы для
SystemBObject
(getYear()
,getMonth()
,getDay()
) - Неизвестный тип
BDate
Если система A клиент версии 2 вызывает систему B службу < strong>версия 1 может дать сбой:
- Неизвестный тип
BDate
наSomethingFromBRequest
(клиент использует более новый объект запроса B, который не распознается версией B 1) - Если клиент системы A достаточно умен, чтобы использовать версию 1 объекта запроса, он может выйти из строя из-за отсутствующих методов в объекте
SystemBObject
(getDate()
).
Если система B клиент версии 1 вызывает систему A службу < strong>версия 2 может дать сбой:
- Введите несоответствие или переполнение для
SystemAObject
(возвращеноLong
, но ожидаетсяInteger
)
Если система B клиент версии 2 вызывает систему A службу < strong>версия 1 может дать сбой:
- Введите несоответствие или переполнение в
SystemARequest
(запроситеLong
вместоInteger
) - Если запрос каким-то образом прошел, возникают проблемы с кастингом (заглушка
Long
, но служба возвращаетInteger
, не обязательно совместимую со всеми реализациями WS)
Возможные решения
- Используйте числа при продвижении версий: например.
SystemAObject1
,SystemBRequest2
и т. д., но отсутствует API для сопоставления исходной/целевой версии. - В подписи передавать XML, а не объекты (фу, передавать экранированный XML в XML, двойная сериализация, десериализация/разбор, распарсинг)
- Другое: напр. есть ли средство Document/literal/WS-I?