我有一个使用jaxb和spring webservice构建的java Web服务应用程序。
我在xsd中有一个复杂的类型:
...
<complexType name="GetRecordsRequest">
<sequence>
<element name="maxRecords" type="int" maxOccurs="1" minOccurs="1"/>
</sequence>
</complexType>
...
使用 xjc ,我有从xsd生成的jaxb类:
public class GetRecordsRequest {
protected int maxRecords;
public int getMaxRecords() {
return maxRecords;
}
public void setMaxRecords(int value) {
this.maxRecords = value;
}
}
我在spring context.xml中使用了 PayloadValidatingInterceptor 来确保用户不能为maxRecords输入除整数之外的任何内容:
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
<property name="interceptors">
<list>
<ref local="validatingInterceptor" />
</list>
</property>
</bean>
<bean id="validatingInterceptor" class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="/WEB-INF/schemas/webservice.xsd" />
<property name="validateRequest" value="true" />
<property name="validateResponse" value="true" />
</bean>
当我在Soap UI中输入此soap请求xml时:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.test.com/ns1">
<soapenv:Header/>
<soapenv:Body>
<ns1:GetRecordsRequest>
<ns1:maxRecords></ns1:maxRecords>
</ns1:GetRecordsRequest>
</soapenv:Body>
</soapenv:Envelope>
我得到的回复信息是:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Client</faultcode>
<faultstring xml:lang="en">Validation error</faultstring>
<detail>
<spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-datatype-valid.1.2.1: '' is not a valid value for 'integer'.</spring-ws:ValidationError>
<spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: The value '' of element 'cis:maxRecords' is not valid.</spring-ws:ValidationError>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
你可以看到结果只是一个字段的两行神秘消息。我只需要一行就可以使响应消息更漂亮吗?有没有办法自定义验证错误响应消息?
答案 0 :(得分:1)
您可以使用AbstractValidatingInterceptor的方法自定义验证错误响应(PayloadValidatingInterceptor是此抽象类的实现),即:
部分示例:
public final class MyPayloadValidatingInterceptor
extends PayloadValidatingInterceptor {
@Override
protected Source getValidationRequestSource(WebServiceMessage webSerMessage_) {
_source = webSerMessage_.getPayloadSource();
validateSchema(_source);
return _source;
}
private void validateSchema(Source source_) throws Exception {
SchemaFactory _schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema _schema = _schemaFactory.newSchema(getSchemas()[0].getFile());
Validator _validator = _schema.newValidator();
DOMResult _result = new DOMResult();
try {
_validator.validate(source_, _result);
} catch (SAXException _exception) {
// modify your soapfault here
}
}
}
答案 1 :(得分:1)
您可以通过扩展PayloadValidatingInterceptor并覆盖handleRequestValidationErrors来自定义验证错误消息。我们可以在messageContext的主体中设置自定义错误消息。
1)您可以返回带有验证错误消息的自定义xml响应,而不是请求验证错误的SOAP Fault。
2)SAXParseException []错误包含请求验证错误。您可以选择仅返回一个错误作为响应。 (或)对于某些预定义错误,您可以返回自定义错误消息,而不是SAXParseException中返回的错误消息。
/**
* The Class CustomValidatingInterceptor.
*/
public class CustomValidatingInterceptor extends PayloadValidatingInterceptor{
/* (non-Javadoc)
* @see org.springframework.ws.soap.server.endpoint.interceptor.AbstractFaultCreatingValidatingInterceptor#handleRequestValidationErrors(org.springframework.ws.context.MessageContext, org.xml.sax.SAXParseException[])
*/
@Override
protected boolean handleRequestValidationErrors(MessageContext messageContext, SAXParseException[] errors) throws TransformerException {
JAXBContext jaxbContext;
StringWriter stringWriter = new StringWriter();
ResponseTransactionDetail transactionDetail = null;
for (SAXParseException error : errors) {
logger.debug("XML validation error on request: " + error.getMessage());
}
if (messageContext.getResponse() instanceof SoapMessage) {
/**
* Get SOAP response body in message context (SOAP Fault)
*/
SaajSoapMessage soapMessage = (SaajSoapMessage)messageContext.getResponse();
SoapBody body = soapMessage.getSoapBody();
// marshal custom error response to stringWriter
/**
* Transform body
*/
Source source = new StreamSource(new StringReader(stringWriter.toString()));
identityTransform.transform(source, body.getPayloadResult());
stringWriter.close();
}
return false;
}