2010-07-08 16 views
5

Próbuję napisać przechwytywacz dla usługi sieci Web, który zmodyfikuje treść komunikatu Soap, zanim zostanie wysłany do punktu końcowego. Jeśli klient wysłał komunikat, w którym wartość jakiegoś elementu wynosi 1, chcę móc zmienić ten element na 2, aby po dotarciu komunikatu do punktu końcowego wyglądało na to, że klient przesłał 2 zamiast 1. Nie jestem pewien, czy jest to trudne zadanie, które mnie wyklucza, czy też łatwe zadanie, które robię mocniej, niż powinno być.W jaki sposób przechwytujący Soap Spring może modyfikować zawartość wiadomości?

Przeszedłem przez kilka przechwytujących Spring; ale przechwytywacze sprawdzania poprawności i rejestrowania nie zmieniają wiadomości, która jest w tranzycie. Wss4jSecurityInterceptor dodaje niektóre właściwości do MessageContext; ale nie byłem w stanie wykorzystać niczego, co robi. Mam powłokę przechwytywacza; ale nic, co robi cokolwiek z dowolnej wartości.

Miałem nadzieję, że była szansa, że ​​ludzie inni już rozwiązali ten konkretny problem. Każdy wgląd byłby doceniony. Dzięki.

Odpowiedz

6

Modyfikowanie ładunku jest nieco trudne. Jedynym sposobem, w jaki udało mi się to zrobić, jest użycie metod getPayloadSource() i na obiektach SoapBody, które eksponują przyjazne obiekty do manipulowania danymi.

Jest irytująco wagi ciężkiej, ale można zrobić coś takiego:

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()); 

chciałbym zobaczyć lepszy sposób to robi.

+0

Dzięki. Masz rację - nie jest to tak proste, jak można mieć nadzieję. Naprawdę rozwiązałem mój problem w inny sposób. Chociaż nie odnosi się bezpośrednio do mojego pierwotnego pytania - rozwiązał mój obecny problem. – Dave

1

Uświadomiłem sobie, że łatwiej było zmienić wniosek w późniejszym czasie. Nie musiałem modyfikować oryginalnego komunikatu SOAP, o ile udało mi się zmodyfikować dane przed osiągnięciem punktu końcowego.

Punkty końcowe, z którymi pracuję, obejmują rozszerzenie obiektu AbstractDom4jPayloadEndpoint, więc zapakowałem te punkty końcowe w proxy, co pozwoliło mi zmodyfikować element żądania przed przejściem do punktu końcowego. tj:

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

I zmodyfikowany kod w tej odpowiedzi, aby wstawić element <authentication/> do wszystkich żądań ciała 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; 
} 

Ten roztwór użyto ponieważ WebServiceMessageCallback wymagałoby mnie do zmiany dokumentu, a SaajSoapMessageFactory jest aktywowany zanim korpus mydła zostanie wstawiony przez skonfigurowany Jaxb2Marshaller.

Powiązane problemy