У нас есть 2 отдельных продукта, которые должны общаться друг с другом через веб-службы. Какова наилучшая практика для поддержки versioining API?
У меня эта статья от 2004 года, утверждая, что нет фактического стандарта и только лучшие практики. Какие-нибудь лучшие решения? Как вы решаете WS-версию?
Описание проблемы
Система A
Client
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;
}
Система B
Client
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;
}
Сценарии сбоев
Если клиент System A версии 1 вызывает службу System B версии 2, он может выйти из строя on:
- отсутствующие методы на
SystemBObject
(getYear()
,getMonth()
,getDay()
) - Неизвестный тип
BDate
Если клиент System A версии 2 вызывает службу System B версии 1, он может выйти из строя на:
- Неизвестный тип
BDate
вSomethingFromBRequest
(клиент использует новый объект запроса B, который B-версия 1 не распознает) - Если клиент System A достаточно умен, чтобы использовать версию 1 объекта запроса, он может не работать с отсутствующими методами в объекте
SystemBObject
(getDate()
)
Если клиент System B версии 1 вызывает службу System A версии 2, он может выйти из строя on:
- Введите missmatch или overflow на
SystemAObject
(возвращаетсяLong
, но ожидаетсяInteger
)
Если клиент System B версии 2 вызывает службу System A версии 1, она может выйти из строя на:
- Введите missmatch или overflow на
SystemARequest
(запросLong
вместоInteger
) - Если запрос каким-то образом прошел, проблемы с литьем (заглушка
Long
, но служба возвращаетInteger
, которая несовместима во всех реализациях WS)
Возможные решения
- Используйте числа при продвижении версий: например.
SystemAObject1
,SystemBRequest2
и т.д., но при этом отсутствует API для соответствия исходной/целевой версии - В сигнатуре передать XML, а не объекты (yuck, pass escaped XML в XML, двойная сериализация, десериализация/синтаксический анализ, unparsing)
- Другое: например. У документа/литерала/WS-I есть средство правовой защиты?