如何调整Grails CXF SOAP服务响应,将iniwebresult放入iniresponsewrapper?
Grails CXF SOAP服务响应结构调整问题
问题背景
我尝试用Groovy编写Grails CXF SOAP服务,现有代码如下:
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement() class Input { @XmlElement(name = "memberCode", required = true, namespace = "java:financial.sekuritas.pt.com.doReceivePushData") String memberCode @XmlElement(name = "fileContents", required = true, namespace = "java:financial.sekuritas.pt.com.doReceivePushData") String fileContents @XmlElement(name = "crc32", required = true, namespace = "java:financial.sekuritas.pt.com.doReceivePushData") String crc32 @XmlElement(name = "urlWS", required = true, namespace = "java:financial.sekuritas.pt.com.doReceivePushData") String urlWS } @Transactional @GrailsCxfEndpoint(address = "/doReceivePushData") class ReportInvestorAccountCIMBService { @Resource WebServiceContext context @WebMethod(operationName = "doReceivePushData") @WebResult(header = true, name = "iniwebresult") @ResponseWrapper(localName="iniresponsewrapper") public String doReceivePushData(@WebParam(name = 'input') @XmlElement(name = "input", required = true, namespace = "http://financial.sekuritas.pt.com/") Input Input) { return 1 } }
当前生成的SOAP响应结构:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <doReceivePushDataResponse> <iniresponsewrapper/> <iniwebresult>string</iniwebresult> </doReceivePushDataResponse> </soap:Body> </soap:Envelope>
期望的SOAP响应结构:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <doReceivePushDataResponse> <iniresponsewrapper> <iniwebresult>string</iniwebresult> </iniresponsewrapper> </doReceivePushDataResponse> </soap:Body> </soap:Envelope>
需要修改代码让iniwebresult被包裹在iniresponsewrapper标签内。
解决方案
问题根源在于两个点:
@WebResult(header = true)会把结果放到SOAP头部而非响应体的包装器内,直接导致iniwebresult脱离了iniresponsewrapper。- 直接返回
String类型无法和@ResponseWrapper正确配合,需要创建专门的响应包装类承载结果字段。
步骤1:创建响应包装类
新增带JAXB注解的包装类,将iniwebresult作为其字段:
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "iniresponsewrapper") class IniResponseWrapper { @XmlElement(name = "iniwebresult", required = true) String iniwebresult }
步骤2:修改服务类方法
调整服务类的注解和返回类型,移除header = true,并返回包装类实例:
@Transactional @GrailsCxfEndpoint(address = "/doReceivePushData") class ReportInvestorAccountCIMBService { @Resource WebServiceContext context @WebMethod(operationName = "doReceivePushData") @WebResult(name = "iniresponsewrapper") public IniResponseWrapper doReceivePushData( @WebParam(name = 'input') @XmlElement(name = "input", required = true, namespace = "http://financial.sekuritas.pt.com/") Input input) { def response = new IniResponseWrapper() response.iniwebresult = "1" // 返回字符串类型的"1",对应期望的string节点 return response } }
说明
- 移除
@ResponseWrapper注解,自定义的IniResponseWrapper类已直接定义响应结构,CXF会自动基于该类生成对应包装节点。 - 返回类型从
String改为IniResponseWrapper,确保结果被正确包裹在iniresponsewrapper内部。 - 去掉
@WebResult的header = true属性,让结果出现在SOAP体的包装器中。
修改后生成的SOAP响应会符合期望结构,iniwebresult将被包裹在iniresponsewrapper标签内。
内容的提问来源于stack exchange,提问作者Kraken
相关产品推荐
相关产品推荐

