EJB自我调用和自我注入

时间:2017-05-11 12:33:22

标签: java-ee transactions ejb self-reference

我有更多关于EJB-s和自我调用和事务的理论和软件设计问题。

假设我有一个EJB类,我用其他方法调用EJB-s方法之一,该方法也在此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注释我将bean注入其中并调用带注释的方法。  我可以使用有点老但很好的JNDI。  3.我可以使用我当前示例中的SessionContext getBusinessObject方法。  4.我可以创建另一个EJB并将这个带注释的方法放在那里。

我的问题是软件设计和清洁代码哪个更好?因为我知道自注射不是一个好方法,JNDI是旧的,但SessionContext解决方案也基于JNDI,如果我将方法分离到另一个EJB,我只是牺牲应用程序的OOP设计来使用EJB技术清洁...那么在这种情况下推荐的解决方案是什么?谢谢你提前!如果这个问题是Stackoverflow的理论问题,那么在Software Engineering Stack Exchange上提出这个问题更为可取,请随意发表评论,我将从此处删除它。

提前感谢!

1 个答案:

答案 0 :(得分:1)

我总是使用SessionContext。在@PostConstruct中,我调用sessionContext.getBusinessObject并设置一个名为'self'的成员变量。然后,当我需要调用本地方法时,我使用'self.someMethod()'。

注意我只在需要单独的事务或想要异步调用该方法时才这样做。