2017-05-11 6 views
0

EJB-S와 자체 호출 및 트랜잭션에 관한 이론 및 소프트웨어 설계 관련 질문이 있습니다.EJB 자체 호출 및 자체 삽입

이 EJB에도있는 다른 메소드로 EJB 메소드 중 하나를 호출하는 EJB 클래스가 있다고 가정 해 보겠습니다. 하지만 두 번째 방법에서는 트랜잭션 주석 기능을 순서대로 사용하려고합니다. 더 구체적으로 말하자면 :

@Local(BorrowingService.class) 
@Stateless 
public class BorrowingServiceBean implements BorrowingService { 

    static final JcanLogger LOG = JcanLoggerFactory 
      .getLogger(BorrowingServiceBean.class); 

    @PersistenceContext(unitName = ApplicationConstants.PERSISTENCE_UNIT_NAME) 
    protected EntityManager em; 

    @Resource 
    private SessionContext sessionContext; 

    @EJB 
    private PersonService personService; 

    @EJB 
    private StatusBean statusBean; 

    @EJB 
    private BookService bookService; 

    private static final long CAUSELESS_RETURN_COST = 5;  
    private static final String CHECKED_ISBN = "0201104040"; 

    public static final long PERSON_ACCOUNT_REDUCTION = 10; 

    @Override 
    public void returnBook(Long bookId, Long userId) { 
     if (bookId == null || userId == null) { 
      throw new IllegalArgumentException("bookId and userId must not be null"); 
     } 

     List<BorrowingEntity> borrowingsByUserId = getBorrowingsByUserId(userId); 

     for (BorrowingEntity borrowingEntity : borrowingsByUserId) { 
      BookEntity tmpBook = borrowingEntity.getBook(); 

      if (tmpBook.getBookId().equals(bookId)) { 
       em.remove(borrowingEntity); 
       break; 
      } 
     } 

     //recomended self invocation could be here 
     onBookReturn(userId, bookId); 
    } 


    /** 
    * Aims to run a post-processing method in a new transaction (shouldn't be removed from here, and should remain as it is). 
    * Intention: The db change followed by the exception here represents some operations that should be rolled back for some reason. 
    */ 
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    @Override 
    public void onBookReturn(Long userId, Long bookId) {  
     BookEntity book = bookService.getBookById(bookId); 
     if (CHECKED_ISBN.equals(book.getIsbnNumber())) { 
      personService.decreasePersonAccount(userId, CAUSELESS_RETURN_COST);   
      throw new InvalidOperationException("An operation has been attempted, that shouldn't be executed. This change should be rolled back."); 
     } 
    } 

} 

나는 이와 같은 상황에 대한 해결책이 있음을 알고 있습니다. 1. 자기 주입을 @EJB annotation과 함께 사용할 수 있습니다. bean을 자체에 주입하고 주석이 달린 메소드를 호출합니다. 2. 약간 오래된 것이지만 JNDI를 사용할 수 있습니다. 3. 현재 예제에있는 SessionContextgetBusinessObject 메서드를 사용할 수 있습니다. 4. 다른 EJB를 만들고 주석이 달린 메소드를 거기에 넣을 수 있습니다.

제 질문은 소프트웨어 디자인과 깨끗한 코드면에서 더 좋습니다. 자체 주입은 좋은 방법이 아니라는 것을 알고 있기 때문에 JNDI는 오래된 것이지만 SessionContext 솔루션도 JNDI를 기반으로합니다. 다른 EJB로 메소드를 분리하면 EJB 기술을 사용하기 위해 애플리케이션의 OOP 디자인을 희생합니다. 그렇다면 상황과 관련하여 권장되는 솔루션은 무엇입니까? 사전에 감사드립니다! 이 질문은 이론적 인 Stackoverflow에 대한 것이고 소프트웨어 엔지니어링 스택 교환에 대해 질문하는 것이 더 바람직 할 것입니다. 의견을 자유롭게하고 여기에서 제거하겠습니다.

미리 감사드립니다.

답변

1

저는 항상 SessionContext를 사용합니다. @PostConstruct에서 sessionContext.getBusinessObject를 호출하고 'self'라는 멤버 변수를 설정합니다. 그런 다음 로컬 메서드를 호출해야 할 때 'self.someMethod()'를 사용합니다.

참고 별도의 트랜잭션이 필요하거나 해당 메서드를 비동기 적으로 호출하려는 경우에만이 작업을 수행합니다.

+0

답변 해 주셔서 감사합니다. 나는 똑같이 했어. – F3R1