I have to correct myself, you won't get nested transactions with
@CommitAfter, because its implementation checks if another transaction is
active -- it won't start another transaction:

https://github.com/apache/tapestry-5/blob/master/tapestry-jpa/src/main/java/org/apache/tapestry5/internal/jpa/CommitAfterMethodAdvice.java#L41-L44

    public void advise(final MethodInvocation invocation)

    {

        final EntityTransaction transaction = getTransaction();


        if (transaction != null && !transaction.isActive())

        {

            transaction.begin();

        }

But advice will still be executed, and your transaction that started by
interceptor of method b() will be committed by interceptor of method a() --
which may be not that behavior you expected, due to implementation details
of @CommitAfter:

https://github.com/apache/tapestry-5/blob/master/tapestry-jpa/src/main/java/org/apache/tapestry5/internal/jpa/CommitAfterMethodAdvice.java#L61-L64


        if (transaction != null && transaction.isActive())
        {
            transaction.commit();
        }



On Fri, Aug 23, 2013 at 11:52 AM, Dmitry Gusev <dmitry.gu...@gmail.com>wrote:

>
>
>
> On Fri, Aug 23, 2013 at 11:11 AM, Martin Kersten <
> martin.kersten...@gmail.com> wrote:
>
>> I review some code and I ran into the transaction issue. Annotating a
>> service @CommitAfter seams to be inappropriate if you have another service
>> method using it and is itself annotated with the @CommitAfter.
>>
>> The problem I have seams within the documentation. For @CommitAfter the
>> documentation states that the transaction is committed at the end of the
>> method.
>>
>> Therefore I think that for the case:
>> @CommitAfter
>> a() {...}
>>
>> @CommitAfter
>> b() { a(); }
>>
>> At least two commits will happen for each of those commits. Am I right
>> here?
>>
>>
> Not exactly. If both a() and b() are from the same interface -- then only
> one transaction will be committed.
> This is because tapestry wraps methods a() and b() with advices, but this
> happens on the proxies, not on the implementation classes.
>
> So if you call your method b() via proxy -- then interceptor for b() will
> start the transaction, then method b() will call method a() on the
> implementation class -- in this case no interceptors will be involved,
> hence you won't get another transaction.
>
> You're getting proxy references when you @Inject'ing your services.
>
> You can see this by examining stack trace if you put a breakpoint in
> method a().
>
> But if you put method a() to Intf1 and b() to Intf2 and if you @Inject
> Intf1 to Intf2 -- you should get two nested transactions.
>
> But your database should support nested transactions.
>
>
>> There is the PersitenceContext annotation and that somehow I can use it to
>> control transactional behavior but In my oppinion this focus about using a
>> second session for two different persistent contexts. Am I right on this
>> one?
>>
>> So in the end it looks like programming or using some other sort of
>> mechanism that is aware of nested logical transactions and ignores the
>> commit inside an ongoing transaction. This behavior can be introduced
>> using
>> HibernateSessionManager.
>>
>> There is also this post
>>
>> http://tawus.wordpress.com/2011/04/23/tapestry-magic-5-advising-services/which
>> describes exactly what I need.
>>
>> The question here is there anything shipped with tapestry that allows this
>> kind of behavior or am I missunderstanding @CommitAfter and this behavior
>> is already present?
>>
>> Is there a standard way to control whether there is a ReadOnly transaction
>> going on or not? I didnt found anything about it. Maybe I am blind. :)
>>
>>
>> Cheers and Thank you,
>>
>> Martin (Kersten),
>> Germany
>>
>
>
>
> --
> Dmitry Gusev
>
> AnjLab Team
> http://anjlab.com
>



-- 
Dmitry Gusev

AnjLab Team
http://anjlab.com

Reply via email to