Как получить транзакции в методе CDI-объекта @PostConstruct

Я экспериментирую с Java EE 7, CDI, JPA и JSF.

Когда веб-приложение запускается, я хотел бы запустить метод инициализации в моем компоненте CDI (помечен @PostConstruct), который выполняет некоторую работу с базой данных (вставляет несколько строк и т. Д.). Для этого мне нужна транзакция, но это оказалось не так просто, как я ожидал.

Я пробовал добавить в свой метод аннотацию @Transactional, но, видимо, она работает только с EJB. Я действительно пробовал преобразовать свой bean-компонент в EJB вместо bean-компонента CDI, но все еще не получил транзакцию для моего метода @PostConstruct. Он работал с другими методами в bean-компоненте, но не с моим методом инициализации @PostConstruct.

Затем я прочитал о создании перехватчика метода для передачи транзакций в компоненты CDI:

http://eubauer.de/kingsware/2012/01/16/cdi-and-transactions-eg-in-jboss-7-0-2/

Я тоже пробовал, но не повезло. Это тоже не работает.

Итак, как получить транзакции в метод инициализации @PostConstruct в компоненте CDI?


person StrangeLoop    schedule 09.11.2013    source источник
comment
Почему вы говорите, что он работает только с EJB? Java EE 7 также @Transactional добавила поддержку CDI, перенеся транзакции в свою спецификацию.   -  person John Ament    schedule 10.11.2013
comment
Вы правы насчет обычных методов, но по какой-то причине он не работает с @PostConstruct методом инициализатора. Казалось бы, естественное место для выполнения некоторой работы по инициализации базы данных, требующей транзакции. Может, есть другой способ сделать это?   -  person StrangeLoop    schedule 10.11.2013
comment
Тогда это звучит как ошибка на вашем сервере приложений. Какой сервер приложений вы используете?   -  person John Ament    schedule 10.11.2013
comment
Забыл упомянуть, что его GlassFish Server Open Source Edition 4.0 (сборка 89)   -  person StrangeLoop    schedule 10.11.2013
comment
подтвердите, что попытка вызвать EJB для сохранения или выполнения какой-либо операции с базой данных из метода postConstruct () внутри компонента CDI не работает. Я также использую GlassFish Server 4.0.   -  person dendini    schedule 23.12.2013


Ответы (1)


Видимо кажется, что:

В @PostConstruct (как и в afterPropertiesSet из интерфейса InitializingBean) нет способа гарантировать, что вся пост-обработка уже выполнена, поэтому (действительно) не может быть никаких транзакций. Единственный способ убедиться, что это работает, - использовать TransactionTemplate.

Итак, единственный способ сделать что-то с базой данных из @PostConstruct - это сделать что-то вроде этого:

@Service("something")
public class Something 
{

    @Autowired
    @Qualifier("transactionManager")
    protected PlatformTransactionManager txManager;

    @PostConstruct
    private void init(){
        TransactionTemplate tmpl = new TransactionTemplate(txManager);
        tmpl.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                //PUT YOUR CALL TO SERVICE HERE
            }
        });
   }
}

ПРИМЕЧАНИЕ: аналогичный поток, но ссылающийся на структуру Spring @Transactional в методе @PostConstruct

person dendini    schedule 23.12.2013
comment
В управляемом bean-компоненте с областью действия приложения с @ManagedBean(eager = true) запросами и сохранением, похоже, работает с EclipseLink 2.4.2, но не с Hibernate 5.2.10.Final (вызывает LazyInitializationException). - person Karl Richter; 05.06.2017