넥사크로(nexacro) 14 클라이언트 개발

이번 장에서는 X-PUSH 메시지를 수신할 클라이언트(넥사크로플랫폼 애플리케이션)를 개발하는 방법을 설명합니다. X-PUSH 클라이언트는 넥사크로 애플리케이션으로 구성할 수 있습니다. 그러므로 X-PUSH 클라이언트를 개발하기 위해서는 넥사크로 애플리케이션 개발에 대한 지식이 필요합니다.

이 문서에서는 넥사크로 애플리케이션 개발에 대해 설명은 하지 않으며 X-PUSH 서버와 관련된 특이 사항만 설명합니다. 애플리케이션 개발과 관련된 상세한 내용은 넥사크로플랫폼 매뉴얼을 참조하십시오.

nexacro14 클라이언트 개발

X-PUSH 클라이언트는 넥사크로 애플리케이션으로 개발할 수 있습니다. 기본적으로 X-PUSH 서버를 통해 메시지를 수신하려면 X-PUSH 프로토콜 어댑터가 추가되어야 하며, 오브젝트를 통해 구성할 수 있습니다.

X-PUSH 프로토콜 어댑터

넥사크로플랫폼에는 X-PUSH 프로토콜 어댑터가 기본패키지에 포함되어 있습니다.

넥사크로 프로젝트에 X-PUSH 오브젝트 추가

프로젝트에 X-Push 오브젝트를 추가하려면 아래 순서를 따라갑니다.

  1. 프로젝트 익스플로러(Project explorer) 원도우에서 "Base" 선택 후 마우스 오른쪽 버튼을 클릭하여 "Edit" 를 선택합니다.

  1. Add 버튼을 눌러 새로운 Object를 생성 후 ID에 "XPush", ClassName에 "nexacro.XPush" 를 입력하고 'OK' 버튼을 클릭합니다.

입력 시 대소문자를 구분해서 입력해주세요.

  1. 추가한 X-PUSH 오브젝트가 정상적으로 등록되었는지 확인합니다.

프로토콜 어댑터 속성

다음 속성값을 변경할 수 있습니다.

속성

형식

기본값

설명

ControlRetry

number

5

Command() 메소드를 호출하여 X-PUSH 서버에 커맨드를 전송할 수 있습니다. "AddF"와 "DelF" 커맨드를 요청했을 때 에러가 발생하면 지정한 값만큼 재시도합니다.

Debug

boolean

false

넥사크로 스튜디오 output 윈도우에 Push 메시지를 보여줄지 여부(true/false)를 결정합니다.

IPList

string

없음

하나 이상의 X-PUSH 서버를 등록합니다. 어댑터는 등록된

서버 중 무작위로 선택해서 연결을 시도합니다. 접속 시도한 서버와 연결이 되지 않으면 실패한 서버를 제외한 서버 중에서 다시 무작위로 선택하여 연결을 시도합니다


다음과 같은 형식으로 서버를 등록합니다.

[X-PUSH 서버의 IP : 포트],…


예) "192.168.1.1:50001,192.168.1.2:50001"

KeepAliveTime

number

30 (초)

X-PUSH 서버와 연결을 유지하기 위해서는 일정 간격으로 메시지를 X-PUSH 서버에 전송해야 합니다. 그 시간 간격을 초 단위로 설정 할 수 있습니다.

KeepTimeOut

number

60 (초)

연결 유지를 위해 X-PUSH 서버에 메시지를 전송할 때 통신의 TimeOut 값을 설정합니다.

LayoutURL

string

없음

메시지 레이아웃 정의 파일의 경로를 설정합니다.

이 속성값은 반드시 설정하셔야 합니다.

경로를 설정할 때 다음과 같은 방법을 허용합니다.


• 다음과 같은 앨리어스를 사용할 수 있습니다.

%System%, %ProgramFiles%, %Tobe%, %Windows%

%Component%, %USERAPP%

• AppGroup을 사용할 수 있습니다. 그러므로 AppGroup

의 cache 기능을 사용할 수 있습니다.

{AppGroup}::file

• URL을 지원합니다.

protocol://host/file

protocol://host:port/file

protocol://file

(현재 "file", "http", "https" 프로토콜만 사용할 수 있습니다)

projectID

string

없음

다중 push의 대상이 되는 프로젝트 이름을 설정하는 Property 입니다

Retry

number

레지스트리에

설정된 값

X-PUSH 서버 연결시에 재접속 횟수를 설정합니다.

아답터는 X-PUSH 서버와 접속에 실패하면 이 값만큼 연결을 시도합니다.

설정하지 않는 경우 레지스트리에 설정된 값을 사용합니다.

SessionID

string

없음

X-PUSH 서버에 연결 시 사용할 SessionID를 설정합니다.

CyPushAdp.Connect() 메소드를 호출할 때 SessionID를 설정하지 않으면 속성값에 지정한 값을 사용합니다. X-PUSH 서버가 Authenticator에게 인증을 요청하면 전달하는 두 개의 값이 바로 UserID와 SessinID입니다.

TimeOut

number

레지스터리에

설정된 값

X-PUSH 서버와 통신시 TimeOut 값을 설정합니다.

설정하지 않는 경우 레지스트리에 설정된 값을 사용합니다.

UserID

string

없음

X-PUSH 서버에 연결 시 사용할 UserID를 설정합니다.

CyPushAdp.Connect() 메소드를 호출할 때 UserID를 설정하지 않으면 지정된 속성값을 사용합니다.

프로토콜 어댑터 이벤트 속성

xpush 어댑터로부터 발생된 이벤트를 정의할 수 있습니다.

onerror

xpush 서버에 요청된 작업이 실패했을 때 발생되는 이벤트

onkeepalive

xpush 서버와 연결을 유지하기 위해 일정 간격 패킷을 주고 받았을 때 발생하는 이벤트

onsuccess

xpush 서버에 요청된 작업이 성공했을 때 발생되는 이벤트

예제

기능 예제 애플리케이션

위치: %XPUSH_HOME%/sample/nexacro_client

예제 애플리케이션의 프로젝트 파일은 %XPUSH_HOME%\sample\nexacro_client\xpushSample.xadl 입니다. 이 파일을 넥사크로 스튜디오에서 오픈합니다.

  1. 넥사크로 스튜디오 메뉴에서 [File > Open > Project] 항목을 클릭합니다.

  1. 예제 프로젝트인xpushSample.xprj 파일을 선택합니다.

  1. Project Explorer 창에서 Base 밑에 sample01_functional을 더블클릭합니다.

아래에서는 예제에서 사용한 일부 코드에 관해 설명합니다.

set_projectid, set_protocolversion

나의 project_id 정보를 설정합니다.

this.XPush00.set_projectid("PRO#1");

x-push와 통신할 프로토콜 버전을 설정합니다.

this.XPush00.set_protocolversion('3');

connection

X-PUSH 서버와 접속을 합니다.

{
	var value = this.IpPort.value;
	this.XPush00.set_iplist(value);

	this.XPush00.connect("user00","pw");
}

xpush00.Connect( uUserID, sPassword )

sUserID

유저 아이디

sPassword

유저 패스워드

subscribe

X-PUSH 서버에 Topic Type, Topic Id 등록

{
var ret = this.XPush00.subscribe(this.topicTYPE.value, this.topicID.value, this, this.dsMessage, "append", "fn_PushCallback_Test_Data");
}

/*
 * 콜백 함수( 메시지 수신 )
 */
this.fn_PushCallback_Test_Data = function (Row, ChangeColumn, AllColumns, Type, ActionType, MessageId) 
{
	trace("fn_PushCallback - NOTI\n" +
		" - ActionType : " + ActionType + "\n" +
		" - Row : " + Row + "\n" +
		" - MessageId : " + MessageId + "\n" );

	trace(this.dsMessage.saveXML() );

	/*
	 * 일반 메시지 수신
	 */
	if (ActionType == "PUSH") {
		trace(this.dsMessage.getColumn(0, "NOTI_00"));
		trace(this.dsMessage.getColumn(0, "NOTI_01"));
		trace(this.dsMessage.getColumn(Row, "NOTI_02"));
		trace(this.dsMessage.getColumn(Row, "NOTI_03"));
	}
	
	/*
	 * 신뢰성 메시지 수신
	 */
	if (ActionType == "RELI") {
		trace(this.dsMessage.getColumn(0, "NOTI_00"));
		trace(this.dsMessage.getColumn(0, "NOTI_01"));
		trace(this.dsMessage.getColumn(0, "NOTI_22"));
	}
}

this.XPush00.subscribe(sMessageType, sMessageId, this, this.dsOperation, "update", "fn_PushCallback_Operation_Data");

sMessageType

Topic Type

sMessageId

Topic Id

this

현재 form

this.dsOperation

DataSet

"update"

수신한 메시지를 데이터셋에 반영하는 방식

"fn_PushCallback_Test_Data"

콜백 함수

X-PUSH 메시지 수신

ActionType으로 일반메시지(PUSH), 신뢰성 메시지(RELI) 구분

미수신 메시지 개수 조회

this.btnReqd_onclick = function(obj:Button,  e:nexacro.ClickEventInfo)
{
	this.XPush00.requestMessageCount("NOTI", "ALL");
}

this.XPush00.requestMessageCount("NOTI", "ALL");

"NOTI"

Topic Type

"ALL"

Topic Id

성공 실패

성공 : onsuccess 에서 확인 (action==10)

실패: onerror 에서 확인(action==10)

미수신 메시지 요청

this.btnReqd_onclick = function(obj:Button,  e:nexacro.ClickEventInfo)
{
	this.XPush00.requestMessage("NOTI", "ALL");
}

this.XPush00.requestMessage("NOTI", "ALL");

"NOTI"

Topic Type

"ALL"

Topic Id

성공 실패

성공 : onsuccess 에서 확인 (reason == 6)

실패 : onerror 에서 확인(errorcode == -902)

수신 확인 메시지 전송

X-PUSH 서버로 부터 신뢰성 메시지를 받으면 수신확인 메시지를 X-PUSH 에 전송

this.fn_PushCallback_Test_Data = function(Row, ChangeColumn, AllColumn, Type, ActionType, MessageId)
{
	AddLog("get push data. reliable message = " + "[ActionType:" + ActionType + "] " + this.dsMessage.getColumn(0, "Title"));
	
	if (ActionType == "RELI") {
		alert(this.dsMessage.getColumn(0, "Title"));
		this.XPush00.sendResponse(MessageId);
	}
}

this.XPush00.sendResponse(MessageId);

MessageId

수신한 신뢰성 메시지의 ID

성공 실패

성공 : onsuccess 에서 확인 (reason == 5)

실패 : onerror 에서 확인(errorcode == -901)

유저 등록

데이터베이스에 유저정보(T_TOPIC Table)를 추가한다. 인증(AUTH)을 한 다음에 유저 등록(ADUI)를 해야 한다.

this.XPush00.registerTopic("NOTI", "ALL");

this.XPush00.registerTopic("NOTI", "ALL");

"NOTI"

Topic Type

"ALL"

Topic Id

성공 실패

성공 : onsuccess 에서 확인 (action == 8)

실패 : onerror 에서 확인(action == 8)

유저 삭제

데이터베이스에 유저정보(T_TOPIC Table)를 삭제한다.

this.XPush00.unregisterTopic("NOTI", "ALL");

this.XPush00.unregisterTopic("NOTI", "ALL");

"NOTI"

Topic Type

"ALL"

Topic Id

성공 실패

성공 : onsuccess 에서 확인 (action == 9)

실패 : onerror 에서 확인(action == 9)

성공/실패 이벤트 처리

onerror

this.XPush00_onerror = function(obj:XPush,  e:XPushErrorEventInfo)

{
	this.fn_setMsg("XPush00_onerror Event\n" + 
		" - eventid: " + e.eventid + "\n" +
		" - action: " + e.action + "\n" + 
		" - statuscode: " + e.statuscode + "\n" +
		" - errormsg: " + e.errormsg + "\n" +
		" - serverip: " + e.serverip + "\n" +
		" - serverport: " + e.serverport + "\n" +
		" - e.message: " + e.message + "\n" +
		" - e.command : " + e.command );

	if (e.command != null)
	{
		this.fn_setMsg("e.command != null\n" +
			" - e.command.check : " + e.command.check + "\n" +
			" - e.command.row : " + e.command.row + "\n" +
			" - e.command.type : " + e.command.type + "\n" +
		   " - e.command.useactiveformcallback : " + e.command.useactiveformcallback + "\n" +
			" - e.command.actiontype : " + e.command.actiontype + "\n" +
			" - e.command.callback : " + e.command.callback + "\n" +
			" - e.command.messagekey : " + e.command.messagekey + "\n" +
			" - e.command.messagetype : " + e.command.messagetype + "\n" +
			" - e.command.objdataset : " + e.command.objdataset + "\n" +
			" - e.command.objform : " + e.command.objform);	

	}
		
	if (e.message != null)
	{
		this.fn_setMsg("e.message != null\n" +
			" - e.message.messagetype: " + e.message.messagetype + "\n" +
			" - e.message.messagekey: " + e.message.messagekey + "\n" +
			" - e.message.messageid: " + e.message.messageid + "\n" +
			" - e.message.devicetoken: " + e.message.devicetoken);
	}
	
	this.fn_setMsg("e.returnvalue : " + e.returnvalue);
}

Action & statuscode

e.action

XPushAction.AUTH (0) - connect()

XPushAction.BYEC (1) - disconnect()

XPushAction.ADDF (2) - subscribe()

XPushAction.DELF (3) - unsubscribe()

XPushAction.REQD (4) - requestMessage()

XPushAction.RECT (5) - sendResponse()

XPushAction.RGST (6) - reqisterDevice()

XPushAction.UNRG (7) - unreqisterDevice()

XPushAction.ADUI (8) - reqisterUser()

XPushAction.UNUI (9) - unreqisterUser()

XPushAction.MSGC (10) - requestMessageCount()

e.statuscode

-100 - Push 서버가 “Byec”를 보냈거나 서버와의 규약에 따라 종료되었습니다.

-101 - 타임아웃 처리되었습니다.

-200 - Command Auth Error. 현재 선택된 IP에 대해인증에 오류가 발생하였습니다.

-201 - iplist 속성에 등록되어 있는 Push 서버로의 접속이 모두 실패했습니다.

-202 - 데이터 전송 채널 인증(authentication)에 오류가 발생하였습니다.

-300 - 서버로의 접속에 실패했습니다.

-301 - 패킷 전송(send/recv) 오류가 발생하였습니다.

-401 - X-PUSH 서버와 접속해제(disconnect) 요청을 실패했습니다.

-501 - X-PUSH 서버로부터 메시지 수신중단(suspend) 요청을 실패했습니다.

-601 - X-PUSH 서버로부터 메시지 수신 재시작(resume) 요청을 실패했습니다.

-701 - X-PUSH 서버로 topic 등록/등록해제 요청을 실패했습니다.

-801 - 메시지 포맷 버전 정보가 일치하지 않습니다.

-901 - 신뢰성 메시지에 대한 수신응답 전송에 실패했습니다.

-902 - 미수신 메시지 요청을 실패했습니다.

-1001 - X-PUSH 서버로 모바일 DeviceToken 정보 등록요청을 실패했습니다.

-1002 - X-PUSH 서버로 유저 topic 정보 등록요청(reqisterUser)이 실패했습니다.

-1003 - X-PUSH 서버로 유저 topic 정보 등록해제(unregisterUser)요청이 실패했습니다.

-1004 - 미수신 메시지 정보요청을 실패했습니다.

onsuccess

this.XPush00_onsuccess = function(obj:XPush,  e:XPushEventInfo)
{
alert("XPush00_onsuccess Event\n" + 
		" - eventid: " + e.eventid + "\n" +
		" - statuscode: " + e.statuscode + "\n" +
		" - errormsg: " + e.errormsg + "\n" +
		" - reason: " + e.reason + "\n" +
		" - action: " + e.action + "\n" +
		" - serverip: " + e.serverip + "\n" +
		" - serverport: " + e.serverport + "\n" +
		" - e.message: " + e.message + "\n" +
		" - e.command : " + e.command + "\n" +
		" - e.returnvalue : " + e.returnvalue);
	if (e.command != null)
	{
		alert("e.command != null\n" +
			" - e.command.check : " + e.command.check + "\n" +
			" - e.command.row : " + e.command.row + "\n" +
			" - e.command.type : " + e.command.type + "\n" +
			" - e.command.useactiveformcallback : " + e.command.useactiveformcallback + "\n" +
			" - e.command.actiontype : " + e.command.actiontype + "\n" +
			" - e.command.callback : " + e.command.callback + "\n" +
			" - e.command.messagekey : " + e.command.messagekey + "\n" +
			" - e.command.messagetype : " + e.command.messagetype + "\n" +
			" - e.command.objdataset : " + e.command.objdataset + "\n" +
			" - e.command.objform : " + e.command.objform);	

	}
		
	if (e.message != null)
	{
		alert("e.message != null\n" +
			" - e.message.messagetype: " + e.message.messagetype + "\n" +
			" - e.message.messagekey: " + e.message.messagekey + "\n" +
			" - e.message.messageid: " + e.message.messageid + "\n" +
			" - e.message.returnvalue: " + e.message.returnvalue + "\n" +
			" - e.message.devicetoken: " + e.message.devicetoken);
			
		if(e.message.returnvalue != undefined || e.message.returnvalue != null) {
			var returnvalue = e.message.returnvalue;
			
			for(var i = 0; i < returnvalue.length; i++) {
				alert("index:" + i + " : " + returnvalue[i].topictype + " : " + returnvalue[i].topicid + " : " + returnvalue[i].count);
			}
		}
	}
}

action

e.action

XPushAction.AUTH (0) - connect()

XPushAction.BYEC (1) - disconnect()

XPushAction.ADDF (2) - subscribe()

XPushAction.DELF (3) - unsubscribe()

XPushAction.REQD (4) - requestMessage()

XPushAction.RECT (5) - sendResponse()

XPushAction.RGST (6) - registerDevice()

XPushAction.UNRG (7) - unregisterDevice()

XPushAction.ADUI (8) - registerTopic()

XPushAction.UNUI (9) - unregisterTopic()

XPushAction.MSGC (10) - requestMessageCount()