1 9장 –멀티-클라이언트/멀티-플랫폼/ 멀티-티어 애플리케이션 구축 멀티-티어 애플리케이션 작성 ................................................................................................................................ 3 DataSnap 애플리케이션 배포 ................................................................................................................................ 8 윈도우와 맥 멀티-티어 데이터베이스 애플리케이션 작성 REST, 웹브로커 및 서비스 기반 DataSnap 서버 애플리케이션 작성 DataSnap 바이트 스트림 필터링 윈도우와 맥 애플리케이션에서 웹 서비스 사용하기 ........................................................................................ 51 웹 서비스 애플리케이션과 서비스를 사용하는 윈도우 및 맥 클라이언트 애플리케이션 작성 윈도우 및 맥 애플리케이션에서 클라우드 스토리지와 서비스 사용하기 ...................................................... 67 RAD Studio 클라우드 서비스 애저 클라우드 서비스 아마존 클라우드 서비스 첫 번째 클라우드 기반 윈도우 및 맥 애플리케이션을 구축 애플리케이션을 클라우드에 배포 요약, 전망, 해야 할 일, 참고자료 ....................................................................................................................... 70
윈도우와 맥 용의 멀티-티어 애플리케이션을 개발하는 방법에 대해 차근차근 알아봅니다. 데이터스냅(DataSnap), 웹 서비스, 클라우드 서비스 등의 활용방법까지 소개합니다.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
TServerMethods1 = class(TComponent) private { Private declarations } public { Public declarations } function EchoString(Value: string): string; function ReverseString(Value: string): string; end; {$METHODINFO OFF}
implementation
uses System.StrUtils;
function TServerMethods1.EchoString( Value: string): string; begin Result := Value; end; function TServerMethods1.ReverseString( Value: string): string; begin Result := System.StrUtils.ReverseString(Value); end; end.
// C++ - ServerMethodsUnit1.cpp //-------------------------------------------------------- #include <SysUtils.hpp> #pragma hdrstop
private { Private declarations } public { Public declarations } function callStoredProcedure (mylocalkey : Integer) : String; end; // C++ class TDSServerModule1 : public TDSServerModule { __published:// IDE-managed Components TSQLConnection *EMPLOYEE_CONNECTION; TSQLDataSet *EMPLOYEE_TABLE; TDataSetProvider *ServerDataSetProvider1; TSQLStoredProc *SQLStoredProc1; private:// User declarations public:// User declarations String _fastcall callStoredProcedure (int mylocalkey); __fastcall TDSServerModule1(TComponent* Owner); };
File > Save All를 클릭하여 프로젝트를 저장합니다.
7 단계 - 방금 추가된 함수에 대한 서버 측 코드 작성하기
callStoredProcedure 함수는 정수형 매개 변수 직원 번호 (EMP_NO)를 가지고 저장 프로시저를
호출합니다. 이 함수는 문자 프로젝트 ID (PROJ_ID)를 얻습니다. 이 함수는 입력 매개 변수를 지정하고
프로시저를 실행 한 후 출력 매개 변수를 검색합니다. TSQLStoredProc 컴포넌트의 StoredProcName
속성의 값을 이미 저장 프로시저 이름 "GET_EMP_PROJ"로 설정했습니다. 델파이에서,
DelphiServerModuleUnit.pas에 다음 함수를 추가합니다:
델파이의 경우, DelphiServerModuleUnit.pas에 다음의 함수를 추가합니다:
function TDSServerModule1.callStoredProcedure( mylocalkey: Integer): String; var myString :String; begin SQLStoredProc1.ParamByName('EMP_NO').AsInteger := mylocalkey; SQLStoredProc1.ExecProc; myString := SQLStoredProc1.ParamByName('PROJ_ID').AsString; result := myString; end; C ++의 경우, CppServerModuleUnit.cpp 안에 다른 멤버 함수 뒤에 다음 함수를 추가합니다:
ClientDataSet의 Active 속성을 True로 설정합니다. TStringGrid 에서 라이브 employee 데이터를 보실 수
있습니다. InterBase 데이터베이스에서 데이터와 메타 데이터를 구해오는 DataSnap 서버에 DataSnap
연결을 통해 데이터와 메타 데이터를 가져오고 있습니다.
ClientDataSet의 Active 속성을 False로 설정합니다. 클라이언트 프로그램은 다음 단계에서 추가하는
체크박스의 OnChange 이벤트 핸들러를 사용하여 ClientDataSet의 Active 속성을 토글링 합니다.
클라이언트 측에 DataSnap 액세스 및 ClientDataSet 컴포넌트를 추가하고 DataSnap 클라이언트의
속성들을 설정 한 후, 폼은 다음과 같아야 합니다:
38
13 단계 – 체크박스에 대한 이벤트 핸들러를 추가하고 업데이트 버튼 적용하기
먼저 서버 연결에 대한 확인 체크박스의 OnChange 이벤트 핸들러를 추가합니다. 체크 박스를 선택하고
오브젝트 인스펙터의 이벤트 탭을 선택하고 기본 골격 코드를 생성하기 위해 OnChange 이벤트를 더블
클릭합니다. DataSnap 서버 연결을 열기/닫기 하고 ClientDataSet을 활성화/비활성화하는 다음 코드를
추가합니다:
// Delphi procedure TForm1.CheckBox1Change(Sender: TObject); begin // if Connect to Server is checked then //open the DataSnap server connection //activate the ClientDataSet if CheckBox1.IsChecked then begin SQLConnection1.Connected := True; ClientDataSet1.Active := True end // if Connect to Server is not checked then //deactivate the ClientDataSet //close the DataSnap server connection else begin ClientDataSet1.Active := False; SQLConnection1.Connected := False end; end;
39
// C++ void __fastcall TForm1::CheckBox1Change(TObject *Sender) { // if Connect to Server is checked then //open the DataSnap server connection //activate the ClientDataSet if (CheckBox1->IsChecked) { SQLConnection1->Connected = True; ClientDataSet1->Active = True; } // if Connect to Server is not checked then //deactivate the ClientDataSet //close the DataSnap server connection else { ClientDataSet1->Active = False; SQLConnection1->Connected = False; } }
"업데이트 적용하기" 버튼의 OnClick 이벤트 핸들러를 추가합니다. 위와 같이 이벤트 핸들러의 기본
골격을 생성하고 다음 코드를 추가합니다:
// Delphi procedure TForm1.ApplyUpdatesButtonClick(Sender: TObject); begin ClientDataSet1.ApplyUpdates(0); end; // C++ void __fastcall TForm1:: ApplyUpdatesButtonClick(TObject *Sender) { ClientDataSet1->ApplyUpdates(0); }
스트링그리드에서 데이터를 변경할 때 변경된 내용이 ClientDataSet의 Delta (Published 가 아님)속성에
저장되고 있습니다. 델타는 클라이언트를 통해 삽입된, 수정된, 삭제된 레코드에 대한 정보만
포함합니다. 클라이언트 데이터 셋이 프로바이더에 연결될 때, 델타는 ApplyUpdates와 Reconcile
메소드에 매개변수로 전달되고 데이터베이스를 업데이트하기 위해 변경 로그의 정보를 사용합니다.
업데이트를 성공적으로 하고 돌아온 후, 델타는 지워집니다.
ApplyUpdates는 업데이트 프로세스를 중단하기 전에 오류의 최대 수를 나타내는, MaxErrors, 하나의
매개 변수를 사용합니다. 프로바이더는 업데이트 프로세스를 중단하기 전에 허용 되야 합니다.
MaxErrors 가 0 이면, 업데이트 오류가 발생하자마자, 전체 업데이트 과정이 종료됩니다. 어떠한 변경
사항도 데이터베이스에 기록되지 않고 클라이언트 데이터 셋의 변경 로그는 그대로 유지됩니다.
MaxErrors 가 -1 이라면, 모든 오류는 묵인되고 변경 로그가 성공적으로 적용한지 못한 모든 기록이
포함되어 있습니다. MaxErrors는 양수 값이라면, MaxErrors에 의해 지정된 것보다 더 많은 오류가
발생하는 경우 모든 업데이트가 중단됩니다. MaxErrors에 의해 지정된 것보다 적은 오류가 발생하면
성공적으로 적용된 모든 레코드들은 자동으로 클라이언트 데이터셋의 변경 로그로부터 지워집니다.
ApplyUpdates는 MaxErrors 보다 항상 작거나 1 더한 수와 같은, 실제 발생하는 오류의 수를 반환합니다.
이 반환 값은 데이터베이스에 기록 할 수 없는 레코드의 수를 나타냅니다.
클라이언트 데이터셋의 ApplyUpdates 메소드는 다음을 수행합니다:
그것은 간접적으로 프로바이더의 ApplyUpdates 메소드를 (이 경우 TCP / IP를 통해 DataSnap
이 단계는 TButton TEdit 박스와 GetProject 버튼을 사용하여 직원의 번호를 가지고 인터베이스
데이터베이스의 GET_EMP_PROJ 저장 프로시저를 실행하고 프로젝트 ID를 반환하는 DataSnap 서버
메소드 호출하고 반환 값을 TLabel의 Text 속성에 표시하는 이벤트 핸들러를 작성하는 방법을
보여줍니다.
“프로젝트 가져 오기" 버튼의 OnClick 이벤트에 대한 이벤트 핸들러 기본 골격을 만듭니다. 저장
프로시저가 정수 값이 사용하기 때문에, TEdit의 사원 번호 텍스트를 정수로 변환해야 하고 결과적으로
프로젝트 ID 문자열을 반환하는 데이터베이스 저장 프로시저를 호출하는 서버 메소드를 호출합니다.
다음은 이벤트 핸들러 코드입니다:
// Delphi procedure TForm1.GetProjectButtonClick(Sender: TObject); var mykey : Integer; //variable to hold text from edit box myServer : TDSServerModule1Client; //server proxy we will call projectIDString : string;// returned from stored proc begin // If DataSnap server is connected call the remote method if SQLConnection1.Connected then begin mykey := StrToInt(Edit1.Text); //conversion to integer // Server creation using the SQLConnection for communication myServer := TDSServerModule1Client.Create( SQLConnection1.DBXConnection); try // Calling method that calls stored procedure with the key // Save value returned from stored procedure projectIDString := myServer.callStoredProcedure(mykey); // if returned string is empty then display no projectID if projectIDString = '' then Label1.Text := '* NoProjID *' else Label1.Text := projectIDString finally myServer.Free //free up the server end
// C++ void __fastcall TForm1::GetProjectButtonClick(TObject *Sender) { // If DataSnap server is connected call the remote method if (SQLConnection1->Connected) { int mykey; //variable to hold text from edit box String projectIDString;// returned from stored proc TDSServerModule1Client *myServer; //server proxy we’ll call mykey = StrToInt(Edit1->Text); //conversion to integer // Server creation using the SQLConnection myServer = new TDSServerModule1Client( SQLConnection1->DBXConnection); try { // Calling method that calls the stored proc with the key. // Save value returned from stored procedure. projectIDString = myServer->callStoredProcedure(mykey); // if returned string is empty then display “* noProjID *” if (projectIDString == "") Label1->Text = "* NoProjID *"; else Label1->Text = projectIDString; } __finally { delete myServer; //free up the server } } }
앞의 코드는 저장 프로시저를 호출해서 반환 된 값 즉, 프로젝트 ID값을 TLabel의 Text 속성에
지정합니다. 저장 프로시저가 사원(NULL 문자열)의 프로젝트 ID를 찾을 수 없다면, TLabel의 Text 속성에
"* NoProjID *"텍스트를 표시합니다.
File > Save All을 선택하여 수정 된 모든 소스 파일들, 프로젝트 및 프로젝트 그룹을 저장합니다.
15 단계– 윈도우 DataSnap 클라이언트 애플리케이션 빌드와 실행하기
이제 프로젝트의 윈도우 클라이언트 측을 빌드하고 실행 할 준비가 되었습니다. 프로젝트 매니저에서
DelphiDBDataSnapClient 또는 CppDBDataSnapClient에서 오른쪽 마우스 버튼을 클릭하여 클라이언트
프로젝트를 빌드하고 발견되는 모든 오류를 수정합니다.
"서버에 연결” 체크박스를 사용하여 클라이언트 애플리케이션을 실행합니다.
체크되었다면, DataSnap 서버에 연결하고 ClientDataSet을 활성화합니다.
체크되어 있지 않다면 ClientDataSet을 비활성화 하고 DataSnap 서버 연결을 끊습니다.
TStringGrid은 직원 테이블로부터 가져온 항목으로 채워집니다. TBindNavigator 컨트롤 또한 테이블
항목을 탐색할 수 있도록 활성화합니다.
TStringGrid에서 셀을 선택하고 값을 변경할 수 있습니다. "업데이트 적용하기" 버튼을 클릭하면
데이터베이스 테이블은 이 변경 사항으로 업데이트됩니다.
마지막으로, 저장 프로시저를 테스트합니다. TEdit 컨트롤에서 유효한 직원 번호 중 하나를 입력하고
"프로젝트 가져 오기”버튼을 클릭합니다. 라벨의 텍스트에 EMPLOYEE_PROJEC T 테이블로부터, 하나가
존재하는 경우, 반환되는 해당 프로젝트 ID로 변경해야 합니다 그렇지 않으면 "* 없음 ProjectID의 *"를
43
표시합니다:
체크박스가 선택되어 있으며 저장 프로시저를 테스트를 완료한 경우 클라이언트 프로그램 폼은 다음과
같이 표시됩니다:
16 단계 – 맥 DataSnap 클라이언트 애플리케이션 빌드 및 실행하기
전에 언급했듯이, DataSnap 클라이언트 애플리케이션 맥 버전을 만들 수 있습니다.
프로젝트 매니저에서 DataSnap 클라이언트의 타깃 플랫폼 노드에서 오른쪽 마우스 버튼으로 클릭하고
대상으로 "OS X"를 추가합니다. 또한 타깃 플랫폼에 대한 원격 프로파일을 설정해야 합니다.
또한 PAServer이 맥에서 실행되고 있는지 확인해야 합니다(IDE는 맥에 내장 된 애플리케이션을 배포 할
수 있도록 PAServer 실행이 필요합니다). 또한 DataSnap 클라이언트를 빌드하고 원격 윈도우 타깃에
배포하려면 다음과 같은 단계를 실행합니다.
또한 클라이언트의 SQLConnection 컴포넌트에 대한 “HostName” 매개 변수를 로컬 호스트에서 DataSnap
서버가 실행중인 컴퓨터 네트워크 이름 또는 TCP / IP 주소로 변경해야 합니다.
오브젝트 인스펙터를 사용하여 SQLConnection1 컴포넌트의 Params 속성을 두 번 클릭 하여 값(Value)
44
리스트 에디터를 표시합니다. 이미 DataSnap 서버를 가리키는 DataSnap의 dbExpress 커넥션을 사용하는
새로운 DataSnap 연결을 변경 또는 생성하는 경우 이 단계를 건너 뛸 수 있습니다. 이 경우, 디폴트
DataSnap 연결 이름을 사용하였고 디폴트 HostName은 “localhost”입니다. HostName 값을 설치를 위한
컴퓨터 이름 또는 TCP/IP 주소로 지정합니다.
DataSnap 클라이언트 애플리케이션을 빌드하고 맥에 배포하기 전에 마지막으로 설정해야 하는 것은
클라이언트가 ClientDataSet을 사용하기 때문에 클라이언트 프로젝트의 배포 옵션에 Midas 라이브러리
기능 파일을 추가 합니다. Project > Deployment를 사용하여 기능 파일 아이콘을 클릭하여 MIDAS
라이브러리를 선택합니다 (프로젝트 배포는 3장 개발환경에서 다루었습니다). 맥 버전을 테스트 할 수
있도록 맥 DataSnap 클라이언트 실행파일과 함께 MIDAS.dylib를 배포합니다.
Run without Debugging (Shift-Control-F9) 또는 Run (F9)을 선택하여 DataSnap 클라이언트 애플리케이션을
컴파일하고 맥에 배포합니다. 윈도우에서 실행되고 있는 DataSnap 서버와 작업할 수 있는지 확인하기
위해 맥에서 클라이언트를 테스트합니다. 맥 DataSnap 클라이언트 애플리케이션은 윈도우
클라이언트처럼 작동합니다.
45
윈도우 및 맥 용 첫 멀티 클라이언트, 멀티 플랫폼, 멀티-티어 DataSnap 데이터베이스 애플리케이션을
작성했습니다!
DataSnap 멀티-티어 애플리케이션 개발에 더 배울 것이 있습니다. 예를 들어, 변경 사항이 있고 서버
연결 체크박스가 선택되어 있지 않다면 적용되어야 하는 모든 업데이트가 데이터셋에 있는지 보기
위해 체크하지 않았습니다. 클라이언트 데이터셋을 비활성화하고 DataSnap 서버 연결을 끊기 전에
항상 ApplyUpdates를 호출 할 수 있습니다. 적용 할 업데이트가 없을 때 ApplyUpdates을 호출하면
서버에 아무 것도 보내자 않으며 런타임 오류가 발생합니다.
또한 델파이 및 C + + DataSnap 서버 애플리케이션 및 / 또는 DataSnap 클라이언트 애플리케이션을 모두
구축할 수 있습니다. 같은 기능을 가지고 있기 때문에, 하나의 서버와 다른 클라이언트를 사용하여
혼합하고 매치 시킬 수 있습니다.
자세한 내용을 배우려면, RadPHP를 사용하여 DataSnap 클라이언트 애플리케이션을 작성 할 수
있습니다 – 그리고 DataSnap 모바일 커넥터 기술을 사용하여 모바일 클라이언트 애플리케이션을
필터들이 RAD Studio에 등록 된 패키지에 있다면 디자인 타임에 사용할 수 있습니다. 이 필터는
패키지에 내장되어 있어야 하며 패키지는 델파이에 설치해야 합니다. 서버 측 설계 시간 지원은 필터
목록 편집기에 필터를 표시할 수 있습니다. 클라이언트 측 설계 시간 지원은 TSQLConnection을
사용하여 디자인 타임 연결을 할 수 있습니다.
클라이언트와 서버 사이의 핸드 셰이크 프로토콜을 기반으로 자동으로 인스턴스화 되는 것처럼
클라이언트 측에서 필터를 연결할 필요가 없습니다. 따라서 클라이언트 코드가 필터링 서버에
연결하기 전에 Uses 절에 유니트 이름을 추가하여 또는 초기화 시간 등 초기 단계에 필터를 등록하는
것이 중요합니다.
48
또한 DataSnap 서버와 클라이언트를 위한 자신의 필터를 만들 수 있습니다. 해야 할일 세 가지가
있습니다: 필터를 정의하고, 필터 코드를 구현하고, 필터를 등록합니다.
필터 정의
모든 필터는 TTransportFilter 클래스에서 확장해야 하며 구현은 최소한 두 개의 메소드 ProcessInput,
ProcessOutput와 식별하는 고유한 ID를 제공해야 합니다.
public function ProcessInput(const Data: TBytes): TBytes; override; function ProcessOutput(const Data: TBytes): TBytes; override; function Id: UnicodeString; override;
처리 매소드는 서로 반대입니다: 한 메소드의 결과값이 초기 입력을 생산하는 다른 메소드의 입력으로
전달됩니다.
각 연결은 필터를 인스턴스 하기 때문에 처리 함수가 스레드 안전이 필요하지 않습니다;
지역 변수는 인스턴스 변수로 사용할 수 있지만 인스턴스 전체 상태를 가정하지 않습니다.
기본으로 매개 변수가 없는 생성자는 필터 인스턴스를 인스턴스화 하는데 사용됩니다. 추가 매개
변수는 서버 인스턴스와 호환되는 클라이언트 인스턴스가 필요할 수 있습니다. 매개 변수 값은 서버
측 필터 및 클라이언트 측 필터간에 교환 할 수 있습니다. 예를 들어, 암호화 키의 위치와 함께
전달되는 경우 대칭 암호화 필터를 구현하기 위해 하나가 선택되어야 한다면 매개변수가 필요합니다.
모든 매개 변수는 쌍으로(이름, 문자열) 노출됩니다. 그들의 이름은 GetParameters 메소드를 통해 반환
할 수 있으며, 그 값은 질의되거나 GetParameterValue 및 SetParameterValue를 사용하여 변경할 수
있습니다.
protected function GetParameters: TDBXStringArray; override; public function GetParameterValue(const ParamName: UnicodeString): UnicodeString; override; function SetParameterValue(const ParamName: UnicodeString; const ParamValue: UnicodeString): Boolean; override;
어떤 경우에는 모든 매개 변수 또는 그 매개 변수의 일부는 디자인 타임에 변경해야 합니다, 매개변수
이름은 GetUserParameters 메소드를 통해 구합니다.
protected
function GetUserParameters: TDBXStringArray; override;
이 메소드에 의해 반환되지 않는 매개 변수 이름은 디자인 타임에 표시하거나 편집 할 수 없습니다
있습니다.
필터 코드 구현
위의 정의 된 함수를 구현하는 데 필요한 코드를 작성합니다. 예를 보실 수 있습니다.
TTransportFilter 클래스는 Data.DBXTransportFilter.pas 소스 파일에 정의되고 구현되어 있습니다.
호출하는 방법을 클라이언트에게 알려줍니다. WSDL의 게시자를 사용하는 방법에 대한 자세한
내용은, 웹 서비스 애플리케이션의 WSDL 문서를 생성을 참조하십시오.
SOAP 디스패처와 WSDL 게시자는 자동 디스패칭 컴포넌트입니다. 이는 전달되어 들어오는 요청들이
자신의 WebDispatch 속성에 지정한 경로 정보를 사용하여 해결하도록 자동으로 웹 모듈에 등록된다는
것을 의미합니다. 웹 모듈을 오른쪽 마우스 버튼으로 클릭하면 이 자동-디스패칭 컴포넌트뿐만 아니라,
DefaultHandler 라는 이름의 한 개의 웹 액션 아이템을 가지고 있습니다.
55
DefaultHandler는 디폴트 액션 아이템입니다. 웹 모듈은(경로 정보가 일치하지 않을 수 있습니다)
핸들러를 찾을 수 없는 요청을 받을 경우, 즉, 디폴트 액션 아이템에 해당 메시지가 전달됩니다.
DefaultHandler는 웹 서비스를 설명하는 웹 페이지를 생성합니다. 디폴트 액션을 변경하려면 이 액션
아이템의 OnAction 이벤트 핸들러를 편집합니다.
2 단계 – 시작 웹 서비스 인터페이스 작성
프로젝트를 생성한 후, 다음 단계는 웹 서비스가 제공하는 메소드에 대한 인터페이스와 구현을
생성하는 것입니다. 다음 대화 상자가 나타납니다:
웹 서비스 인터페이스 작성을 시작하려면 “Yes” 버튼을 클릭합니다. 또한 나중에 인터페이스를 만들 수
있습니다.
서비스 이름에 SimpleCalculator를 입력합니다. 유니트 이름은 서비스 이름과 동일하게 되지만 서비스
인터페이스와 구현에 대해 원하는 유니트 파일 이름을 만들 수 있습니다.
새로운 웹 서비스 추가 마법사는 클라이언트에 노출하여 호출 가능한 인터페이스의 이름을 지정 할 수
있고, 인터페이스와 구현 클래스를 선언하고 등록하는 코드를 생성합니다. 마법사는 생성 된 파일
편집을 도와주는 주석과 샘플 메소드 및 추가 타입 정의를 생성하는 옵션을 가지고 있습니다. 계산기
메소드을 작성할 것이기 때문에, "Generate comments" 체크박스를 선택하고 "Generate Sample
methods"는 선택하지 않습니다.
대화 상자에서 서비스 활성화 모델을 선택할 수 있습니다. 선택은 다음과 같습니다:
Per Request 는 발생하는 각각의 요청에 대한 응답의 구현 클래스의 새 인스턴스를 만듭니다.
요청이 처리 된 후 해당 인스턴스가 해제됩니다.
56
글로벌 오브젝트는 모든 요청을 처리하는 데 사용됩니다 구현 클래스의 단일 인스턴스를
생성합니다.
간단하게 하기 위해, "Per Request"서비스 활성화 모델을 선택합니다.
웹 서비스 애플리케이션 프로젝트를 저장합니다 – File > Save All. 웹 서비스 구현 파일과 웹 모듈 이름을
유지하려면 OK를 클릭합니다. 프로젝트 이름을 “SimpleCalculatorWebService”로 저장합니다.
델파이 또는 C+ +의 프로젝트 매니저 보기에서 웹 서비스 애플리케이션은 다음과 같이 표시됩니다:
3 단계 – 웹 서비스 메소드 정의와 구현
클라이언트 애플리케이션이 사용하는 메소드를 정의하고 구현하는 데 필요한 웹 서비스
애플리케이션을 완성합니다. 간단한 계산기를 들어, Add와 Subtract 메소드을 작성합니다. 다음의 연습
예제에서 간단한 계산기 웹 서비스를 완성하기 위해 Multiple과 Divide 메소드를 정의하고 구현합니다.
델파이의 경우,
a) SimpleCalculatorIntf.pas 파일의 인터페이스 섹션 안의 ISimpleCalculator 인터페이스 선언의 public 영역
안에 다음 라인을 추가합니다:
function Add(a,b: integer): integer; stdcall; function Subtract(a,b: integer): integer; stdcall;
b) SImpleCalculatorImpl.pas 파일의 인터페이스와 구현 섹션에 다음 코드를 추가합니다:
{ TSimpleCalculator } TSimpleCalculator = class(TInvokableClass, ISimpleCalculator) public function Add(a,b: integer): integer; stdcall; function Subtract(a,b: integer): integer; stdcall; end;
57
function TSimpleCalculator.Add(a,b: integer): integer; stdcall; begin Result := a+b; end; function TSimpleCalculator.Subtract(a,b: integer): integer; stdcall; begin Result := a-b; end;
C ++의 경우,
a) SimpleCalculator.h 파일의 ISimpleCalculator 인터페이스 선언 부분 안에 다음 라인을 추가합니다:
public: virtual int Add(int a, int b) = 0; virtual int Subtract(int a, int b) = 0;
b) SimpleCalculator.cpp 파일에서 TSimpleCalculatorImpl 클래스의 public 섹션 안에 다음 선언을
추가합니다:
int TSimpleCalculatorImpl::Add(int a, int b) { return a + b; } int TSimpleCalculatorImpl::Subtract(int a, int b){ return a-b; }
SOAP 서버는 이제 구현 완료 되었고 실행 준비가 되었습니다.
File > Save All를 클릭하여 수정 내용을 저장합니다.
58
4 단계 – SOAP 웹 서버 애플리케이션 실행
Shift-Control-F9를 누르거나 “Run without Debugging”를 선택하여 웹 서버 콘솔 애플리케이션을
시작합니다. 아래의 콘솔 창(실행하는 첫 번째)이 TCP / IP 포트를 사용하도록 요청하는 애플리케이션에
대한 윈도우 방화벽 경고와 함께 표시됩니다:
SimpleCalculatorWebService.exe 애플리케이션에 대한 “액세스 허용” 버튼을 클릭합니다. 웹 서비스는
포트 8085 또는 선택한 포트가 무엇이든지 상관없이 메소드 호출을 받을 준비가 되어 있습니다.
웹 서비스를 테스트하려면 애플리케이션을 실행하는 서버와 포트에서 브라우저를 가리킬 수 있습니다.
개발 머신 인 경우, 웹 서비스의 인터페이스를 액세스 하기 위해 http://localhost:8085/ 사용할 수
있습니다.
이 브라우저 결과 페이지는 웹 서버 애플리케이션 및 또한 WSDL 게시된 인터페이스에 정의 된 웹
서비스를 보여줍니다. 다른 인터넷 웹 서비스 애플리케이션에 브라우저를 지정하고 비슷한 결과를 볼
수 있습니다. ISimpleCalculator[WSDL] 링크에서 오른쪽 마우스를 클릭하면 WSDL 가져 오기 마법사를
사용하여 이후 단계에서 사용하기 위한 클립 보드에 URL을 배치합니다.
59
5 단계 – 웹 서비스를 사용하는 파이어몽키 클라이언트 애플리케이션 작성
이제 웹 서비스 애플리케이션을 실행하고, 간단한 계산기를 사용하기 위해 UI를 제공하고 원격
메소드를 호출하는 파이어몽키 클라이언트 애플리케이션(HD 또는 3D)을 작성할 수 있습니다.
파이어몽키 HD 애플리케이션 작성을 시작합니다. 프로젝트 매니저에서 – 오른쪽 마우스를 클릭하거나
“Add New Project” 스피드 버튼을 클릭하고 프로젝트 카테고리에서 FireMonkey HD Application– Delphi
또는 FireMonkey HD Application – C ++Builder를 선택합니다. 서버와 함께 작업할 새 프로젝트를
추가합니다.
“Save All”를 클릭하여 클라이언트 프로젝트와 프로젝트 그룹을 저장합니다. 클라이언트 프로젝트
이름은 “DelphiFMClientApplication” 또는 “CppFMClientApplication”으로 하고 프로젝트 그룹 이름은
“DelphiCalcWebServicesProjectGroup” 또는 “CppCalcWebServicesProjectGroup”으로 합니다 (또는 선택하는
이름이 무엇이든 상관없음).
6 단계 – 클라이언트 애플리케이션에 대한 웹 서비스 인터페이스 장치를 만들기 위해 W
SDL 가져 오기를 사용
클라이언트 애플리케이션은 웹 서비스 메소드에 대한 인터페이스가 필요합니다. 인터페이스 파일을
작성하려면 클라이언트는 WSDL 가져오기 마법사를 사용해야 합니다. 웹 서버 애플리케이션이
실행되고 있어야 한다는 것을 잊지마십시오.
File > New > Other… 선택하고 델파이 프로젝트 또는 C++ 빌더 프로젝트 웹 서비스 카테고리에서, WSDL
가져오기 마법사를 선택합니다.
60
웹 서비스 애플리케이션에 대한 URL 위치를 입력하거나 붙여 넣습니다.
http://localhost:8085/wsdl/ISimpleCalculator에 간단한 계산기 케이스가 있습니다.
웹 서비스는 로그인 인증을 요구하는 경우, 제공된 박스에 해당 정보를 입력합니다. 간단한 계산기 웹
서비스의 경우, 그냥 "Next" 버튼만 클릭합니다. 그런 다음 WDSL 바인딩 확장을 사용하도록 선택할 수
있는 WSDL 가져 오기 마법사의 두 번째 페이지가 표시됩니다.
기본 선택은 WSDL 가져 오기 마법사가 SOAP 서버에서 버전 정보를 가져 와서 올바른 인터페이스를
생성하도록 하는 것입니다. 선택되어 있는 “Automatic SOAP versioning”은 그대로 놔두고 “Next” 버튼을
이제 웹 서버 리모트 메소드에 대한 액세스 권한이 있으며, 메소드를 사용하는 사용자 인터페이스를
작성 할 수 있습니다. 간단한 계산기 웹 서비스 메소드 Add와 Subtract가 있습니다. UI를 완성하려면, 두
개의 에디터 박스, 에디터 박스를 식별하기 위한 두 개의 TLabel 컴포넌트, “Add”와 “Subtract” 메소드를
호출하기 위한 두 개의 TSpeedButton (또는 TButton), 메소드 결과를 표시하기 위한 TLabel 컴포넌트를
추가합니다.
클라이언트 폼 및 스트럭처 뷰의 모습은 다음과 같습니다:
64
마지막으로, 더하기(+) 및 빼기 (-) 스피드 버튼의 이벤트 핸들러를 추가하는데, 에디터 박스의 내용을
사용하여 웹 서비스 메소드를 호출하고 레이블에 결과를 표시합니다. 각 스피드 버튼을 더블
클릭하여(또는 오브젝트 인스펜터의 이벤트 탭을 사용하여 OnClick 이벤트를 선택합니다) 이벤트
핸들러의 기본 골격을 생성하고 다음 코드를 추가합니다.
//Delphi procedure TForm3.AddSpeedButtonClick(Sender: TObject); var a,b,c: integer; begin a := StrToInt(EditA.Text); b := StrToInt(EditB.Text); c := GetISimpleCalculator.Add(a,b); ResultLabel.Text := IntToStr(c); end; procedure TForm3.SubSpeedButtonClick(Sender: TObject); var a,b,c: integer; begin a := StrToInt(EditA.Text); b := StrToInt(EditB.Text); c := GetISimpleCalculator.Subtract(a,b); ResultLabel.Text := IntToStr(c); end; // C++ void __fastcall TForm3::AddSpeedButtonClick( TObject *Sender) { int a = StrToInt(EditA->Text); int b = StrToInt(EditB->Text); int c = NS_ISimpleCalculator::GetISimpleCalculator()->Add(a,b); ResultLabel->Text = IntToStr(c); }
65
//--------------------------------------------------------------- ------------ void __fastcall TForm3::SubSpeedButtonClick( TObject *Sender) { int a = StrToInt(EditA->Text); int b = StrToInt(EditB->Text); int c = NS_ISimpleCalculator::GetISimpleCalculator()->Subtract(a,b); ResultLabel->Text = IntToStr(c); }
File > Save All로 모든 작업을 저장합니다.
8 단계 – 클라이언트 애플리케이션 컴파일 및 실행하기
실행중인 웹 서비스 애플리케이션이 있는 프로젝트 그룹에서 활성화된 클라이언트 애플리케이션에서,
F9를 누르거나 “Run” 또는 “Run without Debugging” 을 선택합니다.
소스 코드에 문제가 없다면, 클라이언트 애플리케이션을 컴파일 및 실행됩니다.
두 에디터 박스에서 숫자를 입력하고 “더하기” 와 “빼기” 버튼을 클릭하면 결과가 표시됩니다.