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().

Примечание. Я делаю это только в том случае, если мне нужна отдельная транзакция или я хочу вызвать этот метод асинхронно.

Другие вопросы по тегам