DELPHI 6 Update 2#의 버그 및 해결 방법

7872 단어 Delphi
DELPHI 6 Update 2#의 버그 및 해결 방법
Borland는 Delphi 6에 대한 의미가 큰 두 번째 패치를 발표했는데 SOAP/웹 서비스 개발에 있어 큰 강화를 이루었다"DELPHI 6.02 BizSnap/SOAP/WebService의 4 – 패치 2#의 의미".그런데 한 가지 부분은 제가 그 글에서 언급하지 않은 것이 있는데 그것이 바로 SOAP로 다중 응용 개발을 하는 것입니다. 그때 저는 이 부분을 대충 훑어보았는데 패치 전과 많이 다르다는 것을 발견하지 못했기 때문에 개의치 않았습니다. 얼마 전에 liaoqian이라는 네티즌이 Mail에게 이 분야에 대한 질문을 보냈을 때나는 비로소 Delphi 6 Update 2#이 이 부분에 상당히 큰 변화가 있고 작은 버그가 존재한다는 것을 알아차렸다.우선 《DELPHI 6 선도적 연구-BizSnap/SOAP/WebService의 셋째-SOAP로 삼층 데이터베이스 응용 실현》의 예를 본떠서 웹서비스 3층 데이터 응용을 한다.위의 그림에서 보듯이 서버 인터페이스가 생성되었는지 자동으로 묻는 대화 상자가 나타나면 No 를 선택하고 SOAP Server Data Module 를 새로 만듭니다. 다른 작업은 3 과 같습니다.완료되면 IE에 다음을 입력합니다.http://localhost:1024/Demo3.wadSoapDemo3/wsdl다음과 같은 인터페이스 목록을 볼 수 있다.'의3'에 비해 IAP ServerSOAP 인터페이스가 추가되었고 IWSDL Publish 인터페이스의 Namespace URI도 다르다는 것을 알 수 있다.
Port Type
Namespace URI
Documentation
WSDL
IAppServer
urn:Midas-IAppServer
IAppServer
IAppServerSOAP
http://www.borland.com/namespaces/Types
IAppServerSOAP
ISoapDemo3DM
urn:SvrDMSoap-ISoapDemo3DM
ISoapDemo3DM
IWSDLPublish
http://www.borland.com/namespaces/Types
Lists all the PortTypes published by this Service
IWSDLPublish
주의하면 다음과 같은 문제점도 발견할 수 있다.http://localhost:1024/Demo3.wadSoapDemo3Delphi 6.02에 쓰여진 일반적인 Web Service 같은 페이지를 보지 못할 것입니다. 이것은 좀 정상적이지 않습니다.클라이언트 프로그램을 작성할 때 문제가 발생했습니다. 클라이언트 데이터셋의ProviderName 속성에서 아래로 내려가면 사용할 수 있는ProviderName을 볼 수 없지만, 깜빡이는 서버 창은 서버가 실행 중임을 나타냅니다.웹 앱 Debugger의 기록 정보를 살펴보면 다음과 같은 SOAP 오류 응답을 볼 수 있습니다:
<?xml version="1.0" encoding='UTF-8'?>
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" >
 <soap-env:body>
  <soap-env:fault>
   <faultcode>SOAP-ENV:Server</faultcode>
   <faultstring>
No invokable class registered that implements interface 
SOAPMidas.IAppServerSOAP of (soap action/path) 
"http://www.borland.com/namespaces/Types-IAppServerSOAP"
   </faultstring>
  </soap-env:fault>
 </soap-env:body>
</soap-env:envelope>
faultstring 표시에 있는 정보를 주의하십시오. 이것은 오류의 원인을 '호출할 수 있는 등록된 IAppServerSOAP 인터페이스 구현 클래스가 없습니다.' 라고 설명합니다.이 문제를 외면하고 DataSetProvider1을 ClientDataSet1의ProviderName 속성에 직접 쓴 다음 ClientDataSet1의Active 속성을true로 설정하면 바로 이상이 발생합니다. 그 내용은 위의faultstring 내용입니다.저는 Delphi를 포함한 Borland의 거의 모든 제품을 좋아하고 Borland를 믿습니다. 이런 감정은 제가 7, 8년 동안 사용한 수십 개의 다른 Borland 제품과 다른 버전에서 비롯된 것이기 때문에 일부 사람들은 문제에 부딪히면 개발 도구에 Bug이 있다고 원망할 이유가 없습니다.Borland의 제품 버그가 어떻다는 소문이 많지만 사실 소프트웨어가 있으면 버그가 있다는 소문이 있습니다. 저도 Borland에 버그가 없다고 한 것은 아닙니다. Borland에도 버그가 당연히 있습니다. 이 사이트에서 몇 번 언급했는데 Microsoft에 버그가 없나요?하지만 이번에는 델피 6 Update 2가 가져온 버그를 거의 확신할 수 있습니다. 왜냐하면 패치 2#를 하기 전에 저도 위의 방법에 따라 한 걸음 한 걸음 했습니다. 아무런 문제가 없었습니다. 패치 2#를 하기 전에 이런 문제가 생겼습니다.그럼에도 불구하고 버그라는 구체적인 증거를 찾아 해결 방법을 찾아야 하기 때문에 델피 6.02의 일부 SOAP 관련 소스 코드를 읽고 디버깅을 했습니다.첨부: SOAP 부분 소스 보기 설정: Delphi 6에서 Tools | Environment Options를 선택하여 Library 페이지를 선택하고 Browsing path에 경로: $(DELPHI)/source/soap을 추가하면 프로그램에서 Ctrl + MouseLeft Button을 통해 해당하는 SOAP 소스 파일로 빠르게 이동할 수 있습니다.원본 디버그 설정:Delph6에서 Project|Options를 선택하고Compiler 페이지를 선택하여 Debugging 상자에 있는 Use Debug DCUs 하나를 선택한 후 프로그램을 다시 컴파일하면 VCL의 원본 디버그에 들어갈 수 있습니다.추적 디버깅을 통해 SOAPHTTPPasInv 단원의 Procedure THTTPSoapPascal Invoker에서 이상이 발생한 것을 발견했습니다.DispatchSOAP 중:
      ...
      if IntfInfo = nil then
        raise Exception.CreateFmt(SInvInterfaceNotReg, [SoapAction])
      else if InvClassType = nil then
        RaiseNoIntfException(SoapAction)
      ...
InvClassType이 Nil이기 때문에 그 이상이 발생했습니다.이 정보는 이전의 오류 정보와 같습니다. 즉, IAP ServerSOAP 인터페이스의 실현 클래스가 존재하지 않거나 등록되지 않았습니다.그래서 저는 IAP ServerSOAP 인터페이스의 정의를 찾았습니다. SOAP Midas 단원에서
  IAppServerSOAP = interface(IInvokable)
    ['{C99F4735-D6D2-495C-8CA2-E53E5A439E61}']
    function  SAS_ApplyUpdates(...): OleVariant; stdcall;
    function  SAS_GetRecords(...): OleVariant; stdcall;
    function  SAS_DataRequest(...): OleVariant; stdcall;
    function  SAS_GetProviderNames: TWideStringDynArray; stdcall;
    function  SAS_GetParams(...): OleVariant; stdcall;
    function  SAS_RowRequest(...): OleVariant; stdcall;
    procedure SAS_Execute(...); stdcall;
  end;
MIDAS 기술에 익숙한 사람들이 이 코드를 보면 IAP Server 인터페이스와 매우 비슷하다는 것을 알 수 있습니다. 단지 IAP Server에서 그 방법은 모두 AS 입니다.시작, 여기는SAS첫머리그렇다면 왜 이미 IAppServer 인터페이스가 하나 생겼는데Borland는 Update 2에 이런 IAppServerSOAP 인터페이스를 추가해야 합니까?패치2를 하기 전에 저도 SOAP의 일부 코드를 보았습니다. 그때의 SOAP Server Data Module는 IAP Server에서 파생된 것입니다. 비록 IAP Server는 IInvokable에서 파생된 것이 아니지만(Delphi 6의 요구에 따라 모든 SOAP 인터페이스는 IInvokable 인터페이스에서 파생되어야 합니다) 사실 IInvokable는 IInterface에서 직접 파생된 것으로 IInterface와 완전히 같습니다.IInterface는 사실 모든COM 인터페이스의 조상 인터페이스인 IUnknown이다. IAppServer는 IDispatch 인터페이스(COM의 주요 인터페이스로 Automation에 사용되고 그 조상도 IUnknown)에서 파생된 것이기 때문에 IAppServer를 직접 사용해도 안 된다.IAppServerSOAP 인터페이스 정의 앞에 주석이 있다. 즉, IAppServerSOAP는 IAppServer의 SafeCall 유형을 대체하는 방법을 StdCall 형식으로 호출한다. SafeCall이 지원되지 않는 환경에서도 IAppServer의 기능을 실현할 수 있도록 한다.이것이 IAppServerSOAP의 원인입니다.이런 걸 알게 돼서 많이 좋아졌어요.모든 SOAP Server Data 모듈은 Tsoap Data 모듈에서 파생된 것이다. 이것은 SOAP Dm 단원에 정의되어 있는데 그 중에서 다음과 같은 코드가 있다.
    { IAppServerSOAP }
    function  SAS_ApplyUpdates(...): OleVariant; virtual; stdcall;
    function  SAS_GetRecords(...): OleVariant; virtual; stdcall;
    function  SAS_DataRequest(...): OleVariant; virtual; stdcall;
    function  SAS_GetProviderNames: TWideStringDynArray; virtual; stdcall;
    function  SAS_GetParams(...): OleVariant; virtual; stdcall;
    function  SAS_RowRequest(...): OleVariant; virtual; stdcall;
    procedure SAS_Execute(...); virtual; stdcall;
여기가 바로 IAP Server SOAP 인터페이스의 실현이다. 모든 SOAP Server Data 모듈은 Tsoap Data 모듈에서 파생된 것이기 때문에 IAP Server SOAP 인터페이스의 실현 유형은 반드시 이미 실현된 것이지만 등록된 것이 있습니까?우리의 SOAP Server Data Module 단원인 SvrDMSoap에는 다음과 같은 코드가 있습니다.
procedure TSoapDemo3DMCreateInstance(out obj: TObject);
begin
 obj := TSoapDemo3DM.Create(nil);
end;

initialization
   InvRegistry.RegisterInvokableClass(TSoapDemo3DM, TSoapDemo3DMCreateInstance);
분명히 그것도 등록되어 있지만 왜 오류가 발생했습니까?ISoapDemo3DM 인터페이스의 WSDL을 보세요...왜 AS 만XXX ?SAS 없음XXX ?그렇군요. 서버는 IAPServer 인터페이스만 내보냈을 뿐 IAPServerSOAP 인터페이스는 내보내지 않았습니다.그게 문제야!SvrDMSoap 단원을 다시 봅시다.
  ISoapDemo3DM = interface(IAppServer)
    ['{4F618288-9F81-4090-81EF-4ACE0BF6D0BE}']
  end;

  TSoapDemo3DM = class(TSoapDataModule, ISoapDemo3DM, IAppServer)
그렇군요. 원래 ISoap Demo3DM은 IAP 서버 인터페이스에서 파생되었군요. 이것은 SOAP 서버 Data Module Wizard의 Bug이고 IAP 서버 인터페이스의 방법에 따라 SOAP 서버 Data Module를 생성한 것이 분명합니다.문제의 소재를 알면 쉽다. 위의 코드에 있는 두 개의 IAPServer를 모두 IAPServerSOAP로 바꾸고 다시 컴파일한다.다시 클라이언트 프로그램을 살펴보면 모든 것이 정상적이고 ISoapDemo3DM의 WSDL도SAS특히hhttp://localhost:1024/Demo3.wadSoapDemo3표준 Delphi 6.02의 WebService 페이지도 볼 수 있습니다.이로써 이 버그는 완전히 해결되었다.또한 C++ Builder 6에는 이 문제가 없습니다.[Mental Studio] 맹금Apr.23-02

좋은 웹페이지 즐겨찾기