헤르메스 LIFE

[Ajax] Ajax로 SOAP 웹 서비스 호출하기, Part 2: 웹 서비스 클라이언트 확장하기 본문

JSP&JavaScript&HTML

[Ajax] Ajax로 SOAP 웹 서비스 호출하기, Part 2: 웹 서비스 클라이언트 확장하기

헤르메스의날개 2011. 8. 22. 15:38
728x90
원문 : http://www.ibm.com/developerworks/kr/library/ws-wsajax2/

리뷰

본 시리즈 Part 1에서는, RPC 인코딩 및 document-literal 스타일 요청이 가능한 SOAP 웹 서비스 클라이언트를 제공하는 크로스 브라우저 JavaScript를 소개했다. 요청 및 응답 핸들러 지원, 커스텀 XML 직렬화/비직렬화, SOAP Headers 지원이 이 클라이언트에 포함되었다. 이 모든 것들이 WS-Addressing과 WS-ResourceFramework에 포함되어 있다.

ws.js (Part 1)에 정의된 기본 객체들은 다음과 같다.

  1. WS.Call: XMLHttpRequest를 래핑하는 웹 서비스 클라이언트
  2. WS.QName: XML 전용 이름 (XML Qualified Name) 구현
  3. WS.Binder: 커스텀 XML 직렬화/비직렬화 베이스
  4. WS.Handler: 요청/응답 핸들러 베이스
  5. SOAP.Element: XML DOM을 래핑하는 기본 SOAP 엘리먼트
  6. SOAP.Envelope: SOAP.Element를 확장하는 SOAP Envelope 객체
  7. SOAP.Header: SOAP.Element를 확장하는 SOAP 헤더 객체
  8. SOAP.Body: SOAP.Element를 확장하는 SOAP 바디 객체
  9. XML: XML을 핸들링 하는 크로스 플랫폼 유틸리티 메소드

이 객체들 중에서, 다섯 가지는 WS-Addressing과 WS-ResourceFramework 구현에 중요하다: WS.QName, SOAP.Element, WS.Handler, WS.Binder, WS.Call 첫번째 기술자료에서 이러한 객체들의 기본 기능들을 복습하기 바란다.

이 글에서는 두 개의 새로운 JavaScript 파일들을 소개한다. 첫 번째는 WS-Addressing을 지원하는 객체를 정의하고 ( wsa.js ), 두 번째는 WS-ResourceFramework의 기본 구현을 지원하는 객체를 정의한다. ( wsrf.js ).


그림 1. Web Services JavaScript Library를 사용하여 웹 브라우저 내에서 Web Service Resource Framework 서비스 호출하기
Web Services JavaScript Library를 사용하여 웹 브라우저 내에서 Web Service Resource Framework 서비스 호출하기

wsa.js 에 정의된 기본 객체들은 다음과 같다.

  1. WSA.EndpointReference: WS-Addressing EndpointReference 객체.
  2. WSA.EndpointReference.ReferenceParameters: WS-Addressing EPR 레퍼런스 매개변수용 컨테이너.
  3. WSA.EndpointReference.Binder: WSA.EndpointReference 객체용 XML 직렬화/비직렬화
  4. WSA.MessageContext: WS-Addressing SOAP 메시지 헤더 메타데이터용 컨테이너
  5. WSA.Handler: WS-Addressing SOAP 메시지 헤더를 SOAP Envelope에 삽입하는 요청 핸들러.

wsrf.js 에 정의된 기본 객체는 다음과 같다.

  1. WSRF.Request.GetResourceProperty: WS-ResourceFramework GetResourceProperty 연산용 래퍼.
  2. WSRF.Request.GetMultipleResourceProperties: WS-ResourceFrame GetMultipleresourceProperties 연산용 래퍼.
  3. WSRF.Resource: WS-ResourceFramework 연산을 호출하는 클라이언트 인터페이스.

배워야 할 새로운 JavaScript 객체들이 너무 많은 것 같지만, 이들이 제공하는 API는 여러분이 실제로 웹 서비스를 호출할 때 해야 할 많은 작업들을 줄여준다. 예를 들어, Listing 8을 보면, 이 API로 WS-ResourceFramework 호환의 웹 서비스를 단 몇 줄의 코드로 호출할 수 있다는 것을 알 수 있다.


WS-Addressing 지원 구현하기

Web Services Addressing 스팩은 어드레싱 정보를 SOAP Envelope에 삽입하는 메커니즘을 정의한다. WS-Addressing의 핵심에는 EndpointReference 로 알려진 객체가 있는데, 이는 특정 웹 서비스 인스턴스에 대한 레퍼런스 겸 디스크립션 역할을 한다. (Listing 1) WS-Addressing 스팩은 SOAP Envelope 내에서 어드레싱 정보를 직접 전달하는데 사용되는 많은 SOAP 메시지 헤더들을 정의한다.

wsa.js JavaScript 라이브러리는 WS-Addressing EndpointReference와 SOAP 메시지 헤더 엘리먼트에 대한 기본적인 지원을 구현하는 많은 객체들을 제공한다.


Listing 1. WS-Addressing EndpointReference
                <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
  <Address>http://www.example.org/services/HelloWorld</Address>
  <ReferenceParameters>
    <abc:foo xmlns:abc="urn:foo">This is a test</abc:foo>
  </ReferenceParameters>
</EndpointReference>

WSA.EndpointReference 객체는 WS-Addressing EndpointReferences를 나타내는데 사용된다. (Listing 2) 이 코드를 위의 XML과 비교해 보면, API가 어떻게 작동하는지를 이해할 수 있을 것이다.


Listing 2. WSA.js로 EndpointReference 구현하기
                var epr = 
  new WSA.EndpointReference(
    "http://www.example.org/services/HelloWorld");
var epr_rp = epr.create_reference_parameters();
epr_rp.create_child(
  new WS.QName('foo','urn:foo','abc')).
    set_value('This is a test');

WSA.EndpointReference용 API는 현재 WS-Addressing 정보 모델에 정의된 대로 Address와 ReferenceParameters를 지원한다. Metadata 프로퍼티는 현재 구현되어있지 않다. 이는 이 글에서 구현할 클라이언트의 기본 기능에는 중요하지 않다.

WS-Addressing SOAP 메시지 헤더는 웹 서비스 클라이언트에 의해 서비스로 보내지는 SOAP Envelope에 설정된다. ws.js JavaScript 라이브러리에 정의된 WS.Call 객체는 SOAP.Envelope와의 작동 상세를 숨기기 때문에, WS.Handler를 사용하여 올바른 헤더를 삽입한다.

웹 서비스 클라이언트는 모든 요청, 응답, 에러 시 WS.Handler 객체의 메소드를 호출한다. WS-Addressing 구현의 경우, 메시지로 삽입 될 정보를 포함하고 있는 WSA.MessageContext 객체를 사용하는 WSA.Handler가 제공된다. (Listing 3)


Listing 3. WS-Addressing 콘텍트스와 핸들러 사용하기
                var address = 'http://www.example.com/services/HelloWorld';
var ctx     = new WSA.MessageContext();
ctx.to      = new WSA.EndpointReference(address);
ctx.replyto = new WSA.EndpointReference(WSA.ANONYMOUS);
ctx.action  = address + '#SayHello'

var handler = new WSA.Handler();
handler.set_context(ctx);

var call = new WS.Call('');
call.add_handler(handler);

WSA.MessageContext 객체에 대한 프로퍼티는 WS-Addressing SOAP 메시지 헤더에 상응한다.

  • to: WSA.EndpointReference 객체. 이것의 Address는 메시지의 목적지를 구분하는 절대 URI를 지정한다.
  • from: 메시지의 센더(sender)를 구분하는 WSA.EndpointReference 객체.
  • replyto: 응답이 전달될 장소를 구분하는 WSA.EndpointReference 객체.
  • faultto: 오류가 전달될 장소를 지정하는 WSA.EndpointReference 객체.
  • action: 메시지가 실행하기로 한 액션을 구분하는 절대 URI.
  • messageid: 메시지를 식별하는 절대 URI.
  • relatesto: 관련 메시지들을 구분하는 URI 쌍들의 어레이. 이 쌍의 첫 번째 URI는 관계 유형을 구분한다. 두 번째 URI는 관련 메시지의 고유 Message ID를 지정한다.

WSA.Handler가 웹 서비스를 호출하는데 사용되는 WS.Call 객체로 등록되면, WS.Call 객체는 모든 요청 시 핸들러를 호출하면서, 이것을 SOAP.Envelope 객체에 대한 레퍼런스로 전달한다. 이 핸들러는 WSA.MessageContext에서 정보를 가져와서 알맞은 헤더를 메시지로 삽입한다. (Listing 5)


WS-ResourceFramework 지원 구현하기

Web Services Resource Framework은 웹 서비스 표준을 사용하여 Stateful 리소스들의 인스턴스에 액세스 하여 조작하는 규약을 정의한다. 개별 리소스들이 WS-Addressing EndpointReferences에 의해 구분 및 참조된다. 많은 공통 연산들이 이 리소스의 프로퍼티를 검색 또는 수정하는데 사용된다.

wsrf.js JavaScript 라이브러리는 GetResourceProperty와 GetMultipleResourceProperties 연산을 지원하는 Web Services Resource Framework의 부분적인 구현을 제공한다. 이 API는 ws.js wsa.js API를 기반으로 구현되며, 포괄적인 WS-ResourceFramework 구현을 제공하는 것 보다 두 스크립트의 사용을 설명하는데 치중한다.

WS-ResourceFramework 연산들은 document-literal SOAP 요청으로서, 지정된 Resource 인스턴스로 향한다. 대상 리소스는 WS-Addressing EndpointReference에 의해 구분된다. (Listing 4)


Listing 4. A WSRF EndpointReference
                <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
  <Address>http://localhost:9080/SoapAjax2/services/DeviceService</Address>
  <ReferenceParameters>
    <abc:DeviceID xmlns:abc="urn:deviceservice">ABC123</abc:DeviceID>
  </ReferenceParameters>
</EndpointReference>

wsa.js 에서 정의된 메커니즘을 사용하여 SOAP Envelope 내에서 표현될 때, WSRF EndpointReference 내의 정보는 SOAP 메시지 헤더의 형태를 취한다. (Listing 5)


Listing 5. WSRF GetResourceProperty Request
                <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
 <Header>
  <To xmlns="http://www.w3.org/2005/08/addressing">
    http://localhost:9080/SoapAjax2/services/DeviceService</To>
  <abc:DeviceID xmlns="urn:deviceservice">ABC123</abc:DeviceID>
 </Header>
 <Body>
 <GetResourceProperty 
  xmlns="http://docs.oasis-open.org/wsrf/rp-2" 
  xmlns:ns="urn:foo">ns:bar</GetResourceProperty>
 </Body>
</Envelope>

wsrf.js 에서 제공되는 API는 WS-ResourceFramework 웹 서비스들과 인터랙션을 실행하는데 필요한 SOAP Envelope와 WS-Addressing 헤더들과 작동하는 모든 상세들을 숨긴다. 이 코드를 보면 작동 방법에 있어 중요한 측면을 보게 될 것이다.

Listing 6은 WSRF GetResourceProperty 연산용 래퍼 객체이다. 이 래퍼는 wsrf.js 라이브러리에 의해 내부적으로 사용되고 SOAP Envelope를 구현하고 연산에 필수적인 XML을 구현하는 기본 메커니즘을 포함하고 있다. 이 객체는 ws.js 에서 제공되는 SOAP.Element 와 SOAP.Envelope API를 활용한다. 래퍼 객체의 초기화 동안 전달된 "qname" 매개변수는 요청되고 있는 프로퍼티의 XML Qualified 이름이다.


Listing 6. WSRF GetResourceProperty 요청 래퍼
                WSRF.Request.GetResourceProperty = Class.create();
WSRF.Request.GetResourceProperty.prototype = {
  initialize : function(qname) {
    this.envelope = new SOAP.Envelope();
    this.set_qname(qname);
  },
  set_qname : function(qname) {
    var body = this.envelope.create_body();
    var method = body.create_child(
      WSRF.Request.QNAME_GETRESOURCEPROPERTY);
    if (!qname.namespace) qname.namespace = '';
    if (!qname.prefix) qname.prefix = 'ns';
    method.declare_namespace(qname);
    method.set_value(qname.value_of());
  }
};

Listing 7에는 WSRF.Resource 객체에서 온 코드 스니펫이 포함된다. 여러분이 보는 것은 WS.Call 객체의 생성, 올바른 SOAP 메시지 헤더를 설정하는데 사용될 WSA.Handler 객체 준비, WSRF.Request.GetResourceProperty 래퍼 객체의 생성, 웹 서비스 연산의 호출이다.


Listing 7. WSRF GetResourceProperty 호출하기
                get_resource_property : function(qname, callback) {
  var call = new WS.Call(this.address);
  var handler = new WSA.Handler();
  var wsactx = new WSA.MessageContext(this.epr);
  handler.set_context(wsactx);
  call.add_handler(handler);
  var req = new WSRF.Request.GetResourceProperty(qname);
  call.invoke(req.envelope, callback);
}

WS-ResourceFramework Web service에 대한 GetResourceProperty 연산을 호출하려면, 이 애플리케이션은 검색된 프로퍼티를 구분하는 대상 WS-Resource 와 WS.QName 객체용 EndpointReference를 제공하면 된다. (Listing 8)


Listing 8. 정리
                var ADDRESS = 'http://localhost:9080/SoapAjax2/services/DeviceService'

function getDeviceName(deviceID, container) {
  var epr = new WSA.EndpointReference(ADDRESS);
  var epr_rp = epr.create_reference_parameters();
  epr_rp.create_child(
    new WS.QName(
      'DeviceID',
      'urn:deviceservice')).set_value(deviceID);
  var res = new WSRF.Resource(ADDRESS, epr);
  res.get_resource_property(
    new WS.QName('DeviceName','urn:deviceservice'),
    function(call,envelope) {
      $('soap').innerHTML = arguments[2].escapeHTML();
    }
  );
}

Listing 8은 HTML 페이지 내의 어느 곳에서나 호출될 수 있도록 WS-Resource에 대한 호출을 함수로 래핑한다. Listing 9id라고 하는 인풋 필드에서 device id로 전달되는 버튼을 제공하고 응답 SOAP Envelope를 result라고 하는 div 엘리먼트에 디스플레이 한다.


Listing 9. getDeviceName 호출하기
                <input 
  value="Invoke the Web Service" 
  type="button" 
  onclick="getDeviceName($('id').value,$('result'))" />


다음 단계

이 글에서는 본 시리즈 Part 1에 소개된 Ajax 웹 서비스 클라이언트가 확장되어 Web Services Addressing과 Web Services Resource Framework 같은 웹 서비스 표준을 지원하는 방법을 살펴보았다. 다음 글에서는, Web Services Description Language 지원에 대해 살펴보도록 하겠다.



다운로드 하십시오

설명 이름 크기 다운로드 방식
Sample project ws-wsajax2code.zip 14KB HTTP

다운로드 방식에 대한 정보


참고자료

교육

토론

필자소개

Photo of James M Snell

James Snell은 IBM Emerging Technologies Toolkit 팀의 멤버이다. 이머징 웹 서비스 기술 및 표준 분야에서 오랜 시간 경력을 쌓았고, Atom 1.0 스팩에 기여했다. http://www.ibm.com/developerworks/blogs/dw_blog.jspa?blog=351에서 weblog를 관리하고 있다.

728x90