2012-09-12 11 views
5

Wir müssen Webservices konsumieren, die von anderen Teams entwickelt wurden. Verwendung von JAX-WS zum Generieren der Webservices. Wir verwenden wsimort, um die Client-Seitenstubs zu generieren.Wie fügt man SOAP-Header zu einer SOAP-Anfrage mit JAX-WS hinzu?

Das Problem ist, dass ich zusammen mit dem SOAP-Körper die folgenden Informationen als Header übergeben müssen:

<soapenv:Header> 
    <ns1:HeaderData xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
        xmlns:ns1="http://www.example.com/esb/data_type/HeaderData/v1"> 
     <ChannelIdentifier>ABC</ChannelIdentifier> 
    </ns1:HeaderData> 
</soapenv:Header> 


Wir verwenden:

BindingProvider.getRequestContext().put(
    BindingProvider.ENDPOINT_ADDRESS_PROPERTY, 
    serviceConfig.getServiceEndPoint() 
); 

, um den Endpunkt.

Kann jemand vorschlagen, wie Kopfzeilen mit Anfrage übergeben?

Danke, VK

Antwort

12

Verwendung param header = true von @WebParam Anmerkung

@WebMethod 
@WebResult String method(
     @WebParam String anotherParam 
     @WebParam(header = true, mode = Mode.OUT) Holder<String> headerParam) 

header = true, mode = Mode.OUT bedeutet, dass param headerParam nur in Ausgabe im Header sein.
Wenn Sie dies das param in Eingang und Ausgang wollen, machen Mode.INOUT

+0

Diese Antwort sollte akzeptiert werden. Präzise und präzise. –

6

Ich hatte Benutzerdaten in den Header so machte ich es wie folgt hinzuzufügen:

private void modifyRequest(String username, String password) { 
    UserCredentials authHeader = new UserCredentials(); 
    authHeader.setUsername(username); 
    authHeader.setPassword(password); 
    ArrayList<Header> headers = new ArrayList<Header>(1); 
    try { 
     Header soapHeader = new Header(new QName(TQIntegrationV2.TQIntegrationV2Soap.getNamespaceURI(), "UserCredentials"), authHeader, new JAXBDataBinding(UserCredentials.class)); 
     headers.add(soapHeader); 
    } catch (JAXBException ex) { 
     LOGGER.error("Exception trying to serialize header: {}", ex); 
    } 
    ((BindingProvider) proxy).getRequestContext().put(Header.HEADER_LIST, headers); 
} 

Und alles gut funktioniert. Jeder Aufruf an den Webdienst wird mit einem Benutzernamen und einem Kennwort geliefert, die an diesen Header übergeben werden. Sie können dies leicht ändern, um in Ihrem Fall zu arbeiten.

EDIT

Der obige Code CXF API verwendet Header zu ändern. Ich habe dies auch mit JAX-WS getan. Es macht fast die gleichen sind, ändert die Header der Benutzeranmeldeinformationen hinzufügen:

public class MyHandler implements SOAPHandler<SOAPMessageContext> { 

    private static final Logger LOGGER = LoggerFactory.getLogger(MyHandler.class); 

    private String username; 

    private String password; 

    /** 
    * Handles SOAP message. If SOAP header does not already exist, then method will created new SOAP header. The 
    * username and password is added to the header as the credentials to authenticate user. If no user credentials is 
    * specified every call to web service will fail. 
    * 
    * @param context SOAP message context to get SOAP message from 
    * @return true 
    */ 
    @Override 
    public boolean handleMessage(SOAPMessageContext context) { 
     try { 
      SOAPMessage message = context.getMessage(); 
      SOAPHeader header = message.getSOAPHeader(); 
      SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); 
      if (header == null) { 
       header = envelope.addHeader(); 
      } 
      QName qNameUserCredentials = new QName("https://your.target.namespace/", "UserCredentials"); 
      SOAPHeaderElement userCredentials = header.addHeaderElement(qNameUserCredentials); 

      QName qNameUsername = new QName("https://your.target.namespace/", "Username"); 
      SOAPHeaderElement username = header.addHeaderElement(qNameUsername); 
      username.addTextNode(this.username); 
      QName qNamePassword = new QName("https://your.target.namespace/", "Password"); 
      SOAPHeaderElement password = header.addHeaderElement(qNamePassword); 
      password.addTextNode(this.password); 

      userCredentials.addChildElement(username); 
      userCredentials.addChildElement(password); 

      message.saveChanges(); 
      //TODO: remove this writer when the testing is finished 
      StringWriter writer = new StringWriter(); 
      message.writeTo(new StringOutputStream(writer)); 
      LOGGER.debug("SOAP message: \n" + writer.toString()); 
     } catch (SOAPException e) { 
      LOGGER.error("Error occurred while adding credentials to SOAP header.", e); 
     } catch (IOException e) { 
      LOGGER.error("Error occurred while writing message to output stream.", e); 
     } 
     return true; 
    } 

    //TODO: remove this class after testing is finished 
    private static class StringOutputStream extends OutputStream { 

     private StringWriter writer; 

     public StringOutputStream(StringWriter writer) { 
      this.writer = writer; 
     } 

     @Override 
     public void write(int b) throws IOException { 
      writer.write(b); 
     } 
    } 

    @Override 
    public boolean handleFault(SOAPMessageContext context) { 
     LOGGER.debug("handleFault has been invoked."); 
     return true; 
    } 

    @Override 
    public void close(MessageContext context) { 
     LOGGER.debug("close has been invoked."); 
    } 

    @Override 
    public Set<QName> getHeaders() { 
     LOGGER.debug("getHeaders has been invoked."); 
     return null; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 
} 

Und ich definiere diese Prozedur in Spring Konfiguration wie folgt aus:

<bean id="soapHandler" class="your.package.MyHandler"> 
    <property name="username" value="testUser"/> 
    <property name="password" value="testPassword"/> 
</bean> 

<jaxws:client "..."> 
    <jaxws:handlers> 
     <ref bean="soapHandler"/> 
    </jaxws:handlers> 
</jaxws:client> 

Alles, was Sie tun müssen, ist SOAPHandler<SOAPMessageContext> Schnittstelle zu implementieren , überschreiben Sie ihre Methoden und dann können Sie tun, was immer Sie wollen mit einer SOAP Nachricht.

+0

Danke für die Antwort. Können Sie den vollständig qualifizierten Namen der Header-Klasse veröffentlichen? Ich möchte nur herausfinden, ob es von Jaxws API ist. – ikvenu2000

+0

Header ist nicht von JAX-WS aus CXF, ich habe die Antwort wie man den Header in JAX-WS ändern bearbeitet. –

+0

Der JAX-WS-Code hat perfekt funktioniert, danke! – kai