Jakarta ee EJB自调用和自注入

Jakarta ee EJB自调用和自注入,jakarta-ee,transactions,ejb,self-reference,Jakarta Ee,Transactions,Ejb,Self Reference,关于EJB-s、自调用和事务,我有一个更可能的理论和软件设计问题 假设我有一个EJB类,在这个类中,我用另一个方法调用一个EJB-s方法,这个方法也在这个EJB中。但我想在第二种方法中依次使用事务注释特性。更具体地说: @Local(BorrowingService.class) @Stateless public class BorrowingServiceBean implements BorrowingService { static final JcanLogger LOG =

关于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."); 
        }
    }

}
@Local(借用服务.class)
@无国籍
公共类BorrowingServiceBean实现了BorrowingService{
静态最终JcanLogger日志=JcanLogger工厂
.getLogger(借用ServiceBean.class);
@PersistenceContext(unitName=ApplicationConstants.PERSISTENCE\u UNIT\u NAME)
受保护的实体管理器em;
@资源
非公开会话上下文会话上下文;
@EJB
私人私人服务;
@EJB
私有StatusBean StatusBean;
@EJB
私人图书服务;
私人静态最终长期无原因回报成本=5;
已检查私有静态最终字符串\u ISBN=“0201104040”;
公共静态最终长人账户扣减=10;
@凌驾
public void returnBook(长bookId、长userId){
if(bookId==null | | userId==null){
抛出新的IllegalArgumentException(“bookId和userId不能为null”);
}
List BorrowingByUserId=GetBorrowingByUserId(userId);
for(借用性借用性借用性:借用BYUSERID){
BookEntity tmpBook=brookingEntity.getBook();
if(tmpBook.getBookId().equals(bookId)){
em.remove(借用性);
打破
}
}
//推荐的自我调用可能在这里
onBookReturn(userId,bookId);
}
/**
*旨在在新事务中运行后处理方法(不应从此处删除,应保持原样)。
*意图:db change后跟异常表示出于某种原因应该回滚的一些操作。
*/
@TransactionAttribute(TransactionAttributeType.REQUIRES\u NEW)
@凌驾
public void onBookReturn(长userId,长bookId){
BookEntity book=bookService.getBookById(bookId);
如果(已选中\u ISBN.equals(book.getIsbnNumber())){
personService.decreasePersonAccount(用户ID、无原因返回成本);
抛出新的InvalidOperationException(“尝试了一个不应该执行的操作。应该回滚此更改”);
}
}
}
我知道对于这种情况有一些解决办法。 1.我可以将自注入与
@EJB
注释结合使用,我将bean注入自身并调用带注释的方法。 2.我可以使用JNDI,它有点旧,但很好。 3.我可以使用当前示例中的
SessionContext
getBusinessObject
方法。 4.我可以创建另一个EJB并将这个带注释的方法放在那里

我的问题是在软件设计和干净的代码方面,哪个更好?因为我知道自注入不是一种好方法,JNDI很旧,但SessionContext解决方案也基于JNDI,如果我将该方法分离到另一个EJB中,我只会牺牲应用程序的OOP设计来使用EJB技术。。。那么,在这种情况下,推荐的解决方案是什么?谢谢你的进步!如果这个问题对于Stackoverflow来说是理论性的,并且最好在软件工程堆栈交换上问它,请随意评论,我将从这里删除它


提前谢谢

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

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