13.     The Message Façade Pattern
Message Façade패턴은Session Façade패턴의 새로운 버전이다.이 패턴은Session Façade와 같은 목적을 가지고 있으며,더불어 메시지 드리븐 빈으로 구현됨으로써 비동기적으로 실행되는 이점도 가지고 있다.
규모가 큰 시스템 내에서는 클라이언트가 특정 작업의 실행이 긑날 때까지 기자리지 않아도 되도록 유스케이스의 비즈니스 로직이 클라이언트의 로직과 따로 실행되도록 하여 확장성을 확보한다.비동기 행동이라고 불리는 이러한 행동은 클라이언트가 실행을 초기화하는 동안 앉아서 기다릴 필요 없이UI와 상호 작용할 수 있게 해준다.이런 방식은 작업이 일괄적으로 연이어 실행 되고 사용자도 금방 그 사실을 알 수 있어 즉시 다음UI로 이동할수 있기 때문에 커다란 시스템에서 아주 유용하다. 실제로 유스케이스를 싱행하는 시스템의 구성요소들도 확장될수 있으며,다른 유스케이스들을 위한 개발을 시작하더라도 클라이언트에 대한 서브스나 품질에 변함이 없이 시스템 업그레이드를 진행할수 있다.
 
구조

사용자 삽입 이미지

 
의도
EJB클라이언트가 일단 멈추어 기다리거나 다른 빈들로부터의 응답을 기다리지 않고,하나의 트랜젝션 내에서 여러 개의 세션 빈이나 엔티티 빈의 메서드를 호출한다.
 
결론
Session Façade를 사용하면 결합도,퍼포먼스,유지 보수성,재사용성 및 일관성의 문제가 해결되지만,응답 시간과 신뢰성 문제가 완전히 해결되지 않는다.유스 케이스가 끝날 때까지 블록되거나 기다릴 필요 없는 한번의 호출이나 트갠잭션을 통해 유스케이스를 실행하는 중계자의 역할을 하는 서버 사이트 폴트톨러런트한 추상화가 필요하다. Message Driven Bean은 이 목적에 합당하며 이를Façade화 시킨 것이Messag Façade패턴이다.
Message Façade패턴이Session Façade패턴을 능가하는 중요한 장점은 작업을 비동기적으로 실행할 수 있도록 확실하게 보장한다는 점이며 다음과 같은 특징을 같는다.
·          즉각적인 반은시간/비동기적 통신
·          하나의 오류로 인한 중단을 피할수 있다.
·          메시지 드리븐 빈들은 약형 입력(weakly-typed input)매개변수를 갖는다.
·          메시지 드리븐 빈들은 어떤 리턴 값도 가지지 않는다.
·          메시지 드리븐 빈들은 클라이언트에게 예외를 알리지 않는다.
 
폴트톨러런트(Fault-tolerant)
 
시스템을24시간 중단 없이 연속적으로 가동시키기 위한 장비이다.예를 들어 케이블이나 어댑터에 고장이 발생할 경우,고장 부분을 수리해 중단된 서비스를 회복시키는 것이 아니라,고장 부분을 방치한 채 순간적으로 각각의 서비스를 다른 케이블로 우회시켜,서비스를 정지시키지 않는 시스템을 말한다.
 
강형(strong type)과 약형(weak type)
 
모든 객체의 형을 정적으로 정하고 형 일치 및 그에 대한 규칙을 완벽하게 정의하여 컴파일 타임에 형 오류를 검출할 수 있으면 강형이라 하고,정적인 형 체제를 갖추지 않으면 약형이라 한다.
 
예제소스
package facade.bookingmsg;
 
import javax.ejb.*;
import javax.jms.*;
import vo.BookingVO;
import common.*;
import entity.booking.*;
import entity.flight.*;
import entity.hotel.*;
import entity.customer.*;
 
/**
 *MDB예약유스케이스가발생하였을.
 *호텔,항공편예약유스케이스완료에필요한EJB호출하고위임하는
 * Message Facade이다.
 */
public class BookingMsgFacadeEJB implements MessageDrivenBean, MessageListener {
 
                 public void ejbCreate() {}
                 public void ejbRemove() {}
                 public void setMessageDrivenContext(MessageDrivenContext ctx) {}
 
                 public void onMessage(Message msg) {
                 
                                  QueueConnection qc = null;
 
                                  try            {
                                                    ObjectMessage omsg = (ObjectMessage) msg;
                                                    BookingVO booking = (BookingVO) omsg.getObject();
                                                    ServiceLocator locator = ServiceLocator.getInstance();
 
                                                    //예약을수행한다.
                                                    BookingLocalHome bhome =
               (BookingLocalHome) locator.getEJBLocalHome(ServiceLocator.BOOKING);
                                                    BookingLocal bookingejb = bhome.create(booking);
                                                    
                                                    //출발항공편좌석을예약한다.
                                                    FlightLocalHome fhome =
               (FlightLocalHome) locator.getEJBLocalHome(ServiceLocator.FLIGHT);
                                                    FlightLocal flightOut = fhome.findByPrimaryKey(booking.flightIdOut);
                                                    if ((flightOut.getAvailableSeats() - booking.noSeats) > 0) {
                                                                      flightOut.bookSeats(booking.noSeats);
                                                    } else {
                                                                      throw new NotEnoughSeatsException(booking.flightIdOut.toString());
                                                    }
 
                                                    //도착항공편좌석을예약한다.
                                                    FlightLocal flightIn = fhome.findByPrimaryKey(booking.flightIdIn);
                                                    if ((flightIn.getAvailableSeats() - booking.noSeats) > 0) {
                                                                      flightIn.bookSeats(booking.noSeats);
                                                    } else {
                                                                      throw new NotEnoughSeatsException(booking.flightIdIn.toString());
                                                    }
 
                                                    //호텔객실을예약한다.
                                                    HotelLocalHome hhome =
               (HotelLocalHome) locator.getEJBLocalHome(ServiceLocator.HOTEL);
                                                    HotelLocal hotel = hhome.findByPrimaryKey(booking.hotelId);
                                                    if ((hotel.getAvailableRooms() - booking.noRooms) > 0) {
                                                                      hotel.bookRooms(booking.noRooms);
                                                    } else {
                                                                      throw new NotEnoughRoomsException(booking.hotelId.toString());
                                                    }
 
                                                    //예약ID고객정보에추가한다.
                                                    CustomerLocalHome chome =
               (CustomerLocalHome) locator.getEJBLocalHome(ServiceLocator.CUSTOMER);
                                                    CustomerLocal customer = chome.findByPrimaryKey(booking.customerId);
                                                    customer.addBooking(bookingejb.getId());
 
                                                    //예약ID전송한다.
                                                    qc = locator.getJMSQueueConn(ServiceLocator.QUEUECONNFACTORY);
                                                    Queue q = locator.getJMSQueue(ServiceLocator.BOOKING_COMPLETE);
                                                    QueueSession qs = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);                                    
                                                    QueueSender qSender = qs.createSender(q);
                                                    TextMessage txtMsg = qs.createTextMessage("Booking complete: id = " + bookingejb.getId());
                                                    qSender.send(txtMsg);
 
                                  } catch (Exception e) {
                                                    throw new EJBException(e);
                                  } finally {
                                                    if (qc != null)             {
                                                                      try            {
                                                                                       qc.close();
                                                                      } catch (JMSException jmse)     {}
                                                    }
                                  }
 
                 }
}

Posted by 영웅기삼
,