我对Web服务的理解非常有限,我正在努力从SOAP响应信封中读取返回的值。其他一切似乎都运转得很好。
我的任务是创建一个Web服务,并通过重新设计已经为另一个Web服务配置的Java项目来实现。 我继续克隆了正在运行的Web服务项目并开始对其进行修改,以便它能够满足需要(或者至少我希望是这样)。
webservice似乎依赖于名为cxf.xml的配置文件,下面粘贴了内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="documentOperations" implementor="mypackage.service.DocOperationsImpl" address="/documentOperations">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
<entry key="jaxb-validation-event-handler">
<bean class="mypackage.interceptor.ValidationEventHandler" />
</entry>
</jaxws:properties>
<!-- This regulates the authentication process -->
<jaxws:inInterceptors>
<ref bean="logInBound" />
<ref bean="saajInInterceptor" />
<ref bean="wss4JInInterceptor" />
</jaxws:inInterceptors>
<jaxws:schemaLocations>
<jaxws:schemaLocation>DocOperations.xsd</jaxws:schemaLocation>
</jaxws:schemaLocations>
</jaxws:endpoint>
<!-- Remaining part cut off, as more than likely irrelevant -->
自动生成的WSDL定义如下:
<!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.10-b140319.1121 svn-revision#7b34660d6bc70e587e8ec81a17e4d76af68816a6. -->
<!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.10-b140319.1121 svn-revision#7b34660d6bc70e587e8ec81a17e4d76af68816a6. -->
<definitions targetNamespace="http://service.myservice.com/" name="DocOperations">
<types>
<xsd:schema>
<xsd:import namespace="http://service.myservice.com/" schemaLocation="http://localhost:7001/DocumentWebService/DocOperations?xsd=1"/>
</xsd:schema>
</types>
<message name="hideDocument">
<part name="parameters" element="tns:hideDocument"/>
</message>
<message name="hideDocumentResponse">
<part name="parameters" element="tns:hideDocumentResponse"/>
</message>
<portType name="DocOperations">
<operation name="hideDocument">
<input wsam:Action="http://service.myservice.com/DocOperations/hideDocument" message="tns:hideDocument"/>
<output wsam:Action="http://service.myservice.com/DocOperations/hideDocumentResponse" message="tns:hideDocumentResponse"/>
</operation>
</portType>
<binding name="DocOperationsImplPortBinding" type="tns:DocOperations">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="hideDocument">
<soap12:operation soapAction="http://service.myservice.com/DocOperations/hideDocument"/>
<input>
<soap12:body use="literal"/>
</input>
<output>
<soap12:body use="literal"/>
</output>
</operation>
</binding>
<service name="DocOperations">
<port name="DocOperationsImplPort" binding="tns:DocOperationsImplPortBinding">
<soap12:address location="http://localhost:7001/DocumentWebService/DocOperations"/>
</port>
</service>
</definitions>
DocOperations.xsd定义如下:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="http://service.myservice.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://service.myservice.com/" elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:element name="hideDocumentResponse" type="xs:string" />
<xs:element name="documentID" type="xs:string" />
<xs:element name="fileNetGUID" type="xs:string" />
<xs:element name="comments" type="xs:string" />
</xs:schema>
我有两个类:DocOperations和DocOperationsImpl,两者都定义如下:
DocOperations:
@WebService(name = "DocOperations")
@SOAPBinding(parameterStyle = ParameterStyle.WRAPPED, style = Style.DOCUMENT)
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface DocOperations {
public static final String SUCCESS = "success";
public static final String FAILURE = "failure";
@WebMethod(operationName = "hideDocument", action = "http://service.myservice.com/DocOperations/hideDocument")
public String hideDocument(@WebParam(name = "documentID", targetNamespace="http://service.myservice.com/") String documentID, @WebParam(name = "fileNetGUID", targetNamespace="http://service.myservice.com/") String fileNetGUID, @WebParam(name = "comments", targetNamespace="http://service.myservice.com/") String inputComments);
}
DocOperationsImpl:
@WebService(endpointInterface = "mypackage.service.DocOperations", serviceName = "DocOperations")
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class DocOperationsImpl implements DocOperations {
@Override
public String hideDocument(String documentID, String fileNetGUID, String inputComments) {
[...]
}
}
hideDocument方法返回SUCCESS或FAILURE。
正确调用该方法,并执行应该执行的操作。我可以从服务器端日志中看到该方法返回的字符串是SUCCESS(这可以通过我在SOAP响应信封中看到的证实)。 但是,当客户端尝试读取字符串值时,它始终读为空。
这是肥皂请求信封:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-1">
<wsse:Username>TESTUSER</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TESTPASSWORD</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<ns2:hideDocument xmlns:ns2="http://service.myservice.com/" xmlns:ns3="http://service.myservice.com/">
<ns2:documentID>44951196459</ns2:documentID>
<ns2:fileNetGUID>{2F6DE08D-78FB-40E8-95B4-F466167D157D}</ns2:fileNetGUID>
<ns2:comments>Test</ns2:comments>
</ns2:hideDocument>
</soap:Body>
</soap:Envelope>
它被正确解释。
这是肥皂反应信封:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:hideDocumentResponse xmlns:ns1="http://service.myservice.com/">
<return xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://service.myservice.com/" xsi:type="xs:string">success</return>
</ns1:hideDocumentResponse>
</soap:Body>
</soap:Envelope>
但是,从该方法返回的java变量为null:
String documentWasHidden = webServiceClient.hideDocument(documentID, fileNetGUID, commments);
System.out.println("Value of documentWasHidden = " + documentWasHidden);
我的猜测是,标签中的名称空间不应该存在,但是我不知道DocOperations.xsd(或其他地方)是否需要修改和修改。
任何帮助?
附加说明:我使用的是cxf-2.6.0,wsdl4j-1.6.2和wss4j-1.6.5,并且Web服务作为EAR部署到WebLogic 12C(12.1.3)。
答案 0 :(得分:0)
找到解决这个愚蠢问题的解决方法。
首先,我在DocOperations类上修改了SOAPBinding注释:
@SOAPBinding(parameterStyle = ParameterStyle.BARE, style = Style.DOCUMENT)
使用此批注,每个Web服务方法只能接收一个输入参数。因为我需要传递三个,所以我创建了一个自定义Java类,其中包含三个属性的getter / setter:
@XmlRootElement(name = "DocumentToHide", namespace = "http://service.myservice.com")
@XmlAccessorType(XmlAccessType.FIELD)
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class FileInfo implements Serializable {
private static final long serialVersionUID = -4652784599316765768L;
private String documentID;
private String fileNetGUID;
private String comments;
public String getDocumentID() {
return documentID;
}
public void setDocumentID(String documentID) {
this.documentID = documentID;
}
public String getFileNetGUID() {
return fileNetGUID;
}
public void setFileNetGUID(String fileNetGUID) {
this.fileNetGUID = fileNetGUID;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
}
然后,我修改了DocOperations.xsd文件,使其能够识别输入参数。
我替换了下面的行:
<xs:element name="documentID" type="xs:string" />
<xs:element name="fileNetGUID" type="xs:string" />
<xs:element name="comments" type="xs:string" />
使用:
<xs:element name="DocumentToHide" type="tns:DocumentToHide" />
<xs:complexType name="DocumentToHide">
<xs:sequence>
<xs:element name="documentID" type="xs:string" />
<xs:element name="fileNetGUID" type="xs:string" />
<xs:element name="comments" type="xs:string" />
</xs:sequence>
</xs:complexType>
最后,wsimport命令与其他命令一起生成了FileInfo类,然后我在java代码中使用它:
FileInfo documentToHide = new FileInfo();
documentToHide.setDocumentID(documentID);
documentToHide.setFileNetGUID(fileNetGUID);
documentToHide.setComments(commments);
String documentWasMigrated = documentMigrationWebServiceClient.hideDocument(documentToHide);
现在正在正确读取字符串。
现在,SOAP请求信封如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-1">
<wsse:Username>TESTUSER</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TESTPASSWORD</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<ns2:DocumentToHide xmlns:ns2="http://service.myservice.com/">
<ns2:documentID>44951196459</ns2:documentID>
<ns2:fileNetGUID>{2F6DE08D-78FB-40E8-95B4-F466167D157D}</ns2:fileNetGUID>
<ns2:comments>Test</ns2:comments>
</ns2:DocumentToHide>
</soap:Body>
</soap:Envelope>
SOAP响应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<hideDocumentResponse xmlns="http://service.myservice.com/">success</hideDocumentResponse>
</soap:Body>
</soap:Envelope>
值得庆幸的是,它可以被阅读。
但仍然感到困惑的是,为什么它现在正在使用BARE设置,而不是在它被包裹的时候。