how to flush changes to persistent manager - google-app-engine

The scenario is a update entity where i write code as follows:
try {
pm = PMF.get().getPersistenceManager();
BloodDonor bloodDonor = pm.getObjectById(BloodDonor.class,
bean.getBloodDonorSeq());
bloodDonor.setFirstName(firstName);
finally {
try {
if (pm != null && pm.isClosed() == false)
pm.close();
} catch (Exception e) {
log.severe("Exception in finally of execute of updateDonor");
}
log.info("end of updateDonor");
}
So, when it will hit the finally block on close of pm the changes will be written to datastore. My question is in a certain situation say i want to rollback whatever i did in the try block before closing the pm then how to do that? in other words, if i want to nullify the effect of try block then how do i do notify pm to clear all?

You should look at transaction to accomplish what you want to do here.

Related

Behavior when Spring Propagation.REQUIRES_NEW is nested in a Propagation.NESTED

I have code like so
#Transactional(propagation = Propagation.NESTED)
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class C1 {
...
public void xxx() {
try {
obj.someMethod();
} catch (Exception e) {
C2.yyy();
}
}
}
public class C2 {
#Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void yyy() {
...
}
}
My assumption is that when obj.someMethod(); throws a constraint violation exception C2.yyy() should still be able to save stuff to the DB.
However what I see is that when C2.yyy() is called Postgres reports
ERROR: current transaction is aborted, commands ignored until end of transaction block
Why should it do that? After all C2.yyy() should run in a different transaction that should be unaffected by the state of what happened in the invoking code. No?
Update
On further debugging here is what I found - let us say the call stack is like so
#Transactional(readOnly = false, propagation = Propagation.NESTED)
b1.m1()
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
b2.m2()
b3.m3()
b4.m4()
My assumption was that the DB code in m4() would execute in a new transaction because of the annotation on b2.m2(). But it seems the code in TransactionAspectSupport.java looks at the transaction annotation only on the current method and not on the stack. When it does not find any #transactional on m4() it assumes REQUIRES. Isn't this incorrect?
As answered here DatabaseError: current transaction is aborted, commands ignored until end of transaction block : "This is what postgres does when a query produces an error and you try to run another query without first rolling back the transaction".
Meaning that you 'obj' should run in its own transaction and roll back on exception.
Regarding the question in the update: REQUIRES_NEW always creates a new transaction, it is both documented and tested.

ZombieCheck Exception - This SqlTransaction has completed; it is no longer usable -- during simple commit

I have the following code which performs a commit of a single row to a database table (SQL 2008 / .NET 4)
using (var db = new MyDbDataContext(_dbConnectionString))
{
Action action = new Action();
db.Actions.InsertOnSubmit(dbAction);
db.SubmitChanges();
}
Normally everything is fine, but once in a while I get the following exception:
System.InvalidOperationException: This SqlTransaction has completed; it is no longer usable.
at System.Data.SqlClient.SqlTransaction.ZombieCheck()
at System.Data.SqlClient.SqlTransaction.Rollback()
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
There are a number of similar questions on SO but I after reading them I cannot work out the cause.
Could this be simply due to a SQL timeout (the exception occurs close to 25s after the call is made)? Or should I expect a SQL timeout exception in that case?
Does anyone know what else may cause this?
The DataContext.SubmitChanges method has the following code lines in it's body:
// ...
try
{
if (this.provider.Connection.State == ConnectionState.Open)
{
this.provider.ClearConnection();
}
if (this.provider.Connection.State == ConnectionState.Closed)
{
this.provider.Connection.Open();
flag = true;
}
dbTransaction = this.provider.Connection.BeginTransaction(IsolationLevel.ReadCommitted);
this.provider.Transaction = dbTransaction;
new ChangeProcessor(this.services, this).SubmitChanges(failureMode);
this.AcceptChanges();
this.provider.ClearConnection();
dbTransaction.Commit();
}
catch
{
if (dbTransaction != null)
{
dbTransaction.Rollback();
}
throw;
}
// ...
When the connection times out, the catch block is executed and the dbTransaction.Rollback(); line will throw a InvalidOperationException.
If you had control over the code, you could catch the exception like this:
catch
{
// Attempt to roll back the transaction.
try
{
if (dbTransaction != null)
{
dbTransaction.Rollback();
}
}
catch (Exception ex2)
{
// This catch block will handle any errors that may have occurred
// on the server that would cause the rollback to fail, such as
// a closed connection.
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
Console.WriteLine(" Message: {0}", ex2.Message);
}
throw;
}
YES! I had the same issue. The scary answer is that SQLServer sometimes rolls back a transaction on the server side when it encounters an error, and does not pass the error back to the client. YIKES!
Look on the Google Group microsoft.public.dotnet.framework.adonet for "SqlTransaction.ZombieCheck error" Colberd Zhou [MSFT] explains it very well.
and see aef123's comment on this SO post
May I suggest that connection closes earlier that transaction commits. Then the transaction is rolled back. Check this article on MSDN Blog.

Javamail : Proper way to issue idle() for IMAPFolder

I have set MessageCountListener for IMAPFolder. In order to get updates continuously I had to do the following, which is a killer for my app performance wise. It freezes the GUI since it's running for each and every folder.
while (true) {
try {
if (folder != null && folder.isOpen()) {
folder.idle();
} else {
getSyncListenersAttachedFolders().remove(syncFolder.getFolderID());
}
} catch (Exception ex) {
errorLOG.error("IDLE command issue exception.");
getSyncListenersAttachedFolders().remove(syncFolder.getFolderID());
}
}
Is there any better way of issuing idle command which will not run in a while(true) condition.
Expecting a quick response. Thanks in advance.
You need to run it in its own thread.

JDO Exception in google app engine transaction

I am getting the following exception while trying to use transation in app engine datastore.
javax.jdo.JDOUserException: Transaction is still active.
You should always close your transactions correctly using commit() or rollback().
FailedObject:org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManager#12bbe6b
at org.datanucleus.jdo.JDOPersistenceManager.close(JDOPersistenceManager.java:277)
The following is the code snippet I used :
List<String> friendIds = getFriends(userId);
Date currentDate = new Date();
PersistenceManager manager = pmfInstance.getPersistenceManager();
try {
Transaction trans = manager.currentTransaction();
trans.begin();
for(String friendId : friendIds) {
User user = manager.getObjectById(User.class, friendId);
if(user != null) {
user.setRecoCount(user.getRecoCount() + 1);
user.setUpdatedDate(currentDate);
manager.makePersistent(user);
}
}
trans.commit();
} finally {
manager.close();
}
and if the commit or makePersistent fails where is the call to "rollback" ?
I was able to reproduce this - if you declare your transaction inside the try block and close the pm in the finally. You won't get this message if you move your
Transaction trans = manager.currentTransaction();
trans.begin();
to above the try { } section like this:
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
tx.begin();
try {
//do my thing
tx.commit();
}
} catch (Exception e) {
tx.rollback();
} finally {
pm.close();
}
javax.jdo.JDOUserException: Transaction is still active. You should always close your transactions correctly using commit() or rollback().
I think the different 'User' object are not belonging to the same Entity Group. All datastore operations in a transaction must operate on entities in the same entity group.
You may begin the transaction inside the loop , so you will be operating on one entity at a time, or make sure all your objects are in the same group.

Try Catch block in Siebel

I have a script which sends a set of records into a file. I'm using Try - Catch block to handle the exceptions. In the catch block I have a code where it has the pointer to next record. But this is not executing . Basically I wan to skip the bad record n move to next record.
while(currentrecord)
{
try
{
writerecord event
}
catch
{
currentrecord = next record
}
}
In most languages (unless you're using something very strange), If 'writerecord event' doesn't throw an exception, the catch block will not be called.
Don't you mean :
while(currentrecord) {
try { writerecord event }
catch { log error }
finally { currentrecord = next record}
}
Are you trying to loop through some records that are returned by a query? Do something like this:
var yourBusObject = TheApplication().GetBusObject("Your Business Object Name");
var yourBusComp = yourBusObject.GetBusComp("Your Business Component Name");
// activate fields that you need to access or update here
yourBusComp.ClearToQuery();
// set search specs here
yourBusComp.ExecuteQuery(ForwardOnly);
if (yourBusComp.FirstRecord()) {
do {
try {
// update the fields here
yourBusComp.WriteRecord();
} catch (e) {
// undo any changes so we can go to the next record
// If you don't do this I believe NextRecord() will implicitly save and trigger the exception again.
yourBusComp.UndoRecord();
// maybe log the error here, or just ignore it
}
} while (yourBusComp.NextRecord());
}
You can use try-finally structure so that whatever inside the finally block will always be executed, regardless of whether the code throws an exception or not. It's often used to clean up resources such as closing files or connections. Without a catch clause, any thrown exception in your try block will abort execution, jump to your finally block and run that code.
Agree that 'finally' might be the best bet here - but do we know what the exception actually is ? - can you output it in your catch loop, so that :
A) you can prove an exception is being thrown (rather than say a 'null' being returned or something)
B) Make sure the exception you get isn't something that could prevent 'nextrecord' working as well...[not sure what the 'finally' would achieve in the case - presumably the exception would have to bubble up to calling code?
So you're trying to move onto the next record if you failed to commit this one. Robert Muller had it right. To explain...
If the WriteRecord fails, then the business component will still be positioned on the dirty record. Attempting to move to the next record will make the buscomp try to write it again--because of a feature called "implicit saving".
Solution: You'll have to undo the record (UndoRecord) to abandon your failing field changes before moving onto the next one.

Resources