用Java构建SOAP客户机

用Java构建SOAP客户机,java,xml,web-services,soap,jaxb,Java,Xml,Web Services,Soap,Jaxb,我想在Java中使用一个SOAP API,它接收像这样的XML,来调用一个方法: <?xml version="1.0" encoding="utf-8"?> <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instan

我想在Java中使用一个SOAP API,它接收像这样的XML,来调用一个方法:

<?xml version="1.0" encoding="utf-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <env:Body>
        <GetReturnAnalysis xmlns="http://www.address.com/integration">
            <entityCode>186D3CAD-0841</entityCode>
        </GetReturnAnalysis>
    </env:Body>
</env:Envelope>
并生成以下代码以生成要发送的消息:

private  SOAPMessage createSOAPRequest(GetReturnAnalysis request) throws SOAPException, JAXBException, IOException, ParserConfigurationException, SAXException {
    MessageFactory messageFactory = MessageFactory.newInstance("SOAP 1.2 Protocol");
    SOAPMessage message = messageFactory.createMessage();
    SOAPPart soapPart = message.getSOAPPart();
    SOAPEnvelope envelope = soapPart.getEnvelope();
    envelope.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
    envelope.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
    message.getSOAPHeader().detachNode();

    SOAPBody body = envelope.getBody();
    String requestString =  XmlHelper.toOutputString(request);
    Document doc = convertStringToDocument(requestString);
    body.addDocument(doc);
    message.writeTo(System.out);

    message.saveChanges();
    message.writeTo(System.out);


    return message;
  }
(在本代码中,内部调用的方法):

但是当我添加到消息(body.addDocument方法)时,它检索到一个错误(那里不应该有名称空间)

正如您可能已经注意到的,在代码中,我将两个message.writeTo(对于调试,在createSOAPRequest方法上)。第一个正确地给出了XML,第二个正确地给出了XML,在我调用“save”之后,我在GetReturnAnalysis上得到了xmlns属性为空的XML

我想知道你是否能帮我。我是个肥皂迷,在这个问题上有很多麻烦

更新1

我已使用postman成功发送了一条包含以下XML的消息:

<?xml version="1.0" encoding="utf-8"?>
<env:Envelope xmlns="http://www.address.com/integration" xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <env:Body>
        <GetReturnAnalysis >
            <entityCode>186D3CAD-0841</entityCode>
        </GetReturnAnalysis>
    </env:Body>
</env:Envelope>
以及创建SOAP请求方法:

private  SOAPMessage createSOAPRequest(GetReturnAnalysis request) throws SOAPException, JAXBException, IOException, ParserConfigurationException, SAXException {
    MessageFactory messageFactory = MessageFactory.newInstance("SOAP 1.2 Protocol");
    SOAPMessage message = messageFactory.createMessage();
    SOAPPart soapPart = message.getSOAPPart();
    SOAPEnvelope envelope = soapPart.getEnvelope();
    envelope.addNamespaceDeclaration("", "http://www.address.com/integration");
    envelope.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
    envelope.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
    message.getSOAPHeader().detachNode();

    SOAPBody body = envelope.getBody();
    String requestString =  XmlHelper.toOutputString(request);
    Document doc = convertStringToDocument(requestString);
    body.addDocument(doc);
    message.writeTo(System.out);

    message.saveChanges();
    message.writeTo(System.out);    

    return message;
  }
但是,由于某些不确定的原因,当我调用message.saveChanges时,GetReturnAnalysis类的结果如下:

  @XmlRootElement(name = "GetReturnAnalysis", namespace = "http://www.address.com/integration")
  public class GetReturnAnalysisRequest { ...
<GetReturnAnalysis xmlns="">
    <EntityCode>186D3CAD-0841</EntityCode>
</GetReturnAnalysis>ityCode>

186D3CAD-0841
ITY代码>

空的xmlns属性覆盖了我提供的整个名称空间。我想知道为什么会这样?它不能简单地保存我想要保存的字符串而不进行更改吗???

您的代码中有几个问题

命名空间定义:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "GetReturnAnalysis", namespace = "http://www.address.com/integration")
public class GetReturnAnalysisRequest {
  @XmlElement(name = "entityCode", namespace = "http://www.address.com/integration")
  protected String entityCode;

  public GetReturnAnalysisRequest(String entityCode) {
    this.entityCode = entityCode;
  }

  public GetReturnAnalysisRequest() { }

  public String getEntityCode() {
    return entityCode;
  }

  public void setEntityCode(String entityCode) {
    this.entityCode = entityCode;
  }   
}
第二个-将文档生成器设置为命名空间感知

String requestString =  toOutputString(request);

Document doc = convertStringToDocument(requestString);
body.addDocument(doc);
message.writeTo(System.out);
-

使用框架

要使用web服务,实际上应该使用框架。我会建议(我的首选)或。然后,您可以定义服务接口并生成适当的wsdl和客户机类,还可以获得对其他可选协议和扩展(例如安全性)的支持


仅在特殊情况下才直接处理XML,例如RPC文本、自定义安全性或其他不再受支持的协议

您必须定义请求对象的名称空间。但我建议贯穿整个WS生命周期。从拥有WSDL开始,生成客户机类和消息对象,并使用对象级API调用或公开web服务。我建议使用一些成熟的框架,如Axis2或CXF(我的首选)。您能发布错误/异常吗?当我使用空属性调用时,会显示响应:response SOAP Message…SOAP:SenderSystem.Web.Services.Protocols.SoapException:如果没有有效的操作参数,则无法处理请求。请提供有效的soap操作。位于System.Web.Services.Protocol.Soap12ServerProtocolHelper.RouterRequest()处的System.Web.Services.Protocols.SoapServerProtocol.Initialize()。。。异常消息,当我尝试在类上放置名称空间时:namespace\u ERR:试图创建或更改对象的方式与名称空间不符。@Gust2我正在搜索如何为该对象定义名称空间,但尚未找到方法。我相信这会帮我解决问题。。。
private  SOAPMessage createSOAPRequest(GetReturnAnalysis request) throws SOAPException, JAXBException, IOException, ParserConfigurationException, SAXException {
    MessageFactory messageFactory = MessageFactory.newInstance("SOAP 1.2 Protocol");
    SOAPMessage message = messageFactory.createMessage();
    SOAPPart soapPart = message.getSOAPPart();
    SOAPEnvelope envelope = soapPart.getEnvelope();
    envelope.addNamespaceDeclaration("", "http://www.address.com/integration");
    envelope.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
    envelope.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
    message.getSOAPHeader().detachNode();

    SOAPBody body = envelope.getBody();
    String requestString =  XmlHelper.toOutputString(request);
    Document doc = convertStringToDocument(requestString);
    body.addDocument(doc);
    message.writeTo(System.out);

    message.saveChanges();
    message.writeTo(System.out);    

    return message;
  }
<GetReturnAnalysis xmlns="">
    <EntityCode>186D3CAD-0841</EntityCode>
</GetReturnAnalysis>ityCode>
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "GetReturnAnalysis", namespace = "http://www.address.com/integration")
public class GetReturnAnalysisRequest {
  @XmlElement(name = "entityCode", namespace = "http://www.address.com/integration")
  protected String entityCode;

  public GetReturnAnalysisRequest(String entityCode) {
    this.entityCode = entityCode;
  }

  public GetReturnAnalysisRequest() { }

  public String getEntityCode() {
    return entityCode;
  }

  public void setEntityCode(String entityCode) {
    this.entityCode = entityCode;
  }   
}
String requestString =  toOutputString(request);

Document doc = convertStringToDocument(requestString);
body.addDocument(doc);
message.writeTo(System.out);
private Document convertStringToDocument(String xml) throws SAXException, IOException, ParserConfigurationException {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        docFactory.setNamespaceAware(true);
    return docFactory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
  }