Navision에 메시지 보내기: Navision과의 상호 작용

Manuel Oliveira
Microsoft Portugal

적용 대상:
   Microsoft Navision

요약 : ERP를 다른 기술과 통합하는 것이 불가능하다는 점에서 많은 사람들이 Navision을 폐쇄형 응용 프로그램으로 인식하고 있습니다. 이 기사의 주된 목적은 이러한 인식이 잘못되었다는 것을 보여 주는 데 있습니다.

목차:

소개 소개
일반적인 사실 일반적인 사실
"Hello, World" 응용 프로그램 빌드 "Hello, World" 응용 프로그램 빌드
결론 결론

소개

Navision을 사용하여 개발을 수행해 왔다면 Navision 내의 어떤 기능이든 개발할 수 있다고 확신했던 경험이 있었을 것입니다.

이후에 자동화 변수를 만들어 인스턴스화할 수 있음을 알게 되었을 것입니다. 이는 예컨대 Navision 내에서 Microsoft Excel 시트와 상호 작용하는 일부 코드를 작성할 수 있음을 의미합니다. 이러한 작업을 수행할 수 있음으로 인해 확신은 더욱 확고해집니다.

이제 Navision 비즈니스 계층을 타사 응용 프로그램에 노출시키라는 요청을 받았습니다. 이것은 상당히 까다로운 작업이며, Navision 클라이언트에서 Navision 컨트롤과 상호 작용하는 사용자가 매우 많은 수의 컨트롤을 트리거해야 한다는 것을 알게 되면 지금까지 가져 왔던 확신에 의심이 생깁니다.

그렇다면 이러한 시스템을 외부 요청에 비동기로 응답할 수 있는 무인 서버로 변환하는 방법이 있을까요 걱정하지 마십시오. 이 기사에서는 Navision에게 요청을 보내고 응답을 기다리는 간단한 응용 프로그램을 만드는 방법을 설명합니다. 또한 이와는 반대로 이 기사에서는 Navision이 수신 대기 후 기대하는 답변을 생성하도록 지시하는 방법도 보여 줍니다.

일반적인 사실

이러한 솔루션에 대해 살펴보기 전에 Navision에 관한 몇 가지 사실을 알아야 합니다. 이 기사에서 다룰 솔루션은 이러한 과학적 사실들을 기반으로 하는 기본적인 엔지니어링의 일부일 뿐입니다.

그러므로 다음 단락을 읽기 전에 자동화, Windows 서비스 및 이벤트 처리기(대리자)의 개념을 이해해야 합니다.

이것은 매우 강력한 기능입니다. 자동화 변수를 만들고 인스턴스화하여 자동화 서버에 대해 명령을 실행할 수 있을 뿐 아니라, 자동화 서버가 이벤트에 반응하는 방법을 제어할 수도 있습니다.

예를 들어 Navision codeunit을 디자인하는 경우 Microsoft Excel 통합 문서를 나타내는 자동화 변수와 Microsoft Excel 응용 프로그램을 나타내는 또 다른 자동화 변수를 추가합니다. 코드에서 새 통합 문서를 만들어 응용 프로그램에 추가한다고 가정해 봅시다. 이러한 경우, 실제 사용자인 것처럼 이 통합 문서와 상호 작용하는 코드를 작성할 수 있어야 합니다.

응용 프로그램 변수 WithEvents 속성을 설정하면 이벤트 처리기 헤더 모음을 코드 창에 표시하여 이러한 각 이벤트를 처리하기 위한 코드를 작성할 수 있습니다.

예를 들어 사용자가 활성 통합 문서를 저장할 때마다 Navision 테이블에 레코드를 삽입할 수 있습니다. 통합 문서가 저장됨을 나타내는 팝업 메시지 상자가 표시되므로 이 개념을 더욱 분명하게 확인할 수 있습니다.

참고   이는 변수가 소멸되지 않는 한 계속 유효합니다. 사용자가 통합 문서를 닫으면 해당 Navision 변수는 더 이상 이벤트를 처리하지 않습니다. 통합 문서를 다시 여는 경우에도 마찬가지입니다. 또한 실행 중인 Navision 개체가 반환되면 해당 변수가 자동으로 지워집니다. Excel을 계속 실행 중이더라도 Navision에서는 더 이상 자동화 서버로 인식하지 않습니다.

OnRun()
IF NOT CREATE(ExApp,TRUE) THEN
  EXIT;
ExApp.Visible(TRUE);
ExBook := ExApp.Workbooks.Add;
 
ExApp::WorkbookBeforeSave(Wb : Automation "'Microsoft Excel 11.0 Object Library'.Workbook";SaveAsUI : Boolean;VAR Cancel : Boolean)
MESSAGE ('The Excel book ' + Wb.Name + ' is just being saved!');

앞에서 언급한 것처럼 변수 상태가 유지되지 않으면 이 마지막 메시지 상자를 볼 수 없습니다. 그러나 실행을 계속하면 해당 팝업 메시지가 곧 표시됩니다.

단일 인스턴스 codeunit

일반적으로 모든 Navision 개체는 다른 개체에서 실행 또는 호출되지만 트랜잭션이 끝나면 인스턴스가 재설정되며 해당 변수도 마찬가지로 재설정됩니다.

그러나 이 원칙이 적용되지 않는 주목할 만한 경우가 몇 가지 있습니다. 개체 SingleInstance 속성을 설정하면 해당 상태는 후속 호출에서도 지속됩니다.

이해를 돕기 위해 간단한 예를 들어 보겠습니다. 단일 Integer 변수를 가진 codeunit이 있으며, OnRun() 트리거가 이 변수를 1씩만 증가시키고 현재 값을 나타내는 팝업 메시지 상자를 표시한다고 가정해 봅시다.

앞에서 언급한 속성을 변경하지 않고 codeunit을 실행하면 항상 1이 표시됩니다. 속성을 설정한 후에는 1, 2, 3 등이 연속적으로 표시됩니다.

OnRun()
i := i + 1;
MESSAGE (FORMAT (i));

두 기능의 결합

Excel 통합 문서 작성자 codeunit의 SingleInstance 속성을 설정하는 경우에는 어떻게 될까요 본질적으로 codeunit을 한 번 실행하고 나면 Navision이나 Excel 통합 문서를 닫지 않는 한 다른 Navision 기능과 모듈을 실행할 수 있습니다. Excel 통합 문서를 저장할 때마다 그림 1과 같이 통합 문서를 저장함을 나타내는 메시지가 상자가 Navision 클라이언트에 표시됩니다.

그림 1. 통합 문서를 저장할 때 표시되는 메시지 상자

그림 1. 통합 문서를 저장할 때 표시되는 메시지 상자

이러한 기능을 결합함으로써 매우 강력한 기능을 활용할 수 있습니다. 그러나 여전히 해결해야 할 과제가 하나 있습니다. 바로 앞에서 잠깐 언급한 "무인"에 관한 부분입니다. 이것이 다음에 언급할 '사실'입니다. 좀 더 이해하기가 힘들 수도 있겠군요. 이 부분은 Navision 환경을 중심으로 한 다소 복잡한 시나리오 설정과 관련되어 있기 때문이죠.

NAS(Navision Application Server)는 Windows 서비스입니다. NAS에는 예컨대 Navision Database Server를 찾을 위치와 열어야 할 회사 등을 나타내는 매개 변수 모음이 있습니다.

또한 NAS에는 문자열을 Navision에 전달할 수 있도록 하는 시작 매개 변수 값 항목이 있습니다. 이 문자열에 대해서는 잠시 후에 설명합니다.

NAS Windows 서비스를 시작하면 이 서비스는 제공된 매개 변수를 사용하여 특정 서버에 탑재된 특정 데이터베이스 내에서 특정 회사를 엽니다. 이는 매우 유용하지만 사용자 인터페이스가 전혀 없으므로 해당 진입점을 일반적인 주 메뉴로 사용하지는 않습니다. 대신에 codeunit 1에서 ID가 99인 트리거가 실행됩니다.

참고   이 기능은 Navision Application Server 기술 백서에 설명되어 있습니다. Codeunit 1(ApplicationManagement)에는 NASHandler라는 트리거 99가 있습니다. Application Server를 시작할 때 서버, 데이터베이스 및 회사가 성공적으로 일치하면 이 트리거가 시작됩니다.

앞에서 언급한 문자열은 이 트리거에 전달되는 인수입니다. 이 codeunit을 디자인하는 경우 Navision은 이미 다른 문자열 값을 유효한 시작 매개 변수 값으로 고려합니다.

CASE Parameter OF
  'MAILLOG':
    CODEUNIT.RUN(CODEUNIT::"E-Mail Dispatcher");
  'ADCS':
    BEGIN 
      ADCSNASStartup.SetNASID(COPYSTR(ParamStr,SepPosition + 1));
      ADCSNASStartup.RUN;
    END;
  ELSE
    IF CPApplnSrvSetup.GET(Parameter) THEN BEGIN
      CPApplnSrvMgt.SetNASID(Parameter);
      WORKDATE := 0D;
      IF CPApplnSrvMgt.GetSendMail THEN BEGIN
        MailHandler.RUN;
        MailHandler.StartCountDown(2000);
      END;
      IF CPApplnSrvMgt.GetPerformSynch THEN
        MsgDispatcher.RUN;
      IF CPApplnSrvMgt.GetPerformRequests THEN
        RequestHandler.RUN;
    END ELSE
      ERROR(Text018,Parameter);
END;

다시 결합해야 하나요

예, 무조건 그렇게 해야 합니다. 단지 시작 매개 변수 값(예: EXCEL)을 선택한 다음 이러한 매개 변수로 NAS를 시작할 때마다 실행되는 트리거 99 내의 CASE 명령에 항목을 추가하기만 하면 됩니다.

그림 2. 가능한 Navision Application Server 구성

이 구성은 단순히 Excel 통합 문서 변수 이벤트가 Navision 내에서 처리되는 단일 인스턴스 codeunit을 호출합니다.

이러한 시나리오에서는 그림 2에 있는 매개 변수로 NAS 서비스를 시작하면 Excel이 갑자기 시작되는데, 이는 Navision 클라이언트가 사실상 존재하지 않기 때문입니다. 이것이 우리의 흥미를 끄는 첫 번째 부분입니다.

게다가 통합 문서를 저장할 때마다 이벤트 뷰어 메시지가 표시되는데, 이것이 흥미로운 두 번째 부분입니다. 아시다시피 이러한 팝업 메시지 상자를 표시하는 사용자 인터페이스가 없기 때문에 Navision 코드에서는 이벤트 뷰어 메시지를 생성하는 것입니다.

이는 매우 유용한 기능이지만 Navision이 단지 Excel이 아니라 모든 타사 응용 프로그램과 통신해야 한다는 주요 문제를 해결하지는 않습니다.

통신 구성 요소 소개

Navision 통신 구성 요소는 몇몇 전송 인터페이스와 프로토콜을 통해 정보를 주고 받을 수 있도록 하는 자동화 서버 집합입니다. 적어도 소켓, 명명된 파이프 및 메시지 대기열을 사용할 수 있으므로 선택한 옵션에 따라서 견고성과 효율성의 차이점을 경험할 수 있을 것입니다.

개인적으로는 메시지 대기열을 선호하는데, 다음과 같은 방법으로 뛰어난 메시지 추상화를 제공하기 때문입니다.

  • 우선 순위에 따라서 또는 단순히 FIFO(선입선출, first-in first-out) 방식에 따라서 메시지를 대기시킬 수 있습니다.

  • 각 메시지 간의 통일성을 고려합니다.

  • 메시지 수신자를 지정하는 일종의 봉투 안에 메시지를 넣을 수 있습니다.

이것은 실제 우체국에서 편지를 다루는 방법과 매우 비슷하기 때문에 그만큼 뛰어난 추상화가 제공됩니다.

참고   이 기사에서는 설명을 위해 메시지 대기열을 사용합니다. 그러나 코드를 약간 변경하면 다른 방법을 선택할 수도 있습니다. 여기에서 설명하고자 하는 차이점을 보여 주는 Navision 제품 CD의 devguide.chm 파일을 확인해 보시기 바랍니다.

이러한 각 통신 구성 요소 유형은 정보를 수신할 때마다 시작되는 이벤트 처리기를 개발자에게 제공합니다. 메시지 대기열 시스템 시나리오에서 이러한 이벤트 처리기는 최소한 하나 이상의 메시지가 대기열에 있을 때마다 시작되어 사용할 수 있는 상태가 됩니다.

사실로부터 결론 도출

Microsoft Excel을 시나리오에서 제외하고 이러한 통신 구성 요소 유형 중 하나를 포함할 경우 어떻게 될 것인지 잠시 생각해 보겠습니다. 이 경우에는 통합 문서 저장 이벤트 대신 메시지 도착 이벤트를 처리할 것입니다.

요약하자면, 단일 인스턴스 codeunit을 시작하는 Windows 서비스(NAS)를 갖게 될 것이며 이 서비스는 메시지 도착을 처리할 수 있습니다. 이제 Navision에서 메시지를 비동기적으로 수신할 수 있습니다. 이러한 메시지를 구문 분석하고 적절한 비즈니스 계층 기능을 실행하며 초기 메시지에 대한 적절한 응답을 작성하는 코드를 작성하기만 하면 됩니다.

그림

그림 3. 제안된   아키텍처   논리   다이어그램 (Navision )

이제 본격적으로 몇 가지 작업을 준비해 봅니다.

"Hello, World" 응용 프로그램 빌드

마지막 사실을 충분히 숙지하고 이해했다면 지금까지 배운 것들을 현명하게 결합하여 개발자에게 할당된 작업을 수행하는 간단한 시스템을 쉽게 배포할 수 있습니다.

그러나 여기서 이러한 사실을 입증하는 간단한 예를 제공하고자 합니다. 두 개의 텍스트 상자와 한 개의 단추가 있는, 그림 4와 같은 간단한 Microsoft Visual C# 응용 프로그램을 빌드해 봅니다.

첫 번째 텍스트 상자에 내용을 입력한 다음 단추를 누릅니다. 통신에 성공하면 두 번째 텍스트 상자에는 첫 번째 텍스트 상자에 입력한 내용이 대문자로 바뀐 내용이 채워집니다.

그림

그림 4. Visual C# 응용   프로그램   기본     레이아웃

이는 확실히 독립 실행형 응용 프로그램이라 할 수 있습니다. 문자열을 대문자로 표시하는 데 Navision이 필요하지 않기 때문입니다. 반면, Navision을 사용하여 문자열을 대문자로 표시하기 위한 외부 요청을 비동기적으로 처리할 수 있다면 Navision을 모든 용도에 사용할 수 있다는 믿음이 더욱 확고해질 것입니다.

환경 준비(Navision 쪽)

그림 3에서 볼 수 있는 것처럼 시나리오 개발 전에 설정해야 하는 환경이 있습니다.

Navision 제품 CD에서 Navision 클라이언트, 데이터베이스 서버 및 응용 프로그램 서버를 설치할 수 있습니다.

참고   을 사용하고 있습니다. 이 버전에서 Navision Application Server의 기능이 크게 향상되었지만 이 Windows 서비스가 포함되어 있다면 다른 버전을 사용해도 관계없습니다.

먼저 클라이언트를 설치하여 이러한 용도로 사용할 수 있는 데모 데이터베이스를 얻는 것이 좋습니다. 그리고 데이터베이스 서버를 설치합니다.

   캐시의 크기를 수동으로 조정할 수 있는 사용자 지정 설치를 선택해야 합니다. 그렇지 않을 경우 서버는 캐시 크기 조정을 위해 매우 많은 양의 메모리를 할당하는데, 이를 처리할 리소스가 부족할 수도 있기 때문입니다. 개인적인 경험에 따르면 20000Kb 정도가 테스트용으로는 적합합니다. 또한 설치된 데이터베이스에 클라이언트와 함께 서버를 바인딩해야 합니다.

그런 다음 Navision Application Server를 설치합니다. 그러면 각 데이터베이스 서버 유형(Navision Server와 SQL Server)에 대해 하나씩, 두 개의 Windows 서비스가 설치됩니다. 여기서는 Navision Server를 데이터베이스 서버로 사용하므로 다른 하나는 사용하지 않도록 설정할 수 있습니다. 사용 권한이 없는 등의 보안 문제가 발생할 경우에는 다음 계정으로 로그온 권한을 서비스에 부여하여 관리 계정에 바인딩할 수 있습니다.

서비스와 함께 콘솔도 설치됩니다. 이 콘솔을 사용하면 NAS 인스턴스를 관리할 수 있습니다. 그림 2는 이러한 콘솔에 포함될 수 있는 세부 정보 창을 보여 줍니다.

   원하는 진입점을 사용하여 서비스에서 Navision에 연결할 수 있도록 모든 매개 변수가 허용하는지를 먼저 확인한 후에 Application Server 인스턴스를 시작하십시오. 그렇지 않으면 Application Server가 연결을 시도하는 동안 리소스가 소비되고 응용 프로그램 로그가 쓸모 없는 메시지로 채워집니다.

마지막으로 메시지 대기열이 설치되었는지 확인합니다. 이것은 운영 체제에 따라 다릅니다. Windows XP에서는 제어판의 프로그램 추가/제거 옵션에서 Windows 구성 요소 추가/제거 단추를 사용하여 설치할 수 있습니다.

두 개의 대기열을 추가합니다. 여기서는 공개 대기열을 사용하지만 필요에 따라 개인 대기열을 만들 수도 있습니다. 나중에 개인 대기열을 참조할 때는 이름 앞에 private$를 접두어로 사용해야 합니다. fromNavision 및 toNavision과 같이 의미를 알 수 있는 이름을 사용합니다.

이제 다음 단계에서 환경을 필요에 맞도록 지정할 준비가 되었습니다.

필요에 맞도록 Navision 지정

이 기사에서는 Navision을 외부 개발 환경에서 사용할 수 있는 방법을 설명하므로, 외부 개발 환경에 대해 최대한의 투명성을 보장할 수 있도록 메시지 처리를 Navision 쪽에서 처리하도록 하는 것이 좋겠습니다.

다시 말해서 Navision에서 개발하는 코드는 C# 응용 프로그램이 채택하는 메시징 형식을 따라야 합니다. 앞으로 설명하겠지만, 문자열 변수가 있고 해당 문자열을 메시지 대기열로 보내기만 하는 경우에는(C#에서는 이 작업을 단 한 줄의 코드로 처리할 수 있음) XML 문서를 보내게 됩니다. 이 문서에는 이름이 string이고 보내는 문자열의 내용이 내용으로 들어 있는 단일 노드가 있습니다. 예를 들어 그림 4의 메시지를 보내는 경우 XML 문서는 다음과 같습니다.

<?xml version="1.0">
<string>Hello, world!</string> 

이러한 점을 염두에 두고 Navision 데이터베이스를 필요에 맞게 지정하는 방법을 살펴보겠습니다.

먼저, 새 codeunit을 만듭니다. 이 codeunit에 다음 전역 변수를 추가합니다.

이름

DataType

Subtype

WithEvents

MQBus

Automation

'Navision MS-Message Queue Bus Adapter'.MSMQBusAdapter

 

CC2

Automation

'Navision Communication Component version 2'.CommunicationComponent

Yes

InMsg

Automation

'Navision Communication Component version 2'.InMessage

 

InS

InStream

 

 

XMLDom

Automation

'Microsoft XML, v3.0'.DOMDocument

 

XMLNode

Automation

'Microsoft XML, v3.0'.IXMLDOMNode

 

OutMsg

Automation

'Navision Communication Component version 2'.OutMessage

 

OutS

OutStream

 

 

Navision이 CC2라는 자동화 컨트롤로부터 이벤트를 수신하도록 지정하면 코드 창에 추가 프로시저 헤더가 표시됩니다.

CC2::MessageReceived(VAR InMessage : Automation "''.IDISPATCH") 

여기서 특정 대기열이 메시지를 수신할 때마다 실행되는 코드를 작성합니다. 해당 대기열은 다른 위치에서 구성해야 합니다. 대기열을 구성할 수 있는 가장 확실한 위치는 OnRun() 트리거입니다. 이 트리거는 다음과 같습니다.

OnRun()
CREATE(MQBus);
CREATE(CC2);
CREATE (XMLDom);
CC2.AddBusAdapter(MQBus,1);
MQBus.OpenReceiveQueue('.\toNavision',0,0); 

코드의 처음 세 줄은 자동화 변수를 만듭니다. 그리고 4번째 줄은 버스 어댑터를 통신 구성 요소 자동화 변수에 추가합니다. 여기서 다른 버스 어댑터(예: 소켓 버스 어댑터)를 선택하면 코드가 달라집니다.

이러한 구성 요소는 개발자가 버스 어댑터를 구성하여 Navision에서 이벤트를 캡처하는 통신 구성 요소로 추가할 수 있도록 설계되었으며, Navision은 추가된 어댑터에 상관없이 해당 인터페이스를 유지하는 이벤트 처리기를 제공합니다. 다시 말해서 어댑터가 메시지를 수신하도록 구성했다면 메시지가 존재하고 해당 인수가 메시지 본문을 전달할 때마다 처리기가 시작됩니다.

어댑터 구성은 5번째 줄에 있습니다. 여기서는 코드가 새 메시지를 수신 대기하는 메시지 대기열을 지정합니다.

앞에서 언급한 것처럼 새 codeunit에 대한 SingleInstance 속성을 설정해야 하므로 이러한 변수는 트리거가 반환된 후에도 계속 유지됩니다. 코드 창에서 View 메뉴를 선택한 다음 Properties를 선택하여 codeunit의 속성을 표시합니다.

이제 "작업자 스레드"는 다음과 같습니다.

CC2::MessageReceived(VAR InMessage : Automation "''.IDISPATCH")
// 메시지를 가져옵니다.
InMsg := InMessage;
InS := InMsg.GetStream();
 
// 메시지를 XML 문서로 로드하고 노드를 찾습니다.
XMLDom.load (InS);
XMLNode := XMLDom.selectSingleNode ('string');
 
// 응답 대기열을 열고 새 메시지를 만듭니다.
MQBus.OpenWriteQueue('.\fromNavision',0,0);
OutMsg := CC2.CreateoutMessage('Message queue://.\fromNavision');
OutS := OutMsg.GetStream();
 
// 메시지 내용을 작성합니다.
XMLNode.text := UPPERCASE (XMLNode.text);
 
// 메시지를 채운 다음 보냅니다.
OutS.WRITE(XMLDom.xml);
OutMsg.Send(0);(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)
어떠한 작업을 수행하는지 제대로 이해하기 위해 잠시 살펴보도록 하겠습니다.
// 메시지를 가져옵니다.
InMsg := InMessage;
InS := InMsg.GetStream();

처음 두 줄의 코드에서는 수신하는 메시지 내용을 Navision 스트림 변수로 가져옵니다.

// 메시지를 XML 문서로 로드하고 노드를 찾습니다.
XMLDom.load (InS);
XMLNode := XMLDom.selectSingleNode ('string');

그런 다음 XML DOM을 사용하여 Navision 스트림을 열린 파일처럼 가져오고 XML 문서에 로드합니다. 다시 DOM 기능을 사용하여 XML 문서에서 string이라는 노드를 쿼리합니다.

// 응답 대기열을 열고 새 메시지를 만듭니다.
MQBus.OpenWriteQueue('.\fromNavision',0,0);
OutMsg := CC2.CreateoutMessage('Message queue://.\fromNavision');
OutS := OutMsg.GetStream();

이제 회신 대기열을 열고 새 메시지를 만듭니다. 그런 다음 새 메시지 스트림이 되도록 출력 스트림 변수를 초기화합니다.

// 메시지 내용을 작성합니다.
XMLNode.text := UPPERCASE (XMLNode.text);

이 코드 줄은 비즈니스 논리를 나타냅니다. 실제 환경에서는 이 섹션에서 복잡한 Navision 함수를 호출합니다. 이제 이러한 작업이 가능함을 알게 되었습니다. 예를 들어 헤더와 구매서 줄이 포함된 XML 문서를 받아 적절한 위치에 삽입한 다음 게시하면 Navision이 적절하다고 판단하는 모든 내부 모듈이 실행됩니다.

이 경우에는 쉽게 이해할 수 있도록 간단한 문자열 대문자 표시를 비즈니스 논리로 사용합니다.

// 메시지를 채운 다음 보냅니다.
OutS.WRITE(XMLDom.xml);
OutMsg.Send(0);

응답이 완료되면 클라이언트에 전송됩니다.

참고   여기서는 요청 메시지의 내용만 변경했습니다. 실제 시나리오에서는 이와 다를 수 있습니다. 실제 시나리오에서는 요청으로 게시할 구매서를 가져온 다음 클라이언트 응용 프로그램으로 구매서를 되돌려보내는 대신 성공/실패 메시지로 회신합니다. 이 기사에서는 편하게 메시지 구조를 유지하고 내부 데이터를 대문자로 표시하기만 합니다.

지금까지 통신 구성 요소를 사용했고 SingleInstance 속성을 설정했으며 자동화 변수 이벤트를 처리하기 위한 코드를 작성했습니다. 이제 빠진 부분은 이러한 모든 작업을 완전 자동 무인 프로세스로 변환하는 Application Server 부분뿐입니다. 자동화 전에 이 codeunit을 몇 번 정도 수동으로 실행할 수도 있습니다. 이러한 방식으로 Navision Debugger를 사용할 수 있습니다.

앞에서 살펴본 것처럼, 직접 작성한 codeunit을 Application Server에서 자동으로 실행하도록 하려는 경우에는 codeunit 1을 변경해야 합니다. 아래 코드 샘플과 같이 codeunit을 가리키는 전역 변수(예: 이름이 NAVCOMM인 변수)를 codeunit 1에서 만들고 NASHandler 트리거를 찾은 다음 대/소문자 옵션을 추가하면 됩니다.

CASE Parameter OF
  'MAILLOG':
    CODEUNIT.RUN(CODEUNIT::"E-Mail Dispatcher");
  'ADCS':
    BEGIN 
      ADCSNASStartup.SetNASID(COPYSTR(ParamStr,SepPosition + 1));
      ADCSNASStartup.RUN;
    END;
  'NAVCOMM':
    BEGIN 
      NAVCOMM.RUN;
    END;
  ELSE
    IF CPApplnSrvSetup.GET(Parameter) THEN BEGIN
      CPApplnSrvMgt.SetNASID(Parameter);
      WORKDATE := 0D;
      IF CPApplnSrvMgt.GetSendMail THEN BEGIN
        MailHandler.RUN;
        MailHandler.StartCountDown(2000);
      END;
      IF CPApplnSrvMgt.GetPerformSynch THEN
        MsgDispatcher.RUN;
      IF CPApplnSrvMgt.GetPerformRequests THEN
        RequestHandler.RUN;
    END ELSE
      ERROR(Text018,Parameter);
END;

물론 NAS 인스턴스가 이 시작 매개 변수 값(NAVCOMM)을 가지도록 Navision Application Server Manager를 구성해야 합니다. 그렇지 않으면 codeunit이 시작되지 않으므로 외부 요청을 처리할 수 없습니다.

이제 Application Server 인스턴스를 안전하게 시작할 수 있습니다. 응용 프로그램 로그에서는 그림 5와 같은 이벤트가 표시됩니다.

그림 5. Navision Application Server 시작   성공

이 서비스를 위한 클라이언트 응용 프로그램 만들기

이제 대부분의 작업을 Navision에서 처리하므로 다른 쪽의 작업은 최소화되어야 합니다. 이 아키텍처에서는 이러한 작업이 정확하게 이루어지며, 개발자는 요청 서식을 지정하고 응답을 수신할 때 Navision에 대해 거의 신경쓸 일이 없음을 곧 알게 됩니다.

Microsoft Visual Studio .NET 개발 환경을 열고 새 Windows 응용 프로그램 프로젝트를 만듭니다.

기본 폼 위에 그림 4와 같이 세 개의 컨트롤을 배치합니다. 상단 텍스트 상자 이름을 txtSend로, 단추 이름을 btnSend로, 하단 텍스트 상자의 이름을 txtReceive로 지정합니다.

그림

그림 6. 대기열을   표시하는 Visual Studio .NET 서버   탐색기

이제 이러한 용도로 만든 두 개의 대기열을 폼 위로 끌어 두 개의 System.Messaging.MessageQueue 인스턴스를 만듭니다. 그림 6과 같은 서버 탐색기를 사용할 수 있습니다. 대기열의 이름을 mqFromNavisionmqToNavision으로 적절하게 지정합니다.

다음 코드를 Form 생성자에 추가합니다.

public Form1()
{
   //
   // Windows Form 디자이너 지원에 필요합니다.
   //
   InitializeComponent();
 
   //
   // TODO: InitializeComponent 호출 후에 임의의 생성자 코드를 추가합니다.
   //
   mqFromNavision.Formatter = new
      System.Messaging.XmlMessageFormatter(new Type[] {typeof(String)});
}

이 코드 줄은 문자열을 포함하는 메시지가 필요함을 mqFromNavision 변수에 알립니다.

이 변수의 속성 페이지를 열고 Events 단추를 클릭합니다. ReceiveCompleted 항목을 두 번 클릭하면 다음과 같이 채워질 대리자가 만들어집니다.

private void mqFromNavision_ReceiveCompleted(object sender, System.Messaging.ReceiveCompletedEventArgs e)
{
   System.Messaging.Message m = 
      mqFromNavision.EndReceive(e.AsyncResult);
   txtReceive.Text = (string)m.Body;
}

메시지를 수신하는 것은 메시지를 대기열에서 가져와 해당 데이터를 하단 텍스트 상자에 복사하는 것처럼 간단합니다. 이 대기열에서 수신할 메시지 종류를 이미 시스템에 알렸기 때문에 안전하게 본문을 가져와 다른 위치에 표시할 수 있습니다. 여기서, Navision에 대한 특정 참조는 표시되지 않습니다.

한 가지 빠뜨린 점이 있다면, 메시지를 Navision을 보낼 수 있다는 것입니다. 여기서는 Navision에 대한 필수 외부 참조만 표시됩니다. 즉, 다음과 같습니다.

private void btnSend_Click(object sender, System.EventArgs e)
{
   mqToNavision.Send (txtSend.Text, "Navision MSMQ-BA");
   mqFromNavision.BeginReceive (new System.TimeSpan (0,0,0,30));
}

메시지를 Navision으로 보낼 때는 레이블을 Navision MSMQ-BA로 지정합니다. 그렇지 않으면 위에서 구현한 CC2::MessageReceive Navision 트리거가 메시지를 인식하지 않습니다.

결론

마지막으로 이 기사를 통해 수행한 작업에 대해 최소한 다음과 같은 몇 가지 사항을 짚어 봐야 합니다.

Navision 비즈니스 모델을 사용하려는 이러한 종류의 통합을 수행하는 것과 관련하여 최우선으로 염두에 두어야 하는 사항이자 가장 중요한 사항은 Navision 비즈니스 모델을 정확하게 사용해야 한다는 것입니다. 잘못된 입력 데이터로부터 보호되는 복잡한 비즈니스 논리를 다루다 보면 이 사항은 개발에 있어서 까다로운 문제가 될 수 있습니다.

Navision은 실제로 많은 사람들이 Navision 클라이언트를 사용하도록 하기 위해 설계되었습니다. 이러한 점을 고려할 때 사용자가 잘못된 데이터를 입력하는 경우 트랜잭션을 롤백하고 오류 메시지 상자를 생성하는 것이 바람직합니다. 그러나 사용자가 Application Server인 경우에는 이러한 상황에서 트랜잭션을 롤백하는 것이 좋지 않을 수 있습니다. 특히 시스템이 요청을 보낸 사람에게 응답 메시지를 보내지 않은 경우에는 더욱 그러합니다.

비즈니스 모델에 따라 오류가 구성되지 않도록 입력 데이터의 유효성을 미리 검사하거나, 보다 유연한 모델에서 오류가 처리되도록 비즈니스 모델을 변경하는 것은 개발자의 책임입니다. 이러한 경우 개발자가 오류 메시지를 통해 응답 메시지를 보증한다면 외부 응용 프로그램에서는 생소한 문제가 발생하지 않을 것입니다.

통신 계층을 웹 서비스로 래핑하는 것을 고려해 보십시오. 외부 응용 프로그램이 메시지 대기열로 이동하는 메시지를 인스턴스화하도록 하는 것보다는 웹 메서드를 호출하도록 하는 것이 좋습니다. 웹 서비스 빌드 여부에 상관없이 메시지 대기열 경로를 구성 키로 지정해 보십시오. 그러면 환경을 변경해야 하는 경우 시나리오가 다른 대기열 집합을 가리키도록 손쉽게 지정할 수 있습니다.

또한 코드를 예외 캐처(exception catcher)와 예외 처리기(exception handler)로 래핑하는 것도 좋습니다. 이 기사에서는 단지 개념을 검증하는 것이 목적이므로 이렇게 하지는 않았습니다. 그러나 NAS 서비스가 작동하지 않는 등 문제가 발생하는 경우에는 처리되지 않은 까다로운 예외(exception)가 발생합니다. 개발자라면 이런 문제를 가끔씩 경험하는 것도 좋겠지만, 사용자에게는 전혀 즐거운 일이 아니겠죠.

Manuel Oliveira는 Microsoft Portugal에서 제휴 엔지니어로 일하고 있습니다. 이전에는 Microsoft Business Solutions 제품 관리자로서 자사 응용 프로그램을 Navision과 통합하려는 파트너와 긴밀하게 협력해 왔습니다. 그는 이 기사에 사용된 것과 유사한 방식으로 Navision 3.70과 Autodesk Inventor 8.0 간에 커넥터를 구현했습니다.