Как перехватчик Spring Soap может изменить содержимое сообщения?
Я пытаюсь написать перехватчик для веб-службы, которая будет изменять содержимое сообщения Soap перед отправкой на конечную точку. Если клиент отправил сообщение, где значение какого-либо элемента равно 1, я хочу иметь возможность изменить этот элемент на 2, чтобы при поступлении сообщения в конечную точку выглядело, как если бы клиент отправил 2 вместо 1. Я не уверен, является ли это трудной задачей, которая озадачивает меня, или легкой задачей, которую я делаю сложнее, чем нужно.
Я прошел через некоторые перехватчики весны; но перехватчики проверки и регистрации не каждый изменяют сообщение, которое находится в пути. Wss4jSecurityInterceptor добавляет некоторые свойства к MessageContext; но я не смог использовать все, что он делает. У меня есть оболочка перехватчика; но ничего, что делает что-либо ценное.
public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws Exception {
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) messageContext
.getRequest();
SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
SOAPBody soapBody = soapMessage.getSOAPBody();
return true;
}
Я надеялся, что есть шанс, что еще кто-то уже решил эту конкретную проблему. Любое понимание будет оценено. Благодарю.
3 ответа
Изменение полезной нагрузки немного сложнее. Единственный способ найти эту работу - использовать getPayloadSource()
а также getPayloadResult()
методы на SoapBody
, которые выставляют javax.xml.transform
дружественные объекты для манипулирования данными.
Это раздражающе тяжеловесно, но вы можете сделать что-то вроде этого:
Transformer identityTransform = TransformerFactory.newInstance().newTransformer();
DOMResult domResult = new DOMResult();
identityTransform.transform(soapBody.getPayloadSource(), domResult);
Node bodyContent = domResult.getNode(); // modify this
identityTransform.transform(new DOMSource(bodyContent), soapBody.getPayloadResult());
Я хотел бы увидеть лучший способ сделать это.
Я изменил код в этом ответе, чтобы вставить <authentication/>
элемент во все запросы тела SOAP:
@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
logger.trace("Enter handleMessage");
try {
SaajSoapMessage request = (SaajSoapMessage) messageContext.getRequest();
addAuthn(request);
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
return true;
}
protected void addAuthn(SaajSoapMessage request) throws TransformerException {
Transformer identityTransform = TransformerFactory.newInstance().newTransformer();
DOMResult domResult = new DOMResult();
identityTransform.transform(request.getPayloadSource(), domResult);
Node bodyContent = domResult.getNode();
Document doc = (Document) bodyContent;
doc.getFirstChild().appendChild(authNode(doc));
identityTransform.transform(new DOMSource(bodyContent), request.getPayloadResult());
}
protected Node authNode(Document doc) {
Element authentication = doc.createElementNS(ns, "authentication");
Element username = doc.createElementNS(ns, "username");
username.setTextContent(authn.getUsername());
Element password = doc.createElementNS(ns, "password");
password.setTextContent(authn.getPassword());
authentication.appendChild(username);
authentication.appendChild(password);
return authentication;
}
Это решение было использовано, потому что WebServiceMessageCallback потребовал бы от меня изменения документа, а SaajSoapMessageFactory активировался до того, как тело мыла было вставлено настроенным Jaxb2Marshaller.
Я понял, что было проще изменить запрос на более поздний момент. Мне не нужно было изменять исходное сообщение SOAP, если я мог изменять данные до того, как они достигли моей конечной точки.
Конечные точки, с которыми я работаю, расширяют AbstractDom4jPayloadEndpoint - поэтому я завернул эти конечные точки в прокси-сервер, который позволил мне изменить элемент запроса, прежде чем перейти к моей конечной точке. то есть:
public class MyProxyEndpoint extends AbstractDom4jPayloadEndpoint
@Override
protected Element invokeInternal(
Element requestElement,
Document responseDocument ) throws Exception
{
if( requestElement != null )
{
// alter request element
}
return ( Element ) this.invokeMethod.invoke(
this.target,
requestElement,
responseDocument );
}