Как перехватчик Spring Soap может изменить содержимое сообщения? - PullRequest
5 голосов
/ 08 июля 2010

Я пытаюсь написать перехватчик для веб-службы, который будет изменять содержимое сообщения 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 ]

6 голосов
/ 23 июля 2010

Изменение полезной нагрузки немного сложно.Единственный способ найти эту работу - использовать методы 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());

Я бы хотел увидеть лучший способ сделать это.

1 голос
/ 13 ноября 2016

Я изменил код в этом ответе, чтобы вставить элемент <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.

1 голос
/ 28 июля 2010

Я понял, что проще изменить запрос на более позднем этапе. Мне не нужно было изменять исходное сообщение SOAP, если я мог изменять данные до того, как они достигли моей конечной точки.

Конечные точки, с которыми я работаю, расширяют AbstractDom4jPayloadEndpoint - поэтому я обернул эти конечные точки в прокси, который позволил мне изменить элемент запроса, прежде чем перейти к моей конечной точке. i.e.:

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 );
    }
...