请教一个WEB SERVICE的问题 ( 积分: 300 )

  • 主题发起人 主题发起人 沙隆巴斯的主人
  • 开始时间 开始时间

沙隆巴斯的主人

Unregistered / Unconfirmed
GUEST, unregistred user!
WEB SERVICE服务器由JAVA实现(TOMCAT+AXIS)
在一个JWS中有两个方法:getName与getPhoneBook
整个文件如下所示
public class HelloClient
{
public String getName(String name)
{
return "hello "+name;
}
public PhoneBook getPhoneBook(){
PhoneBook result = new PhoneBook();
result.name = "0";
result.number = 0;
return result;
}
}
其中PhoneBook 的定义如下:
public class PhoneBook{
public String name;
public int number;
};
以上文件部署后通过浏览器可以访问到

-
<wsdl:definitions targetNamespace=&quot;http://xbw1:1977/axis/HelloClient.jws&quot;>
-
<!--
WSDL created by Apache Axis version: 1.2.1
Built on Jun 14, 2005 (09:15:57 EDT)
-->
-
<wsdl:types>
-
<schema targetNamespace=&quot;http://DefaultNamespace&quot;>
<import namespace=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;/>
-
<complexType name=&quot;PhoneBook&quot;>
-
<sequence>
<element name=&quot;name&quot;
nillable=&quot;true&quot;
type=&quot;xsd:string&quot;/>
<element name=&quot;number&quot;
type=&quot;xsd:int&quot;/>
</sequence>
</complexType>
</schema>
</wsdl:types>
-
<wsdl:message name=&quot;getNameRequest&quot;>
<wsdl:part name=&quot;name&quot;
type=&quot;xsd:string&quot;/>
</wsdl:message>
<wsdl:message name=&quot;getPhoneBookRequest&quot;>
</wsdl:message>
-
<wsdl:message name=&quot;getPhoneBookResponse&quot;>
<wsdl:part name=&quot;getPhoneBookReturn&quot;
type=&quot;tns1:PhoneBook&quot;/>
</wsdl:message>
-
<wsdl:message name=&quot;getNameResponse&quot;>
<wsdl:part name=&quot;getNameReturn&quot;
type=&quot;xsd:string&quot;/>
</wsdl:message>
-
<wsdl:portType name=&quot;HelloClient&quot;>
-
<wsdl:operation name=&quot;getPhoneBook&quot;>
<wsdl:input message=&quot;impl:getPhoneBookRequest&quot;
name=&quot;getPhoneBookRequest&quot;/>
<wsdl:output message=&quot;impl:getPhoneBookResponse&quot;
name=&quot;getPhoneBookResponse&quot;/>
</wsdl:operation>
-
<wsdl:operation name=&quot;getName&quot;
parameterOrder=&quot;name&quot;>
<wsdl:input message=&quot;impl:getNameRequest&quot;
name=&quot;getNameRequest&quot;/>
<wsdl:output message=&quot;impl:getNameResponse&quot;
name=&quot;getNameResponse&quot;/>
</wsdl:operation>
</wsdl:portType>
-
<wsdl:binding name=&quot;HelloClientSoapBinding&quot;
type=&quot;impl:HelloClient&quot;>
<wsdlsoap:binding style=&quot;rpc&quot;
transport=&quot;http://schemas.xmlsoap.org/soap/http&quot;/>
-
<wsdl:operation name=&quot;getPhoneBook&quot;>
<wsdlsoap:operation soapAction=&quot;&quot;/>
-
<wsdl:input name=&quot;getPhoneBookRequest&quot;>
<wsdlsoap:body encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
namespace=&quot;http://DefaultNamespace&quot;
use=&quot;encoded&quot;/>
</wsdl:input>
-
<wsdl:output name=&quot;getPhoneBookResponse&quot;>
<wsdlsoap:body encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
namespace=&quot;http://xbw1:1977/axis/HelloClient.jws&quot;
use=&quot;encoded&quot;/>
</wsdl:output>
</wsdl:operation>
-
<wsdl:operation name=&quot;getName&quot;>
<wsdlsoap:operation soapAction=&quot;&quot;/>
-
<wsdl:input name=&quot;getNameRequest&quot;>
<wsdlsoap:body encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
namespace=&quot;http://DefaultNamespace&quot;
use=&quot;encoded&quot;/>
</wsdl:input>
-
<wsdl:output name=&quot;getNameResponse&quot;>
<wsdlsoap:body encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
namespace=&quot;http://xbw1:1977/axis/HelloClient.jws&quot;
use=&quot;encoded&quot;/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
-
<wsdl:service name=&quot;HelloClientService&quot;>
-
<wsdl:port binding=&quot;impl:HelloClientSoapBinding&quot;
name=&quot;HelloClient&quot;>
<wsdlsoap:address location=&quot;http://xbw1:1977/axis/HelloClient.jws&quot;/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
 
WEB SERVICE服务器由JAVA实现(TOMCAT+AXIS)
在一个JWS中有两个方法:getName与getPhoneBook
整个文件如下所示
public class HelloClient
{
public String getName(String name)
{
return &quot;hello &quot;+name;
}
public PhoneBook getPhoneBook(){
PhoneBook result = new PhoneBook();
result.name = &quot;0&quot;;
result.number = 0;
return result;
}
}
其中PhoneBook 的定义如下:
public class PhoneBook{
public String name;
public int number;
};
以上文件部署后通过浏览器可以访问到

-
<wsdl:definitions targetNamespace=&quot;http://xbw1:1977/axis/HelloClient.jws&quot;>
-
<!--
WSDL created by Apache Axis version: 1.2.1
Built on Jun 14, 2005 (09:15:57 EDT)
-->
-
<wsdl:types>
-
<schema targetNamespace=&quot;http://DefaultNamespace&quot;>
<import namespace=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;/>
-
<complexType name=&quot;PhoneBook&quot;>
-
<sequence>
<element name=&quot;name&quot;
nillable=&quot;true&quot;
type=&quot;xsd:string&quot;/>
<element name=&quot;number&quot;
type=&quot;xsd:int&quot;/>
</sequence>
</complexType>
</schema>
</wsdl:types>
-
<wsdl:message name=&quot;getNameRequest&quot;>
<wsdl:part name=&quot;name&quot;
type=&quot;xsd:string&quot;/>
</wsdl:message>
<wsdl:message name=&quot;getPhoneBookRequest&quot;>
</wsdl:message>
-
<wsdl:message name=&quot;getPhoneBookResponse&quot;>
<wsdl:part name=&quot;getPhoneBookReturn&quot;
type=&quot;tns1:PhoneBook&quot;/>
</wsdl:message>
-
<wsdl:message name=&quot;getNameResponse&quot;>
<wsdl:part name=&quot;getNameReturn&quot;
type=&quot;xsd:string&quot;/>
</wsdl:message>
-
<wsdl:portType name=&quot;HelloClient&quot;>
-
<wsdl:operation name=&quot;getPhoneBook&quot;>
<wsdl:input message=&quot;impl:getPhoneBookRequest&quot;
name=&quot;getPhoneBookRequest&quot;/>
<wsdl:output message=&quot;impl:getPhoneBookResponse&quot;
name=&quot;getPhoneBookResponse&quot;/>
</wsdl:operation>
-
<wsdl:operation name=&quot;getName&quot;
parameterOrder=&quot;name&quot;>
<wsdl:input message=&quot;impl:getNameRequest&quot;
name=&quot;getNameRequest&quot;/>
<wsdl:output message=&quot;impl:getNameResponse&quot;
name=&quot;getNameResponse&quot;/>
</wsdl:operation>
</wsdl:portType>
-
<wsdl:binding name=&quot;HelloClientSoapBinding&quot;
type=&quot;impl:HelloClient&quot;>
<wsdlsoap:binding style=&quot;rpc&quot;
transport=&quot;http://schemas.xmlsoap.org/soap/http&quot;/>
-
<wsdl:operation name=&quot;getPhoneBook&quot;>
<wsdlsoap:operation soapAction=&quot;&quot;/>
-
<wsdl:input name=&quot;getPhoneBookRequest&quot;>
<wsdlsoap:body encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
namespace=&quot;http://DefaultNamespace&quot;
use=&quot;encoded&quot;/>
</wsdl:input>
-
<wsdl:output name=&quot;getPhoneBookResponse&quot;>
<wsdlsoap:body encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
namespace=&quot;http://xbw1:1977/axis/HelloClient.jws&quot;
use=&quot;encoded&quot;/>
</wsdl:output>
</wsdl:operation>
-
<wsdl:operation name=&quot;getName&quot;>
<wsdlsoap:operation soapAction=&quot;&quot;/>
-
<wsdl:input name=&quot;getNameRequest&quot;>
<wsdlsoap:body encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
namespace=&quot;http://DefaultNamespace&quot;
use=&quot;encoded&quot;/>
</wsdl:input>
-
<wsdl:output name=&quot;getNameResponse&quot;>
<wsdlsoap:body encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
namespace=&quot;http://xbw1:1977/axis/HelloClient.jws&quot;
use=&quot;encoded&quot;/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
-
<wsdl:service name=&quot;HelloClientService&quot;>
-
<wsdl:port binding=&quot;impl:HelloClientSoapBinding&quot;
name=&quot;HelloClient&quot;>
<wsdlsoap:address location=&quot;http://xbw1:1977/axis/HelloClient.jws&quot;/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
 
然后在 Delphi2005中导入次WSDL,得到
// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL : http://xbw1:1977/axis/HelloClient.jws?wsdl
// Encoding : UTF-8
// Version : 1.0
// (2005-8-18 23:13:38 - 1.33.2.5)
// ************************************************************************ //
unit HelloClient1;
interface
uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;
type
// ************************************************************************ //
// The following types, referred to in the WSDLdo
cument are not being represented
// in this file. They are either aliases[@] of other types represented or were referred
// to but never[!] declared in thedo
cument. The types from the latter category
// typically map to predefined/known XML or Borland types;
however, they could also
// indicate incorrect WSDLdo
cuments that failed to declare or import a schema type.
// ************************************************************************ //
// !:string - &quot;http://www.w3.org/2001/XMLSchema&quot;
// !:int - &quot;http://www.w3.org/2001/XMLSchema&quot;
PhoneBook = class;
{ &quot;http://DefaultNamespace&quot;
}

// ************************************************************************ //
// Namespace : http://DefaultNamespace
// ************************************************************************ //
PhoneBook = class(TRemotable)
private
Fname: WideString;
Fnumber: Integer;
published
property name: WideString read Fname write Fname;
property number: Integer read Fnumber write Fnumber;
end;

// ************************************************************************ //
// Namespace : http://DefaultNamespace
// transport : http://schemas.xmlsoap.org/soap/http
// style : rpc
// binding : HelloClientSoapBinding
// service : HelloClientService
// port : HelloClient
// URL : http://xbw1:1977/axis/HelloClient.jws
// ************************************************************************ //
HelloClient = interface(IInvokable)
['{9C1A956D-90D0-8EE9-4A40-F80E9AE12639}']
function getPhoneBook: PhoneBook;
stdcall;
function getName(const name: WideString): WideString;
stdcall;
end;

function GetHelloClient(UseWSDL: Boolean=System.False;
Addr: string='';
HTTPRIO: THTTPRIO = nil): HelloClient;

implementation
function GetHelloClient(UseWSDL: Boolean;
Addr: string;
HTTPRIO: THTTPRIO): HelloClient;
const
defWSDL = 'http://xbw1:1977/axis/HelloClient.jws?wsdl';
defURL = 'http://xbw1:1977/axis/HelloClient.jws';
defSvc = 'HelloClientService';
defPrt = 'HelloClient';
var
RIO: THTTPRIO;
begin
Result := nil;
if (Addr = '') then
begin
if UseWSDL then
Addr := defWSDL
else
Addr := defURL;
end;
if HTTPRIO = nil then
RIO := THTTPRIO.Create(nil)
else
RIO := HTTPRIO;
try
Result := (RIO as HelloClient);
if UseWSDL then
begin
RIO.WSDLLocation := Addr;
RIO.Service := defSvc;
RIO.Port := defPrt;
end else
RIO.URL := Addr;
finally
if (Result = nil) and (HTTPRIO = nil) then
RIO.Free;
end;
end;

initialization
InvRegistry.RegisterInterface(TypeInfo(HelloClient), 'http://DefaultNamespace', 'UTF-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(HelloClient), '');
RemClassRegistry.RegisterXSClass(PhoneBook, 'http://DefaultNamespace', 'PhoneBook');
end.
 
以上的步骤都非常正常,完全符合预期
在DELPHI中调用getName方法,结果也很正确
但调用getPhoneBook方法,出现EDOMParseError with message 'XMLdo
cument must have a top level element'
 
根据上面的情况,初步判断是DELPHI对收到的WEB SERVICE回应的解析出现了问题。关键应该是在对:
PhoneBook = class(TRemotable)
private
Fname: WideString;
Fnumber: Integer;
published
property name: WideString read Fname write Fname;
property number: Integer read Fnumber write Fnumber;
end;

此对象的解析上。
 
我想请教各位DFW关于此问题的解决方法。
前提是体系结构不能改。后台是:
数据库:ORACLE
业务层:J2EE的EJB,主要是实体BEAN与SESSION BEAN
边界层:TOMCAT + AXIS实现WEB SERVICE 
前台:还是希望通过DELPHI实现
现在在“边界层”与“前台”间遇到了障碍,请各位不吝赐教。
 
public class PhoneBook{
public String name;
public int number;
};
换成这个试试:
public class PhoneBook{
private String name;
private int number;
public getxxx() {
}
pubic setxxx(xx) {
}
};
 
先多谢zbird。
尝试过把PhoneBook按照JAVA BEAN的形式来写,但解决不了问题。
其实WS的服务端已经正常返回了结果,但客户端没有能够正确解析。
 
可能和JDK或TOMCAT的版本有关系。
以前出过类似的问题。
当时客户端用tomcat5.5+jdk1.5无法调用成功。
换回jdk1.4+tomcat4.1调用成功。
 
to zbird:
正在尝试jdk1.4+tomcat4.1
另外,AXIS有版本要求吗
你在DELPHI客户端做了什么设置吗?我一直是直接调用的GetHelloClient.getPhoneBook.name ,而没有用任何THTTPRIO之类的控件
 
to zbird:
换成 jdk1.4+tomcat4.1,问题依然
 
根据出错提示,应该是xml文件没有根节点,你设置根节点了吗?
 
to yzxcsw:
怎么设置根节点?
 
问题解决了。
我最初的判断“DELPHI对收到的WEB SERVICE回应的解析出现了问题”,这个判断是错误的。问题出在JAVA端。
在WS中返回的自定义对象,按照规则,需要符合JavaBean规范,并且实现了Serializable接口。这个Serializable接口是关键,因为OBJECT 到 XML的转化是需要序列化的。然后就是在发布WS的配置文件中加入beanMapping元素。
通过JAVA端的这两处修改,DELPHI就可以完全正常的使用自定义对象了。
 
谢谢zbird的意见,也谢谢yzxcsw的参与。
 
后退
顶部