5.넥사크로 애플리케이션 개발

Edit

이 장에서는 이전 장에서 만든 서비스를 사용하여 넥사크로 애플리케이션을 개발하는 방법에 대해 설명합니다. 넥사크로 애플리케이션은 Nexacro Studio 툴을 이용하여 개발합니다. 서비스 개발은 이전 장을 참고합니다.

이번 장은 사용자가 넥사크로 및 Nexacro Studio에 익숙하다는 전제 하에 작성 되었습니다. 따라서, 기본적인 넥사크로 애플리케이션 개발 단계에 대한 상세정보는 설명하지 않습니다.

이 장에서 설명하는 Nexacro Studio를 이용한 Nex-UP 서비스를 사용한 애플리케이션 개발단계는 다음과 같습니다.

5.1TypeDefinition-Module 등록하기

Nex-UP의 호출 스크립트를 사용하기 위하여 NexUpLibrary를 등록합니다. 아래와 같이 NexUpLibrary.json을 추가합니다.

5.2TypeDefinition-Service 등록하기

Nex-UP Editor에서 생성한 서비스를 호출하기 위해 URL을 등록합니다. 아래와 같이 TypeDefinition에서 Service를 추가합니다.

Field Name

Field Value

Prefix

‘nexupSvc’

서비스 호출 스크립트 코드에서 사용되는 Prefix를 입력합니다.

Type

‘bs’

Nex-UP 서비스를 호출하기 위해서는 반드시 bs 타입을 선택해야 합니다.

URL

‘http://localhost:8080/nexup’

Nex-UP 서버 URL을 입력합니다.

ServiceList

‘/studio/getServices.do’

서비스 리스트 호출 url을 입력합니다.

데이터셋Layout

‘/studio/getService.do?’

입출력 정보를 획득하기 위한 url을 입력합니다.

Prefix의 경우 'nexupSvc'로 고정합니다. 서비스 호출 시 사용되는 값입니다.

5.3서비스 인터페이스 정보 가져오기

서비스 인터페이스에 대한 정보를 가져오는 방법은 2가지 형태로 제공됩니다.

5.3.1Nex-UP Editor에서 정보 가져오기

1

Nex-UP Editor의 SqlMap Explorer에서 저장된 서비스를 선택합니다.

2

Output Dataset을 선택하고 Ctrl + C 키를 이용하여 복사합니다.

3

Nexacro Studio화면에 Output Dataset을 붙여넣기 합니다.

4

붙여넣기 했던 Output Dataset을 그리드로 Drag & Drop합니다.

5.3.2Nex-UP 서버에서 정보 가져오기

1

Project Explorer에서 해당 Service를 Refresh하여 Nex-UP 서버의 서비스 목록을 가져옵니다.

가져온 서비스 목록이 표시 됩니다.

2

서비스 목록에서 'BOOKINFO_S' 서비스를 Refresh하여 인터페이스 정보(입출력 정보)를 가져옵니다.

3

Project Explorer의 서비스 인터페이스 정보에서 입출력 데이터셋을 Invisible Objects 에디터로 드래그 앤 드롭 합니다.

5.4서비스 호출 스크립트 작성하기

Nex-UP 서비스를 호출하기 위한 스크립트는 Nex-UP Editor에서 제공합니다.

5.4.1조회

1

Nex-UP Editor의 SqlMap Explorer에서 앞서 만든 서비스를 선택합니다.

2

마우스 우클릭으로 팝업 메뉴를 오픈합니다.

그림 5-1서비스 선택

3

팝업에서 view CallFunction을 선택하면 Script를 확인 가능 합니다.

그림 5-2서비스 호출 스크립트 확인 - Nexacro

4

Nexacro Studio에서 Button Event를 추가합니다.

5

앞서 Nex-UP에서 복사 했던 호출 스크립트를 버튼 이벤트 함수에 추가합니다.

6

Nexacro Studio의 Quick View를 클릭하여 조회결과를 확인합니다.

5.4.2추가, 삭제

1

Nexacro Studio에서 dataset에 대한 추가, 삭제 버튼을 생성합니다.

그림 5-3추가, 삭제버튼 추가

2

Nexacro Studio에서 dataset에 대한 추가, 삭제 스크립트를 작성합니다.

그림 5-4추가, 삭제 버튼 이벤트에 스크립트 추가

3

Nexacro Studio에서 dataset에 대한 저장버튼을 생성합니다.

그림 5-5저장버튼 추가

4

Nex-UP Editor에서 Insert, Update, Delete에 대한 서비스를 각각 선택하고 View Call Function 메뉴를 선택합니다.

그림 5-6입력, 수정, 삭제 서비스를 선택합니다

5

호출 스크립트를 복사합니다.

그림 5-7Insert, Update, Delete 를 위한 스크립트를 복사합니다.

5.4.3저장

1

Nexacro Studio에서 저장버튼 더블클릭하여 이벤트를 추가합니다.

그림 5-8저장버튼 이벤트 추가

2

Nexacro Studio에서 저장버튼 이벤트에 Nex-UP에서 복사한 스크립트를 붙여넣습니다.

그림 5-9저장 스크립트 붙여넣기

3

CallBack 스크립트를 복사합니다.

4

Call Back 스크립트를 붙여 넣습니다.

5

Nexacro Studio에서 QuickView버튼을 클릭하여 테스트 합니다.

그림 5-10그리드에 데이터를 추가

5.5서비스 호출 구조

nexup.AddService함수를 사용하여 서비스를 추가하고 nexup.CallService함수를 통하여 추가된 서비스를 실행하게 됩니다.

그림 5-11서비스 호출 구조

  1. nexup.AddService

nexup.AddService(this, serviceId, inDataset, outDataset, strParam, useRowType, condition)

Parameter

Description

this

현재 호출되는 화면의 form객체

serviceId

Nex-UP Editor에서 개발한 서비스 아이디(Sql Id)

inDataset

입력값으로 전송할 Dataset. 여러개일 경우 공백으로 추가

ex) "input0=Dataset0:U input1=Dataset1:U"

outDataset

출력값으로 전달받을 Dataset.

일반적으로 Table을 조회한 서비스는 하나의 out dataset을 전달받게 되며

Procedure나 Function에서는 공백으로 구분하여 여러 out dataset을 전달 받을 수 있습니다.

ex) "Dataset2=output1"

strParam

parameter값을 설정합니다. 여러개인 경우에는 공백으로 구분합니다.

ex) "a=b c=d"

useRowType

Nex-UP Editor에서 Looping Dataset을 선택한 경우 Nex-UP Framework에서전달받은 Dataset으로 서비스를 수행하는 방식을 정의

Looping Dataset속성값을 가지는 Dataset을 기준으로 반복 수행됨.


- rowType(기본값) : Dataset의 RowType과 Nex-UP Editor에서 만든 서비스의 SqlType과 매핑되는 서비스를 실행

- all : 전달받은 전체 Dataset만큼 서비스를 반복 실행

- column=value : 특정 컬럼의 값이 value와 일치하는 경우만 서비스가 실행됨.

condition

서비스를 실행하기 위한 선행조건 여러 서비스 조합시에 앞단서비스를 처리하고 그 결과에 대하여 서비스의 실행여부를 설정할 수 있습니다.

  1. nexup.CallService

nexup.CallService(this, trId, CallbackFunc, Async, DataType, Compress, mybatisExecutorType)

Parameter

Description

this

현재 호출되는 화면의 form객체

trId

transaction을 구분하기 위한 ID값

CallbackFunc

transaction의 결과를 돌려줄 Function의 이름

Async

비동기 여부를 지정합니다.

DataType

전송할 데이터의 포맷을 지정합니다.

- 0 : XML

- 1 : Binary

- 2 : SSV

기본값 : 0

Compress

통신시 PostData를 압축할지 여부를 지정합니다.

- true : 압축

- false : 압축하지 않음

기본값 : false

mybatisExecutorType

Insert Update, Delete 서비스 사용시 서비스 실행 방식을 선택

- simple(기본값) : 여러개의 DB Query가 실행될 경우 DB Query가 각각 개별적으로 실행

- batch : 여러개의 DB Query가 실행될 경우 Query를 묶어서 한번에 실행

5.6서비스 호출 예시

  1. 기본 호출

//Service Add(BOOK.EX_BOOKINFO_S)
nexup.AddService(this, "BOOK.EX_BOOKINFO_S", "", "dsBOOKINFO=dsBOOKINFO", "P_PARAM=" + this.edtTtitle.value);

//Call Service 호출
nexup.CallService(this, "serviceId", "fn_CallBack");
  1. Dataset의 rowType에 따라 입력, 수정, 삭제 처리

//Service Add(BOOK.EX_BOOKINFO_I)
nexup.AddService(this, "BOOK.EX_BOOKINFO_I", "dsBOOKINFO=dsBOOKINFO:U", "", "");

//Service Add(BOOK.EX_BOOKINFO_D)
nexup.AddService(this, "BOOK.EX_BOOKINFO_D", "dsBOOKINFO=dsBOOKINFO:U", "", "");

//Service Add(BOOK.EX_BOOKINFO_U)
nexup.AddService(this, "BOOK.EX_BOOKINFO_U", "dsBOOKINFO=dsBOOKINFO:U", "", "");

//Call Service 호출
nexup.CallService(this, "serviceId", "fn_CallBack");
  1. 상위 쿼리의 결과에 따른 분기 처리 (condition사용)

그림 5-12condition 사용

//Service Add(BOOK.EX_BOOKINFO_S)
nexup.AddService(this, "BOOK.EX_BOOKINFO_S", "", "dsBOOKINFO=dsBOOKINFO", "");

nexup.AddService(this, "BOOK.noname2", "", "Dataset0=Dataset0", "", "", "#{dsBOOKINFO.ISBN} == null");
nexup.AddService(this, "BOOK.noname3", "", "Dataset0=Dataset0", "", "", "#{dsBOOKINFO.ISBN} != null");

//Call Service 호출
nexup.CallService(this, "serviceId", "fn_CallBack");

5.7공통 데이터 사용하기

그림 5-13condition 사용

5.7.1Common Data 구성요소

공통 데이터

그림 5-14condition 사용


항목

설명

1

Copy type NP17

- 데이터셋복사할때 Nexacro17Clipboard 타입으로 설정

- 선택시선택값이 로컬 profile값으로 저장되고 불러온다.

2

+, -

- 공통 변수(Variable) 및 데이터셋(Dataset)을 추가/삭제

3

Copy CommonVariables Layout

- UI프로젝트에서 사용할 공통변수 및 공통 데이터셋 Layout을 복사한다.

4

OK버튼

- 공통데이터 레이아웃 xml 파일을 생성

- 공통global dataset 생성

- Rows값을 로컬 profile로 저장

- 창을 종료

5

Cancel 버튼

- 수정된 내용 반영없이 창을 닫는다.

5.7.2공통 변수 설정

공통 변수 설정 화면

그림 5-15condition 사용


항목

설명

1

Variables

- 현재 추가된 공통 변수 목록

2

+, -

- 변수를 추가/삭제

3

Variables

- 등록된 변수의 값을 할당

5.7.3공통 데이터셋 설정

공통 데이터셋 설정 화면

그림 5-16condition 사용


항목

설명

1

Datasets

- 현재 추가된 공통 데이터셋목록

2

+, -

- 데이터셋을 추가/삭제

3

Contents

- 선택된 Dataset 정보 탭

4

Source

- 선택된 Dataset의 XML 스크립트 확인

5

Columns

- 선택된 Dataset의 컬럼정보를 추가/삽입/삭제 할 수 있다.

- 변경된 컬럼정보는 하단에 Rows의 그리드에 바로 반영한다.

6

Rows

- 선택된 Dataset의 데이터를 추가/삽입/삭제 할 수 있다.

5.7.4공통 데이터셋 XML파일(예시)

Nex-UP Editor 환경설정(Config)에서 OK버튼으로 저장시 자동 생성

  1. 1.WEB-INF/common 폴더에 생성

  2. 2.commonData1.xml 파일을 생성

  3. 3.공통 데이터셋 레이아웃을 정의

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<layout xmlns="http://www.nexacro.com/nexup/service" name="commonData1">
    <input>
        <variables>
            <variable name="commonVar1" size="0" dataType="string"/>
        </variables>
        <dataSets>
            <dataSet description="" name="gdsCommonIn1">
                <columnInfo dataType="string" description="" isConstant="false" name="userId" size="255"/>
                <columnInfo dataType="string" description="" isConstant="false" name="clientIP" size="255"/>
            </dataSet>
        </dataSets>
    </input>
    <output>
        <variables/>
        <dataSets/>
    </output>
</layout>

5.7.5Spring Interceptor Java Class파일 생성(예시)

public class ConverterKeywordInterceptor implements HandlerInterceptor {

    private static final String LOGIN_DATASET_NAME = "dsLogin";
    private static final String LOGIN_DATASET_COL_NAME = "USERID";
    private static final String COMM_DATASET_USERID_COL_NAME = "userId";
    private static final String COMM_DATASET_IP_COL_NAME = "clientIP";
    
    @Autowired
    DefaultSessionHandler defaultSessionHandler;

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {

        NexacroContext nexacroContext = NexacroContextHolder.getNexacroContext();
        PlatformData platformData = nexacroContext.getPlatformData();

        //변경할 Variable
        Variable var = platformData.getVariable("commonVar1");
        if(var != null && "#{clientIP}".equals(var.getString())){
            var.set(request.getRemoteAddr());
        }
        
        //변경할 Dataset
        DataSet dataSet = platformData.getDataSet("gdsCommonIn1");
        if (dataSet != null && dataSet.getRowCount() > 0) {
            //일반 Data에서 처리
            convertDataSet(request, dataSet);
            //sessionData에서 처리
            convertFromSessionData(request, dataSet);
        }
        return true;
    }
.............
........
...
}

5.7.6Interceptor Java Class에 치환 로직 추가(예시)

//세션정보 치환
private void convertFromSessionData(HttpServletRequest request,DataSet dataSet) {
    if (defaultSessionHandler.isUseSession()) {
        // session check
        ServiceData loginServiceData = (ServiceData) WebUtils.getSessionAttribute(request,defaultSessionHandler.getSessionName());
        if (loginServiceData != null) {            
            // #{userId} --> session에 담긴 data로 변경된다.
            String columnName = this.COMM_DATASET_USERID_COL_NAME;
            int row = 0;
            
            String strValue = dataSet.getString(row, columnName);
            if (strValue.equals("#{userId}")) {
                //sessionData에 담긴 값
                //login할때 호출할 서비스의 결과 Dataset이름("dsLogin")과 column이름("USERID")을 지정하면 된다.
                Object value = getDatasetColumn(loginServiceData, this.LOGIN_DATASET_NAME, this.LOGIN_DATASET_COL_NAME, 0);
                dataSet.set(row, columnName, value);                                                  
                System.err.println("userId="+ dataSet.getString(0, "userId"));
            }
        }
    }
}
//아이피정보 치환
private void convertDataSet(HttpServletRequest request, DataSet dataSet) {
    // #{remoteIP} --> getRemoteAddr의 값으로 변경된다.
    String columnName = this.COMM_DATASET_IP_COL_NAME;
    int row = 0;
    
    String remoteIP = dataSet.getString(row, columnName);
    if (remoteIP.equals("#{clientIP}")) {
        dataSet.set(row, columnName, request.getRemoteAddr());
        System.err.println("clientIP="+ dataSet.getString(row, "clientIP"));
    }
}
//데이터셋정보 추출
private Object getDatasetColumn(ServiceData loginServiceData,String dsName, String columnName, int index) {
    List<Map> dsDataset2 = (List<Map>) loginServiceData.getDataSet(dsName);
    Map row = dsDataset2.get(index);
    Object value = row.get(columnName);
    return value;
}

5.7.7Interceptor 설정 추가

......................
...........
...
 <mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.nexacro.spring.servlet.NexacroInterceptor" />
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/dynamicService*"/>
        <bean class="com.nexacro.nexup.web.servlet.SessionInterceptor">
            <property name="errorView" ref="nexacroView" />
        </bean>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="nexacro.sample.interceptor.ConverterKeywordInterceptor"/>
    </mvc:interceptor>                              
</mvc:interceptors>
......................
...........
...

5.7.8Nexacro 프로젝트에 공통데이터셋 추가

그림 5-17condition 사용