4.화면 개발 실습

4.1화면 구성

넥사크로를 이용하여 사원관리 화면을 만들어 보면서, 컴포넌트 사용법과 데이터 처리 방식에 대해 알아봅니다.

소스참고
nexacro17_Education_Materials\Sample\EduProject\Form\Form_Emp.xfdl

그림 4-101_화면예

1헤더 영역
화면의 타이틀과 조회, 입력, 삭제, 저장 버튼으로 구성 합니다.

2조회 영역
부서코드와 성별을 조회 조건으로 구성 합니다.
부서코드는 팝업창을 통해서 검색 가능하게 구성 하며, reset 버튼을 이용하여 조회 조건을 초기화 합니다.

3목록 영역
조회 데이터를 목록 형태로 표현 합니다.

4상세 영역
목록에서 선택하는 데이터에 대해 상세 정보를 보여 주며, 편집이 가능하게 구성 합니다.

4.2테이블 레이아웃

사원관리 화면에서 사용하는 테이블 레이아웃은 아래와 같습니다.

표 4-1사원 테이블(TB_EMP)

컬럼명

타입

셜명

비고

EMPL_ID

varchar2(5)

사원번호

영문 대문자 2자리 숫자 3자리로 구성(AB123)

FULL_NAME

varchar2(50)

성명


DEPT_CD

varchar2(2)

부서코드


POS_CD

varchar2(2)

직급코드


HIRE_DATE

varchar2(8)

입사일


SALARY

integer(12)

연봉


GENDER

varchar2(1)

성별코드

M(male) / F(Female)

MARRIED

varchar2(5)

결혼여부

1(true) / 0(false)

MEMO

varchar2(100)

비고사항


CREATE TABLE [TB_EMP](
    [EMPL_ID] VARCHAR2(5), 
    [FULL_NAME] VARCHAR2(50), 
    [DEPT_CD] VARCHAR2(2), 
    [POS_CD] VARCHAR2(2), 
    [HIRE_DATE] VARCHAR2(8), 
    [GENDER] VARCHAR2(1), 
    [MARRIED] VARCHAR2(5), 
    [SALARY] INTEGER(12), 
    [MEMO] TEXT);
표 4-2부서 테이블(TB_DEPT)

컬럼명

타입

셜명

비고

DEPT_CD

varchar2(2)

부서코드


DEPT_NAME

varchar2(50)

부서명


CREATE TABLE [TB_DEPT](
    [DEPT_CD] VARCHAR2(2), 
    [DEPT_NAME] VARCHAR2(50));
표 4-3직급 테이블(TB_POS)

컬럼명

타입

셜명

비고

POS_CD

varchar2(2)

직급코드


POS_NAME

varchar2(50)

직급명


CREATE TABLE [TB_POS](
    [POS_CD] VARCHAR2(2), 
    [POS_NAME] VARCHAR2(50));

4.3화면개발

4.3.1화면 레이아웃 구성

신규 화면을 생성합니다.
[Menu] File > New > Form (.xfdl)

그림 4-202_컴포넌트

헤더 영역과 화면 레이아웃을 위한 컴포넌트를 생성 후 아래와 같이 속성을 변경합니다.

그림 4-302_컴포넌트

컴포넌트

설명

속성

속성값

1 Static

제목 영역

id

st_title

text

Employees

2 Button

조회 버튼

id

btn_retrieve

text

Retrive

입력 버튼

id

btn_add

text

Add

삭제 버튼

id

btn_del

text

Delete

저장 버튼

id

btn_save

text

Save

3 Div

조회조건 영역

id

div_search

border

1px solid #9c9c9c

4 Grid

데이터 목록 영역

id

grd_list

5 Div

상세 영역

id

div_detail

border

1px solid #9c9c9c

4.3.2Dataset 생성

Dataset은 화면에서 사용하는 데이터를 테이블 형태로 관리하는 Object 입니다.
화면 하단의 Invisible Object 창에 생성이 되며 각각의 아이디를 아래와 같이 변경합니다.

그림 4-402_컴포넌트

컴포넌트

설명

속성

속성값

1 Dataset

사원 데이터

id

ds_emp

부서 코드 데이터

id

ds_dept

직급 코드 데이터

id

ds_pos

생성한 Dataset을 더블클릭 후 화면에서 사용할 테스트용 데이터를 아래와 같은 방법으로 입력합니다.
컬럼과 레코드를 직접 입력

그림 4-502_컴포넌트

샘플 데이터로 추가
데이터셋 편집기의 하단 [Source] 항목을 선택하면 데이터셋 소스 편집기 창이 오픈 됩니다.
하단의 XML형식의 샘플 데이터를 복사하여 해당 창에 붙여넣기 후 OK 버튼을 클릭하시면 샘플 데이터가 추가 됩니다.
샘플 데이터
nexacro17_Education_Materials\Sample\Sample Data\ds_emp.xml

그림 4-602_컴포넌트

<ColumnInfo>
  <Column id="EMPL_ID" type="STRING" size="10"/>
  <Column id="FULL_NAME" type="STRING" size="50"/>
  <Column id="DEPT_CD" type="STRING" size="10"/>
  <Column id="POS_CD" type="STRING" size="10"/>
  <Column id="HIRE_DATE" type="DATE" size="10"/>
  <Column id="SALARY" type="INT" size="10"/>
  <Column id="GENDER" type="STRING" size="10"/>
  <Column id="MARRIED" type="STRING" size="10"/>
  <Column id="MEMO" type="STRING" size="10"/>
</ColumnInfo>
<Rows>
  <Row>
    <Col id="EMPL_ID">AA001</Col>
    <Col id="FULL_NAME">Olivia</Col>
    <Col id="DEPT_CD">01</Col>
    <Col id="POS_CD">03</Col>
    <Col id="HIRE_DATE">20101003</Col>
    <Col id="SALARY">83000</Col>
    <Col id="GENDER">W</Col>
    <Col id="MARRIED">true</Col>
    <Col id="MEMO">ivory</Col>
  </Row>
  <Row>
    <Col id="EMPL_ID">AA002</Col>
    <Col id="FULL_NAME">John</Col>
    <Col id="DEPT_CD">02</Col>
    <Col id="POS_CD">04</Col>
    <Col id="HIRE_DATE">20051011</Col>
    <Col id="SALARY">76000</Col>
    <Col id="GENDER">M</Col>
    <Col id="MARRIED">false</Col>
    <Col id="MEMO">greenyellow</Col>
  </Row>
  <Row>
    <Col id="EMPL_ID">BB001</Col>
    <Col id="FULL_NAME">Jackson</Col>
    <Col id="DEPT_CD">03</Col>
    <Col id="POS_CD">03</Col>
    <Col id="HIRE_DATE">20070206</Col>
    <Col id="SALARY">95000</Col>
    <Col id="GENDER">M</Col>
    <Col id="MARRIED">true</Col>
    <Col id="MEMO">aliceblue</Col>
  </Row>
  <Row>
    <Col id="EMPL_ID">BB002</Col>
    <Col id="FULL_NAME">Maia</Col>
    <Col id="DEPT_CD">04</Col>
    <Col id="POS_CD">02</Col>
    <Col id="HIRE_DATE">20090512</Col>
    <Col id="SALARY">60000</Col>
    <Col id="GENDER">W</Col>
    <Col id="MARRIED">false</Col>
    <Col id="MEMO">ivory</Col>
  </Row>
  <Row>
    <Col id="EMPL_ID">CC001</Col>
    <Col id="FULL_NAME">Adam</Col>
    <Col id="DEPT_CD">01</Col>
    <Col id="POS_CD">04</Col>
    <Col id="HIRE_DATE">20010109</Col>
    <Col id="SALARY">88000</Col>
    <Col id="GENDER">M</Col>
    <Col id="MARRIED">true</Col>
    <Col id="MEMO">greenyellow</Col>
  </Row>
  <Row>
    <Col id="EMPL_ID">DD001</Col>
    <Col id="FULL_NAME">Ray</Col>
    <Col id="DEPT_CD">02</Col>
    <Col id="POS_CD">03</Col>
    <Col id="HIRE_DATE">20160202</Col>
    <Col id="SALARY">60000</Col>
    <Col id="GENDER">M</Col>
    <Col id="MARRIED">true</Col>
    <Col id="MEMO">lightpink</Col>
  </Row>
</Rows>
동일한 방식으로 나머지 데이터셋도 샘플 데이터를 생성 합니다.

그림 4-702_컴포넌트

<ColumnInfo>
  <Column id="DEPT_CD" type="STRING" size="2"/>
  <Column id="DEPT_NAME" type="STRING" size="50"/>
</ColumnInfo>
<Rows>
  <Row>
    <Col id="DEPT_CD">01</Col>
    <Col id="DEPT_NAME">Accounting</Col>
  </Row>
  <Row>
    <Col id="DEPT_CD">02</Col>
    <Col id="DEPT_NAME">HR</Col>
  </Row>
  <Row>
    <Col id="DEPT_CD">03</Col>
    <Col id="DEPT_NAME">Sales</Col>
  </Row>
  <Row>
    <Col id="DEPT_CD">04</Col>
    <Col id="DEPT_NAME">Marketing</Col>
  </Row>
  <Row>
    <Col id="DEPT_CD">05</Col>
    <Col id="DEPT_NAME">Education</Col>
  </Row>
</Rows>

그림 4-802_컴포넌트

<ColumnInfo>
  <Column id="POS_CD" type="string" size="32"/>
  <Column id="POS_NAME" type="string" size="32"/>
</ColumnInfo>
<Rows>
  <Row>
    <Col id="POS_CD">04</Col>
    <Col id="POS_NAME">Officer</Col>
  </Row>
  <Row>
    <Col id="POS_CD">03</Col>
    <Col id="POS_NAME">Assistant Manager</Col>
  </Row>
  <Row>
    <Col id="POS_CD">02</Col>
    <Col id="POS_NAME">Division Manager</Col>
  </Row>
  <Row>
    <Col id="POS_CD">01</Col>
    <Col id="POS_NAME">Chairman</Col>
  </Row>
</Rows>

4.3.3화면 디자인

조회 영역

조회 영역에 사용 할 컴포넌트를 구성합니다.

그림 4-902_컴포넌트

컴포넌트

설명

속성

속성값

1 Static


text

Department

2 Edit

부서코드

id

edt_dept_cd

부서명

id

edt_dept_nm

3 Button

부서 검색 버튼

id

btn_dept

text

find

4 Static


text

Gender

5 Radio

성별

id

rdo_gender

innerdataset

설정1

6 Button

조회조건 초기화 버튼

id

btn_reset

text

reset

설정1


라디오 컴포넌트 항목을 구성할 데이터를 innerdataset 속성에 설정 합니다.


InnerDataset 설정 창에서 하단의 아이콘을 이용하여 빈 로우를 추가 후 코드, 코드명을 입력 합니다.


아래와 같이 innerdataset 속성이 설정 되며,

입력한 코드, 코드명으로 라디오 버튼의 항목이 설정 됩니다.

목록 영역

그리드 컴포넌트를 통해서 데이터를 목록 형태로 출력 합니다.
그리드 컴포넌트를 더블 클릭하여 그리드 편집창을 오픈 합니다. 마우스 우클릭하여 컨텍스트 메뉴를 이용하거나 상단의 아이콘을 통해 그리드를 디자인 합니다.

그림 4-1004_Grid design

1 [Add Head Row] 를 선택합니다. 그리드의 제목이 표현되는 영역입니다.
2 [Add Body Row] 를 선택합니다. 그리드의 데이터가 표현되는 영역입니다.
3 [Add Summary Row] 를 선택합니다. 그리드 하단에 합계, 평균, 갯수 등을 표현하는 영역입니다.
4 [Add Column > Add Body Column] 를 통해 컬럼을 추가합니다.

그림 4-1104_Grid design

Head Row의 각각의 Cell을 선택하여 표현할 데이터의 제목을 입력 합니다. 
Cell의 text속성에 적용합니다.

그림 4-1204_Grid design

상세영역 구성

상세 데이터가 출력될 영역을 구성합니다.

그림 4-1302_컴포넌트

컴포넌트

설명

속성

속성값

1 Static

성명 Label

text

Name

사원번호

text

Emp ID

부서

text

Department

직급

text

Position

성별

text

Gender

결혼여부

text

Married

입사일

text

Hire Date

연봉

text

Annual Salary

비고사항

text

Memo

2 Edit

성명 데이터

id

edt_name

3 MaskEdit


id

msk_id

format

AA-###

type

string

4 Combo

부서 데이터

id

cbo_dept

innerdataset

ds_dept

codecolumn

DEPT_CD

datacolumn

DEPT_NAME

5 ListBox

직급 데이터

id

lst_pos

innerdataset

ds_pos

codecolumn

POS_CD

datacolumn

POS_NAME

6 Radio

성명 데이터

id

rdo_gender

innerdataset

조회영역 설정 동일

7 CheckBox

결혼여부 데이터

id

chk_married

8 Calendar

입사일자

id

cal_date

9 MaskEdit

연봉

id

msk_salary

format

#,###

type

number

10 TextArea

비고사항

id

txt_memo

화면 결과

최종적으로 디자인된 화면 입니다.

그림 4-1402_컴포넌트

4.3.4데이터 바인딩

바인딩(Binding)이란 데이터 컴포넌트와 표현(Presentation) 컴포넌트를 스크립트 코딩 없이 연결하여 데이터를 입출력 하거나 컴포넌트를 동작시키는 방법 입니다.
화면의 스크립트 양을 상당부분 줄여주고, 출력 속도를 높일 수 있으며, 임의의 데이터를 넣어서 동작을 확인하면서 UI/UX 설계도 할 수 있는 기능입니다.

그리드 바인딩

Dataset과 Grid간의 바인딩 처리를 합니다.

방식1 - 그리드 포맷을 유지한 데이터 바인딩

Grid 컴포넌트 Properties창의 binddataset 속성에 'ds_emp'를 지정합니다.

컴포넌트

설명

속성

속성값

4 Grid

데이터 목록 영역

binddataset

ds_emp

아래와 같은 확인 창에서 No를 선택하여, 기존에 작성한 Grid 포맷을 그대로 사용합니다.

그림 4-1510_바인딩_1

Gird를 더블 클릭하여 그리드 편집창을 오픈 합니다. 데이터가 표현되는 body 로우의 첫번째 셀을 선택합니다.
text 속성의 두번째 버튼을 클릭하여 출력하고자 하는 데이터셋 컬럼을 선택합니다.
ID, Dept 컬럼도 동일하게 설정 합니다.

그림 4-1604_Grid design

아래와 같이 기존 그리드 포맷을 유지하면서 데이터가 표현 됩니다.

그림 4-1704_Grid design

방식2 - 그리드 포맷을 새로 생성하여 데이터 바인딩

작업중인 화면의 Objects 항목에 데이터셋 목록이 표현 됩니다.
데이터셋을 선택하여 그리드에 드래그앤드롭하여 적용합니다.

그림 4-1804_Grid design

아래와 같은 확인 창에서 Yes를 선택하여, 데이터셋 컬럼 기준으로 Grid 포맷을 다시 생성 합니다.

그림 4-1910_바인딩_1

아래와 같이 데이터셋 컬럼 기준으로 그리드 포맷이 다시 생성 되며 데이터가 표현 됩니다.

그림 4-2010_바인딩_1

상세영역 바인딩

방식1 - 바인딩 속성을 이용한 바인딩

우측의 Edit 컴포넌트를 선택하고 Properties 창의 Bindable 아이콘을 선택합니다. 
value 속성에 'ds_emp'을 선택하고 우측 컬럼 지정 부분에 'FULL_NAME' 컬럼을 지정합니다.

그림 4-2104_setting column

방식2 - 드래그앤드롭을 이용한 바인딩

'ds_emp' 데이터셋을 확장하면 데이터셋 컬럼 목록이 표현 됩니다.
'EMPL_ID' 컬럼을 선택하여 사원번호가 표현되는 MaskEdit 컴포넌트에 드래그앤드롭하여 적용합니다.

그림 4-2204_setting column

컴포넌트와 데이터셋 컬럼과의 바인딩 정보창이 오픈 됩니다. OK버튼을 선택하여 적용합니다.

그림 4-2304_setting column

같은 방법으로 나머지 컴포넌트에도 각각 바인딩하여 적용 합니다. 
설정이 완료되면 다음과 같은 출력 결과를 확인하실 수 있습니다.

그림 4-2404_setting column

4.3.5조회영역 처리

조회영역의 부서 검색 팝업 창과 성별을 구별하여 조회 할 수 있도록 처리 합니다.

부서 검색 화면

신규 화면을 생성합니다.
[Menu] File > New > Form (.xfdl)

그림 4-2502_컴포넌트

아래와 같이 컴포넌트를 배치 합니다.

그림 4-2602_컴포넌트

컴포넌트

설명

속성

속성값

1 Static

제목 영역

text

Department Search

2 Grid

데이터 목록 영역


grd_list

3 Button

OK버튼

id

btn_ok

text

OK

Cancel버튼

id

btn_cancel

text

Cancel

4 Dataset

부서코드 데이터

id

ds_dept

ds_dept 데이터셋을 더블 클릭 후 아래와 같이 테스트용 데이터를 입력합니다.

그림 4-2702_컴포넌트

<ColumnInfo>
  <Column id="DEPT_CD" type="STRING" size="2"/>
  <Column id="DEPT_NAME" type="STRING" size="50"/>
</ColumnInfo>
<Rows>
  <Row>
    <Col id="DEPT_CD">01</Col>
    <Col id="DEPT_NAME">Accounting</Col>
  </Row>
  <Row>
    <Col id="DEPT_CD">02</Col>
    <Col id="DEPT_NAME">HR</Col>
  </Row>
  <Row>
    <Col id="DEPT_CD">03</Col>
    <Col id="DEPT_NAME">Sales</Col>
  </Row>
  <Row>
    <Col id="DEPT_CD">04</Col>
    <Col id="DEPT_NAME">Marketing</Col>
  </Row>
  <Row>
    <Col id="DEPT_CD">05</Col>
    <Col id="DEPT_NAME">Education</Col>
  </Row>
</Rows>
ds_dept를 그리드에 바인딩하여 데이터를 표현합니다.
최종적으로 아래와 같이 팝업창을 구성 합니다.

그림 4-2802_컴포넌트

부서 검색 팝업 실행

Employees 화면에서 부서 검색 화면을 호출하여 그 결과를 리턴 받는 스크립트를 작성 합니다.
조회영역 '검색' 버튼의 onclick 이벤트를 생성합니다.
이벤트의 빈 영역을 더블클릭하여 자바스크립트 함수를 생성합니다.

그림 4-2902_컴포넌트

부서 검색 화면을 팝업으로 호출 하는 스크립트를 작성 합니다.
// Search Area Dept Popup
this.div_search_btn_dept_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    var nLeft = system.clientToScreenX(this, 10);
    var nTop  = system.clientToScreenY(this, 10);

    var objChild = new ChildFrame("popDept", "absolute", nLeft, nTop, 300, 400);
    objChild.set_formurl("Popup::Pop_DeptSearch.xfdl");
    objChild.set_openalign("center middle");
    objChild.set_dragmovetype("all");  

    objChild.showModal(this.getOwnerFrame()
                     , {}
                     , this
                     , "fn_callback_pop");
};
부서 검색 화면에서 리턴값을 받는 스크립트를 작성합니다.
// Dept Popup Callback
this.fn_callback_pop = function(sPopupId, sReturn)
{
    if(sReturn == undefined){
        sReturn = "";
    }
    if(sPopupId == "popDept")
    {
        if(sReturn.length > 0){
            var arrRtn = sReturn.split("|");
            this.div_search.form.edt_dept_cd.set_value(arrRtn[0]);
            this.div_search.form.edt_dept_nm.set_value(arrRtn[1]);
        }
    }
}
부서 검색 화면에서 리턴 보내주는 스크립트를 작성합니다.
Pop_DeptSearch 화면에 fn_ok 명으로 함수를 생성합니다.
this.fn_ok = function()
{
    var sRtn =  this.ds_dept.getColumn(this.ds_dept.rowposition, "DEPT_CD") + "|";
        sRtn += this.ds_dept.getColumn(this.ds_dept.rowposition, "DEPT_NAME");
    this.close(sRtn);
}
Pop_DeptSearch 화면의 그리드 oncelldblclick 이벤트와 OK버튼의 onclick 이벤트에 위에서 작성한 fn_ok 함수를 지정합니다.

그림 4-3011_MASK

부서 검색 화면을 종료하는 스크립트를 작성합니다.
Pop_DeptSearch 화면에 fn_cancel 명으로 함수를 생성합니다.
this.fn_cancel = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.close();
};
Pop_DeptSearch 화면의 Cancel버튼의 onclick 이벤트에 위에서 작성한 fn_cancel 함수를 지정합니다.
결과를 확인 합니다.

그림 4-3112_combo

성별 조회 & 조건 초기화

성별에 따라서 조회 데이터를 필터 처리하여 보여줍니다.
성별이 표현되는 라디오 컴포넌트의 onitemchanged 이벤트를 생성하여 스크립트를 작성 합니다.
this.div_search_rdo_gender_onitemchanged = function(obj:nexacro.Radio,e:nexacro.ItemChangeEventInfo)
{
    if(e.postvalue == "A")
    {
        this.ds_emp.filter("");
    }
    else
    {
        this.ds_emp.filter("GENDER == '" + e.postvalue + "'");
    }        
};
조회조건 초기화 reset버튼의 onclick 이벤트를 생성하여 스크립트를 작성합니다.
this.div_cont_btn_reset_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.div_search.form.edt_dept_cd.set_value("");
    this.div_search.form.edt_dept_nm.set_value("");
    this.div_search.form.rdo_gender.set_value("A");
};

4.3.6Grid Display & Edit

그리드 컴포넌트를 데이터 형식에 맞게 보여주고, 데이터를 직접 입력 할 수 있는 상태로 수정 합니다.
샘플참고
nexacro17_Education_Materials\Sample\EduProject\Comp\Comp_Grid_Cell.xfdl

그림 4-32예시

expression?

컴포넌트, 혹은 Grid 셀의 텍스트를 계산을 통해 출력하고자 할 때 사용할 계산식(Expression)을 지정하는 속성 입니다.
 
Expression Script는 넥사크로플랫폼 FormScript 문법에 따라 작성합니다.
 
대표적인 사용의 예는 Grid에서 Dataset Expression을 사용하는 것입니다.
Dataset Expression Script는 Dataset과 Bind되어 있는 Grid 등의 Component에 속성으로 정의하여 Dataset의 Row 별로 임의의 지정된 동작을 수행하게 하기 위한 기능입니다.
또한, Dataset의 getCaseSum(), filter(), findRowExpr() 등의 메소드에도 Expression Script가 인자로 사용됩니다.
 
Dataset Expression은 eval script 처럼 동작하지만 Expression Script가 Component 또는 Dataset이 속한 Form Context를 기반으로 하되 Form Context와 Dataset Expression Script의 Context는 서로 독립되어 있어 Expression Script에서 선언된 변수가 Form Context에 영향을 미치지 않는다는 점에서 차이가 있습니다.
단, Form Context에 정의된 변수를 Dataset Expression Script의 Context에서 읽거나 쓸 수 있고 변경된 값은 Form Context에도 영향을 미칩니다.
성명과 사원번호의 컬럼 순서를 변경하고, 맨 앞쪽에 빈 컬럼을 하나 추가하여 제목을 'No' 로 변경합니다.
컬럼 순서 변경은 잘라내기, 붙여넣기 방식으로 변경 합니다.

순번이 표현되는 셀의 text 속성 세번째 버튼을 클릭하면 Expression을 적용 할 수 있는 창이 오픈 됩니다.
해당창에 'currow + 1' 값을 입력 합니다.

currow는 Dataset에서 현재 Expression을 실행하고 있는 Row의 Index값을 의미합니다.

성별을 표현하는 셀에 코드값이 아닌 명으로 출력을 합니다. 자바스크립트의 삼항 연산자를 이용하여 조건처리를 할 수 있습니다.

삼항연산자 는 세개의 피연산자를 입력받는 연산자 입니다.

(A ? B : C) 형식으로 사용합니다.

-A: 조건

-B: 조건이 참일 때 처리

-C: 조건이 거짓일 때 처리

Summary Row를 추가하여 합계 등의 집계 데이터를 출력 합니다.

데이터셋의 getRowCount(), getSum() Method를 호출하여 표현 합니다.
호출하는 방식은 아래와 같습니다.
"Total : " + comp.parent.ds_emp.getRowCount()
comp.parent.ds_emp.getSum('SALARY')
comp는 Expression을 적용하고 있는 컴포넌트를 의미 합니다. 
Expression을 Grid에 적용하고 있습니다. 따라서 comp는 Grid 컴포넌트를 의미 합니다. 
comp.parent는 Grid의 부모, 즉 화면객체를 의미합니다.
comp.parent.ds_emp 는 'dataset' 이라는 예약어로도 접근 가능합니다.
'dataset' 예약어는 Grid에 바인딩 되어있는 Dataset을 의미합니다.

위 스크립트는 아래 스크립트로도 사용이 가능합니다.
"Total : " + dataset.getRowCount()
dataset.getSum('SALARY')

그림 4-3314_expr_4

그림 4-3414_expr_4

Expression을 적용한 결과 화면입니다.

그림 4-3514_expr_4

자주 사용되는 expression구문의 예

Expression Script는 넥사크로플랫폼 Form Script 문법에 따라 작성함이 원칙이고 자주 사용되는 예에 대한 설명입니다.
Grid에 값을 출력하거나 레코드 별로 다른 속성값 처리를 하는 경우 다음과 같이 자주 사용되는 구문을 응용하여 처리합니다.
EMPL_ID + " " + FULL_NAME
SALARY / 12
GENDER == "M" ? "Male" : "Female"
Math.round(SALARY / 12)
comp.parent.ds_emp.getAvg("SALARY")
dataset.getRowCount()
//Form 변수 호출
comp.parent.fv_test
//Form 함수 호출
comp.parent.fn_test()

호출되는 함수의 수행시간이 길어지는 경우는 Grid 성능저하의 원인이 되므로 권장하지

않는 내용입니다. (서버와 통신, for loop, while loop 등..)

currow

Cell Display & Edit

그리드 셀 모양을 데이터에 따라 적당한 형식으로 보여주고, 편집도 가능하게 처리합니다.
셀의 displaytype, edittype 속성을 변경 합니다.

속성

속성값

Name

displaytype

text

edittype

text

Empl ID

displaytype

mask

edittype

mask

maskeditformat

AA-###

maskedittype

string

Dept

displaytype

combotext

edittype

combo

combodataset

ds_dept

combocodecol

DEPT_CD

combodatacol

DEPT_NAME

Position

displaytype

combocontrol

edittype

combo

combodataset

ds_pos

combocodecol

POS_CD

combodatacol

POS_NAME

Hire Date

displaytype

date

edittype

date

Salary

displaytype

number

edittype

mask

maskeditformat

#,###

Married

displaytype

checkboxcontrol

edittype

checkbox

Memo

displaytype

text

edittype

textarea

데이터 형식에 따라 여러가지 형태로 셀의 모양을 변경 할 수 있습니다.

4.4데이터 통신

화면에서 JSP를 이용한 서버 처리와 데이터 통신 방식에 대해 설명합니다.

그림 4-36서비스 구성도

transaction은 Dataset의 처리를 위해 Service를 호출하는 메소드로 Async 방식을 기본으로 제공하고 있습니다. transaction의 인자값으로 통신 방식을 변경 할 수 있으며, Async와 Sync의 특성과 장단점을 정확하게 이해하여 적용해야 합니다..

Async(비동기)


Async 방식은 transaction 함수가 Service를 호출 후 통신 완료와 관계없이 다음 스크립트를 수행하며 통신 결과는 콜백 함수에서 확인이 가능합니다.

동시에 여러 개의 Service를 사용할 수 있기 때문에 권장하고 있으며, 각각의 통신 결과는 콜백 함수에서 transaction ID별로 구분하여 사용합니다.

특히 폼의 onload 이벤트에서 transaction 호출은 무조건 Async 방식으로 처리하여야 합니다. 폼이 Load되는 시점에 Sync 방식으로 Service를 호출할 경우 transaction이 종료되는 시점까지 Drawing이 정상적으로 이루어지지 않습니다.


Sync(동기)

Sync 방식은 transaction 함수가 Service를 호출 후 통신이 완료되는 시점까지 대기하다가 통신 결과를 받으면 다음 스크립트를 실행합니다.

여러 개의 Service 호출에 사용할 경우 하나의 Service 호출 후 통신이 완료된 시점에 다음 통신을 수행합니다. 화면 처리에서 선 transaction 통신 후 다음 단계로 이동할 때 사용하며 특수한 경우가 아니면 사용을 하지 않는 것을 원칙으로 합니다.

특히 폼의 onload 이벤트에서 사용하는 것은 금합니다.

4.4.1서버 설정

넥사크로플랫폼과 서버와의 데이터 통신을 위해 X-API를 설치하고 서버 서비스를 이해 합니다.

X-API 설치

X-API는 넥사크로플랫폼 클라이언트와 서버와의 통신을 위한 API 입니다.
데이터 구조 정의와 데이터 통신을 수행 합니다.
X-API 설치는 Jar파일을 클래스 경로에 포함하면 됩니다.  
JVM 구동시 정의된 클래스 경로나, Web Application의 /WEB-INF/lib 디렉토리에 위치 시키면 됩니다.

여기서는 Tomcat 서버를 이용하여 설정을 합니다.
설치된 Tomcat 서버의 lib 폴더에 아래의 파일을 복사하여 붙여 넣은 후 ReStart 합니다.
nexacro17-xapi-1.0.jar
commons-logging-1.1.1.jar
nexacro17_server_license.xml

그림 4-3701_JAR

설치 확인

X-API 가 정상적으로 설치 되었는지 확인 하기 위해서는 다음과 같은 jsp 파일을 작성하여 실행 합니다.
소스참고
nexacro17_Education_Materials\Sample\JSP\nexacroTest.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<html>
    <head>
        <title>JarInfo</title>
        <style>
        * { font-family: Verdana }
        </style>
    </head>
    <body>
        <pre>
        <%
        new com.nexacro17.xapi.util.JarInfo().info(out);
        %>
        </pre>
    </body>
</html>
출력 정보와 라이선스 정보가 출력 됩니다.

그림 4-3801_JAR

jar파일과 라이선스파일은 라이선스 정책 관계로 교육자료로 제공되지 않습니다.

자세한 내용은 투비소프트 기술지원사이트(http://support.tobesoft.co.kr)에 문의바랍니다.

서버 경로 설정

톰캣 서버에 JSP 서비스 파일이 위치 할 디렉토리를 다음과 같이 구성합니다.
[Tomcat]\webapps\edu\nexacro17
위에서 지정한 서버 경로를 화면에서 호출 하기 위하여 넥사크로 스튜디오에서 지정 합니다.

Project Explorer > TypeDefinition 의 Services 항목을 더블클릭하여 Services Edit창을 오픈합니다. 
+버튼을 이용하여 Service를 다음과 같이 등록 합니다.

그림 4-39typedef

로컬 서버 설정 없이 아래의 경로를 지정하면 서버와의 통신 결과를 확인 할 수 있습니다.

http://demo.nexacro.com/edu/nexacro17/

(단, nexacro browser를 통해서만 확인 가능)

화면 실행 경로 설정

개발된 화면을 톰캣 서버를 이용하여 실행되도록 경로를 설정 합니다.
[Menu] > Tools > Options
Generate Path 를 톰캣 서버 경로 안의 프로젝트 명으로 지정 합니다.

그림 4-40typedef

아래와 같은 확인 창에서 "Yes" 버튼을 클릭 합니다. 
Generate Path 가 변경되면서 프로젝트가 reload 됩니다.

그림 4-41typedef

변경된 Generate Path에 작업된 파일을 다시 Generate 합니다.
[Menu] > Generate > Application
화면을 웹 브라우저를 통하여 실행시 넥사크로 내장 웹서버가 아니라 설정한 톰캣 서버를 이용하여 실행 합니다.
체크 박스를 해제 후 톰캣 서버의 화면 경로를 지정 합니다.

그림 4-42typedef

4.4.2조회 처리

화면 조회 스크립트

Retrieve 버튼의 onclick 이벤트에 'fn_retrieve' 으로 함수를 생성 후, 다음과 같이 스크립트를 작성합니다.
this.fn_retrieve = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    var sDeptCd = this.div_search.form.edt_dept_cd.value;
    
    this.transaction("svcSelect"
                    ,"SvcURL::select_emp.jsp?sDept="+sDeptCd
                    ,""
                    ,"ds_emp=out_emp"
                    ,""
                    ,"fn_callback");                    
};

// 비동기 통신 결과를 받을 콜백 함수 지정
this.fn_callback = function(svcID, errCD, errMSG)
{
    if(errCD < 0){
        this.alert("Error: " + errMSG);
        return;
    }

    if(svcID == "svcSelect"){
        this.alert("Retrieve Success!!!");
    }
}
transaction
데이터 처리를 위해 서비스를 호출하는 메소드로 기본 비동기 방식으로 동작 합니다.

구문

설명

strSvcID

transaction을 구분하기 위한 ID 입니다.

strURL

transaction을 요청할 서버 페이지 주소 입니다.

strInDatasets

서버로 보낼 Dataset 입니다.

"입력ID=Dataset ID" 형식으로 문자열로 설정합니다.

빈칸으로 구분하여 여러개의 Dataset을 전송 할 수 있습니다.

ex) "input1=Dataset00 input2=Dataset01"


각각의 Dataset ID 뒤에 :U, :A, :N 옵션이 붙을 수 있습니다.

:U - 갱신된 내용만 전송

:A - 모든 정보를 전송

:N - Delete를 제외한 데이터만 전송

strOutDatasets

서버에서 보내는 데이터를 받을 Dataset 입니다.

"Dataset ID=출력ID" 형식으로 문자열로 설정합니다.

빈칸으로 구분하여 여러개의 Dataset을 받을 수 있습니다.

ex) "Dataset00=output0 Dataset01=output1"

strArgument

서버로 보낼 파라미터(변수) 입니다.

"변수ID=변수값" 형식으로 문자열로 설정합니다.

빈칸으로 구분하여 여러개의 파라미터(변수)를 전송 할 수 있습니다.

ex) "arg1=nexacro arg2=platfrom"

strCallbackFunc

서버의 처리 결과를 받을 콜백함수를 문자열로 지정합니다.

[bAsync]

[옵션]

비동기 통신 여부를 설정합니다.

"true" 비동기 통신 / "false" 동기 통신 으로 처리합니다.

Default : true

[nDataType]

[옵션]

전송할 데이터의 형태를 설정합니다.

"0" XML / "1" Binary / "2" SSV 형식으로 송수신 합니다.

Default : 0

※ HTML5 버전에서는 XML, SSV 형식만 지원 합니다.

[bCompress]

[옵션]

서버 통신시 데이터의 압축 여부를 지정합니다.

Default : false

※ HTML5 버전에서는 지원하지 않습니다.

조회 서비스 페이지(JSP) 작성

조회 서비스를 ‘select_emp.jsp’ 로 생성하고 다음과 같이 작성 합니다. 
여기서 순수 JSP에 관련된 내용은 다루지 않습니다.
소스참고
nexacro17_Education_Materials\Sample\JSP\select_emp.jsp
필요한 package를 import합니다.
...
<%@ page import="com.nexacro17.xapi.data.*" %>
<%@ page import="com.nexacro17.xapi.tx.*" %>
...
조회 조건값으로 Get 방식으로 전송된 변수를 받습니다.
...
String sDept = request.getParameter("sDept");
...
조회 결과를 보낼 PlatformData를 생성합니다. PlatformData 는 데이터 송수신의 기본 단위 입니다.
...
PlatformData out_pData = new PlatformData();
...
데이터베이스 설정 정보를 작성합니다.
샘플 프로젝트 "EduProject > File " 폴더 안에 있는 로컬DB(sqlite) 파일을 이용하거나 각자 설정한 DB를 이용합니다.
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:....);
SQL을 작성하고 쿼리를 실행하여 처리 결과를 ResultSet 객체로 받습니다.
...
String SQL;
SQL  = "SELECT EMPL_ID    \n" +
       "     , FULL_NAME  \n" +
       "     , DEPT_CD    \n" +
       "     , POS_CD     \n" +
       "     , GENDER     \n" +
       "     , HIRE_DATE  \n" +
       "     , MARRIED    \n" +
       "     , SALARY     \n" +
       "     , MEMO       \n" +
       "  FROM TB_EMP     \n" +
       " WHERE 1=1        \n" ;
        
if(sDept != null && sDept.length() != 0 && !sDept.equals("undefined"))
{
    SQL += "AND DEPT_CD = '" + sDept + "'";
}
SQL += " ORDER BY DEPT_CD, EMPL_NAME";
    
rs = stmt.executeQuery(SQL);
...
조회 결과 ResultSet 데이터를 Dataset 형태로 변환 합니다.
...
DataSet ds = new DataSet("out_emp");
ds.addColumn("EMPL_ID"    ,DataTypes.STRING  ,(short)10 );
ds.addColumn("FULL_NAME"  ,DataTypes.STRING  ,(short)50 );
ds.addColumn("DEPT_CD"    ,DataTypes.STRING  ,(short)10 );
ds.addColumn("POS_CD"     ,DataTypes.STRING  ,(short)10 );
ds.addColumn("GENDER"     ,DataTypes.STRING  ,(short)10 );
ds.addColumn("HIRE_DATE"  ,DataTypes.DATE    ,(short)10 );
ds.addColumn("MARRIED"    ,DataTypes.STRING  ,(short)10 );
ds.addColumn("SALARY"     ,DataTypes.INT     ,(short)10 );
ds.addColumn("MEMO"       ,DataTypes.STRING  ,(short)10 );
            
while(rs.next())
{
    int row = ds.newRow();
    ds.set(row ,"EMPL_ID"       ,rs.getString("EMPL_ID")  );
    ds.set(row ,"FULL_NAME"     ,rs.getString("FULL_NAME"));
    ds.set(row ,"DEPT_CD"       ,rs.getString("DEPT_CD")  );
    ds.set(row ,"POS_CD"        ,rs.getString("POS_CD")   );
    ds.set(row ,"GENDER"        ,rs.getString("GENDER")   );
    ds.set(row ,"HIRE_DATE"     ,rs.getString("HIRE_DATE"));
    ds.set(row ,"MARRIED"       ,rs.getString("MARRIED")  );
    ds.set(row ,"SALARY"        ,rs.getString("SALARY")   );
    ds.set(row ,"MEMO"          ,rs.getString("MEMO")     );
}
...
Dataset을 PlatformData에 추가 합니다.
...
out_pData.addDataSet(ds);
...
PlatformData에 에러를 체크 할 변수를 추가 합니다.
...
VariableList varList = out_pData.getVariableList();
varList.add("ErrorCode", nErrorCode);
varList.add("ErrorMsg" , strErrorMsg);
...
PlatformData를 클라이언트 화면으로 전송합니다.
...
HttpPlatformResponse pRes = new HttpPlatformResponse(response, PlatformType.CONTENT_TYPE_XML, "UTF-8");
pRes.setData(out_pData);

pRes.sendData();
...
톰캣 서버를 이용하여 결과를 확인 합니다.

그림 4-43typedef

그림 4-4401_화면예

웹 브라우저에서 실행 하실 경우 동일 출처 정책(Same Origin Policy) 에 따라 클라이언트의 화면 페이지와 데이터 통신시 호출하는 서버 페이지의 도메인이 일치 하여야 합니다.

즉 화면을 로컬 PC에서 http://localhost:8080 도메인으로 실행 하였으면, 해당 화면에서 호출하는 서버 페이지도 동일한 도메인 http://localhost:8080 으로 호출해야 합니다.

4.4.3입력 처리

화면 입력 스크립트

Add 버튼의 onclick 이벤트에 'fn_add' 으로 함수를 생성 후, 다음과 같이 스크립트를 작성합니다.
this.fn_add = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    // 데이터셋의 마지막 row에 새로운 row를 추가
    this.ds_emp.addRow();

    // 추가한 row의 입사일자 컬럼에 오늘 일자를 초기값으로 설정
    this.ds_emp.setColumn(this.ds_emp.rowposition, "HIRE_DATE", this.fn_today());    
};

// 자바스크립트를 이용하여 오늘 일자 계산
this.fn_today = function()
{
    var objDate = new Date();
    var sToday  = objDate.getFullYear().toString();
        sToday += (objDate.getMonth()+1).toString().padLeft(2, "0")
        sToday += objDate.getDate().toString().padLeft(2, "0"); 

    return sToday;
};

Dataset의 원하는 위치에 새로운 row를 추가 하고 싶은 경우 insertRow() 메소드를 사용합니다.

4.4.4삭제 처리

화면 삭제 스크립트

Delete 버튼의 onclick 이벤트에 'fn_delete' 으로 함수를 생성 후, 다음과 같이 스크립트를 작성합니다.
this.fn_delete = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    // 선택되어 있는 row를 삭제
    this.ds_emp.deleteRow(this.ds_emp.rowposition);    
};

4.4.5저장 처리

화면 저장 스크립트

Save 버튼의 onclick 이벤트에 'fn_save' 으로 함수를 생성 후, 다음과 같이 스크립트를 작성합니다.
this.fn_save = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    var sTitle = nexacro.wrapQuote(this.titletext);
    this.transaction("svcSave"
                    ,"SvcURL::save_emp.jsp"
                    ,"in_emp=ds_emp:u"
                    ,""
                    ,"in_var1="+sTitle
                    ,"fn_callback");        
};
조회 스크립트에서 작성한 콜백 함수를 다음과 같이 수정 합니다.
this.fn_callback = function(svcID, errCD, errMSG)
{
    if(errCD < 0){
        this.alert("Error: " + errMSG);
        return;
    }
    if(svcID == "svcSelect"){
        this.alert("Retrieve Success!!!");
    }
    else if(svcID == "svcSave"){
        this.alert("Save Success!!!");
    }
}

저장 서비스 페이지(JSP) 작성

저장 서비스를 ‘save_emp.jsp’ 로 생성하고 다음과 같이 작성 합니다. 
여기서 순수 JSP에 관련된 내용은 다루지 않습니다.
소스참고
nexacro17_Education_Materials\Sample\JSP\save_emp.jsp
필요한 package를 import합니다.
<%@ page import="com.nexacro17.xapi.data.*" %>
<%@ page import="com.nexacro17.xapi.tx.*" %> 
전송된 Dataset에서 컬럼에 해당하는 값을 추출합니다.
public String  dsGet(DataSet ds, int rowno, String colid) throws Exception
{
    String value;
    value = ds.getString(rowno,colid);
    if( value == null )
         return "";
    else
         return value;
} 
HttpServletRequest를 이용하여 HttpPlatformRequest 생성하고 전송된 XML 데이터를 분석합니다.
HttpPlatformRequest pReq = new HttpPlatformRequest(request);
pReq.receiveData();
데이터를 PlatformData 형태로 저장하고 변수와 Dataset을 할당 받습니다.
PlatformData in_pData = pReq.getData();
VariableList in_varList = in_pData.getVariableList();
String sVar1 = in_varList.getString("in_var1");
DataSet ds = in_pData.getDataSet("in_emp");
전송된 데이터를 쿼리를 이용하여 DB 테이블에 적용합니다

먼저 삭제한 레코드에 대해서 Delete 쿼리를 실행 합니다.
/******** DELETE ********/
for( i = 0; i < ds.getRemovedRowCount(); i++ )
{
    String sEmpID = ds.getRemovedData(i, "EMPL_ID").toString();
    SQL = "DELETE FROM TB_EMP WHERE EMPL_ID = '" + sEmpID + "'";
    stmt.executeUpdate(SQL);
}
입력 수정된 레코드에 대해서 쿼리를 실행 합니다.
/******** INSERT, UPDATE ********/
for( i = 0; i < ds.getRowCount(); i++ )
{
    int rowType = ds.getRowType(i);    
    if( rowType == DataSet.ROW_TYPE_INSERTED )
    {
        SQL = "INSERT INTO TB_EMP( EMPL_ID,     \n" +
              "                    FULL_NAME,   \n" +
              "                    DEPT_CD,     \n" +
              "                    POS_CD,      \n" +
              "                    GENDER,      \n" +
              "                    HIRE_DATE,   \n" +
              "                    MARRIED,     \n" +
              "                    SALARY,      \n" +
              "                    MEMO)        \n" +
              "     VALUES('" + dsGet(ds, i, "EMPL_ID")   + "',\n" +
              "            '" + dsGet(ds, i, "FULL_NAME") + "',\n" +
              "            '" + dsGet(ds, i, "DEPT_CD")   + "',\n" +
              "            '" + dsGet(ds, i, "POS_CD")    + "',\n" +
              "            '" + dsGet(ds, i, "GENDER")    + "',\n" +
              "            '" + dsGet(ds, i, "HIRE_DATE") + "',\n" +
              "            '" + dsGet(ds, i, "MARRIED")   + "',\n" +
              "            '" + dsGet(ds, i, "SALARY")    + "',\n" + 
              "            '" + dsGet(ds, i, "MEMO")      + "')  ";   
    }
    else if( rowType == DataSet.ROW_TYPE_UPDATED )
    {
        String sOrgEmpID = ds.getSavedData(i, "EMPL_ID").toString(); 
        SQL = "UPDATE TB_EMP     \n" +
              "   SET EMPL_ID   = '" + dsGet(ds, i, "EMPL_ID")   + "',\n" +
              "       FULL_NAME = '" + dsGet(ds, i, "FULL_NAME") + "',\n" +
              "       DEPT_CD   = '" + dsGet(ds, i, "DEPT_CD")   + "',\n" +  
              "       POS_CD    = '" + dsGet(ds, i, "POS_CD")    + "',\n" +
              "       GENDER    = '" + dsGet(ds, i, "GENDER")    + "',\n" +
              "       HIRE_DATE = '" + dsGet(ds, i, "HIRE_DATE") + "',\n" +
              "       MARRIED   = '" + dsGet(ds, i, "MARRIED")   + "',\n" +
              "       SALARY    = '" + dsGet(ds, i, "SALARY")    + "',\n" +
              "       MEMO      = '" + dsGet(ds, i, "MEMO")      + "' \n" +
              " WHERE EMPL_ID   = '" + sOrgEmpID + "'";
    }                    
    stmt.executeUpdate(SQL);
}
저장 처리 결과를 전송할 PlatformData 생성합니다.
PlatformData out_pData = new PlatformData();
PlatformData에 에러 체크를 할 변수와 화면으로 전송 할 변수를 추가 합니다.
VariableList out_varList = out_pData.getVariableList();
out_varList.add("ErrorCode", nErrorCode);
out_varList.add("ErrorMsg" , strErrorMsg);
out_varList.add("out_var"  , sVar1);

"ErrorCode"와 "ErrorMsg"는 화면에 작성한 콜백함수의 2번째, 3번째 인자에서 받습니다.

필수로 지정하고 전송하셔야 합니다.

추가로 지정한 변수는 화면에 동일한 변수명으로 폼변수를 선언하여 받을 수 있습니다.

PlatformData를 클라이언트 화면으로 전송합니다.
HttpPlatformResponse pRes = new HttpPlatformResponse(response, PlatformType.CONTENT_TYPE_XML, "UTF-8");
pRes.setData(out_pData);

pRes.sendData();
톰캣 서버를 이용하여 결과를 확인 합니다.

그림 4-45typedef

그림 4-4601_화면예

4.4.6코드 처리

화면에서 사용하는 부서코드와 직급코드를 서버에서 호출 합니다.

화면 코드조회 스크립트

부서 검색 화면의 onload 이벤트를 생성합니다. 이벤트 영역을 더블클릭하여 기본 함수명 생성하고, 다음과 같이 스크립트를 작성합니다.
this.Form_onload = function(obj:nexacro.Form,e:nexacro.LoadEventInfo)
{
    this.transaction("svcCode"
                    ,"SvcURL::select_code.jsp"
                    ,""
                    ,"ds_dept=out_dept ds_pos=out_pos"
                    ,""
                    ,"fn_callback");    
};

트랜잭션의 3번째(서버로 보내는 데이터셋), 4번째(서버에서 받을 데이터셋) 인자에 빈칸으로 구분을 하여 여러개의 데이터셋을 보내거나 받을 수 있습니다.

코드조회 서비스 페이지(JSP) 작성

코드 조회 서비스를 ‘select_code.jsp’ 로 생성하고 다음과 같이 작성 합니다. 
여기서 순수 JSP에 관련된 내용은 다루지 않습니다.
소스참고
nexacro17_Education_Materials\Sample\JSP\select_code.jsp
필요한 package를 import합니다.
...
<%@ page import="com.nexacro17.xapi.data.*" %>
<%@ page import="com.nexacro17.xapi.tx.*" %>
...
JSP의 조회 결과 ResultSet을 메타데이터를 이용하여 데이터셋 형식으로 변환하는 클래스를 생성 합니다.
...
<%!
// ResultSet ==> Dataset
public DataSet RsToDs(ResultSet rs, String dsID) throws Exception
{
    int i;
    int iColCnt;
    String sColName;
    String sColType;;
    int ColType = 0; 
    int ColSize = 255; 
    
    DataSet ds = new DataSet(dsID);
    ResultSetMetaData rsmd = rs.getMetaData();

    iColCnt = rsmd.getColumnCount();
    for( i = 1 ; i <= iColCnt ; i++ )
    {
        sColName = rsmd.getColumnName(i).toUpperCase();        
        sColType = rsmd.getColumnTypeName(i);

        ColType = DataTypes.STRING;
        if(sColType.equals("INTEGER"))    ColType = DataTypes.INT;
        if(sColType.equals("DECIMAL"))    ColType = DataTypes.DECIMAL;
        
        ds.addColumn(sColName, ColType, ColSize);        
    }
    while(rs.next())
    {
        int row = ds.newRow();
        for( i = 1 ; i <= iColCnt ; i++ )
        {
            sColName = rsmd.getColumnName(i).toUpperCase();
            ds.set(row, sColName, rsGet(rs, sColName));
        }
    }

  return ds;
}

public String rsGet(ResultSet rs, String id) throws Exception
{
    if( rs.getString(id) == null ){
        return "";
    } 
    else {
        return rs.getString(id);
    }
}
%>
...
조회 결과를 보낼 PlatformData를 생성합니다.
...
PlatformData out_pData = new PlatformData();
...
쿼리 작성, 실행 후 ResultSet 조회 결과를 Dataset 형태로 변환하는 클래스를 호출 하여 Dataset 형태로 변환 후 PlatformData 에 추가합니다.
...
String SQL;        
SQL = " SELECT DEPT_CD, DEPT_NAME FROM TB_DEPT";            
rs = stmt.executeQuery(SQL);
out_pData.addDataSet(RsToDs(rs,"out_dept"));        
         
SQL = " SELECT POS_CD, POS_NAME FROM TB_POS";
rs = stmt.executeQuery(SQL);
out_pData.addDataSet(RsToDs(rs,"out_pos"));        
...
PlatformData에 에러 체크를 할 변수를 추가 합니다.
...
VariableList varList = out_pData.getVariableList();
varList.add("ErrorCode", nErrorCode);
varList.add("ErrorMsg" , strErrorMsg);
...
PlatformData를 클라이언트 화면으로 전송합니다.
...
HttpPlatformResponse pRes = new HttpPlatformResponse(response, PlatformType.CONTENT_TYPE_XML, "UTF-8");
pRes.setData(out_pData);

pRes.sendData();
...
부서코드와 직급코드 조회 결과를 확인 합니다.

그림 4-4701_화면예