是否有保证的方法来获取自定义soap处理程序中的操作名称?

时间:2012-11-23 20:20:55

标签: java web-services soap jax-ws soaphandler

我有一个针对传入消息的自定义SOAP消息处理程序,它将根据正在调用的操作运行不同的代码。我第一次尝试获取操作名称看起来像这样:

public boolean handleMessage(SOAPMessageContext context)
{
    String op = context.get(MessageContext.WSDL_OPERATION);
    ...

此操作失败,因为似乎永远不会设置属性MessageContext.WSDL_OPERATION。然后我尝试使用它:

public boolean handleMessage(SOAPMessageContext context)
{
    Map<?, ?> headers = (Map<?, ?>)context.get(MessageContext.HTTP_REQUEST_HEADERS);    
    ArrayList<String> SOAPAction = ((ArrayList<String>) headers.get("SOAPAction"));
    String opName = SOAPAction.get(0);
    //opName will be formatted like "urn#myOperation", so the prefix must be removed
    opName = ((opName.replace("\"","").split("#"))[1]);

这样可行,但我担心可能会出现标题属性“SOAPAction”未设置(或甚至不存在)的情况,或者没有我期望的值。我也有点担心,因为我不知道这是否是获取操作名称的“官方”方式 - 我通过查看调试器中context的内容来解决这个问题。

在处理传入的SOAP消息时,有没有更好的方法来获取操作名称?

4 个答案:

答案 0 :(得分:5)

我参加这个派对的时间已经很晚了,但过去一周我试图这样做。接受的答案实际上并不适用于每个JAX-WS实现(至少不是我尝试过的)。

我一直在尝试在我的开发环境中使用独立Metro工作,但也在实际环境中使用与WebSphere 7捆绑在一起的Axis2。

我在Metro上找到了以下工作:

String operationName = body.getChildNodes().item(0).getLocalName();

以及以下适用于Axis2:

String operationName = body.getChildNodes().item(1).getLocalName();

发生的事情是Axis2将一个Text类型的节点作为第一个孩子插入Body,但Metro不会。此文本节点返回null本地名称。我的解决方案是执行以下操作:

NodeList nodes = body.getChildNodes();

// -- Loop over the nodes in the body.
for (int i=0; i<nodes.getLength(); i++) {
  Node item = nodes.item(i);

  // -- The first node of type SOAPBodyElement will be
  // -- what we're after.
  if (item instanceof SOAPBodyElement) {
    return item.getLocalName();
  }
}

如评论中所述,我们实际上正在寻找SOAPBodyElement类型的第一个节点。希望这将有助于其他人在将来看到这个。

答案 1 :(得分:4)

您可以调用body.getElementName().getLocalName()来检索消息有效内容的SOAP body元素的名称。它有点冗长和手动,但它的工作原理。您可以在处理程序中包含以下内容

if ((boolean) context.get(MessageContext.MESSAGE_INBOUND_PROPERTY){ //for requests only
            SOAPEnvelope msg = context.getMessage().getSOAPPart().getEnvelope(); //get the SOAP Message envelope
                SOAPBody body = msg.getBody();
            String operationName = body.getChildNodes().item(1).getLocalName();
}

上述代码的结果保证带有WSDL中指定的操作名称

编辑:此解决方案完全基于Web服务实现为document / literal-wrapped或RPC / literal的条件

答案 2 :(得分:1)

SOAPMessageContext包含此信息,可以像这样轻松检索:

public boolean handleMessage(SOAPMessageContext msgContext) {
    QName svcn = (QName) smc.get(SOAPMessageContext.WSDL_SERVICE);      
    QName opn = (QName) smc.get(SOAPMessageContext.WSDL_OPERATION);
    System.out.prinln("WSDL Service="+ svcn.getLocalPart());
    System.out.prinln("WSDL Operation="+ opn.getLocalPart());

    return true;
}

答案 3 :(得分:0)

如果有人搜索&#34;优雅&#34;获得所需属性的方法

    for(Map.Entry e : soapMessageContext.entrySet()){
            log.info("entry:"+ e.getKey() + " = " + e.getValue());
    }

然后决定你需要什么信息并获得它!

soapMessageContext.get(YOUR_DESIRED_KEY);