Search code examples
jsf-2cdi

TransactionRequiredException in a method that is already annotated with @Transactional


public void postPessoa() {
    savePessoa();
    initializePessoa();
}

@Transactional(rollbackOn = {Exception.class})
public void savePessoa() {
    pessoa = getEntityManager().merge(pessoa);
}

If I call postPessoa() I got TransactionRequiredException in merge(), but if I call savePessoa() directly from JSF it works, and I didn't understand why this behavior.

JSF:

<p:commandButton id="btnSalvar" value="Salvar" action="#{pessoasController.savePessoa}"/>

<p:commandButton id="btnSalvar" value="Salvar" action="#{pessoasController.postPessoa}"/>

Solution

  • You have to add

    @Transactional
    

    ...on class level OR on postPessoa(), too.

    from spring-doc:

    In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. @PostConstruct.