We have a Google Code Share project, which hosts a number of generic samples. This article highlights the current content that showcases use of our API around the platform features Batch Apex and Apex Scheduler with our Journal API. Though the Journal API was used, the principles apply in the same way to our other document APIs such as Invoice.

The sample illustrates a common requirement we see around custom objects that are either created for integration purposes or present from applications already installed in an organisation. The sample illustrates invoking the FinancialForce API from a list view and detail page custom button, Batch Apex and also the recently announced Spring '10 Apex Scheduler.

developer_batch_apex

Here we see an object called "Simple Journal". It has Value and Analysis fields only, the rest of the information needed by FinancialForce is calculated either by the custom Apex code or by the FinancialForce API. This sample is deliberately contrived to show a number of ways in which records from this object can used to create and post Journals in FinancialForce, via our API.

Custom Buttons

First, let's look at the custom buttons. There are two in the sample, one on the detail page and one on the list view page. This one is called "Create Journals", this allows the user to select records from a custom list view and click a button to process them. A list view is standard page available for no additional development once a custom object is defined.

w660_batchapex_1

The custom button was created on the Setup > Create > Objects page, by clicking on the custom button and adding a JavaScript button as shown here.

w660_batchapex_2

This button script invokes an Apex Web Service that, in turn, starts a Batch Apex job to process the selected records.

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * Simple web service to issue a Batch Apex job
 * to create the corresponding journals
**/
webservice static void createJournals(List<ID> ids)
{
    // Users current company
    List<String> currentCompanies = c2g.CODAAPICompany_2_0.GetCurrentCompanies(null);
    String currentCompany = currentCompanies[0];
    // Start Batch Apex job to create Journals
    Database.executeBatch(new SimpleJournalImportBatch(ids));
}

The "Create Journal" button on the detail page works in much the same way, only in this case it creates the journal interactively as it is only operating on a single record. Follow these links to view the Custom Button definition and the Apex Code class that calls the Journal API.

w660_batchapex_3

Batch Apex

As shown above, the SimpleJournalImportBatch Apex class is invoked from the List View custom button. The full code sample for wrapping FinancialForce API calls can be seen here. Note that this sample makes use of the BulkCreateJournal and BulkPostJournal API calls once all the Journals have been setup in Apex. This is very important to avoid hitting governor limits that FinancialForce API calls are not made excessively within loops, this is for the same reason as Salesforce recommends bulkification of code within triggers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Build a list of Journals
List<c2g.CODAAPIJournalTypes_3_0.Journal> journals =
new List<c2g.CODAAPIJournalTypes_3_0.Journal>();
// Process Batch Apex execute records
for(SObject record : records)
{
    SimpleJournal__c simpleJournal = (SimpleJournal__c) record;
    // Setup Journal Header
    c2g.CODAAPIJournalTypes_3_0.Journal journal =
    new c2g.CODAAPIJournalTypes_3_0.Journal();
    // Create Line 1
    c2g.CODAAPIJournalLineItemTypes_3_0.JournalLineItem lineItem1 =
    new c2g.CODAAPIJournalLineItemTypes_3_0.JournalLineItem();
    // Create Line 2
    c2g.CODAAPIJournalLineItemTypes_3_0.JournalLineItem lineItem2 =
    new c2g.CODAAPIJournalLineItemTypes_3_0.JournalLineItem();
    // Add Journal to bulk list
    journals.add(journal);
}
// Bulk Create and Post Journals
c2g.CODAAPICommon_3_0.Context context = new c2g.CODAAPICommon_3_0.Context();
List<c2g.CODAAPICommon.Reference> refs =
c2g.CODAAPIJournal_3_0.BulkCreateJournal(context, journals);
c2g.CODAAPIJournal_3_0.BulkPostJournal(context, refs);

Apex Scheduler

Making use of the Apex Scheduler is very simple if you have already used Batch Apex, the above example was easily adapted to create a new sample class that can be seen in full here. By have the class implement a new interface and a new method, the system recognises the class when using the Schedule button on the Classes view.

1
2
3
4
5
6
7
8
9
10
global class SimpleJournalImportScheduler implements Schedulable,
Database.Batchable<SObject>{
    global void execute(SchedulableContext ctx)
    {
        // Start Batch Apex job to create Journals
        Database.executeBatch(new SimpleJournalImportScheduler());
    }
    // Remaining code to implement Database.Batchable
    // ...
}

Once such a class is uploaded to your org, go to Setup > Develop > Classes and click the Schedule Apex button.

w660_batchapex_4

For more information on the Apex Scheduler, refer to the Salesforce Apex Reference Guide at developer.force.com.

IMPORTANT USAGE NOTICE PLEASE READ

Copyright © 2009, FinancialForce.com, inc

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of the FinancialForce.com, inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.