개발자라면 데이터베이스 테이블을 간단히 업데이트하는 애플리케이션을 빌드할 필요를 느낄 때가 가끔 있다. IBM Mashup Center 버전 2를 사용하면
하나의 INSERT문이나 UPDATE, DELETE SQL문을 실행할 수 있는 관계형(JDBC) 피드를 쉽게 작성할 수 있다.
이 기사에서는 매시업 애플리케이션에서 이러한 피드를 활용할 수 있게 도움을 주는 위젯을 개발하는 방법을 살펴본다.
이 기사에서는 독자가 이미 위젯 작성과 관련된 기본사항은 물론이고 매시업과 피드를 빌드하는 데 익숙하다고 가정한다. 특히, Javascript로 프로그래밍하는 방법을 알아야 하며 IBM Mashup Center를 사용해 본 경험이 있어야 한다. 참고자료 섹션에는 매시업을 빌드하는 몇 가지 기본적인 과정을 이해하는 데 도움이 되는 유용한 기초 정보를 제공하는 두 가지 주제 즉, "Creating a feed from an enterprise database(JDBC)" 및 "Developing widgets for IBM Mashup Center"를 가리키는 링크가 있다.
IBM Mashup Center를 사용하면 관계형 쿼리에 의해 리턴되는 데이터 피드를 작성할 수 있다. 이 피드는 관심이 있는 테이블과 열을 선택하거나 데이터베이스를 쿼리하는 SQL문을 사용하여 작성할 수 있다. 이 피드는 쿼리 결과 세트에서 리턴되는 데이터를 이용하여 작성한다.
IBM Mashup Center 버전 2를 사용하면 SELECT SQL문을 사용할 수 있는 것은 물론이고 INSERT문이나 UPDATE DELETE SQL문을 실행하는 관계형 피드 생성기를
사용할 수 있다. SQL문을 하나만 실행할 수 있기 때문에 이 기능을 복잡한 트랜잭션 처리에 사용하는 것은 적합하지 않다.
그러나 업데이트 기능을 사용하여 다음 사례와 같은 비교적 단순한 시나리오를 대부분 지원할 수 있다.
-
경향 분석을 수행할 스냅샵 생성.
예를 들어, 매일 새로 들어오는 주문의 총수를 리턴하는 피드가 있다고 가정하자.
피드 내용을 실행하여 데이터베이스 테이블에 저장함으로써 주문 도달 경향을 표시하는 피드를 생성할 수 있다.
데이터 매시업 편집기를 사용하면 반복되는 각 항목의 내용을 해당하는 행에
삽입하는FOREACH연산자를 이용하여 데이터 메시업을 작성할 수 있다. - 설명이나 주석 유지. 사용자의 선호도나 의견을 수집할 수 있는 간단한 여론 조사 애플리케이션을 예로 들 수 있다.
- 데이터베이스에서 유지되는 ToDo 목록을 유지보수하는 양식 개발
- 서비스 요청을 제출하는 양식 개발. 이러한 사례로는 건물이나 프린터, IT 시스템을 대상으로 하는 서비스 요청이 있다.
때로는 관계형 업데이트 피드를 사용하는 간단한 매시업 페이지를 작성하는 것이 간단하지 않을 때도 있다. 예를 들면, 사용자 입력을 수집하는 텍스트 상자와 같은 제어를 IBM Mashup Center와 함께 제공된 User Input 위젯을 사용하여 생성할 수 있다. 그러나 User Input 위젯은 관계형 업데이트 피드를 직접 실행할 수 없으며 IBM Mashup Center에는 실행 결과를 적절하게 표시할 수 있는 위젯이 없다.
이 기사에서는 위에 있는 두 번째 시나리오를 통해 이러한 관계형 업데이트 피드를 사용하기 쉽게 해주는 사용자 정의 위젯을 빌드하는 방법을 설명한다. 사용자 정의 위젯은 HTML 양식을 구성 매개변수로 받는다. 이 위젯은 HTML 양식을 렌더링하여 양식 데이터를 관계형 업데이트 피드에 제출하고 업데이트 상태를 표시한다. 이 사용자 정의 위젯은 임의의 HTML 양식 단편을 받기 때문에 HTML 양식의 레이아웃을 세밀하게 제어할 수 있다. 또한, HTML 양식 단편을 사용하면 다양한 페이지에서 사용되는 동일한 양식을 쉽게 작성할 수 있다. 다음 섹션에서는 HTML 양식 위젯의 기능을 설명하기 위해 사용한 것과 동일한 시나리오를 먼저 살펴본다.
설정을 최소화하고 따라 하기 쉽도록 샘플 시나리오에서는 IBM Mashup Center와 함께 설치한 Apache Derby 샘플 데이터베이스와 함께 제공되는 정책 테이블을 사용한다. 그림 1에는 이 기사에서 빌드하는 방법을 살펴볼 샘플 매시업 애플리케이션의 스크린샷이 표시되어 있다. 이 애플리케이션은 매우 간단하며 두 개의 위젯으로 구성되어 있다.
그림 1. Sample Mashup 페이지
위에 있는 그림 1에 표시된 바와 같이 왼쪽에 있는 DataViewer 위젯은 데이터베이스에서 검색한 중요한 정책 목록을 표시하는 데 사용한다. 행(정책)을 선택하면 해당 정책과 관련된 자세한 정보가 오른쪽에 있는 HTML 양식 위젯에 표시된다. 사용자는 주소를 변경할 수 있으며 HTML 양식 위젯에서 Submit 단추를 클릭할 수도 있다. 이 단추는 관계형 업데이트 피드를 실행하도록 구성된다. 실행 결과는 XML 문서로 작성된다. XML 문서는 구문 분석되며 간단한 성공 또는 실패 메시지가 표시된다. 그림 2에는 성공 메시지가 표시되어 있다.
지금 당장 샘플 위젯을 받아서 자신의 양식에 사용하기를 원하면 다운로드 섹션에서 샘플 위젯을 다운로드하여 IBM Mashup Center에 추가한다. 그런 다음에는 위젯을 빌드하는 방법에 대한 설명을 건너뛰어 종합하기 섹션으로 바로 이동한다.
그림 2. 실행에 성공했다는 메시지
위에 있는 기능을 지원하는 위젯을 빌드하기 전에 한 가지 작업을 더 수행해야 하는데, 그것은 관계형 피드를 정의하는 일이다. 다음 섹션에서는 관계형 피드를 어떻게 정의하는지 살펴보도록 하자.
앞서 언급한 바와 같이 따라 하기 쉽도록 이 기사에 있는 샘플 시나리오에서는 IBM Mashup Center 샘플 데이터베이스와 함께 제공된 정책 테이블을 사용한다.
다음 단계를 따라 정책 테이블을 위한 관계형 피드를 작성한다.
- Catalog Home 페이지로 이동하여 Create를 클릭한다.
- New Feed를 선택한다.
- 피드 데이터 소스로 Enterprise Database(JDBC)를 선택한다.
-
정책 테이블이 있는 데이터베이스에 액세스하기 위해 Connection Profile 필드에 있는 Mashup Hub Sample Database를 선택한다.
아직 프로파일이 없는 경우에는 다음과 같은 정보를 입력하여 프로파일을 작성한다.
- Connection Profile Name:
MashupHub Sample Database - Database Type:
Derby Embedded - Connection Type:
Driver Manager (Non-managed Connection) - Database Name:
<installDir>/Hub/installedApps/Mashup Hub.ear/mashuphub-enterprise.war/hubsample
- Connection Profile Name:
-
다음 SQL문을 사용하여 그림 1에 표시된 두 개의 위젯에 해당하는 두 개의 피드를 작성한다.
-
첫 번째 피드는 정책 목록을 표시하는 DataViewer 위젯을 위한 것이다.
state매개변수를 추가하면 특정 상태에 대한 정책을 제거할 수 있다.select * from samples.policyholders where state = ':state'
-
두 번째 피드는 HTML 양식 위젯에서 사용한 관계형 업데이트 피드를 위한 것이다.
update samples.policyholders set address = ':address', city = ':city', state = ':state' where policyid = ':policyid'
이 기사에서는 독자가 이미 IBM Mashup Center를 사용하여 관계형 피드를 작성하는 데 익숙하다고 가정한다. 이러한 쿼리는 모두 매개변수를 사용하므로 SQL문을 JDBC 피드 편집기의 Advanced 상자에 붙여 넣어서 쿼리를 작성해야 한다. 참고자료 섹션에는 관계형 피드를 작성하는 것과 관련된 세부사항을 제공하는 링크가 있다.
-
첫 번째 피드는 정책 목록을 표시하는 DataViewer 위젯을 위한 것이다.
계속 진행하기전에 관계형 업데이트 피드를 사용할 때 특히 유념해야 할 몇 가지 사항을 검토하자.
HTTP GET의 사용참고자료 섹션에 있는 W3C 기사에서 설명하고 있는 바와 같이 "상호작용을 통해, 서비스 등록과 같은 사용자가 이해할 수 있는 방식으로 자원의 상태를 변경"하는 경우에는
HTTP POST를 사용해야 한다. 이렇게 하는 이유는HTTP GETURL은 책갈피에 추가하거나 캐시하기가 쉬워서 우연히 호출되거나 불필요하게 호출될 수 있기 때문이다. 이 기사를 통해 개발하는 HTML 양식 위젯은HTTP POST를 액세스 메소드로 사용한다. 기본적으로 IBM Mashup Center는GET과POST를 모두 지원한다. Feed Detail 페이지에 있는 Access Method 단추를 펼쳐서 GET 선택란을 선택 취소하여HTTP GET액세스를 사용 안함으로 설정할 수 있다.- 중복 행 방지
관계형 업데이트 피드는 하나의 SQL문으로 구성된다. 이 피드에는 오류 처리 로직이 없기 때문에 개발자는 데이터베이스 제한조건에 의존하여 데이터의 시맨틱 무결성을 보장해야 한다. 예를 들어, 중복 행이 없음을 보장하려면 하나의 열을
KEY열로 선언해서 이전에 삽입된 키를 사용하는 행이 삽입되지 않도록 해야 한다. - 캐싱
일반적으로 업데이트를 수행하는 피드는 캐시해서는 안 된다. 그러나 업데이트 피드를 데이터 매시업에서 사용하는 경우에는 예외이다. 편집 과정에서 캐시를 하지 않으면 결과물이 미리 표시될 때마다 업데이트 피드가 실행된다. 기본적으로
source연산자는 한 시간 동안 입력 피드를 캐시한다. 매시업 구성 과정에서는 이 정도 시간이면 충분하다. 완료한 매시업을 저장하기 바로 전에 관계형 업데이트 피드를 사용하는source연산자에서 캐싱을 꺼야 한다.
이제는 이러한 준비 과정에서 벗어나 사용자 정의 HTML 양식 위젯을 빌드할 차례이다.
Mashup Center 위젯은 iWidget 스펙을 따른다. 여기에는 두 가지 유형의 위젯이 있다. 두 위젯은 기본적으로 배치 방법에 차이가 있다.
- WAR 파일 기반 위젯 — 이 위젯에는 서버 기반 컴포넌트가 포함될 수 있으며 이 위젯은 애플리케이션 서버에 배치될 수 있다.
- 경량 위젯 — 이 위젯은 완전히 클라이언트 측에서 실행하며 애플리케이션 서버에 배치할 필요가 없다. 이 기사에서 설명한 샘플 HTML 양식 위젯은 경량 위젯이다.
다음 단계를 따라 IBM Mashup Center 버전 2를 사용하여 샘플 HTML 양식 위젯을 개발하는 과정을 시작해보자.
-
그림 3에 표시된 바와 같이 Mashup Builder 페이지의 오른쪽 모서리 상단에 있는 Go to View를 클릭하고 Create a New Widget... 메뉴를 선택한다.
그림 3. Create Widget 메뉴
- 그림 4에 표시된 바와 같이 Widget Builder 대화 상자에서 Work with the widget editor를 선택한다.
그림 4. Widget Builder 대화 상자
- 다음 대화 상자에서 Create a new project를 선택한다.
-
New Widget Project 대화 상자에서 Create a project from starter files를 선택한다. 이렇게 하면 스켈레톤 위젯 정의 및 카탈로그 파일과 함께 새 프로젝트가
작성된다. 모든 파일은 서버에서 유지보수된다. 그림 5에 표시된 바와 같이 Customized Widget Project 대화 상자의 "Select a file" 아래에는 파일의 이름이
표시되어 있다.
이 목록 아래에 있는 단추를 사용하여 기존의 파일을 선택하여 편집하거나 추가 파일을 프로젝트에 업로드할 수 있다.
그림 5. 사용자 정의한 Widget Project 대화 상자
- 테스트할 준비가 되면 Export를 클릭한 후, Add to palette를 선택한다.
이 기사의 샘플 프로젝트는 매우 간단하며 두 개의 파일만 포함되어 있다.
생성된 catalog.xml 파일을 변경할 필요는 없다. 이 파일은 단지, 위젯이 도구 상자 메뉴에 표시될 때 이 위젯의 이름과 위젯 정의 파일(iWidget.xml)의 위치를 제공할 뿐이다. iWidget.xml 파일에는 로직을 구현하는 Javascript 파일과 위젯이 전송하거나 수신한 정적 이벤트, 보기 모드 레이아웃 및 편집 모드 레이아웃이 지정된다. 이 섹션에서는 이러한 각 영역을 처리하기 위해 iWidget.xml에서 변경해야 하는 사항을 단계별로 살펴본다.
Listing 1에는 iWidget.xml 파일의 루트 요소가 표시되어 있다. iwidget 루트 요소의 iScope 속성이 가장 중요하다. 이 속성은 iWidget 콜백 함수를 구현하는
Javascript 오브젝트를 지정한다. Javascript를 포함하고 있는 파일은 자원 요소를 사용하여 로드한다. 이와 같은 속성에 대한 세부사항은 참고자료 섹션에 있는
위젯 프로그래밍 및 API 문서를 참조한다.
Listing 1. iWidget.xml 헤더
<iw:iwidget name="htmlForm"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
iScope="sample.mashupcenter.htmlForm"
allowInstanceContent="true" supportedModes="view edit"
mode="view" lang="en">
<iw:resource uri="htmlForm.js"/>
|
Listing 2에는 위젯의 사전 정의된 수신 이벤트 하나와 두 개의 송신 이벤트에 대한 정의가 표시되어 있다. 수신 이벤트는 handled 속성과 onEvent 속성을 지정하여 나타낸다. onEvent 속성의
값은 이벤트가 수신될 때 호출할 함수의 이름이다.
published 속성의 값은 발행된 이벤트의 이름을 정의한다.
이 기사 뒷부분에 있는 이벤트 처리 및 생성 섹션에서는 이러한 이벤트가 어떻게 처리되는지 살펴본다.
Listing 2. iWidget.xml 이벤트 스펙
<iw:event id="ResetForm" handled="true" onEvent="handleReset"
eventDescName="desc_handleReset"/>
<iw:eventDescription id="desc_handleReset" payloadType="any" title="Clear all Fields"
description="Clear all the fields in the form" lang="en">
</iw:eventDescription>
<iw:event id="actionSuccessful" eventDescName="desc_actionSuccessful" published="true"/>
<iw:eventDescription id="desc_actionSuccessful" payloadType="text"
description="Number of records updated by WebService" lang="en">
</iw:eventDescription>
<iw:event id="actionFailed" eventDescName="desc_actionFailed" published="true" />
<iw:eventDescription id="desc_actionFailed" payloadType="text"
description="Failure to assign" lang="en">
</iw:eventDescription>
|
마지막으로 이 위젯 정의 파일에서도 보기 모드와 편집 모드의 위젯 레이아웃이 지정된다. 이 레이아웃은 iw:content 요소에 CDATA로 포함된 HTML 마크업으로 지정한다. Listing 3에는
보기 모드를 위한 HTML 마크업이 표시되어 있다. Javascript로 처리할 수 있도록 모든 div 요소에 id를 지정했다.
또한, 각 id 값에는 _IWID_를 접두부로 사용했다.
IBM Mashup Center는 런타임 시, 위젯을 생성하는 과정에서 모든 _IWID_ 접두부를 실제 고유 위젯 인스턴스 ID로 바꾼다.
이렇게 하면 같은 HTML 페이지에 다수의 위젯 인스턴스가 있는 경우에도 각각 고유한 ID를 갖게 된다.
보기 모드 정의에는 두 개의 div 요소가 있다.
id가 _IWID_formdiv인 div 요소는 HTML 양식 단편을 포함하게 되며 초기에는 공백 상태로 존재한다. 다른 div 요소에는 style이 display:none으로 지정되어
있으며 이렇게 하면 div 요소가 보이지 않게 된다.
이 요소는 양식을 제출한 결과를 표시하기 위한 템플리트를 포함하고 있으며 업데이트 피드 중 하나를 실행한 후에 Javascript를 사용하여 이 요소를 보이게 할 수 있다.
Listing 3. iWidget.xml 보기 모드 레이아웃
<iw:content mode="view">
<![CDATA[
<div id='_IWID_formdiv'></div>
<div id='_IWID_resultdiv' style='display:none; font-size:1.3em;'>
<div id="_IWID_ResultXML" ></div>
<br />
<a href=""
onclick="javascript:iContext.iScope().showFormAndHideResult();return false;">
Back</a>
</div>
]]>
</iw:content>
|
편집 모드 섹션에는 텍스트 영역 하나와 텍스트 상자 세 개가 있는 양식의 코드가 있다.
편집 모드 섹션은 사용자가 Edit Settings를 클릭할 때 표시된다. 텍스트 영역은 HTML 양식 단편을 입력하는 데 사용된다. 세 개의 텍스트 상자는 세 개의 URL을 입력하기 위한 것이다. 섹션의
뒷부분에서는 이러한 URL을 양식에 있는 단추에 연결하는 방법을 설명하게 된다. URL 값은 양식의 method 속성에 입력할 값과 동일해야 한다.
다시 말해서 이름 값 쌍 앞에 ? 문자가 있는 URL은 제거된다.
htmlForm Edit 대화 상자에는 렌더링된 양식의 스크린샷이 표시된다. 간단히 하기 위해 이 기사에 편집 모드 HTML 레이아웃을 전부 전재하지는 않는다. 이 레이아웃은 참고자료 섹션에 있는 해당 링크에서 다운로드할 수 있는 완전한 위젯 패키지에 포함되어 있다.
Javascript 구현 파일의 이름은 htmlForm.js로 지정된다.
이 파일은 load, unload, view, edit 및 기타 사용자 정의 이벤트와 같은 표준 이벤트와 서버 통신을 처리하는 Dojo 클래스이다.
이제 이 파일에 포함된 함수에 대한 개요를 간단히 살펴보자.
onLoad— 이 함수에는 초기화 코드가 삽입된다. 일반적으로 이 함수에는 앞서 Edit Settings 대화 상자를 호출하는 과정에서 저장한 구성 정보를 가져오는 기능이 포함된다.보기와 편집 모드의 HTML 마크업에 있는 모든
id속성에는 위젯이 작성될 때 실제 위젯 인스턴스id로 바뀌는_IWID_접두부가 포함되어 있다는 점을 상기해보자. 이러한 사실은 Javascript 코드에서id로 식별하는 HTML 요소를 가져올 수 있으려면iContext오브젝트의 인스턴스 위젯id를 사용하여 실제id를 구성해야 한다는 점을 의미한다. Listing 4에서는 위젯 구성 데이터를iContext와 연관된 위젯attributes오브젝트에서 가져온다.
Listing 4.onLoad함수onLoad: function() { this.uid = "_" + this.iContext.widgetId + "_"; this.formDivNode = dojo.byId(this.uid + 'formdiv'); this.resultNode = dojo.byId(this.uid + 'resultdiv'); // load attributes var attributes = this.iContext.getiWidgetAttributes(); this.formHtml = attributes.getItemValue( "formHtml" ); :::::::::::::::::::::::: },
onUnload— 이 함수는 페이지가 전환되기 바로 전에 호출된다. 일반적으로 정리 과정이 필요 없는 경우에는 이 함수를 구현하지 않아도 된다. 그러나 Dojo V1.3 Dijit id는 유일해야 하고 페이지 간에 전환될 때 정리 과정에서 자동으로 제거되지 않기 때문에 정리 작업을 직접 수행해야 한다.
Listing 5.onUnload함수onUnload: function() { // need to clear all existing dijits (to free up id's) if ( this.formDijit != null ) this.formDijit.destroyRecursive( false ); },
onview— 이 함수는 위젯이 표시될 때마다 호출된다. 위젯을 구성하지 않은 경우(페이지에 처음 위젯을 끌어 놓은 경우), 샘플 위젯에는 기본 메시지가 표시된다. 다른 함수는 다음 섹션에서 자세하게 설명한다.
Listing 6.onview함수onview: function() { if ( this.formHtml == null || this.formHtml.length <= 0 ) { this.formDivNode.innerHTML = "Switch To Edit to specify HTML form"; } else if ( this.viewContent.length <= 0 ) { this.displayForm(); this.reCreateEvents( ); } // else form already there, no need to do anything },
onedit— 이 함수는 Edit Settings를 클릭할 때 호출된다. Listing 7에 있는 코드는 Edit Settings 대화 상자를 이전 호출 과정에서 사용자가 입력한 값으로 미리 채운다.
Listing 7.onedit함수onedit: function() { dojo.byId( this.uid + "formHtml" ).value = this.formHtml; ::::::::::::::::::::::::::::::::::: },
saveConfigData— 이 함수는 내장 이벤트가 아니다.이 함수는 특정 위젯을 위한 함수로 편집 모드 HTML 마크업의 Save 단추onclick메소드에서 지정한다. Listing 8에 있는 코드는 단지 Edit Settings 대화 상자에서 사용자가 최근에 입력한 값을 가져와서 저장한다.onModeChanged이벤트는 종료할 위젯 런타임을 Edit Settings 대화 상자에 알리기 위해 사용한다.
Listing 8.saveConfigData함수saveConfigData: function() { this.formHtml = dojo.byId( this.uid + "formHtml" ).value; :::::::::::::::::::::::::::::::::::::::::::::::::: this.iContext.iEvents.fireEvent("onModeChanged", null, "{newMode:'view'}"); var attributes = this.iContext.getiWidgetAttributes(); attributes.setItemValue("formHtml" , this.formHtml ); :::::::::::::::::::::::::::::::::::::::::::::::::: attributes.save(); },
참고자료 섹션에는 완전한 위젯 패키지를 다운로드할 수 있는 링크가 있다. 이제까지 모든 위젯에서 공통으로 사용하는 함수를 살펴보았으므로 다음 섹션에서는 샘플 위젯에 고유하게 사용된 함수를 살펴보도록 하자.
위젯을 사용하려면 HTML 양식을 제공해야 한다.
원하는 편집기나 코드 생성 도구를 사용하여 양식을 작성할 수 있다. HTML 양식을 작성한 후에는 양식의 각 입력 필드에 적합한 dojotype 속성을 지정했는지 확인한다. (관련 예제는
종합하기 섹션에 있는 샘플 HTML Listing을 참조한다.)
양식에는 다양한 단추가 있을 수 있다. 단추를 활성화하려면 다음과 같은 값으로 정의된 onclick 속성을 단추에 지정해야 한다.
onclick="_${widgetId}_iContext.iScope().submit('formUrl1');"
|
위에 있는 것은 위젯의 Javascript 파일에서 정의한 submit 함수를 호출하는 구문이다. submit 함수를 처리하는 방법은 양식 제출 처리하기 섹션에서 세부적으로
설명한다. 지금은 위 예제에 있는 ${widgetId} 서브스트링을 해당 위젯의 실제 id로 바꾸어 이 예제가 올바른 Javascript 구문이 되도록 한다. 이렇게 하는 방법은 다음에서 살펴본다.
Edit Settings 대화 상자에 붙여 넣은 HTML 양식 단편을 표시하려면 Listing 9에 표시된 바와 같이 iWidget.xml 보기 모드 레이아웃 플레이스홀더 div의
innerHTML에 HTML 문자열을 할당한다. 그러나 이렇게 하려면 ${widgetId} 문자열을 실제 위젯 id로 바꾸어야 한다. Dojo 문자열 유틸리티 함수 substitute를 호출하여 이 작업을 수행한다.
Listing 9에도 이 함수가 표시되어 있다.
Listing 9에 있는 코드에서 마지막으로 주목해야 할 사항은 양식에 Dojo Dijit가 포함되어 있으므로 Dojo parse 메소드를 호출하여 Dojo 작동이 효력을
미치도록 해야 한다는 점이다.
Listing 9.
displayForm 함수
displayForm: function()
{
// fix up button onclick action to point to submit method of this widget.
this.viewContent = dojo.string.substitute( this.formHtml
, { widgetId: this.iContext.widgetId });
"
// Add form content to the view content root node.
if ( this.formDijit != null ) // need to clear all existing dijits (to free up id's)
this.formDijit.destroyRecursive( false );
this.formDivNode.innerHTML = this.viewContent;
// Parse dojo components to display Dojo widgets
dojo.parser.parse( this.formDivNode );
this.formDijit = this.getFormDijit( this.formDivNode );
},
|
샘플 HTML 양식 위젯의 한 가지 중요한 특징은 위젯에 데이터를 연결할 수 있다는 점이다. 샘플 시나리오 섹션에서 설명한 바와 같이 DataViewer 위젯의 행을 클릭하면 이 행의 열이 위젯의 양식 입력 필드에 전달된다. 양식마다 양식 입력 필드가 다르기 때문에 iWidget.xml 이벤트 스펙 섹션에서 두 개의 송신 이벤트와 사전 정의된 수신 이벤트를 대상으로 했던 것과 같이 입력 양식 필드의 수신 이벤트를 iWidget.xml에서 정적으로 정의할 수는 없다.
Listing 10에 표시된 바와 같이 각 양식 입력 필드의 이벤트를 동적으로 작성하려면 먼저, 모든 양식 입력 필드를 위해 제공된 HTML을 구문 분석해야 한다.
Listing 10.
createEventsForFields 함수
createEventsForFields : function( )
{
this.eventNames = [];
this.dijitMap = {};
var children = this.formDijit.getChildren();
for (var i = 0 ; i < children.length ; i++ ) {
var widget = children[i];
var name = widget.attr( 'name' );
if ( name == null || name.length == 0 )
continue; // skip over unnamed form input fields
if ( widget.type == 'radio' && widget.checked == false )
continue; // for radio button, pick the one that is true
|
양식 입력 필드를 식별한 후에는 Listing 11에 표시된 바와 같이 동일한 이름으로 양식 입력 필드의 이벤트를 작성한다.
Listing 11. 동적으로 이벤트 작성하기
this.eventNames.push( name );
this._createEvent({
name : name,
type: "any",
isHandled : true,
handlingFn : dojo.hitch(this, this.handleEvent )
});
|
Listing 12에 표시된 바와 같이 for 루프의 마지막 부분에서는 dijitMap에 각 이벤트를 추가한다. 나중에 이 맵을 사용하여 이벤트가 호출될 때 올바른 이벤트가
시작되도록 한다.
Listing 12. 이벤트 이름을 저장할
dijitMap// will also create dijit mapping to process event this.dijitMap[ name ] = widget; |
다음에는 이벤트가 개시될 때 이를 처리하는 코드를 삽입해야 한다. 위에 있는 특정 이벤트 중에서 하나가 위젯에 연결되면, dijitMap 코드를 이용하여 올바른 양식 입력 필드를 찾기 위해 이벤트 이름을 사용한다. 양식 입력 필드가 널(NULL)이 아니면 Listing 14에서와 같이 수신한 페이로드를 위젯 값으로 설정한다.
Listing 14.
handleEvent 함수
handleEvent: function(iEvent){
::::::::::::::::::::::::::::::::::::::::::::::::::
var evtname = iEvent.name;
var widget = this.dijitMap[ evtname ];
if ( widget != null )
widget.setValue( iEvent.payload );
}
|
HTML 양식 표시하기 섹션에서 언급한 바와 같이 HTML 양식 단편에 있는 단추에는 submit 함수를 명시적으로 호출하는 기능이 있어야 한다.
이 단추를 눌렀을 때 htmlForm Edit 대화 상자에서 정의한 피드 URL 중 어느 것을 실행할 것인지는 submit 함수의 인수로 정의한다. Listing 15에 표시된 바와 같이
인수는 다음 문자열 중의 하나가 된다.
-
formUrl1— First form method 필드에 입력한 피드 URL을 실행한다. -
formUrl2— Second form method 필드에 입력한 피드 URL을 실행한다. -
formUrl3— Third form method 필드에 입력한 피드 URL을 실행한다.
Listing 15.
submit 함수
submit: function( action ) {
::::::::::::::::::::::::::::::::::::::::::::::::::
var actionURL = "";
//Specify the root URL of the feed that you want to trigger:
if ( action == 'formUrl1' ) {
if ( this.formUrl1 && this.formUrl1.length > 0 )
actionURL = this.formUrl1;
} else if ( action == 'formUrl2' ) {
if ( this.formUrl2 && this.formUrl2.length > 0 )
actionURL = this.formUrl2;
} else if ( action == 'formUrl3' ) {
if ( this.formUrl3 && this.formUrl3.length > 0 )
actionURL = this.formUrl3;
::::::::::::::::::::::::::::::::::::::::::::::::::
|
선택한 조치에 올바른 기본 URL을 지정했으므로 이제 사용자가 양식에 입력한 값을 수집해야 한다. 이 작업은 collectNVP 함수를 사용하여 수행한다. Listing 16에
표시된 바와 같이 다양한 입력 양식 필드에서 값을 가져오는 성가진 작업은 Dojo 라이브러리 양식 Dijit getValues 함수를 사용하여 처리한다. 코드에서
루프를 사용하여 필드를 처리하고 필드 값을 인코딩하여 올바르지 않은 문자가 있는지 확인해야 한다.
Listing 16.
collectNVP 함수
collectNVP: function( ) {
this.debugTrace( "collectNVP entered" );
var formData = "";
var temp = this.formDijit.getValues();
for ( var name in temp ) {
if ( formData.length > 1 ) formData += '&';
//Encode the key and value, to make sure there are no invalid characters.
formData += encodeURI( name );
formData += "=";
// encodeURI( value ); doesn't escape &, ...
var value = temp[ name ];
formData += escape( value );
}
return formData;
}
|
양식 데이터와 기본 URL을 수집한 후, Dojo 라이브러리 xhrPost 메소드를 사용하여 Ajax 호출을 제출한다. JDBC 피드 작성하기 섹션에서 언급한 바와 같이
HTTP GET 대신 HTTP Post를 액세스 메소드로 사용하여 관계형 업데이트 피드를 실행한다.
Listing 17에 표시된 바와 같이 xhrPost 메소드의 인수에서 로드(성공) 및 오류 케이스를 처리하는 콜백 함수를 지정한다. 이러한 콜백 함수에 대한 세부사항은
다음 두 섹션에서 설명한다. urlToLoad 인수에는 기본 URL이나 양식 메소드가 포함되어 있으며 이 인수를 직접 사용하지는 않는다. 이는 브라우저의
샌드박스 규칙에 따라 사용자가 제공한 기본 URL이 Mashup Server AJAX 프록시를 거치도록 경로를 재지정해야 하기 때문이다.
이 작업은 iContext를 통해 액세스할 수 있는 reWriteURI 함수를 호출하여 수행할 수 있다.
Listing 17. 양식 제출
// Using POST for update type URL
submitUrl: function(urlToLoad, formdata )
var location = this.iContext.io.rewriteURI( urlToLoad );
dojo.xhrPost({
url : location,
postData: formdata,
load : dojo.hitch( this, this.handleFeedContent ),
error : dojo.hitch( this, this.handleErrorResponse ),
handleAs: "xml",
sync : true
});
}
|
xhrPost Ajax 호출에서 지정하였듯이 handleFeedConent 함수는 양식이 성공적으로 제출되었을 때 호출된다. 이 위젯은 MashupCenter 관계형(JDBC) 업데이트 피드에
대해서만 작동하도록 설계되었다.
이 피드는 그림 6에 표시된 XML 응답을 리턴한다. 다른 응답이 수신되면 프로그램은 "지원되지 않는 결과 양식"이 리턴되었다는 메시지를 표시한다.
그림 6. 성공적인 업데이트 피드 응답
Listing 18에 표시된 바와 같이 올바른 양식이 리턴되면 handleFeedConent 함수는 "Operation successful" 메시지와 성공적으로 삽입된 행 수를 표시한다.
또한, 이 함수는 앞서 위젯 정의 파일 섹션에서 설명한 iWidget.xml 파일에서 정적으로 정의한 actionSuccessful 이벤트를 실행한다.
Listing 18. 성공적인 양식 제출
handleFeedContent: function(data){
::::::::::::::::::::::::::::::::::::::::::::::::::
resultHTML += "Operation successful.";
resultHTML += rowCount;
resultHTML += " record(s) changed.";
this.iContext.iEvents.fireEvent("actionSuccessful", null, "" );
::::::::::::::::::::::::::::::::::::::::::::::::::
|
Listing 19에 표시된 바와 같이 MashupCenter Relational(JDBC) 플러그인 호출이 오류(-1)를 리턴하면, handleFeedConent 함수는 systemmsg 요소에서
리턴된 메시지가 포함된 결과 문자열을 생성한다. 또한, 이 함수는 iWidget.xml 이벤트 스펙 섹션에서 정의한 actionFailed 이벤트를 실행한다.
Listing 19. 성공적인 양식 제출 후 리턴된 오류 메시지
handleFeedContent: function(data){
::::::::::::::::::::::::::::::::::::::::::::::::::
if ( rowCount == "-1" ) {
var msg = "Unknown error. <br><br>";
var msgList = dojo.query( "systemmsg" , data );
if ( msgList && msgList[0] )
msg = dojox.xml.parser.textContent( msgList[0] );
resultHTML += msg;
this.iContext.iEvents.fireEvent("actionFailed", null, rowCount );
|
양식 데이터를 제출하는 과정에서 발생하는 오류 처리하기
Listing 20에 표시된 바와 같이 양식 데이터를 제출할 때 오류가 발생하면 handleErrorResponse 함수는 displayResult 함수를 호출하여 통신 실패로 인해 리턴된 결과를 표시한다.
Listing 20.
handleErrorResponse 함수
handleErrorResponse: function(data)
{
this.debugTrace( "handleErrorResponse entered data=" + data );
this.displayResult( data );
}
|
양식이 성공적으로 제출되었건 오류가 발생했건 관계없이 displayResult 함수를 사용하여 양식의 크기를 기억하고, 현재의 입력 양식을 숨기고, 양식 제출
결과를 표시한다.
처음에는 iWidget.xml 보기 모드 레이아웃에서 resultNode에 대한 style을 display:none으로 정의했기 때문에 resultNode가 표시되지 않았다.
Listing 21에 표시된 바와 같이 displayResult 함수에서 style.display 정의를 block으로 변경하여 resultNode를 표시할 수 있다.
Listing 21.
displayResult 함수
displayResult: function(data)
{
// save the current size
var formSize = dojo.contentBox( this.formDivNode );
// hide the form
this.formDivNode.style.display = "none";
// show the result
this.resultNode.style.display = "block";
dojo.contentBox( this.resultNode, formSize );
var resultXmlNode = dojo.byId(this.uid + 'ResultXML');
resultXmlNode.innerHTML = data;
},
|
resultdiv에는 showFromAndHideResult 함수를 호출하는 백링크가 포함된다.
Listing 22에 표시된 바와 같이 이 함수는 resultdiv를 숨기고 양식을 다시 표시한다.
Listing 22.
showFormAndHideResult 함수
//Clear data, hide the result node, and show the form again.
showFormAndHideResult: function()
{
this.debugTrace( "handleFeedContent entered" );
this.formDivNode.style.display = "block";
// clear any message text
var resultXmlNode = dojo.byId(this.uid + 'ResultXML');
resultXmlNode.innerHTML = "";
this.resultNode.style.display = "none";
},
|
이제 HTML 양식 위젯을 샘플 시나리오 섹션에서 살펴본 샘플 매시업 애플리케이션에 통합할 차례이다.
먼저, 정책 레코드를 위한 HTML 양식 단편을 처리하자. Listing 23과 같이 HTML 테이블을 사용하여 텍스트 상자를 구성한다.
앞서 살펴본 바와 같이 이 양식에서는 Dojo Dijit를 사용해야 한다. 보통의 HTML 페이지에서와 마찬가지로 입력 양식 필드에는 관계형 업데이트 피드에서 사용한
매개변수의 이름과 일치하는 이름을 지정해야 한다.
이 피드는 앞서 JDBC 피드 작성하기 섹션에서 작성한 바 있다.
HTML 양식에는 INSERT 조치나, UPDATE, DELETE 조치를 조합한 것에 해당하는 다양한 단추가 있을 수 있다.
추가로 확장할 수 있다는 사실을 보여주기 위해 이 양식에는 기능이 지정되지 않은 단추가 포함되어 있다. 이 단추에는 대응하는 피드가 없으며 이 단추의 레이블은
Delete Policy로 지정된다.
Listing 23. 정책 HTML 양식
<form dojotype="dijit.form.Form" style="font-size:1.3em;">
<div style='background-color:#D1EACC; height:4em; padding-top:5px; padding-bottom:5px'>
<center><h3>Policy Address Update and Delete Form</h3></center>
</div>
<br>
<table>
<tr><td>Policy Id:</td>
<td><input type="text" name="policyid" dojotype="dijit.form.TextBox"
style="width: 6em;" readonly /></td>
<td></td>
<td></td>
</tr>
:::::::::::::::::::::::::::::::::::::::::
<tr>
<td></td>
<td colspan='4' align='right'>
<button dojotype="dijit.form.Button" value="formUrl1">Update Address
onclick="_${widgetId}_iContext.iScope().submit('formUrl1');"
</button>
<button dojotype="dijit.form.Button" value="formUrl2">Delete policy</button>
</td>
</tr>
</table>
</form>
|
그림 7과 같은 htmlForm Edit 대화 상자로 이동하여 HTML 양식 단편을 Form HTML 필드에 붙여 넣고 JDBC 피드 작성하기 섹션에서 작성한 관계형 피드를 해당 양식 메소드 필드에 붙여 넣는다. Save를 클릭하여 위젯 구성을 완료한다.
그림 7. htmlForm Edit 대화 상자
모든 입력 필드는 DataViewer 위젯에서 행을 선택할 때 채워진다. 이벤트 처리 및 생성 섹션에서 설명한 바와 같이 HTML 양식 위젯은 각 입력 양식 필드의 수신 이벤트를 동적으로 작성한다. 따라서 개발자는 수신 이벤트를 DataViewer 송신 이벤트에 연결하기만 하면 된다. 그림 8에는 생성된 수신 이벤트 중의 하나를 DataViewer 위젯의 해당 송신 이벤트에 연결하는 과정이 표시되어 있다.
그림 8. 수신 이벤트 연결
마지막으로 HTML 양식 위젯의 actionSuccessful 이벤트를 URL Customizer 위젯에 연결해야 한다. URL Customizer 위젯은 DataViewer 위젯에 연결되어
DataViewer 위젯에 사용한 것과 같은 URL을 사용하도록 구성된다. 그림 9에는 URL Customizer와 연결 그래프가 표시되어 있다.
그림 9. URL Customizer 및 연결 그래프
업데이트 조작이 성공적으로 완료되면 이벤트가 실행되고 DataViewer가 자동으로 새로 고쳐진다. 샘플 애플리케이션에서는 업데이트 조작을 통해 DataViewer에 표시되는 내용을 변경하지 않으며 이러한 동작이 단지 예로 든 것에 불과하다.
그림 10. 송신 이벤트 연결
이 기사에서는 동적 이벤트 등록과 서버 통신을 포함하여 위젯을 구성하는 기본적인 단계를 살펴보았다. 이 기사에서 배운 내용을 실제로 해보고 확장하려면 관계형 업데이트 피드에 대한 오류를 더욱 정교하게 처리하도록 위젯을 개선해야 한다.
때로는 매시업 애플리케이션이 서로 다른 소스에서 가져온 정보를 표시하는 대시보드가 되기도 한다. 이 위젯과 함께 관계형 업데이트 피드를 사용하면 보고 기능뿐만 아니라 간단한 업데이트 조치를 수행하는 수단을 제공하는 매시업 애플리케이션을 신속하게 빌드할 수 있다.
| 설명 | 이름 | 크기 | 다운로드 방식 |
|---|---|---|---|
| Sample code for this article | HTMLformWidget.zip | 8KB | HTTP |
교육
- Setting up an IBM Rational Application Developer-based iWidget development environment 기사를 읽어보고 Widget Builder 외에 다른 개발 도구를 사용하는 방법을 배우자.
- Integrating Flex applications with IBM Mashup Center 기사를 읽어보고 Flex를 사용하여 위젯을 개발하는 방법을 배우자.
- Creating a feed from an enterprise database (JDBC) : Mashup Center 2.0.0.2 기사를 읽어보고 관계형 피드를 처리하는 방법을 배우자.
- Solution development using DB2 and InfoSphere MashupHub 기사를 읽어보고 InfoSphere MashupHub에서 다양한 피드를 작성하여 DB2 데이터베이스와 함께
사용하는 방법을 배우자.
- Dojo에 관해 배우려면 Official Dojo Documentation 웹 페이지를 참조한다.
- Dojo Dijit Reference Guide를 참조하여 사용자 정의하기 쉽고 액세스가 가능한 Dojo의 Themeable UI 라이브러리인 Dijit에 관해 자세히 배우고 사용자 정의 양식을
작성하는 데 사용할 수 있는 위젯 목록을 확인하자.
- Dojo의 유효성 검증 텍스트 상자 dijit를 읽어보고 텍스트 필드에 맞는 클라이언트 사이트 양식 유효성 검증 기능을 입력 양식에 추가하자.
- 사용자 정의 위젯을 작성하는 방법을 소개하는 유익한 기사인 Developing widgets for IBM Mashup Center 1.0을 읽어보자.
- 최신 위젯 프로그래밍과 API 문서 링크를 따라가 보자.
- 자원의 URI 주소 지정 가능성과 HTTP GET이나 POST 메소드 선택 간의 관계에 대한 토론에 대해서는 URIs, Addressability, and the use of HTTP GET and POST 문서를 읽어보자.
제품 및 기술 얻기
- IBM Mashup Center에 대한 실습 경험을 얻으려면 Lotus greenhouse를 방문한다.
- developerWorks에서 IBM Mashup Center 무료 시험판을 다운로드하자.
토론
Louis Mau is part of the InfoSphere MashupHub development team. His current focus is to help customers build situational applications using the IBM Mashup Center. Prior to this role, he was the architect for DB2 Everyplace Sync Server, which helps synchronize data from enterprise databases onto a small foot print database running on mobile devices.
Klaus Roder is a Solutions Architect for IBM Mashup Center at the IBM Silicon Valley Lab. His current focus is developing and deploying enterprise mashups with customers using IBM Mashup Center. Prior to his current role, Klaus worked on the IBM Web Interface for Content Management (WEBI) project and the WebSphere Information Integrator Content Edition (IICE) development team. Klaus holds a Masters degree in Computer Science from the University of Applied Science in Würzburg and is a member of the San Francisco Bay Area ACM chapter.