2016-05-09 15 views
0

Während der Integration mit externen System musste ich von einer Umgebung zu einer anderen wechseln. Das bedeutet, dass Sie die URL, in der wsdl platziert wird, ändern und die Benutzeranmeldeinformationen in die Kopfzeile eingeben. Sieht ziemlich einfach aus, aber dann habe ich seltsames Verhalten bemerkt. Wenn ich versuche, Service A zu nennen, die auf Port 1 ist, dann aus irgendeinem Grund die Soapaction-Kopf mit dem Wert des Dienstes B ersetzt wird, die auch 1 auf Port sieht es so etwas wie:SOAPAction Header passt nicht zum Service

ID: 496 
Address: https://domain/env/port 
Encoding: UTF-8 
Http-Method: POST 
Content-Type: text/xml 
Headers: {Accept=[*/*], password=[test], SOAPAction=["serviceB"], UserName=[test]} 
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><a:aRequest xmlns:a="http://a/namespace/">... 

Dann ist die Antwort natürlich, dass das unerwartete Anfrageobjekt übergeben wurde. Was ist komischer, dass manchmal der SOAPAction Header ist ok, der Service, der aufgerufen wurde, ist in Ordnung und das Anfrageobjekt ist in Ordnung, aber die Antwort sagt immer, dass es andere Anfrage Objekt erwartet, weil aus irgendeinem Grund Server anderen Service, den ich wollte Anruf.

Also meine Frage ist: In welcher Weise der SAOPAction-Wert eingestellt ist - ist es aus generierten Klasse von @WebMethod(action = "serviceA") entnommen oder wird es beim Lesen wsdl-Datei generiert? Ich muss es herausfinden, wenn das Problem auf meiner Seite oder auf der externen Serverseite ist.

EDIT: Ich bemerkte, dass: Wenn ich serviceA zum ersten Mal aufrufen, dann ist SOAPAction Header auf Operation ServiceB gesetzt. Dann rufe ich das zweite mal den serviceA an und der Response Code ist 200. Dann rufe ich serviceB das erste Mal an und der SOAPAction Header wird auf serviceA gesetzt. Wenn ich serviceB das zweite Mal anrufe, dann ist der Response-Code 200. So sieht es aus, als gäbe es irgendeine Art von Caching (?!) ...

EDIT: Ok, also sieht es so aus: Ich erstelle Port mit Service-Klasse von javax.xml.ws Paket mit Service myservice = Service.create(serviceName) Methode und myservice.getPort(MySpecifiedPort.class). Ich annotate diese Methode mit @Produces und wenn ich diesen Port brauche, dann injiziere ich es mit @Inject Annotation. Manchmal erhalte ich (denke ich) die Instanz aus dem Pool. Und wenn das passiert, wird die SOAPAction auf den Wert des vorherigen Aufrufs gesetzt. Aber warum ist das passiert? Sollte SOAPAction nicht jedes Mal neu eingestellt werden, wenn ich WS anrufe? Whis sieht es so aus, als wäre es irgendwie zwischengespeichert?

Antwort

0

Endlich hoffe ich, dass ich die Lösung gefunden habe. Das Problem war, dass, um HTTP-Header mit Anmeldeinformationen zu setzen Ich habe:

Map<String, List<String>> headers = (Map<String, List<String>>) bp.getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS); 
if (headers == null) { 
    headers = new HashMap<>(); 
} 
headers.put("UserName", Collections.singletonList(configuration.getProperty(API_USERNAME))); 
headers.put("password", Collections.singletonList(configuration.getProperty(API_PASSWORD))); 
bp.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers); 

Aus irgendeinem Grunde das Problem und Soapaction-Kopf verursacht wurde manchmal aus dem vorherigen Anruf erinnert. Die Lösung ist SOAPHandler

class CredentialsHandler implements SOAPHandler<SOAPMessageContext> { 

    private Configuration configuration; 

    public CredentialsHandler(Configuration configuration) { 
     this.configuration = configuration; 
    } 

    @Override 
    public boolean handleMessage(SOAPMessageContext context) { 
     try { 
      Map<String, List<String>> headers = new HashMap<>(); 
      headers.put("UserName", Collections.singletonList(configuration.getProperty(API_USERNAME))); 
      headers.put("password", Collections.singletonList(configuration.getProperty(API_PASSWORD))); 
      context.put(MessageContext.HTTP_REQUEST_HEADERS, headers); 
     } catch (ConfigurationException e) { 
      throw new IllegalStateException("Configuration exception"); 
     } 

     return true; 
    } 
} 

Und an der Stelle zu implementieren, wo meine Header wurden die folgende Codezeile setzen hinzugefügt:

bp.getBinding().setHandlerChain(Collections.<Handler>singletonList(new CredentialsHandler(configuration)));