EJB самообращение и самоинъекция
У меня есть более вероятный вопрос теоретического и программного проектирования относительно 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
аннотация Я внедряю компонент в себя и вызываю аннотированный метод.
2. Я мог бы использовать JNDI, который немного стар, но хорошо.
3. Я мог бы использовать SessionContext
"s getBusinessObject
метод, который в моем текущем примере.
4. Я мог бы создать другой EJB и поместить туда этот аннотированный метод.
Мой вопрос с точки зрения дизайна программного обеспечения и чистого кода, который лучше? Поскольку я знаю, что самоинжекция не является хорошим способом, JNDI устарел, но решение SessionContext также основано на JNDI, и если я разделяю метод на другой EJB, я просто жертвую ООП приложения для использования чистой технологии EJB. Итак, что такое рекомендуемое решение в такой ситуации? Спасибо за продвижение! Если этот вопрос является теоретическим для Stackru и было бы предпочтительнее задать его на бирже разработки программного обеспечения, не стесняйтесь комментировать, и я удалю его отсюда.
Спасибо за заранее!
1 ответ
Я всегда использую SessionContext. В @PostConstruct я вызываю sessionContext.getBusinessObject и устанавливаю переменную-член с именем self. Затем, когда мне нужно вызвать локальный метод, я использую функцию self.someMethod().
Примечание. Я делаю это только в том случае, если мне нужна отдельная транзакция или я хочу вызвать этот метод асинхронно.