SOAPAction标头与服务不匹配

时间:2016-05-09 06:12:09

标签: java web-services http soap

在与外部系统集成期间,我不得不从一个环境切换到另一个环境。这意味着更改放置wsdl的URL并将用户凭据放在标头中。看起来很容易,但后来我发现了奇怪的行为。当我尝试调用端口1上的服务A时,由于某种原因,SOAPAction头被替换为服务B的值,它也在端口1上。它看起来像:

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/">...

然后响应当然是传递了意外的请求对象。 更奇怪的是,有时SOAPAction标头没问题,已经被调用的服务没问题且请求对象没问题,但响应仍然说它期望不同的请求对象,因为出于某种原因,服务器调用了我想调用的其他服务。

所以我的问题是:以什么方式设置SAOPAction值 - 是从@WebMethod(action = "serviceA")生成的类中获取还是在读取wsdl文件时生成的?如果问题出在我身边或外部服务器端,我需要弄明白。

编辑: 我注意到:当我第一次调用serviceA时,SOAPAction头被设置为操作serviceB。然后我第二次调用serviceA和响应代码为200.然后我第一次调用serviceB,SOAPAction头设置为serviceA。当我第二次调用serviceB时,响应代码是200.所以看起来有某种缓存(?!)......

编辑: 好的,所以它看起来像这样:我使用Service myservice = Service.create(serviceName)方法和myservice.getPort(MySpecifiedPort.class)从javax.xml.ws包创建带有Service类的Port。我用@Produces注释了这个方法,如果我需要这个端口,那么我用@Inject注释注入它。有时我从池中收到(我认为)实例。如果发生这种情况,则将SOAPAction设置为上一次调用的值。但为什么会这样呢?每次调用WS时,不应该将SOAPAction设置为new吗?这看起来像是以某种方式缓存了吗?

1 个答案:

答案 0 :(得分:0)

最后,我希望我找到了解决方案。问题是,为了使用凭据设置http标头我做了:

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

由于某种原因,这会导致问题,并且有时会记住前一次调用中的SOAPAction标头。解决方案是实现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;
   }
}

在添加标题的位置放置以下代码行:

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