我有一个公开方法的SOAP服务
TradeDetail getTradeDetail()
TradeDetail存储5个字段,交易编号,日期等
我需要向TradeDetail添加几个字段。我想保持向后兼容性(暂时),看起来我的选项仅限于创建一个带有额外字段的新类
TradeDetail2 getTradeDetail2()
现在这将有效 - 我以前做过。但是,人们使用过其他解决方案吗?
E.g。
我可以很快退出原始界面,因此代码将被清理,额外的TradeDetail2将永远不会持续!
感谢
答案 0 :(得分:3)
我很同情 - 我的一些网络服务充斥着myMethod()
,myMethod2()
,myMethod3()
等等,因为我需要添加一些新字段。
您是否有理由保留方法名称并为每个API版本创建新的端点?例如:
然后,无论您需要做多少未来的更改,您的方法名称都是合理的。
使用您的Web服务的任何应用程序可能都需要针对新的WSDL进行重写和/或重建,以便利用新字段,因此,为什么不在新的v1.1 API上重写/重建它们。
我发现使用您的服务与应用程序的所有者/开发人员进行通信时也会有所帮助 - 例如,“日期”之后将不再支持我们的Web服务API版本[旧],请确保你至少使用版本[new]。“
答案 1 :(得分:3)
这就是为什么我更喜欢完全控制XML到Object的映射,这样我就可以将模型与XML接口分开。在您的情况下,我只需向TradeDetail添加新字段,并将其视为“可选”以实现向后兼容性。这将是我的团队使用的框架中针对TradeDetail的示例XML-> Object映射,为您的界面编写:
// this would go into my client endpoint class
public TradeDetail getTradeDetail() {
Element requestRoot = new Element("GetTradeDetail");
Element responseRoot = invokeWebServiceAndReturnJdomElement(requestRoot);
return mapTradeDetail(responseRoot);
}
// this would go into my client XO mapping class
public TradeDetail mapTradeDetail(Element root) {
TradeDetail tradeDetail = new TradeDetail();
tradeDetail.setField1 = fetchString(root, "/GetTradeDetail/Field1");
tradeDetail.setField2 = fetchInteger(root, "/GetTradeDetail/Field2");
tradeDetail.setField3 = mapField3(root, "/GetTradeDetail/Field3");
tradeDetail.setField4 = fetchString(root, "/GetTradeDetail/Field4");
}
这种客户端会忽略新字段,因此与新版本的协议兼容,直到我在版本2中的同一方法的末尾添加类似这样的内容:
if (fetchXPath(root, "/GetTradeDetail/Field5") != null) {
// so we're talking with server which speaks new version of protocol
tradeDetail.setField5 = fetchString(root, "/GetTradeDetail/Field5");
}
服务器可以使用类似的代码,可能检查客户端版本,并仅在客户端支持新版协议时映射额外字段。
在我看来,应该编写客户端,以便添加到协议中的额外字段不会破坏客户端 - 我不会因为上游提供商添加了新功能而没有告知我这一点而感到沮丧它。如果提供者更改现有的必填字段,当然,客户需要修改。这就是为什么上游提供商应该版本协议并支持旧版本至少几个月。
答案 2 :(得分:1)
这篇文章Best practices for Web services versioning可能有些用处。