메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

Enterprise Flex RIA 해부(20) : 관리 부분 - 레이아웃과 내비게이션

한빛미디어

|

2008-11-12

|

by HANBIT

11,463

제공 : 한빛 네트워크
저자 : Tony Hillerson
역자 : 추홍엽
원문 : Anatomy of an Enterprise Flex RIA Part 20: Administration Section: Layout and Navigation

지난 기사에서는 애플리케이션으로 데이터를 검색하는 것에 대해 살펴봤다. 이제는 애플리케이션의 관리 부분을 살펴봄으로써 Flex와 LiveCycle Data Services, 그리고 EJB 3.0을 결론지으려 한다.

관리 부분: 레이아웃과 내비게이션

관리 부분은 단지 조금 더 복잡할 뿐이다. (그림 25)


[그림 25] 관리 부분

관리 부분에 대한 메인 내비게이션인 상단부에 ApplicationControlBar가 있다. 컨트롤 바에는 ViewStack에 엮여 있는 ToggleButtonBar가 있는데, 버튼 바에는 스택이 가진 뷰 숫자 만큼의 버튼이 생기고 뷰의 레이블이 버튼의 레이블로서 사용된다.

ApplicationControlBar의 오른쪽에는 AdminModel의 outstandingReservations 속성에 엮여있는 레이블도 있다. outstandingReservations 속성은 얼마나 많은 새 예약이 들어오고 아직 체크 아웃되지 않았는지를 나타내는데, 누군가 책을 예약해 놓고 아직 찾아가지 않은 것을 의 미한다. 관리자는 그 책들을 체크 아웃할 준비를 해야 한다. 나중에 이 속성을 어떻게 설정하는지 살펴보겠다.

뷰 스택의 세 개의 뷰는 책 관리 부분, 예약 대기 부분, 체크 아웃 부분이다. 관리 부분에서는 People (Authors와 Users), Subjects, 그리고 Books 를 생성, 갱신, 삭제한다. 예약 대기 부분은 아직 체크 아웃되지 않은 예약 목록을 보여준다. 체크 아웃 부분은 체크 아웃된 책들의 목 록을 보여주고 관리자가 그 책들을 체크인 할 수 있게 한다.

관리 부분: 액션에서의 데이터 관리

CRUD 뷰들이 어떻게 동작하는지 살펴보자. EditBooksPanel은 BookEdit, SubjectEdit, AuthorEdit 이렇게 세 개의 편집 패널을 포함한다. Subject나 Author가 선택되면 이 세 패널과 EditBooksPanel 사이에는 상호작용이 일어난다. 이들 중 하나가 선택되면 SubjectEdit와 AuthorEdit 컴포넌트로부터 이벤트가 발생하는데 EditBooksPanel가 이것을 받아서 새 Book을 생성하거나 편집할 때 현재 Author나 Subject로 설정한다.

그러나 더욱 흥미로운 것은 이 세 가지 중 하나를 편집할 때이다. 먼저 편집할 분리된 폼 대신, 편집 모드에서 DataGrid를 사용했다. 이런 단순한 유스 케이스에 대해 이것은 멋지게 작동한다. 좀 더 복잡한 유스케이스에 대해서는 폼이 필요할 수도 있다. 다음의 SubjectEdit를 보 자.

...
    
    [Bindable]
    private var model:AdminModel = AdminModel.getInstance();

    public function get selectedSubject():Subject {
          return subjectGrid.selectedItem as Subject;
     }

    private function init():void {
          new GetAllSubjectsEvent().dispatch();
     }

    private function subjectSelected():void {
          dispatchEvent(new Event("subjectSelected"));
     }

    private function removeSubject():void {
          new DeleteSubjectEvent(subjectGrid.selectedItem as Subject).dispatch();
     }

    private function createNewSubject():void {
          var subject:Subject = new Subject();
          subject.name = "New Subject";
          model.subjects.addItem(subject);
     }
    
DataGrid에는 creationComplete에서 정확한 데이터로 채워지는데 이것은 GetAllSubjects 이벤트가 발생하여 뷰가 보여질 준비를 했을 때이다.

    
        
          
          
         
    


    
    

그러나 제목을 편집하기 위한 코드를 살펴보자 - 코드를 찾을 수 있다면 그 코드이다. 하나의 로우(row)가 편집되거나 추가될 때, 그것을 캐치해서 퍼시스턴스 서비스로 보내고 싶을 것이다. 그렇지 않은가? 물론 그렇게 할 필요가 있는게 맞다. 그러나 실제로는 그 작업을 전부 LCDS의 데이터 관리 기능이 한다. 우리가 작업해야 할 필요가 있는 것은 관리되고 있는 컬렉션에 이미 있는 데이터들이 변경되게 만들거나, 컬렉션에서 로우를 추가 혹은 삭제하는 것 뿐이다.

init 메소드가 데이터를 로드했을때, 데이터 서비스에서 컬렉션을 얻어 모델에 넣는다. 그러면 그리드는 해당 모델이 가진 컬렉션에 바인딩된다. 컬렉션의 DTO들은 다음과 같이 모두 관리 표시가 되어 있기 때문이다.
...
    [Managed]
    [RemoteClass(alias="lcds.examples.bookie.entity.Subject")]
    public class Subject extends BaseEntity {
 ... 
DataService는 자동으로 동기화(기본 상태)를 하기 때문에, 클라이언트의 LCDS 코드는 어떠한 변경사항들도 해당 DTO들로 자동 저장하는 것을 안다.

이것은 개발하는 수고를 덜어줄 엄청난 도움이 될 것이다. 변경사항들을 서비스 레이어로 통과하는 모든 특정 객체들에 연결해 주는 추가적인 코드는 이미 작성되어 있다 - 여러분은 그것에 대해 전혀 생각하지 않아도 된다.

원한다면 샘플 코드를 더 살펴보라. 그러나 중요한 "과제"는 데이터 관리 기능이 얼마나 훌륭히 작동을 해서 여러분이 직접을 그것을 하지 않아도 되느냐 하는 것이다.

관리 부분: 예약 알림

Bookie에서 살펴볼 마지막 하나는 새로운 예약을 접수했을때 그것을 알려주는 것이다. JBoss에서 이런 내용이 어떻게 설정되었는지 알고 있고, ReservationsDAOBean이 그런 메시지를 어떻게 생성하는지도 알고 있다. 이제 Flex가 그 메시지들을 받기 위해 어떻게 등록하는지를 살펴보자.

먼저 Cairngorm 서비스 정의에서 lcds.examples.bookie.business.Services를 보면 reservationConsumer라는 Consumer에 대한 정의가 있다.

Consumer는 메시지를 구독하고 받기 위한 LCDS의 클래스이다. reservationConsumer는 messaging-config.xml에 정의된 outstandingReservationTopic부분에 destination으로 설정되어 있다.

    
         
              0
         
         
              Topic
              javax.jms.ObjectMessage
              
                   TopicConnectionFactory
              
              
                   topic/outstandingReservationTopic
              
              
                   outstandingReservationTopic
              
              NON_PERSISTENT
              DEFAULT_PRIORITY
              AUTO_ACKNOWLEDGE
              false
         
    

destination은 주제와 커넥션 팩토리를 가리키고 LCDS가 필요로 하는 주제의 속성을 설정한다. 메시지를 받기 시작하려면 consumer에게 구독하라고만 하면 된다. 여기서는 lcds.examples.bookie.business의 Consumer에 대한 래퍼(wrapper)같은 것을 만든 것 뿐이다. reservationConsumer의 setter 메소드에서 Consumer를 받아서 (아직 없다면) 그 Consumer를 구독하고, 메시지를 받기 시작한다.
package lcds.examples.bookie.business {
 ... 
     public class NotificationManager {
  ... 
           private var _reservationNotificationView:NewReservationNotification;
           public function set reservationNotificationView(view:NewReservationNotification)
           :void {
                 _reservationNotificationView = view;
            }
  
           private var _consumer:Consumer;
           public function set reservationConsumer(consumer:Consumer):void {
                 if (!consumer.subscribed) consumer.subscribe();
                 consumer.addEventListener(MessageEvent.MESSAGE, onNewReservation);
                 _consumer = consumer;
            }
  
  ...  
           public function onNewReservation(me:MessageEvent):void {
                 var reservation:Reservation = Reservation(me.message.body);
                 new ReservationRecievedEvent(reservation).dispatch();
                 notifyOfReservation(reservation);
            }
  
           public function notifyOfReservation(reservation:Reservation):void {
                 _reservationNotificationView.show(reservation);
            }
 }
NotificationManager는 오직 하나만 있어야 하기 때문에 싱글턴으로 만들었다. 이 NotificationManager를 시작하기 위해 admin.mxml는 초기화될 때 lcds.examples.bookie.command.admin.ReservationNotificationSubscribeCommand라는 명령을 내리는데, 이 명령은 단순히 NotificationManager에 consumer를 지정한다. 또 이것은 NewReservationNotification 컴포넌트의 인스턴스를 얻는데, 이 인스턴스는 새로운 예약이 들어왔을때 알림을 보여준다.
package lcds.examples.bookie.command.admin {
     public class ReservationNotificationSubscribeCommand
                                   implements ICommand {
  
           public function execute(event:CairngormEvent):void {
                 var evt:ReservationNotificationSubscribeEvent = 
                      event as ReservationNotificationSubscribeEvent;
                 var consumer:Consumer = 
                 EnterpriseServiceLocator.
                      getInstance().
                      getConsumer("reservationConsumer");
   
                 var manager:NotificationManager =
                      NotificationManager.getInstance();
                 manager.reservationConsumer = consumer;
                 manager.reservationNotificationView =
                      evt.reservationNotificiation;
           }
      }
}
일단 메시지가 수신되고, NotificationManager.onNewReservation가 호출되면, lcds.examples.bookie.command.admin.ReservationReceivedCommand에 대응하는 이벤트가 발생한다. 그러면 NotificationManager는 NewReservationNotification에게 자신을 보여주라고 한다. 이 뷰가 예약된 책들의 모음을 보여주는 간단한 HBox이고, 그러고 나면 Thunderbird 이메일 클라이언트가 새 메일이 도착했을때 보여주는 것과 유사하게 애니메이션으로 처리된다. (그림 26)


[그림 26] 자동 예약 업데이트

다음은 이 작은 위젯에 대한 코드이다.
...
         private var hideTimer:Timer;

         public function show(reservation:Reservation):void {
               reservationTitles.text =
                    reservationTitles.text +
                    reservation.book.title + "n";
               reservationTitles.maxWidth = this.width;
               if (hideTimer == null || !hideTimer.running) {
                     hideTimer = new Timer(3000, 1);
                     hideTimer.addEventListener(
                          TimerEvent.TIMER_COMPLETE, hide);
                } else {
                     hideTimer.reset();
                }
               visible = true;
          }

         public function showEffectComplete():void {
               if (hideTimer != null) hideTimer.start();
          }

         public function hide(event:TimerEvent):void {
               visible = false;
          }

         public function hideEffectComplete():void {
               reservationTitles.text = "";
               hideTimer = null;
          }
    
    {hideDissolve}
    {showWipeDown}
    
    
    
    
...
이것을 테스트하려면 애플리케이션을 디플로이하고, 사용자 애플리케이션과 관리자 애플리케이션을 같이 열어본다. (그림 27)


[그림 27] 사용자 애플리케이션과 관리자 애플리케이션

사용자 쪽에서 몇몇 책을 검색해서 예약하고, 관리자 쪽에 알림이 오는지 지켜보자. 매끄럽다. 그리고 쉽다!

전체 연재는 언제든지 여기서 찾을 수 있다.
TAG :
댓글 입력
자료실

최근 본 책0