You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by David Van Couvering <da...@vancouvering.com> on 2007/04/20 01:40:57 UTC

Help requested around rollback semantics

Hi, all.  I am hoping you can help me out here.  You don't have a users 
list so I'm sending it to dev.

I've been implementing some code against JPA and I was trying to figure 
out how to handle a transaction rollback. I wasn't sure if JPA is 
responsible for rolling back the state of any objects in the persistence 
context.

The answer appears to be no, and I found this in the spec:

===
3.3.2 Transaction Rollback

For both transaction-scoped and extended persistence contexts, 
transaction rollback causes all pre-existing managed instances and 
removed instances[15] to become detached. The instances’ state will be 
the state of the instances at the point at which the transaction was 
rolled back. Transaction rollback typically causes the persistence 
context to be in an inconsistent state at the point of rollback. In 
particular, the state of version attributes and generated state (e.g., 
generated primary keys) may be inconsistent. Instances that were 
formerly managed by the persistence context (including new instances 
that were made persistent in that transaction) may therefore not be 
reusable in the same manner as other detached objects—for example, they 
may fail when passed to the merge operation.
====

As an app writer, this statement is somewhat disconcerting.

I was wondering if there is any guidance available for how I can write 
an app against JPA that handles rollback correctly.

I'm writing a controller that interacts with entity objects, passing 
them around to various methods, storing them in member variables, and so 
on. I don't want to detach them, because (a) it is costly for me to copy 
all the data into a separate, detached instance, and then during the 
merge operation to have them copied back into the instance stored in the 
persistence context and (b) I never know if I can access a field or 
relationship because I don't know if the field or related instance has 
been loaded yet. When I keep them attached, JPA takes care of this for me.

Then let's say I perform a persist() operation and it fails and rolls 
back. This means all my objects I've been passing around and storing in 
various places are suddenly detached and "may be" in an inconsistent 
state (which from the perspective of a program is the same as saying 
they *are* in an inconsistent state), and thus are invalid.

So now what do I do? Is there a recommended approach for dealing with 
this? How does my application detect this in some global way, and 
reloads from the persistence context all the instances it was keeping 
around?

The other concern I have is I'd like consumers of my controller to use 
entity objects as POJOs without having to know or care if they are 
entities. But the rollback semantics means my callers have to deal with 
handling a rollback. Alternately I could pay the copy cost of detaching 
my objects before passing them up to higher levels, but then my caller 
will still have to deal with the semantics of detached objects (e.g. 
lazy fields or associated instances may be null). I don't see any way to 
expose entities directly to higher levels of my app that are 
entity-unaware... Which means I have to wrap my entities into proxy 
classes that handle all the JPA semantics internally and don't expose 
this to the caller.

I am concerned that the rollback consequences can slip past developers, 
who will then build apps that behave very erratically after a 
transaction rollback. I know it's in the spec, but having worked with 
lots of developers, most of them don't read the spec, but instead 
cut-and-paste from examples. It would be great if we did a blog about 
this, and provided some code showing how to do it right... I could do 
this, but before I do I thought I'd check with you all first for any 
thoughts you have on this.

Thanks!

David

RE: Help requested around rollback semantics

Posted by Phill Moran <pj...@rogers.com>.
Have you checked with Spring/JUnit they support rollback during tests

-----Original Message-----
From: David.Vancouvering@Sun.COM [mailto:David.Vancouvering@Sun.COM] On Behalf
Of David Van Couvering
Sent: April 20, 2007 1:46 PM
To: open-jpa-dev@incubator.apache.org
Subject: Re: Help requested around rollback semantics

I'll probably have to write an abstraction on top of JPA with a different
"driver" for each implementation (OpenJPA, TopLink) so I can
(a) deal with these issues and (b) use extensions without tying application code
to a particular vendor.

David

Patrick Linskey wrote:
> Yeah, it's not ideal, and is something we're hoping to resolve in the 
> next version of the spec. The good news is that OpenJPA provides a 
> bunch more flexibility.
> 
> -Patrick
> 


Re: Help requested around rollback semantics

Posted by David Van Couvering <da...@vancouvering.com>.
I'll probably have to write an abstraction on top of JPA with a 
different "driver" for each implementation (OpenJPA, TopLink) so I can 
(a) deal with these issues and (b) use extensions without tying 
application code to a particular vendor.

David

Patrick Linskey wrote:
> Yeah, it's not ideal, and is something we're hoping to resolve in the
> next version of the spec. The good news is that OpenJPA provides a bunch
> more flexibility.
> 
> -Patrick
> 

RE: Help requested around rollback semantics

Posted by Patrick Linskey <pl...@bea.com>.
Yeah, it's not ideal, and is something we're hoping to resolve in the
next version of the spec. The good news is that OpenJPA provides a bunch
more flexibility.

-Patrick

-- 
Patrick Linskey
BEA Systems, Inc.
_______________________________________________________________________
Notice:  This email message, together with any attachments, may contain
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
entities,  that may be confidential,  proprietary,  copyrighted  and/or
legally privileged, and is intended solely for the use of the individual
or entity named in this message. If you are not the intended recipient,
and have received this message in error, please immediately return this
by email and then delete it. 

> -----Original Message-----
> From: David.Vancouvering@Sun.COM 
> [mailto:David.Vancouvering@Sun.COM] On Behalf Of David Van Couvering
> Sent: Thursday, April 19, 2007 6:18 PM
> To: open-jpa-dev@incubator.apache.org
> Subject: Re: Help requested around rollback semantics
> 
> That's what I thought: broken and detached.  Might as well 
> just throw them out.  Not to be blunt, but this just sucks.  
> It's as if JPA believes nobody will ever really experience a 
> rollback...
> 
> Bleagh!
> 
> David
> 
> Patrick Linskey wrote:
> >> In generic JPA, the only way to deal with the situation 
> you describe 
> >> would be to manually call EntityManager.refresh() on each instance 
> >> that was involved in the transaction so as to ensure that 
> it is up to 
> >> date.
> > 
> > Actually, I think it's even tougher than this. I think that after 
> > rollback, entities are in an 'error' state, and you really can't do 
> > much of anything with them. I don't think that there's even a 
> > guarantee that you can re-attach such instances.
> > 
> > I believe that in either a transactional or extended PC, 
> instances are 
> > detached into this error state after a rollback. So, I don't think 
> > that you can actually call refresh() on them, per the spec.
> > 
> > -Patrick
> > 
> 

Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

Re: Help requested around rollback semantics

Posted by David Van Couvering <da...@vancouvering.com>.
That's what I thought: broken and detached.  Might as well just throw 
them out.  Not to be blunt, but this just sucks.  It's as if JPA 
believes nobody will ever really experience a rollback...

Bleagh!

David

Patrick Linskey wrote:
>> In generic JPA, the only way to deal with the situation you 
>> describe would be to manually call EntityManager.refresh() on 
>> each instance that was involved in the transaction so as to 
>> ensure that it is up to date.
> 
> Actually, I think it's even tougher than this. I think that after
> rollback, entities are in an 'error' state, and you really can't do much
> of anything with them. I don't think that there's even a guarantee that
> you can re-attach such instances.
> 
> I believe that in either a transactional or extended PC, instances are
> detached into this error state after a rollback. So, I don't think that
> you can actually call refresh() on them, per the spec.
> 
> -Patrick
> 

RE: Help requested around rollback semantics

Posted by Phill Moran <pj...@rogers.com>.
I thought that under any circumstance (except primary key messed up) that a
refresh would reload current database object image? If this is not the case how
does refresh work under any circumstances? Does it validate that the detached
object is in a valid state as a gate to refresh?

-----Original Message-----
From: Patrick Linskey [mailto:plinskey@bea.com] 
Sent: April 19, 2007 8:57 PM
To: open-jpa-dev@incubator.apache.org
Subject: RE: Help requested around rollback semantics

> In generic JPA, the only way to deal with the situation you describe 
> would be to manually call EntityManager.refresh() on each instance 
> that was involved in the transaction so as to ensure that it is up to 
> date.

Actually, I think it's even tougher than this. I think that after rollback,
entities are in an 'error' state, and you really can't do much of anything with
them. I don't think that there's even a guarantee that you can re-attach such
instances.

I believe that in either a transactional or extended PC, instances are detached
into this error state after a rollback. So, I don't think that you can actually
call refresh() on them, per the spec.

-Patrick

--
Patrick Linskey
BEA Systems, Inc.
_______________________________________________________________________
Notice:  This email message, together with any attachments, may contain
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
entities,  that may be confidential,  proprietary,  copyrighted  and/or legally
privileged, and is intended solely for the use of the individual or entity named
in this message. If you are not the intended recipient, and have received this
message in error, please immediately return this by email and then delete it. 

> -----Original Message-----
> From: Marc Prud'hommeaux [mailto:mprudhomapache@gmail.com] On Behalf 
> Of Marc Prud'hommeaux
> Sent: Thursday, April 19, 2007 5:20 PM
> To: open-jpa-dev@incubator.apache.org
> Subject: Re: Help requested around rollback semantics
> 
> David-
> 
> > So now what do I do? Is there a recommended approach for
> dealing with
> > this? How does my application detect this in some global way, and 
> > reloads from the persistence context all the instances it
> was keeping
> > around?
> 
> In my opinion, JPA is pretty weak when it comes to rollbacks. 
> This might be due to its legacy of being part of the EJB spec, where 
> individual entity instances typically aren't accessible after a 
> transaction has completed.
> 
> In generic JPA, the only way to deal with the situation you describe 
> would be to manually call EntityManager.refresh() on each instance 
> that was involved in the transaction so as to ensure that it is up to 
> date.
> 
> Fortunately, in OpenJPA you have a little more control over the post- 
> rollback behavior. You can use the openjpa.RestoreState property to 
> define what should be done with that state of persistent instances 
> after a rollback occurs. See:
> 
>    http://incubator.apache.org/openjpa/docs/latest/manual/
> manual.html#ref_guide_pc_scos_restore
> 
> 
> 
> 
> On Apr 19, 2007, at 4:40 PM, David Van Couvering wrote:
> 
> > Hi, all.  I am hoping you can help me out here.  You don't have a 
> > users list so I'm sending it to dev.
> >
> > I've been implementing some code against JPA and I was trying to 
> > figure out how to handle a transaction rollback. I wasn't sure if 
> > JPA is responsible for rolling back the state of any
> objects in the
> > persistence context.
> >
> > The answer appears to be no, and I found this in the spec:
> >
> > ===
> > 3.3.2 Transaction Rollback
> >
> > For both transaction-scoped and extended persistence contexts, 
> > transaction rollback causes all pre-existing managed instances and 
> > removed instances[15] to become detached. The instances'
> state will
> > be the state of the instances at the point at which the
> transaction
> > was rolled back. Transaction rollback typically causes the 
> > persistence context to be in an inconsistent state at the point of 
> > rollback. In particular, the state of version attributes and 
> > generated state (e.g., generated primary keys) may be
> inconsistent.  
> > Instances that were formerly managed by the persistence context 
> > (including new instances that were made persistent in that
> > transaction) may therefore not be reusable in the same manner as 
> > other detached objects-for example, they may fail when passed to the 
> > merge operation.
> > ====
> >
> > As an app writer, this statement is somewhat disconcerting.
> >
> > I was wondering if there is any guidance available for how I can 
> > write an app against JPA that handles rollback correctly.
> >
> > I'm writing a controller that interacts with entity objects, passing 
> > them around to various methods, storing them in member variables, 
> > and so on. I don't want to detach them, because (a) it is costly for 
> > me to copy all the data into a separate, detached instance, and then 
> > during the merge operation to have them copied back into the 
> > instance stored in the persistence context and (b) I never know if I 
> > can access a field or relationship because I don't know if the field 
> > or related instance has been loaded yet. When I keep them attached, 
> > JPA takes care of this for me.
> >
> > Then let's say I perform a persist() operation and it fails and 
> > rolls back. This means all my objects I've been passing around and 
> > storing in various places are suddenly detached and "may be" in an 
> > inconsistent state (which from the perspective of a program is the 
> > same as saying they *are* in an inconsistent state), and thus are 
> > invalid.
> >
> > So now what do I do? Is there a recommended approach for dealing 
> > with this? How does my application detect this in some global way, 
> > and reloads from the persistence context all the instances it was 
> > keeping around?
> >
> > The other concern I have is I'd like consumers of my controller to 
> > use entity objects as POJOs without having to know or care if they 
> > are entities. But the rollback semantics means my callers have to 
> > deal with handling a rollback. Alternately I could pay the copy cost 
> > of detaching my objects before passing them up to higher levels, but 
> > then my caller will still have to deal with the semantics of 
> > detached objects (e.g. lazy fields or associated instances may be 
> > null). I don't see any way to expose entities directly to higher 
> > levels of my app that are entity-unaware...
> > Which means I have to wrap my entities into proxy classes that 
> > handle all the JPA semantics internally and don't expose this to the 
> > caller.
> >
> > I am concerned that the rollback consequences can slip past 
> > developers, who will then build apps that behave very erratically 
> > after a transaction rollback. I know it's in the spec, but having 
> > worked with lots of developers, most of them don't read the spec, 
> > but instead cut-and-paste from examples. It would be great if we did 
> > a blog about this, and provided some code showing how to do it 
> > right... I could do this, but before I do I thought I'd check with 
> > you all first for any thoughts you have on this.
> >
> > Thanks!
> >
> > David
> 
> 

Notice:  This email message, together with any attachments, may contain
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
entities,  that may be confidential,  proprietary,  copyrighted  and/or legally
privileged, and is intended solely for the use of the individual or entity named
in this message. If you are not the intended recipient, and have received this
message in error, please immediately return this by email and then delete it.


RE: Help requested around rollback semantics

Posted by Patrick Linskey <pl...@bea.com>.
> In generic JPA, the only way to deal with the situation you 
> describe would be to manually call EntityManager.refresh() on 
> each instance that was involved in the transaction so as to 
> ensure that it is up to date.

Actually, I think it's even tougher than this. I think that after
rollback, entities are in an 'error' state, and you really can't do much
of anything with them. I don't think that there's even a guarantee that
you can re-attach such instances.

I believe that in either a transactional or extended PC, instances are
detached into this error state after a rollback. So, I don't think that
you can actually call refresh() on them, per the spec.

-Patrick

-- 
Patrick Linskey
BEA Systems, Inc.
_______________________________________________________________________
Notice:  This email message, together with any attachments, may contain
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
entities,  that may be confidential,  proprietary,  copyrighted  and/or
legally privileged, and is intended solely for the use of the individual
or entity named in this message. If you are not the intended recipient,
and have received this message in error, please immediately return this
by email and then delete it. 

> -----Original Message-----
> From: Marc Prud'hommeaux [mailto:mprudhomapache@gmail.com] On 
> Behalf Of Marc Prud'hommeaux
> Sent: Thursday, April 19, 2007 5:20 PM
> To: open-jpa-dev@incubator.apache.org
> Subject: Re: Help requested around rollback semantics
> 
> David-
> 
> > So now what do I do? Is there a recommended approach for 
> dealing with 
> > this? How does my application detect this in some global way, and 
> > reloads from the persistence context all the instances it 
> was keeping 
> > around?
> 
> In my opinion, JPA is pretty weak when it comes to rollbacks. 
> This might be due to its legacy of being part of the EJB 
> spec, where individual entity instances typically aren't 
> accessible after a transaction has completed.
> 
> In generic JPA, the only way to deal with the situation you 
> describe would be to manually call EntityManager.refresh() on 
> each instance that was involved in the transaction so as to 
> ensure that it is up to date.
> 
> Fortunately, in OpenJPA you have a little more control over 
> the post- rollback behavior. You can use the 
> openjpa.RestoreState property to define what should be done 
> with that state of persistent instances after a rollback occurs. See:
> 
>    http://incubator.apache.org/openjpa/docs/latest/manual/
> manual.html#ref_guide_pc_scos_restore
> 
> 
> 
> 
> On Apr 19, 2007, at 4:40 PM, David Van Couvering wrote:
> 
> > Hi, all.  I am hoping you can help me out here.  You don't have a  
> > users list so I'm sending it to dev.
> >
> > I've been implementing some code against JPA and I was trying to  
> > figure out how to handle a transaction rollback. I wasn't sure if  
> > JPA is responsible for rolling back the state of any 
> objects in the  
> > persistence context.
> >
> > The answer appears to be no, and I found this in the spec:
> >
> > ===
> > 3.3.2 Transaction Rollback
> >
> > For both transaction-scoped and extended persistence contexts,  
> > transaction rollback causes all pre-existing managed instances and  
> > removed instances[15] to become detached. The instances' 
> state will  
> > be the state of the instances at the point at which the 
> transaction  
> > was rolled back. Transaction rollback typically causes the  
> > persistence context to be in an inconsistent state at the point of  
> > rollback. In particular, the state of version attributes and  
> > generated state (e.g., generated primary keys) may be 
> inconsistent.  
> > Instances that were formerly managed by the persistence context  
> > (including new instances that were made persistent in that  
> > transaction) may therefore not be reusable in the same manner as  
> > other detached objects-for example, they may fail when passed to  
> > the merge operation.
> > ====
> >
> > As an app writer, this statement is somewhat disconcerting.
> >
> > I was wondering if there is any guidance available for how I can  
> > write an app against JPA that handles rollback correctly.
> >
> > I'm writing a controller that interacts with entity objects,  
> > passing them around to various methods, storing them in member  
> > variables, and so on. I don't want to detach them, because (a) it  
> > is costly for me to copy all the data into a separate, detached  
> > instance, and then during the merge operation to have them copied  
> > back into the instance stored in the persistence context and (b) I  
> > never know if I can access a field or relationship because I don't  
> > know if the field or related instance has been loaded yet. When I  
> > keep them attached, JPA takes care of this for me.
> >
> > Then let's say I perform a persist() operation and it fails and  
> > rolls back. This means all my objects I've been passing around and  
> > storing in various places are suddenly detached and "may be" in an  
> > inconsistent state (which from the perspective of a program is the  
> > same as saying they *are* in an inconsistent state), and thus are  
> > invalid.
> >
> > So now what do I do? Is there a recommended approach for dealing  
> > with this? How does my application detect this in some global way,  
> > and reloads from the persistence context all the instances it was  
> > keeping around?
> >
> > The other concern I have is I'd like consumers of my controller to  
> > use entity objects as POJOs without having to know or care if they  
> > are entities. But the rollback semantics means my callers have to  
> > deal with handling a rollback. Alternately I could pay the copy  
> > cost of detaching my objects before passing them up to higher  
> > levels, but then my caller will still have to deal with the  
> > semantics of detached objects (e.g. lazy fields or associated  
> > instances may be null). I don't see any way to expose entities  
> > directly to higher levels of my app that are entity-unaware...  
> > Which means I have to wrap my entities into proxy classes that  
> > handle all the JPA semantics internally and don't expose this to  
> > the caller.
> >
> > I am concerned that the rollback consequences can slip past  
> > developers, who will then build apps that behave very erratically  
> > after a transaction rollback. I know it's in the spec, but having  
> > worked with lots of developers, most of them don't read the spec,  
> > but instead cut-and-paste from examples. It would be great if we  
> > did a blog about this, and provided some code showing how to do it  
> > right... I could do this, but before I do I thought I'd check with  
> > you all first for any thoughts you have on this.
> >
> > Thanks!
> >
> > David
> 
> 

Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

Re: Help requested around rollback semantics

Posted by Marc Prud'hommeaux <mp...@apache.org>.
David-

> So now what do I do? Is there a recommended approach for dealing  
> with this? How does my application detect this in some global way,  
> and reloads from the persistence context all the instances it was  
> keeping around?

In my opinion, JPA is pretty weak when it comes to rollbacks. This  
might be due to its legacy of being part of the EJB spec, where  
individual entity instances typically aren't accessible after a  
transaction has completed.

In generic JPA, the only way to deal with the situation you describe  
would be to manually call EntityManager.refresh() on each instance  
that was involved in the transaction so as to ensure that it is up to  
date.

Fortunately, in OpenJPA you have a little more control over the post- 
rollback behavior. You can use the openjpa.RestoreState property to  
define what should be done with that state of persistent instances  
after a rollback occurs. See:

   http://incubator.apache.org/openjpa/docs/latest/manual/ 
manual.html#ref_guide_pc_scos_restore




On Apr 19, 2007, at 4:40 PM, David Van Couvering wrote:

> Hi, all.  I am hoping you can help me out here.  You don't have a  
> users list so I'm sending it to dev.
>
> I've been implementing some code against JPA and I was trying to  
> figure out how to handle a transaction rollback. I wasn't sure if  
> JPA is responsible for rolling back the state of any objects in the  
> persistence context.
>
> The answer appears to be no, and I found this in the spec:
>
> ===
> 3.3.2 Transaction Rollback
>
> For both transaction-scoped and extended persistence contexts,  
> transaction rollback causes all pre-existing managed instances and  
> removed instances[15] to become detached. The instances’ state will  
> be the state of the instances at the point at which the transaction  
> was rolled back. Transaction rollback typically causes the  
> persistence context to be in an inconsistent state at the point of  
> rollback. In particular, the state of version attributes and  
> generated state (e.g., generated primary keys) may be inconsistent.  
> Instances that were formerly managed by the persistence context  
> (including new instances that were made persistent in that  
> transaction) may therefore not be reusable in the same manner as  
> other detached objects—for example, they may fail when passed to  
> the merge operation.
> ====
>
> As an app writer, this statement is somewhat disconcerting.
>
> I was wondering if there is any guidance available for how I can  
> write an app against JPA that handles rollback correctly.
>
> I'm writing a controller that interacts with entity objects,  
> passing them around to various methods, storing them in member  
> variables, and so on. I don't want to detach them, because (a) it  
> is costly for me to copy all the data into a separate, detached  
> instance, and then during the merge operation to have them copied  
> back into the instance stored in the persistence context and (b) I  
> never know if I can access a field or relationship because I don't  
> know if the field or related instance has been loaded yet. When I  
> keep them attached, JPA takes care of this for me.
>
> Then let's say I perform a persist() operation and it fails and  
> rolls back. This means all my objects I've been passing around and  
> storing in various places are suddenly detached and "may be" in an  
> inconsistent state (which from the perspective of a program is the  
> same as saying they *are* in an inconsistent state), and thus are  
> invalid.
>
> So now what do I do? Is there a recommended approach for dealing  
> with this? How does my application detect this in some global way,  
> and reloads from the persistence context all the instances it was  
> keeping around?
>
> The other concern I have is I'd like consumers of my controller to  
> use entity objects as POJOs without having to know or care if they  
> are entities. But the rollback semantics means my callers have to  
> deal with handling a rollback. Alternately I could pay the copy  
> cost of detaching my objects before passing them up to higher  
> levels, but then my caller will still have to deal with the  
> semantics of detached objects (e.g. lazy fields or associated  
> instances may be null). I don't see any way to expose entities  
> directly to higher levels of my app that are entity-unaware...  
> Which means I have to wrap my entities into proxy classes that  
> handle all the JPA semantics internally and don't expose this to  
> the caller.
>
> I am concerned that the rollback consequences can slip past  
> developers, who will then build apps that behave very erratically  
> after a transaction rollback. I know it's in the spec, but having  
> worked with lots of developers, most of them don't read the spec,  
> but instead cut-and-paste from examples. It would be great if we  
> did a blog about this, and provided some code showing how to do it  
> right... I could do this, but before I do I thought I'd check with  
> you all first for any thoughts you have on this.
>
> Thanks!
>
> David