Page 1 of 1

An improved PO.save() with error handling for 2.5.1g

PostPosted: Fri Jul 01, 2005 5:52 pm
by neilg
Red1 mentions things have changed drastically in 2.5.2x. So I don't think much of this is applicable in that version. For the people (like me) stuck on the old version for a while this will apply:

For 2.5.1g:

Saving your object which extends PO is not as easy as it seems.

You need to do the following in order to deal with possible errors:

(I think it is best put into another class (e.g. decorator) because it needs to be done each time we save.
Code: Select all
try
        {
            if (!po.save())
            {
//save error
                throw new SystemException("Could not save the record:" + Log.retrieveError().getName());
            }
        } catch (Exception e)
        {
//db error
                e.printStackTrace();
            throw new SystemException("Could not save the record:" + e.getMessage());
        }
[/b]

PostPosted: Fri Jul 01, 2005 6:52 pm
by neilg
Here is a wrapper class to make things easier.

Example usage
Code: Select all
POManager.getInstance(po).save();
or if you wish to trap any errors
Code: Select all
try
        {
            POManager.getInstance(po).save();
        } catch (PersistenceException e1)
        {
            e1.printStackTrace();
            //also do some logging here if you wish
            if (isInteractive)
            {
                Console.getConsole().printStackTrace(e1);
                throw new SystemException(e1);
            }
        }


Code: Select all
/*
* Created on Jul 1, 2005
*
*/
package za.co.ntier.core;
import org.compiere.model.PO;
import org.compiere.util.Log;
import org.compiere.util.ValueNamePair;

public class POManager
{
   
    private PO po;
    private Exception exception;
    private boolean error;
    private String errorMessage;

    private POManager(PO po)
    {
        this.po=po;
    }
   
    public static POManager getInstance(PO po)
    {
        return new POManager(po);
    }
   
    public void save()
    throws PersistenceException
    {
        exception=null;
        error=false;
        errorMessage=null;
        try
        {
            if (!po.save())
            {
                ValueNamePair pair;
                //
                error=true;
                pair=Log.retrieveError();
                if (pair==null)
                {
                    errorMessage="Could not save the record in the database for " + po.get_TableName();
                } else
                {
                    errorMessage=pair.getName();
                }
            }
        } catch (Exception e)
        {
            exception=e;
            e.printStackTrace();
            if (e.getMessage()!=null)
            {
                error=true;
                errorMessage="Error saving: " + e.getMessage();
            }
            else
            {
                error=true;
                errorMessage="Error saving: " + e.toString();
            }
        }
        if (error==true)
        {
            throw new PersistenceException(errorMessage, exception);
        }
    }
   
    public boolean isError()
    {
        return error;
    }

    public Exception getException()
    {
        return exception;
    }

    public String getErrorMessage()
    {
        return errorMessage;
    }

    public static class PersistenceException extends RuntimeException
    {

        public PersistenceException()
        {
            super();
        }

        public PersistenceException(String message, Throwable cause)
        {
            super(message, cause);
        }

        public PersistenceException(String message)
        {
            super(message);
        }

        public PersistenceException(Throwable cause)
        {
            super(cause);
        }

       
       
    }
   

}


Note: Testing status: Some live testing done. Before save verified

Use eclipse templates

PostPosted: Fri Jul 01, 2005 7:52 pm
by neilg
If you define an eclipse template (Prefs/Java/Editor/Template) as 'sve' then when you type sve <control space> it will magically put the whole code into the editor for you.
Code: Select all
POManager.getInstance(${po}).save();

Use this one if you want to catch the error. I've saved mine as 'sveCatch':
Code: Select all
try
{
POManager.getInstance(${po}).save();
}
catch (PersistenceException e)
{
e.printStackTrace();
throw new SystemException(e);
}

PostPosted: Sun Jul 03, 2005 2:12 pm
by neilg
I think PersistenceManager is better as a RuntimeException. Saves you keep on catching it (- then what ? sometimes you just want it to unwind).

Don't want to add more unnecessary work for the developer.

Editted the original post to reflect this change.

PostPosted: Tue Jul 05, 2005 5:46 pm
by neilg
Improvements:

- The beforeSave wasn't setting error to true, so beforeSave errors were not being trapped (one code change and all referring code fixed!)
- Simplified the PersistenceException class
- Some testing has been done
- Editted the original post to reflect the changes

PostPosted: Wed Jul 06, 2005 12:19 am
by red1
Neil,
U do swim with the dolphins. :)
But right now, in version 252d compiere really has no triggers at all. And we have a hard time tracing many of them. Some we can figure out but many is NO. They dont seem to be in any particular place, dont seem to be in beforeSave.

Also have u figured out how the WorkFlow engine work?

PostPosted: Wed Jul 06, 2005 12:52 am
by neilg
Hi Red1,

Thanks for the info on 2.5.2.

I really have to get it running soon so that I can come up to the present year. It might not be so long really before I start working on a live 2.5.2.

I've looked very briefly at the workflow engine. Why do you mention it?

Regards Neil

PostPosted: Wed Jul 06, 2005 4:33 am
by trifon
Workflow engine is something like "terra incognita" for most of Compiere developers.

Regrds,
Trifon

PostPosted: Wed Jul 06, 2005 4:42 am
by neilg
Looks like something worthwhile getting to know.