我有更多关于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上提出这个问题更为可取,请随意发表评论,我将从此处删除它。
提前感谢!
答案 0 :(得分:1)
我总是使用SessionContext。在@PostConstruct中,我调用sessionContext.getBusinessObject并设置一个名为'self'的成员变量。然后,当我需要调用本地方法时,我使用'self.someMethod()'。
注意我只在需要单独的事务或想要异步调用该方法时才这样做。