 |
|
난이도 : 중급 Dan Kehn, 선임 소프트웨어 엔지니어,
IBM
2008 년 3 월 25 일 IBM Lotus Sametime Connect를 여러분 팀만의 채팅 기능으로 커스터마이즈하는 방법을 배워보겠습니다. 이 확장은 REST 서비스 API를 사용하여 IBM Lotus Connections에서 접근 가능한 프로파일 정보를 이용합니다.
이 글은 사용자는 대화 상대의 동료에게 더 쉽게 도움을 요청할 수 있게 IBM Lotus Sametime Connect를 확장하는 방법을 다룬다. 솔루션은 IBM Lotus Connections의 프로파일(Profiles) 구성요소에 있는 부서 계층을 활용한다. 같은 솔루션은 비즈니스만의 관계를 사용하여 직원들을 연결하는 데 도움이 되도록 쉽게 확장할 수 있다(예를 들어 특정 흥미를 공유하고 전문가를 알아보고 조직 구성원을 지원하는 등).
표준 Lotus Sametime Connect 채팅 창 인터페이스에는 그림 1처럼 Invite Others 버튼이 있다.
그림 1. Lotus Sametime Connect의 Invite Others 버튼
이 버튼을 클릭하면 그림 2에서 볼 수 있는 것처럼 다방향 채팅을 시작할 수 있는 대화상자가 열린다.
그림 2. Invite Others 대화상자
이클립스와 IBM Lotus Sametime SDK를 사용하여 그림 3에서 강조한 것처럼 채팅 창 툴바에 특별한 버튼을 추가한다.
그림 3. 채팅 창의 수정된 툴바
Invite Coworkers 버튼은 Invite Others 버튼과 같은 대화상자를 보여주지만 초기 설정이 대화 상대의 온라인 동료라는 점이 다르다.
필요한 사전지식
이 글에서 보여주는 코딩 기법을 이해하려면 다음 기술과 전문성을 갖춰야 한다.
- 약간의 자바 프로그래밍 기술
- REST API 지식
- 이클립스 IDE 지식
- Abdera와 XPath에 대해 안다면 도움이 되겠지만 필수조건은 아니다.
솔루션을 실행하려면 워크스테이션에 Lotus Sametime Connect V7.5.1이나 V8.0이 설치해야 하고 IBM Lotus Connections 서버에 웹 접근이 가능해야 한다. 접근할 수 있는지 여부는 회사 Lotus Connections 서버의 프로파일 홈 페이지(예를 들어 http://<connections.insertyourwebsite>.com/profiles/; 적절한 URL을 모른다면 시스템 관리자에게 연락한다)를 방문하여 접근할 수 있는지 확인할 수 있다.
이 기사의 예제 코드는 다운로드 절에서 받을 수 있다. 플러그인 프로젝트가 두 개 포함되어 있다.
- com.ibm.collaboration.realtime.sample.invitecoworkers에 이 글에 대한 완전하게 코딩된 솔루션이 있다
- com.lotuslabs.invitecoworkers에 이 글에 대한 부분적으로 코딩된 솔루션이 있다.
이 글을 통해 솔루션을 완성하는 데 필요한 코드를 추가한다. 개발 환경을 설정하려면 아래 단계를 따른다.
주의: 솔루션은 아래 지시된 필요한 도구의 특별 버전으로 코딩됐다. 최신 버전일수록 별 수정 없이 사용할 수 있겠지만 이 글은 아래 버전으로 테스트됐다.
-
이클립스 3.2.2 버전을 설치한다.
- 이클립스를 시작하고 IBM Lotus Expeditor Toolkit V6.1.1을 설치한다. 설치는 developerWorks의 "Using IBM Lotus Expeditor Toolkit V6.1.1 with IBM Lotus Notes V8 and IBM Lotus Sametime V7.5.1" 중 "Lotus Sametime V7.5.1 developer" 절의 설명을 참고하자. 이클립스 플러그인 개발에서 Lotus Sametime Connect를 실행할 수 있는지 확인하자.
- File - Import - General - Existing Projects를 선택하여 article 프로젝트(다운로드 절을 보라)를 작업공간에 임포트하자. 솔루션이 다음 단계에서 설치될 Abdera 라이브러리를 사용하므로 이 시점에서는 컴파일러 오류가 날 것이다.
-
Abdera 0.3.0을 받는다. 그림 4처럼 article 프로젝트에 abdera.0.3.0-incubating.jdk142.zip 파일 압축을 푼다(예를 들어 C:\eclipse\workspace\com.lotuslabs.invitecoworkers와 C:\eclipse\workspace\com.ibm.collaboration.realtime.sample.invitecoworkers에 ZIP 파일 압축을 푼다).
- 두 프로젝트를 선택한 후 Package Explorer 팝업 메뉴에서 새로고침을 한다. 이클립스는 새 라이브러리를 인식하고 두 프로젝트를 다시 빌드한다. 이 단계를 마치고 나면 Problems 창에 오류가 없어야 한다.
- article 단계를 따르려면 com.lotuslabs.invitecoworkers 프로젝트를 수정한다. 솔루션 프로젝트인 com.ibm.collaboration.realtime.sample.invitecoworkers는 참고자료고 지금은 필요 없다. 계속하기 전에 닫는다.
그림 4. Abdera 설치로 Package Explorer에 보이는 솔루션 프로젝트
솔루션 개요
솔루션에는 두 기술이 있다. Lotus Sametime Connect는 인스턴트 메시징 사용자 인터페이스, 디렉터리 서비스, 채팅 API를 클라이언트에 제공한다. Lotus Connections Profiles 서버는 부서 정보를 제공한다. 이 API들을 결합함으로써 확장은 더 풍부한 협업 경험을 전달한다.
다음은 배울 기술이다.
- 새 UI 요소(특히 새 Invite Coworkers 버튼)를 Lotus Sametime Connect에 추가하는 방법.
- 이메일 주소와 같은 대화 상대에 관한 추가 정보에 접근하는 방법
- 부서 관계(매니저, 동료 등)에 관한 정보를 찾아오기 위해 Lotus Connections Profiles를 활용하는 방법
- Lotus Connections Profiles에서 연락처 목록에 있는 Lotus Sametime에 있는 사람들과 부서 연락 정보를 매핑하는 방법
이클립스 플러그인 개발 환경(PDE)은 이 글의 "필요한 사전지식" 절에서 설명한 것처럼 이미 설정되어 있어야 한다. 특별히 흥미롭지 않는 솔루션 부분은 이미 구현됐으므로 여기 나열된 기술에 주목할 수 있다. 본 실습의 일환으로 이클립스 통합 개발 환경(IDE)을 사용한다. 이 글은 독자들이 이클립스 IDE에 경험이 있다고 가정하고 있다.
이클립스 플로그인 모델과 Lotus Sametime Connect 애플리케이션 프레임워크가 낯설다면 요약부분을 읽자. 이 글의 요점이 뭔지 파악하는 데 도움이 될 것이다.
Lotus Sametime 커넥스 아키텍처 개요
Lotus Sametime Connect만의 특징 중 하나는 확장성이다. 이클립스 플러그인 모델 덕에 새 기능을 사용자 인터페이스로 자연스럽게 커스터마이즈할 수 있다.
이클립스 리치 클라이언트 플랫폼(RCP)과 IBM Lotus Expeditor는 Lotus Sametime Connect의 토대 역할을 한다. 이 플랫폼을 선택하면 다른 애플리케이션 구성요소, 즉 다른 플러그인과 자연스럽게 통합할 수 있다는 장점이 있다. 이 플러그인들은 간단하게는 새 툴바 버튼이, 복잡하게는 완전히 통합된 미니 애플리케이션이 될 수 있다. Lotus Sametime Connect - 이클립스 - IBM Expeditor 아키텍처의 전반적인 목표는 확장성, 통합, 재사용이라는 세 가지 장점을 제공하는 데 있다.
이클립스/Lotus Expeditor를 통합 플랫폼으로 사용하면 환경에 새 기능을 추가할 수 있는 능력을 갖게 된다. 유연하면서도 일관적인 사용자 경험은 상품의 강조점(selling point)이지만 이클립스 프로그래머들에게는 기존 기술을 활용하여 표준 이클립스 RCP 사업 분야의 애플리케이션을 개발할 수 있다는 혜택이 있다.
이클립스 애플리케이션 개발의 주 원칙은 Lotus Sametime Connect와 IBM Lotus Notes V8 같은 여타의 Lotus Expeditor 기반 제품들에 대한 확장을 만드는 데 직접 적용된다. 이클립스 애플리케이션 개발 경험이 없는 프로그래머들도 이 원칙에서 일반적인 객체지향 프로그래밍 패턴을 인식한다. 예를 들어 이클립스는 모델(Workbench)과 뷰(JFace 프레임워크의 ViewParts와 하위 레벨의 그래픽 구성요소)의 분리라는 고전적인 원칙을 따른다. 그러므로 구성요소를 명확히 분리한다는 원칙은 생산성을 위해 개별 부분을 익혀야 한다는 부담을 덜어준다. Lotus Sametime 아키텍처는 이 원칙을 고수한다.
그림 5는 Lotus Sametime Connect의 주요 구성요소를 보여준다. 자바 런타임, 이클립스 RCP, Lotus Expeditor 층은 Lotus Notes V8 등 IBM에서 관리하는 클라이언트 제품에 공통되는 기반이다. 상자로 둘러쌓인 구성요소는 Lotus Sametime Connect에 한정된 것이고 여기에는 공개적이고 구현에 한정된 플러그인이 포함된다.
그림 5. Lotus Sametime Connect 구성요소
Lotus Sametime은 이클립스 플랫폼을 기반으로 하기 때문에 애플리케이션은 기본적으로 여러 개의 플러그인이 한 데 엮인 것이다. 각 플러그인은 특정 기능을 정의하는 자바 클래스 패키지라 생각할 수 있다. 이 몇몇 패키지는 다른 것들에 의해 확장되도록 디자인되어 있어 기본 기능을 강화하는 추가 플러그인을 개발할 수 있다. 적절한 플러그인을 의존성으로 선언하기 위해 플러그인이 필요로 하는 기본 기능을 결정해야 한다. 이렇게 하면 클래스 라이브러리와 만드는 토대가 되는 확장점에 접근할 수 있다.
필수 플러그인 목록에 의해 제공되는 주어진 확장점으로 사용자 인터페이스와 통합하는 플러그인을 어디에 둘 것인지 결정한다. 각 플러그인은 제어 기능을 기반으로 다중 확장점을 가질 수 있다. 예를 들어 Lotus Sametime의 채팅 창 플러그인의 의존성(플러그인 식별자인 com.ibm.collaboration.realtime.chatwindow에 의해 참조되는)은 채팅 창 툴바와 팝업 애드온(채팅 창 Send 부분 아래에 뜨는 창)을 추가하는 확장점에 접근할 수 있다. 적절한 확장점이 식별되어야 하고 확장은 정의되어야 한다. 이클립스에는 단계별로 안내하는 템플릿 주도 마법사가 있어 이를 간단히 해결한다.
확장점이 식별되고 플러그인 확장이 정의된 후 새 기능을 수행하는 데 필요한 자바 클래스를 코딩한다. 이클립스는 필요한 슈퍼클래스와 확장에 필요한 인터페이스를 권장하며 지원한다.
이 글의 목적을 위해 Invite Others 대화상자에 대화 상대의 동료 목록을 나타내 사용자 인터페이스에 하나의 확장점만 추가하고 원하는 기능을 구현하는 데 몇 가지 구성요소를 추가한다. 다루는 구성요소는 다음과 같다.
- 채팅 창에 버튼을 제공하는 사용자 인터페이스 구성요소
- 디렉터리 서비스와 기타 기능 구현에 접근하는 서비스
- 이메일을 실제 Lotus Sametime person 객체에 매핑하는 디렉터리
- 채팅 세션을 초기화하는 메시징 서비스
또한 REST API를 사용해 Lotus Connections Profiles 서버에서 데이터를 찾아오는 방법을 다룬다.
채팅 창에 Invite Coworkers 버튼 추가하기
Lotus Sametime 구성요소를 구성하는 플러그인에서 개발자가 자신의 개발에 사용하는 인터페이스와 만들어진 클래스에 접근할 수 있는 확장점을 선언한다. 확장점은 Lotus Sametime의 기능을 확장할 수 있다는 의미다. 플러그인에서 확장을 정의하여 다른 개발자들이 기능을 만들 수 있도록 할 수 있다. 하지만 그 기능은 이 글에서는 다루지 않겠다.
RCP라는 이클립스 애플리케이션 사용자 인터페이스는 그래픽 위젯(엔트리 필드, 버튼, 툴바 등)과 상위 사용자 인터페이스 요소(주요 창 또는 Workbench, 뷰, 편집기 등)를 정의한다. Lotus Sametime Connect는 이클립스 사용자 인터페이스 확장을 지원하고 빌드한다. 예를 들어 플러그인은 이클립스 확장점인 org.eclipse.ui.actionSet를 사용하여 Lotus Sametime 연락 목록 주 창에 메뉴를 제공할 수 있다. 다른 확장점은 Lotus Sametime Connect에 의해 정의된다. 이런 확장은 기본 RCP로 제공되는 것과 같은 방법으로 플러그인 모델 런타임으로 선언되지만 이 글의 솔루션처럼 Lotus Sametime에 한정된 매개변수와 값을 가진다.
- 미리 이렇게 하지 않았다면 데스크톱에서 이클립스 IDE 단축키를 연다. 이 단축키는 플러그인 프로젝트인 com.lotuslabs.invitecoworkers를 연다. 빠진 부분 대부분은 자바 코드 조각으로 이 글에서 짧게 다룰 것이다. 가장 먼저 할 일은 앞서 본 채팅 창 툴바에 툴바 버튼 확장을 만드는 것이다.
- com.lotuslabs.invitecoworkers 프로젝트의 plugin.xml 파일을 더블클릭하여 플러그인 manifest 편집기를 여는 것으로 시작하자. 다중 탭이 달린 페이지로 이뤄진 마법사 같은 편집기가 열린다. 한 페이지는 소스 코드(plugin.xml)를 보여주고 다른 페이지에는 필요한 필드를 채우고 manifest 파일 소스를 적절히 수정할 수 있는 편집기가 들어 있다. 그림 6처럼 Extensions 페이지로 바꾼 후 Add를 클릭하여 새 확장을 만들자.
그림 6. Extensions 대화상자
이 대화상자는 가능한 많은 확장을 모두 보여준다. 엔트리 필드에 "chatwindow"라 넣고 목록에서 com.ibm.collaboration.realtime.chatwindow.chatAction을 선택한다. 확장을 선택하면 아래의 정보 박스에서 간단한 목적 설명을 업데이트한다.
- Finish 버튼을 클릭하여 플러그인에 확장을 추가하자.
- 버튼의 행동을 다루기 위해 채팅 동작을 정의하자. 이전 단계에서 만든 확장은 하나 이상의 채팅 동작을 정의할 수 있다. 확장을 선택하여 채팅 동작을 정의하고 New - chatAction 팝업 메뉴를 선택한다.
확장의 우측 창은 현 선택에 맞는 업데이트를 한다. 여기서 확장을 매개변수화할 수 있다. 그림 7에서 보이는 것과 아래 나열한 것을 매치하는 값을 업데이트하자.
- Id 필드에 com.lotuslabs.invitecoworkers.chatAction을 넣는다.
- 클래스 필드에서 Browse 버튼을 클릭하고 com.lotuslabs.invitecoworkers.InviteCoworkersToChatAction을 선택한다.
- 유형 필드의 드롭다운 목록에서 buddy를 선택한다.
- tooltipText 필드에서 STIG: Invite Coworkers를 선택한다.
- 이미지 필드에서 Browse를 클릭하고 images/invitecoworkers.png를 선택한다.
- 경로 필드에 buddy/end를 넣는다.
- showsFor 필드의 드롭다운 목록에서 both를 선택한다.
그림 7. Extension Element Details 대화상자
새롭게 제공된 툴바 버튼의 행동은 InviteCoworkersToChatAction이라는 사용자 요청에 응답하는 클래스에 의해 정의된다. 정의의 골격이 제공되므로 처음부터 하나를 더 만들 필요는 없다. 그림 7처럼 클래스 매개변수를 채우자.
- 5. 확장을 만들었다. plugin.xml 페이지로 넘어가 소스를 보고 제대로 됐는지 확인한다. Listing 1의 인용구와 매치되는가?
Listing 1. chatAction 확장
<extension
point="com.ibm.collaboration.realtime.chatwindow.chatAction">
<chatAction
class="com.lotuslabs.invitecoworkers.InviteCoworkersToChatAction"
id="com.lotuslabs.invitecoworkers.chatAction"
image="images/invitecoworkers.png"
path="buddy/end"
showsFor="both"
tooltipText="STIG: Invite Coworkers..."
type="buddy"/>
</extension>
|
중요 매개변수는 다음과 같다.
-
class. 사용자가 처음 메뉴 선택을 선택하고 run(...) 메서드가 호출될 때 이 클래스의 인스턴스가 만들어진다.
-
image. 툴바 버튼을 나타내는 그래픽.
-
path. 툴바에서 새 컨트리뷰션이 삽입되어야 하는 위치. 여기에는 비슷한 기능으로 묶인 이미 정의된 위치가 여러 개 있다. 이 예에서는 동작이 마지막 부분(buddy/end) 툴바에서 파트너와 관련된 선택에 추가된다.
-
type. 컨트리뷰션이 있어야 하는 위치(Send 영역의 툴바를 위한 포맷, 다방향 채팅 영역에서 참여자 목록의 툴바를 위한 목록, 주 툴바를 위한 버디).
- 6. 변경을 저장하자. 컨트리뷰트된 동작이 선택될 때 아무것도 안 하더라도 IDE에서 이를 시작해 Lotus Sametime Connect에서 보이는지 얼른 확인하자. Run - Run을 선택하면 시작 구성(launch configuration) 대화상자가 나타난다.
이클립스 개발 환경의 가장 강력한 기능 중 하나는 빠른 코딩-테스트-수정 주기를 지원한다는 것이다. 시작 구성은 이미 설치된 이클립스 제품에 기반을 둔 테스트 환경을 정의한다. 이 경우 Lotus Sametime Connect는 이미 설치됐고 이클립스 IDE는 이를 참조한다. 프로젝트 com.lotuslabs.inviteothers는 PDE의 런타임 설치 구성에 의해 이 설치와 결합되므로 배치 없이 플러그인을 테스트할 수 있거나 제품 설치를 수정하면 된다. IDE에서 띄운 Lotus Sametime Connect 환경은 변경이 이루어지면(예를 들어 프레퍼런스, 이전 로그인, 창 위치) PDE 도구에 의해 관리되는 별도 디렉터리에 저장된다.
- 7. 그림 8처럼 클라이언트 서버 하의 ST8.0을 선택하고 난 후 Run 버튼을 클릭한다.
그림 8. 런타임 구성
- 8. 시간이 약간 지난 후 Lotus Sametime Connect가 로그인 대화상자와 함께 열린다. 채팅을 시작하면(스스로 채팅 창을 열자) 채팅 창 툴바에 새로 컨트리뷰트된 동작이 나타나는지 확인하고 로그인한다. Invite Coworkers 버튼을 클릭하면 나중에 실제 코드와 변경할 정보 메시지가 나타난다.
 |

|
프로파일에서 동료 연락 정보 찾아오기
Lotus Connections는 사회적 소프트웨어로 직원들이 정보와 관계를 활용하도록 돕는다. 이는 다음 기능을 포함한다.
-
커뮤니티. 커뮤니티는 IBM Lotus Sametime과 이메일을 사용하여 같은 흥미를 공유하는 사람들이 정보를 교환, 공유하거나 상호작용하여 협업할 수 있도록 한다.
-
활동. 활동은 효율적으로 임무를 실행할 수 있게 필요한 정보와 사람들을 정리할 수 있도록 디자인되었다. 예를 들어 활동은 대시보드로 작업을 추적할 수 있고 다른 이들과 작업을 공유하고 개인과 팀이 해야 할 일을 관리하는 데 도움을 준다.
-
블로그. 블로그를 통해 개인의 생각을 보여주고 다른 이들의 생각을 배울 수 있다.
-
Dogear. 북마크를 저장하고 공유할 수 있도록 한다.
그리고 Lotus Connections에는 Lotus Sametime Connect와 결합할 수 있는 기능이 포함된다.
-
프로파일. 일반적으로 사진, 보고서 구조, 이름, 이름 발음, 업무 시간대, 개인의 전문성이나 흥미에 관한 정보를 포함하는 디렉터리다.
동료 프로파일 - 어떤 데이터가 있는가?
Lotus Sametime 디렉터리 서비스는 의도적으로 가볍게 되어 있다. 예를 들어 이는 개인 주소나 전화번호 같은 정보를 포함하지 않는다. 디렉터리는 개인 이메일 주소, 선호하는 이름, 로그인(대체로 Lotus Sametime 로그인 아이디와 같음)을 포함한다. 반대로 Lotus Connections Profiles는 디렉터리에 나열한 다음 정보를 포함하고 있다.
- 주소
- 전화번호
- 부서 번호
- 매니저/보고 사슬
- 프로파일/배경 정보
- 개인화한 태그(Dogear와 관련된)
이 글에서는 Lotus Connections Profiles API를 사용해 두 정보 소스(Lotus Sametime 디렉터리, Lotus Connections Profiles)를 결합한다. 더 자세히 알아보기 전에 그림 9와 같은 Lotus Connections Profiles 사용자 인터페이스에 대해 알아보자. 이는 회사 Lotus Connections URL로 접근할 수 있다(예를 들어, http://<connections.insertyourwebsite>.com/profiles/).
그림 9. Lotus Connections Profiles 사용자 인터페이스
와일드카드 검색을 사용해 동료 몇 명을 검색해보자. 웹 사용자 인터페이스에서 검색한 것은 대화 상대 동료를 찾을 때 플러그인 확장에서 검색한 것과 같다.
동료 프로파일 - 반환된 데이터 포맷 = Atom
HTML 페이지로 나타난 Lotus Connections Profiles 데이터 또한 아톰(Atom) 피드 포맷으로 반환되는 REST API를 사용해 질의할 수 있다. 예를 들어 다음 검색은 John Smith를 위해 사용자에게 익숙한 HTML 페이지로 반환됐다.
http://<connections.insertyourwebsite>.com/profiles//html/profileView.do?uid=JSmith
HTML 페이지 데이터는 프로그램에 더 익숙한 포맷으로 찾을 수 있다. HTML 페이지 소스와 아톰 피드 간의 차이를 보려면 다음 URL를 넣고 난 후 아톰 포맷 소스 데이터(마우스 오른쪽 버튼을 클릭하고 View Page Source를 선택한다. 소스 창에서 View Wrap Long Line을 선택해야 할 것이다)를 본다.
http://<connections.insertyourwebsite>.com/profiles//atom/profile.do?uid=JSmith
다른 Lotus Connections Profiles REST API 예는 다음 페이지에서 볼 수 있다.
http://<connections.insertyourwebsite>.com/profiles//atom/apihelp.do
브라우저에서 보이는 결과가 아톰 피드 포맷이라는 것을 알 수 있을 것이다. 대다수의 브라우저는 이 포맷들을 인식하고 자동으로 구독을 제안한다. 예제 질의 포맷은 다음에 보일 것이다. 결과량이 상당한 것처럼 보이지만 Abdera("DOM에 아톰 피드를")와 XPath("DOM 트리의 특정 노드를 선택")를 사용하여 Lotus Sametime Connect 확장은 이 피드 결과들를 쉽게 분석해 현재 대화 상대의 동료를 찾는다.
이 XML 문서의 노드는 쉽게 분석되기 위해 태그가 붙어 있음을(예를 들어 <a class="email" ...>와 <div class="x-office">) 기억하자. 코드는 이 표식들을 이용하여 listing 2에서 강조한 필요한 요소만을 인용한다.
동료 프로파일 - 대화 상대 이메일 얻기
프로파일 데이터베이스를 검색하는 비결은 Lotus Sametime 디렉터리와 Lotus Connections Profiles 서버에 저장된 대화 상대의 이메일 주소다. 사용자가 툴바 버튼을 클릭했을 때 채팅에 참여하는 파트너는 InviteCoworkersToChatAction.run 메서드에 접근할 수 있다. Listing 3을 보자.
Listing 3. 파트너 이메일 얻기
DirectoryInfo directoryInfo =
handler.getFirstPartner().getPerson().getDirectoryInfo();
String partnerEmail = (
String) directoryInfo.get(DirectoryInfo.MAIL_ADDRESS);
|
메서드의 핸들러 매개변수는 ChatWindowHandler의 인스턴스다. ChatWindowHandler는 Lotus Sametime Connect 채팅 창의 인터페이스 역할을 하는 클래스다. 이는 채팅 창 사용자 인터페이스 요소(예를 들어 파일이 전송될 때 이를 표시하는 Send Area 아래의 영역인 팝업 애드온)를 보여주고 채팅 내용을 추가하는 메서드를 정의하는 것을 추적한다.
Listing 3에서 본 코드 인용문을 InviteCoworkersToChatAction의 run 메서드(편의를 위해 프로젝트 com.lotuslabs.invitecoworkers의 code_snippets.txt에 코드 스니팻이 제공된다)에 입력한다. 새로 참조된 클래스를 설명하기 위해 import 문을 추가해야 한다. Ctrl+O(임포트 정리)를 눌러 한 번에 수행한다.
채팅 창 핸들러(Chat Window Handler)는 질의와 확장을 사용할 수 있는 action 메서드를 가지고 있다. 채팅 세션은 일반적으로 둘 이상의 사람과 관련 있다. 코드의 첫 행은 첫 대화 상대를 찾아오고 그 파트너를 현재 로그인된 동일인으로 매핑한다. Person 인스턴스는 Lotus Sametime 커넥터가 아는 이를 나타내고 상태(온라인, 자리 비움, 다른 용무 중) 같은 정보나 관련된 디렉터리 정보를 반환할 수 있다.
Lotus Connections Profiles 서버를 호출할 것인가 하지 말 것인가?
대화 상대의 이메일 주소를 가지고 있으면 간단히 Lotus Connections Profiles 서버를 호출하여 동료들의 이메일 주소를 찾아오고자 할 것이다. 기술적으로는 가능하지만 버튼의 run 메서드가 사용자 인터페이스 스레드에서 실행됨을 기억하자. 코드가 잠재적으로 긴 호출을 만든다면 Lotus Sametime Connect 사용자 인터페이스가 멈춘다. "애플리케이션 xxx가 응답하지 않습니다"라는 마이크로소프트 윈도우 메시지를 본 적이 있다면 이게 무슨 뜻인지 정확히 이해할 것이다.
다행히 이클립스는 jobs라는 백그라운드 작업의 필요성을 해결하는 유용한 프레임워크를 가지고 있다. job 인스턴스는 백그라운드 스레드의 풀에서 실행 스레드를 나타낸다. 만드는 것은 job 클래스를 하위클래스로 두고 기본 run 메서드를 오버라이드해 job 인스턴스를 실행하도록 계획하는 것만큼이나 쉽다. job 매니저는 job의 런타임 메서드를 다음 기회에 실행한다. 프로젝트에는 이미 CoworkerLookupEmailsJob 클래스의 뼈대가 들어 있다. 다음 코드를 InviteCoworkersToChatAction.run에 입력하여 인스턴스를 만들고 실행하자.
CoworkerLookupEmailsJob job =
new CoworkerLookupEmailsJob(partnerEmail, this);
job.schedule();
생성자는 job이 동료들의 이메일 주소를 찾아올 때 사용해야 하는 이메일 주소를 포함한다. 두 번째 매개변수는 Listing 4에서 볼 수 있는 플러그인의 ICoworkerLookupHandler 인터페이스에 의해 정의되는 알림 메시지 프로토콜을 사용해 job을 마칠 때 통지를 받는 객체다.
Listing 4. ICoworkerLookupHandler 인터페이스
public interface ICoworkerLookupHandler {
public void emailLookupsComplete(String emails[]);
public void contactLookupsComplete
(ContactInfo[] cis, int failedCount);
}
|
이제 Lotus Connections Profiles 서버에서 가져온 이메일 룩업의 InviteCoworkersToChatAction 핸들링과 이 글 나중에 다룰 Lotus Sametime 디렉터리에서 가져온 연락처 룩업을 자세히 살펴보자. CoworkerLookupEmailsJob 인스턴스에 필요한 단 하나의 job 메서드는 run(...) 메서드로 Listing 5에서 볼 수 있다.
Listing 5. CoworkerLookupEmailsJob.run은 job의 스레드 풀에서 호출된다.
protected IStatus run(IProgressMonitor pm) {
String emails[] = getCoworkerEmails();
handler.emailLookupsComplete(emails);
return Status.OK_STATUS;
}
|
이 메서드는 백그라운드 프로세싱의 부분처럼 job 풀 스레드의 하나에서 호출된다. 다음 절에서는 이 클래스에서 가장 중요한 getCoworkerEmails 메서드를 다루겠다. 이미 봤듯이 이 메서드는 job의 run 메서드에서 호출되며 핸들러(InviteCoworkersToChatAction)는 스레드가 완료되기 전에 끝났음을 공지 받는다.
동료 프로파일 - 아톰 얻기 및 파싱하기
Lotus Connections Profiles 서버에 질의하는 것은 아톰 피드 포맷으로 반환된다. 코딩을 간단히 하려면 아파치 Abdera 프레임워크를 사용한다. 여기에는 아톰 피드 처리를 가능케 하는 파서와 더 쉬운 처리 과정을 위한 최상위 문서 및 엔트리 문서가 포함된다. 여러분의 코드로 XML을 파싱하거나 포맷의 유효화를 검사할 필요가 없다. XPath라는 또 다른 프레임워크는 Abdera에 의해 반환되는 문서 노드를 탐색하는 데 도움이 된다. 결국 아톰 응답의 포션을 위치하고 인용하는 것은 쉽다. 다음 단계를 따르자.
- CoworkerLookupEmailsJob의 getCoworkerEmails 메서드를 시작할 때 Abdera와 XPath를 하나씩 만들자. Abdera/XPath 프레임워크를 초기화하는 비용을 절약하자면 시작할 때 이를 시행하고 인스턴스를 저장한다. 이 패키지들은 스레드에 안전하다.
Abdera abdera = new Abdera();
XPath xpath = abdera.getXPath();
Parser parser = abdera.getParser();
- Listing 6처럼 로컬 변수를 선언한다.
Listing 6. 로컬 변수 선언
URI uri;
InputStream in;
Document doc;
List emailList;
int i;
|
URI는 아톰 피드의 소스, 즉 Lotus Connections Profiles 서버를 식별한다. 입력 스트림은 서버에서 가져온 내용이고 문서는 아톰 피드 결과의 루트며 emailList는 반환된 동료의 이메일 주소 목록이다.
- 보고서 사슬을 위해 아톰 피드 결과를 찾아오고 분석한다. Activator는 플러그인이 처음 로드될 때 만들어진 하나의 클래스다. 이는 사용자가 선택된 서버(예를 들어 Listing 7에서 볼 수 있는 코드 Activator.getDefault().getServerURI()) 같은 글로벌 데이터가 있기에 편리한 장소다. 나머지 URI는 원하는 서비스(reportingChain.do)이자 매개변수(email= 과format=lite)다. Abdera 파서는 Listing 7처럼 필요에 따라 반환 결과를 읽고 분석한다.
Listing 7. Abdera 파서 초기화하기
uri = new URI(Activator.getDefault().getServerURI() +
"reportingChain.do?email=" + email
+ "&format=lite");
in = uri.toURL().openStream();
doc = parser.parse(in, Activator.getDefault().getServerURI());
|
이 코드를 다음에 getCoworkerEmails 메서드에 삽입하자. 이 코드가 대화 상대의 동료를 직접 질의하지 않고 보고서 사슬을 질의하는지 의아할 것이다. Lotus Lotus Connections Profiles API는 보고서 사슬이나 관리할 사람을 위해 질의를 정의한다. 그러므로 누군가의 동료를 가지려면 매니저의 "관리할 사람"을 질의해야 한다.
팁: Listing 7의 코드와 그 뒤를 따르는 코드 부분은 try/catch 블록으로 닫혀야 한다. 디버그 목적을 위해 예외 블록은 시스템 콘솔(e.printStackTrace())로 프린트되어야 한다. 필요에 따라 catch/try 블록을 추가한다. 이를 위해 이클립스 편집기는 필요한 곳에 질문 행의 왼편에 작은 전등 아이콘과 함께 지시한다. 이 아이콘을 클릭하여 제안된 교정 리스트를 본다.
- 보고서 사슬에 원하는 노드를 넣는다. 몇 단계 전의 긴 XML 목록을 기억하는가? 이를 쉽게 처리하기 위해 XPath를 사용한다. 정규식을 사용하여 XPath는 원하는 노드만, 특히 class=email 요소에 붙은 노드만 선택한다.
emailList = xpath.selectNodes("//*[@class='email']", doc);
in.close();
- 선택된 노드에서 필요한 데이터를 추출하자. 반환되는 노드만이 선택된 기준과 매칭된 것이다. Listing 8은 XML 결과에서 노드의 예다.
Listing 8. 프로파일 결과 내의 이메일 주소
<a class="email"
href="mailto:johndoe@us.ibm.com">
johndoe@us.ibm.com
</a>
|
그러므로 노드는 <a>와 속성 클래스며 <a>와 </a> 사이의 href에 더한 데이터다. Listing 9의 코드는 href 속성으로부터 이메일을 제외하고 이를 job의 반환 결과에 저장한다.
Listing 9. 매칭된 이메일 주소 추출하기
String reportingChainEmails[] = new String[emailList.size()];
i = 0;
Iterator iter = emailList.iterator();
while (iter.hasNext()) {
ExtensibleElement element = (ExtensibleElement) iter.next();
reportingChainEmails[i] =
element.getAttributeValue("href").substring(7);
i++;
}
|
주의: 이메일 속성에 mailto:라는 접두사가 붙기 때문에element.getAttributeValue("href").substring(7)이 필요하다.
- 관리되는 사람들을 위해 아톰 피드 결과를 찾아오고 분석한다. 전에 설명했듯이 서버에 두 번째 호출하는 것은 대화 상대(즉 "내 매니저가 관리하는 사람들 = 나의 동료들(the people my manager manages = my coworkers)")의 동료를 찾아오는 데 필요하다. Listing 10의 코드는 이전 호출의 코드와 매우 비슷하다.
Listing 10. Abdera 파서 초기화하기
uri = new URI(Activator.getDefault().getServerURI() +
"peopleManaged.do?email="
+ reportingChainEmails[1]);
in = uri.toURL().openStream();
doc = parser.parse(in, Activator.getDefault().getServerURI());
|
- 관리된 사람에 원하는 노드를 놓는다.
emailList = xpath.selectNodes("//*[@class='email']", doc);
in.close();
- 선택된 노드에서 필요한 데이터를 추출한다. 최종 동료 목록을 만든다(물론 대화 상대가 부서 사람이 아닌 한). Listing 11처럼 대화 상대는 이미 참여한 채팅에 초대할 필요가 없으므로 관리되는 사람 목록에서 제거된다.
Listing 11. 동료 이메일 주소 추출하기
if (emailList.size() > 1) {
String coworkerEmails[] = new String[emailList.size() - 1];
i = 0;
iter = emailList.iterator();
while (iter.hasNext()) {
ExtensibleElement element = (ExtensibleElement) iter.next();
String s = element.getAttributeValue("href").substring(7);
if (!s.equals(email)) {
coworkerEmails[i] = s;
i++;
}
}
return coworkerEmails;
}
|
 |

|
동료 연락 정보를 실제 사람과 매핑하기
지난 절에서 InviteCoworkersToChatAction이 ICoworkerLookupHandler.emailLookupsComplete 메서드를 통해 job이 완성됐음을 통지 받는다고 언급했다. 이 두 단계 접근은 job이 필요하다는 것을 염두에 둔다. 검색은 사용자 인터페이스가 블록될 수 없는 불확실한 시간을 갖기 때문이다. InviteCoworkersToChatAction.emailLookupsComplete이 호출되면 이는 비사용자(non-user) 인터페이스 스레드에서 온다. 즉 CoworkerLookupEmailsJob은 예약된 그 스레드에서 온다. 그러므로 이 또한 비사용자 인터페이스 스레드에서 실행된다.
이제 해야 할 일은 앞에서 찾아온 이메일 주소를 Lotus Sametime Person 객체로 매핑하는 것이다. 이 객체들은 Lotus Sametime 커뮤니티에 로그인한 사용자의 데이터(예를 들어 ID, 상태)를 캡슐화한다.
- Lotus Sametime의 디렉터리 서비스에 접근한다. 각 커뮤니티에는 관련된 서비스가 있다. 특히 InviteCoworkersToChatAction.emailLookupsComplete에서 질의된 디렉터리 서비스(Listing 12를 보자)에 관심있다.
Listing 12. Lotus Sametime의 디렉터리 서비스에 접근하기
Community community = communityMgr.getDefaultCommunity();
RtcSession rtcSession = community.getRtcSession();
DirectoryServiceFactory dirSvcFactory =
(DirectoryServiceFactory)
community.getService(DirectoryServiceFactory.SERVICE_TYPE);
DirectoryService dirSvc = dirSvcFactory.getDirectoryService(rtcSession);
|
RTC는 실시간 공동작업(Real-Time Collaboration)을 뜻한다. RTC 세션은 클라이언트와 커뮤니티 서버 간의 연결을 나타낸다.
- 주어진 이메일 주소로 Lotus Sametime 디렉터리 연락 정보를 찾아보자. 이메일 주소로 Lotus Sametime person을 찾는 것은 Lotus Connections Profiles 서버에서 검색하는 것과 같은 유형의 제약이 있다. 특히 검색 시간이 불확실할 때 그렇다. 그 다음 코드는 Lotus Sametime의 Lookup 인터페이스를 사용할 때 찾아지는 것처럼 데이터를 받기 위해 구조화돼야 한다.
Lookup lookup = dirSvc.createUserLookup();
lookup.addLookupListener(new ContactLookupListener(emails, this));
lookup.lookup(emails);
LookupListener는 결과와 함께(해결됨, 실패함) 각 디렉터리 룩업이 끝났음을 보고받는다.
- 연락 정보 룩업 요청을 하나의 인스턴스로 묶는다. 모든 룩업이 끝나기 전까지 Invite Coworkers 버튼이 대화상자에 나타나지 않으므로 LookupListener 클래스를 정의하여 Listing 13처럼 결과를 단일 패킷에 합쳐 넣는다.
Listing 13. 연락 정보 룩업 요청 묶기
public class ContactLookupListener implements LookupListener {
// variable declarations omitted
public ContactLookupListener(String emails[],
ICoworkerLookupHandler handler) {
this.numEmails = emails.length;
this.handler = handler;
}
public void handleLookupEvent(LookupEvent event) {
if (event.getType() == LookupEvent.RESOLVE_SUCCESS) {
contactInfos.add(event.getContactInfos()[0]);
} else {
resolveFailures++;
}
...cont'd
|
Lotus Sametime 디렉터리가 이메일 주소를 연락 정보로 해석할 때마다(사용자의 Lotus Sametime 로그인과 커뮤니티 포함) ContactLookupListener는 이를 다른 곳에 저장한다.
- Listing 14처럼 모든 연락처가 해석될 때 요청자에게 알린다.
Listing 14. 연락 정보 룩업 요청 묶기 (계속)
// code excerpt continued from previous step
if (numEmails == (contactInfos.size() + resolveFailures)) {
handler.contactLookupsComplete((ContactInfo[])
contactInfos.toArray(new ContactInfo[contactInfos.size()]),
resolveFailures);
}
}
}
|
마지막 변경이 완료되면 InviteCoworkersToChatAction 핸들러는 contactLookupsComplete 메서드를 통해 보고 받는다.
 |

|
요약
지금까지 다음 내용을 성공적으로 마쳤다.
- 채팅 창 툴바(plugin.xml)에 버튼 추가하기
- 대화 상대의 이메일 주소(InviteCoworkersToChatAction)를 찾아오기 위해 메서드 코딩하기
- 멀티스레드 애플리케이션 프로그래밍의 중요성을 배우면서 Lotus Connections Profiles 서버에서 대화 상대의 동료(CoworkerLookupEmailsJob)의 이메일 주소 질의하기
- Lookup 콜백 인터페이스를 사용하여 Lotus Sametime 연락 정보(ContactLookupListener)와 동료의 이메일 주소 매핑하기
이제 연락 정보와 다방향 채팅을 초기화할 수 있는 실제 Lotus Sametime person 객체를 매핑하기 위해 코드를 작성한다.
조각을 모아 테스트하기
이제 두 단계가 더 남았다.
- 이전 절에서 질의한 연락 정보를 Lotus Sametime 디렉터리 LookupListener 인터페이스를 사용하여 매핑하기
- "Invite Others to Chat" 대화상자 내보내기
약간의 코드를 완성한 후 이클립스 플러그인 개발 환경을 사용해 실행, 테스트하고 오류를 수정한다.
찾아온 연락처 처리하기 - 스레딩 문제
ContactLookupListener가 마지막으로 해석된 연락처 정보를 받을 때 ICoworkerLookupHandler.contactLookupsComplete 메서드를 구현하는 InviteCoworkersToChatAction이라는 핸들러를 알린다(주의: 이 메서드는 샘플 인터페이스의 부분으로 구현된다. Lotus Sametime API의 부분이 아니다). InviteCoworkersToChatAction 구현은 완전한 상태로 Listing 15에서 볼 수 있다.
Listing 15. 비UI 스레드에서 UI 요청 수행하기
public void contactLookupsComplete
(final ContactInfo[] cis, int failedCount) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (!getShell().isDisposed()) {
getShell().setEnabled(true);
getShell().setCursor(
Display.getDefault().getSystemCursor(SWT.CURSOR_ARROW));
inviteToChat(cis);
}
}
});
}
|
빠진 코드는 inviteToChat 행뿐이며 이는 Listing 15에 이탤릭으로 표시된다. 코드의 단 한 행이라고? 주변의 모든 이상한 코드는 무엇이란 말인가?
이메일 룩업과 연락정보 룩업은 사용자 인터페이스 스레드와는 다른 백그라운드 스레드에서 작업됐다는 사실을 기억하자. 이렇게 하면 운영체제의 "이 애플리케이션은 더 이상 응답하지 않습니다"라는 경고가 나오는 것을 피하고 사용자 인터페이스는 응답할 수 있는 상태가 된다. Listing 15의 복잡한 코드는 백그라운드 스레드에서 사용자 인터페이스 스레드로(Display.asyncExec(Runnable)) 바꾸는 것을 처리한다.
코드를 좀 더 자세히 보면 Lotus Sametime을 확장하는 데 초점을 맞추기 위해 몇 가지 사용자 인터페이스 작업을 건너 뛰었음을 발견할 것이다. 예를 들어 InviteCoworkersToChatAction이 백그라운드 업무를 하기 전에 창의 커서를 시스템 기다림 커서로 설정하고 Invite Coworkers 버튼을 사용할 수 없게 했다. 즉 시스템이 사용자 대신 작동하고 있다는 중요한 피드백을 줌으로써 참을성 없는 사용자들이 잘못 클릭한 줄 알고 버튼을 또 클릭하지 않도록 한다. Display.asyncExec(Runnable) 위의 코드 래퍼(wrapper)는 같은 사용자 인터페이스 카테고리에 들어간다. 사용자 인터페이스 스레드 상에서 실행해야 하는 코드의 블록을 큐에 넣는 것이 목적이다. Invite Coworkers 버튼을 다시 사용할 수 있게 하는 코드는 커서를 보통 상태로 반환하고 Invite 대화상자를 띄운다. 이 모든 것은 사용자 인터페이스 스레드에서 작동해야 하는데 그 이유는 그래픽 하위 시스템은 모든 호출이 이 하나의 스레드에서 발생한다고 추정하기 때문이다(이는 앞선 유형처럼 사용자 행위를 가능케 하는 창 시스템의 일반 속성이다).
inviteToChat 호출을 추가하면 편집기에 경고 표시로 작은 빨간 X와 준비된 솔루션으로 아이디어 전등이 떠야 한다. 전등을 클릭해 새 메서드를 정의하도록 수락하거나 수동으로 입력할 수 있다.
private void inviteToChat(ContactInfo[] contactInfos) {
//TODO in next section
}
찾아온 연락처 처리하기 - PeopleService
Listing 16의 다음 코드 조각에서 ServiceHub 클래스가 다시 쓰인다. 이름처럼 서비스 중앙에 위치해 다른 구성요소를 등록하고 소비하는 역할을 한다. 이미 CommunityService를 찾아오는 데 ServiceHub를 사용하는 것을 보았다. 이제 PeopleService라는 또 다른 서비스 제공자를 찾아오는 데 이것을 사용한다.
Listing 16. PeopleService에 접근하기
private void inviteToChat(ContactInfo[] contactInfos) {
try {
PeopleService peopleSvc;
peopleSvc = (PeopleService)
ServiceHub.getService(PeopleService.SERVICE_TYPE);
|
Community 서비스와 People 서비스는 Lotus Sametime Connect와 함께 제공되는 두 가지 서비스 예다. 더 수준높은 사용을 위해 Lotus Business Partners는 음성 채팅 서비스나 화상 채팅 서비스 같은 미리 정의한 서비스 구현을 제공한다. 이렇게 추가로 쓸 수 있는(pluggable) 서비스 아키텍처는 여러 판매자가 제공하는 구성요소 부분에서 더 유연한 솔루션 구축을 가능케 한다.
샘플 코드에서 PeopleService는 사용자의 연락 정보(로그인)와 Lotus Sametime 환경의 실제 런타임 표현을 매핑하기 위해 getPerson(...) API를 제공한다.
Person person = peopleSvc.getPerson(id, communityId, isExternal);
반환된 Person 객체는 새 채팅 대화(예를 들어 연락 정보에서 실제 사람에게로)를 만드는 호출에서 매개변수가 될 수 있다.
ContactLookupListener에서 찾아온 제공된 연락 정보 요소를 사용하여 Listing 17의 코드를 동일한 Person 인스턴스와 매핑해보자.
Listing 17. 연락 정보에서 person 객체 찾아오기
Person persons[] = new Person[contactInfos.length];
for (int i = 0; i < contactInfos.length; i++) {
persons[i] = peopleSvc.getPerson(contactInfos[i].getId(),
contactInfos[i].getCommunityId());
}
|
Invite Others 대화상자를 열자. Invite Others 대화상자를 만든 것으로 마침내 끝이 보인다. 이는 Listing 18에서 볼 수 있는 PersonService의 다른 메서드를 사용하여 완성된다.
Listing 18. 대화 상대의 동료로 채팅 초기화하기
if (persons.length > 1)
peopleSvc.createNwayInvite(persons);
else
peopleSvc.createConversation(persons[0]);
|
이 코드의 마지막 행이 예제를 완성시킨다. 이제 테스트할 차례다.
테스트와 디버그하기
이제 코드가 완성됐다. 이클립스 IDE의 아래쪽 Problems 창에 오류가 없는지 확인하자. 그림 10을 보자.
그림 10. 이클립스 IDE의 Problems 창
필요하면 오류를 수정하라. 메서드 부분을 제대로 코딩했는지 확실치 않으면 프로젝트 com.lotuslabs.invitecoworkers와 솔루션 com.ibm.realtime.collaboration.sametime.sample.invitecoworkers를 비교해 본다. 두 프로젝트가 같은 일을 하지만 각기 독특한 패키지 이름과 플러그인 식별자를 가지고 있으므로 동시에 실행할 수 있다(물론 이 경우 두 개의 제공된 Invite Coworker 버튼이 있을 수 있다. 매우 혼란스러울 것이다).
플러그인 없이 해결하고자 한다면 Open Project/Close Project 팝업 메뉴 선택을 사용한다. 이클립스는 런타임 인스턴스를 내보낼 때 연 프로젝트만 고려한다. 그림 11을 보자.
그림 11. 필요에 따라 이클립스 프로젝트 열기/닫기로 유효한 이클립스 프로젝트를 선택하자.
그림 11에서 솔루션 프로젝트가 열리고 아티클 프로젝트는 닫혔다. 닫힌 프로젝트가 무시되므로 오류는 Problems 목록에서 자동 제거된다.
IDE에서 프로젝트를 실행하는 단계는 "채팅 창에 Invite Coworkers 버튼 추가하기" 절에서 한 것과 같다. Run - Run을 선택하고 나서 ST8.0 런타임 시작 구성을 선택한다. 문제를 디버그하려면 왼쪽 가장자리를 더블클릭해 중단점을 설정한다. 푸른 원은 중단점을 나타낸다. 그림 12를 보자.
그림 12. 이클립스 디버거의 예제 중단점
디버거를 실행하려면 Run 대신 Run - Debug를 선택한다.
코드가 중단점에 이른 후 변수 값을 점검하고 코드를 훑어나간다(힌트: F5 = 메서드 안으로 이동, F6 = 메서드 위로 이동, F7 = 메서드 끝으로 이동, F8 = 다시 시작). 그림 13은 디버그 퍼스펙티브와 InviteCoworkersToChatAction.run 메서드에서 멈춘 디버거를 보여준다. 디버그 창은 실행 스택을 보여주고 변수 창은 선택된 메서드의 로컬 변수를 보여준다.
그림 13. 디버그 퍼스펙티브
코드를 즉시 수정할 수도 있다. 코드를 수정하면 메서드는 작동하는 인스턴스로 재컴파일된다. 중단점이 메서드 중간에 있고 처음부터 시작하고 싶다면 디버그 창 팝업 메뉴에서 Drop to Frame을 선택한다.
결론
Lotus Sametime Connect의 확장성이 새롭고 더 생산성 있는 협업으로 이끌 수 있음을 배웠길 바란다. 이 간단한 예제를 부서적 관계만 아는 것 대신 조직 전반의 관계를 아는 데 어떻게 확장할 수 있는지 상상하는 것은 쉽다. 예를 들어 회사는 전문 분야를 나타내는 직원의 디렉터리 속성을 가지고 있을 수 있다. 방금 작성한 것과 같은 코드를 수정해 이 속성들을 질의하고 맞춤 초대 대화상자를 보여주거나 맞춤 대화상자를 띄워 인스턴트 미팅 같은 Lotus Sametime의 특성을 활용할 수 있다.
다운로드 하십시오
참고자료 교육
제품 및 기술 얻기
토론
필자소개  | |  | Dan Kehn은 노스 캐롤라이나에 위치한 IBM Research Triangle Park에서 수석 소프트웨어 엔지니어로 근무하고 있다. 다양한 소프트웨어 경험을 가지고 있고 Rational Application Developer 같은 개발 도구 및 운영체제 성능, 메모리 분석, 사용자 인터페이스 디자인에 관한 업무를 진행해 왔다. 또한 수상한 책, The Java Developer's Guide to Eclipse의 공동 저자이기도 하다. 현재 비즈니스 파트너들이 제품을 IBM Lotus Sametime Connect로 통합하는 것을 돕는 Technical Enablement Specialist로 일하고 있다. |
기사에 대한 평가
 |
| 이 문서 북마킹 하기
|
|