Sample code for transaction and exception handling in import and report jobs

The following sample code illustrates transactions and exception handling within import and report jobs. Batchable interface might optionally be used in import and report extension point implementation.

Sample import extension point

Sample code for transactions and exception handling in a Java™ API-based import exit point implementation. This sample uses batchable interface for persisting items:
public class sampleImport implements ImportFunction
{
    // This function wraps an Exception in a RuntimeException to allow
    // ImportFunction to throw an unchecked exception, which is compatible
    // with its signature.
    private void throwRuntime(Exception e) 
    {
        throw new RuntimeException(e);
    }

    // This function evaluates the exception to determine if it is critical.
    // The code below is just an example, where an exception is deemed
    // critical if it is an instance of SQLException.
    private boolean isCriticalException(Exception e)
    {
        Throwable rootCause = e;
        Throwable cause = (e == null) ? null : e.getCause();
        while (cause != null) 
        {
            rootCause = cause;
            cause = cause.getCause();
        }
        return rootCause instanceof SQLException;
    }

    // This function must return null if there are no more items.
    private Collection<Item> getNextItemSetFrominput()
    {
        // Read the data from input, create new items and set the values
        // using spec map.
    }

    public void doImport(ImportFunctionArguments inArgs)
    {
        Catalog catalog = inArgs.getCatalog();
        Catalog.startBatchProcessing();
        Collection<Item> itemSet = null;
        Context context = PIMContextFactory.getCurrentContext();

        while((itemSet = getNextItemSetFromInput() != null)
        {
            for(Item item : itemSet)
            {
                item.save();
            }
            try
            {
                List<ExtendedValidationErrors> errs=catalog.flushBatch();
                // Process the failed items as identified from errs.
                // Perform any additional work for succeeded items.
                context.commit(); 
            }
            catch(Exception e)
            {
                context.rollback();
                if (isCriticalException(e) )
                    throwRuntime(e);
                // Process all items in the batch as failed
            }
            finally
            {
                try
                {
                    context.startTransaction();
                }
                	catch(PIMAlreadyInTransctionException paie)
                {
                    // unexpected exception. re-throw
                    throwRuntime(e);
                }
            }
        }
        catalog.stopBatchProcessing();
    }
}

Sample report extension point

Sample code for transactions and exception handling in a Java API-based report exit point implementation:
public class sampleReport implements ReportFunction
{
    // This function wraps an Exception in a RuntimeException.
    private void throwRuntime(Exception e) 
    {
        throw new RuntimeException(e);
    }

    private boolean isCriticalException(Exception e)
    {
        // evaluate the exception to determine if it is critical
    }

    // This function must return null if there are no more items.
    private Item getNextItemToSave()
    {
        // Create a new item to be saved as part of this report
    	}

    public void doReport(ReportFunctionArguments inArgs)
    {
        int numItemsPerTransaction = 200; // Commit every 200 
        Item item=null;
        Int numItemsSinceCommit = 0;
        Context context = PIMContextFactoy.getCurrentContext();

        while((item = getNextItemToSave() != null)
        {
            try
            {
                ExtendedValidationErrors errs = item.save();
                if (errs != null)
                {
                    // handle the errors
                }
                else
                {
                    numItemsSinceCommit++;
                    // perform any additional actions for this item.
                }
            }
            catch(Exception e)
            {
                if ( isCriticalException(e) )
                    throwRuntime(e);
                // Process the failure for this item
            }
            if (numItemsSinceCommit >= numItemsInTransaction)
            {
                numItemsSinceCommit = 0;
                try
                {
                    context.commit();
                }
                catch(Exception e)
                {
                    context.rollback();
                    if ( isCriticalException(e) )
                        throwRuntime(e);
                    // Process failure for all items since last commit
                }
                finally
                {
                    try
                    {
                        context.startTransaction();
                    }
                    catch(PIMAlreadyInTransactionException e)
                    {
                        // unexpected exception. re-throw
                        throwRuntime(e);
                    }
                }
            }
        }
    }
}