This page provides details on the general error recovery mechanism provided by the Desktop SDK.The easiest recovery procedure is available via QBFC, if you are using that QBFC automates most of what you need to do. However, in this chapter we’ll cover both QBFC and qbXML procedures.
If your application adds, deletes, voids, or modifies data in the QuickBooks company file, you need to implement an error recovery routine. This routine enables your application to respond to and recover from conditions that interrupt normal processing of requests and responses. Examples of such error conditions include system crashes and power outages as well as internal system errors and out-of-memory conditions.
A simple error recovery routine asks QuickBooks to save its state, so that when a processing error occurs, you can ask QuickBooks to check its state and it can return status information to you about the request in question. For example, suppose your application sends a CheckAdd request to QuickBooks. The ProcessRequest method (or DoRequests method for QBFC) fails to return a response or result code. What should your application do? Does it assume the check was created? Does it assume the check wasn’t created? Either assumption, if incorrect, will cause problems. The correct approach is for your application to invoke an error recovery routine that checks the status of the CheckAdd request and determines whether processing succeeded or failed before it asks QuickBooks to add the check a second time.
If your application is a read-only application (that is, the only requests it sends are query requests), then you do not need to implement an error recovery routine.
When you receive an error from QuickBooks that indicates an error in processing a request, or when you do not receive a response from QuickBooks at all, your application needs to invoke its error recovery routine. In addition, if your application adds, deletes, modifies, or voids data in the QuickBooks company file, it should invoke its error recovery routine upon startup, in case the previous session terminated before all outstanding requests were successfully processed.
Applications integrating with QuickBooks should invoke their error recovery routine when any of the following error conditions occurs:
The General Error Recovery Mechanism403
QBFC automates the SDK error-recovery mechanism described later in this chapter (see “Using Error Recovery in qbXML-based Applications”) by automatically managing the newMessageSetID and oldMessageSetID attributes and by saving the request message set to disk. This enables your application to determine which request corresponds to the response status that the error-recovery feature returns.
For QuickBooks,QBFC error-recovery information is unique to a given integrated application (via a GUID specified by ErrorRecoveryID) and company file. As a result, a session must be started before certain QBFC error-recovery functions can be executed. (Only EnableErrorRecovery, ErrorRecoveryID, and SaveAllMsgSetRequestInfo can be executed before a session is started.)
Note
Note
QBFC automated error recovery is available only for data message sets (not for subscription and event messages).
In general, these are the steps you need to follow to use QBFC’s automated error recovery in your application:
Error Recovery and Query Requests
Generally, error recovery is not used with query requests. If your application does not receive a response from a query request, you would usually just resubmit the query. We recommend that your application disable error recovery before querying, and then re-enable it before starting other requests.
If your application doesn’t use QBFC, you’ll have to do more work in implementing error recovery. You’ll need to know a few things that are simply done automatically and behind the scenes for QBFC.
The QuickBooks SDK error recovery mechanism employs two attributes: newMessageSetID and oldMessageSetID. Message set IDs need to be unique strings and are limited to 23 characters. (The colon, backward slash, and forward slash cannot be used in these IDs.) The newMessageSetID identifies the current message and enables the error recovery mechanism by signaling to QuickBooks that you want it to save the state of this message.
When you are sure QuickBooks has successfully processed a given message set, you send the message ID as the oldMessageSetID attribute, which has the effect of asking QuickBooks to clear that ID and associated data from its saved state.
Your application is responsible for generating the message set IDs, which must be unique within your application space. How you generate the value for the message ID is application-specific. For instance, you might use a language-dependent tool to generate the value. (The tool should ensure a unique value, not just a randomly generated one.)
In some circumstances, you may need to delete all error recovery information that applies to your applications. To do this, simply set the oldMessageSetID value to ClearAllMessageSets. (oldMessageSetID = ClearAllMessageSets).
The following steps outline a general procedure for implementing error recovery within your application. First, steps 1 through 6 describe what your application needs to do during normal, successful processing of a request.
If a crash or other processing error occurs, you will need to invoke your error recovery routine.
Here are the general steps:
At startup, check for a saved request message set. (If the request message set is still save on disk—step 2, above—it was never cleared. This condition indicates some problem with normal processing outlined in steps 1 through 6.)
If a saved request message set is present, resend the request set. This action has the effect of performing a status check for the message set. If QuickBooks has already processed all or some of the request, it will return the status for it. If QuickBooks has not already processed the request, it will process it and send a response.
Based on the response from QuickBooks, you will need to fix the problem, if there is one. (If you just keep sending the same request without fixing problems, you’ll be in an endless loop.) After you’ve fixed or identified the problem, you need to generate a new newMessageSetID.
Repeat steps 2 through 6, (sending the revised request with its new newMessageSetID to QuickBooks).
The following example shows a CheckAdd request that includes a newMessageSetID. If an error in processing occurred and no response was received, the error recovery routine could send this same request again. If the request had been previously received, QuickBooks would interpret this second, identical request as a status check and would send back the response shown in the next example.
<QBXMLMsgsRq newMessageSetID = "DE9437D9-AA85-21E4-D643"
onError="continueOnError">
<CheckAddRq requestID = "1">
<CheckAdd>
<AccountRef>
<FullName>Checking</FullName>
</AccountRef>
<PayeeEntityRef>
<FullName>East Bayshore Auto Mall</FullName>
</PayeeEntityRef>
<TxnDate>2001-10-14</TxnDate>
<Memo>Installment check</Memo>
<ExpenseLineAdd>
<AccountRef>
<FullName>Automobile</FullName>
</AccountRef>
<Amount>520.00</Amount>
</ExpenseLineAdd>
</CheckAdd>
</CheckAddRq>
</QBXMLMsgsRq>
And the response to the preceding status check (the CheckAdd request with error recovery indicated by the newMessageSetID):
<?xml version="1.0" ?>
<QBXML>
<QBXMLMsgsRs newMessageSetID="DE9437D9-AA85-21E4-D643"
messageSetStatusCode="0">
<CheckAddRs requestID="1" statusCode="0" statusSeverity="Info" statusMessage="Status OK"/>
</QBXMLMsgsRs
</QBXML>
A messageSetStatusCode is returned to your application in response to an error recovery request, such as a status check or a clear status. It is also returned if some specific error recovery operation is invoked and fails, such as a standard check for a validmessage set ID; if the call fails, then a messageSetStatusCode is returned.
A messageSetStatusCode is not returned, for instance, if your application issues a check status request that returns successfully. It is good practice to test for this status code, regardless of the fact that in some cases it is not returned.
The following table shows the error recovery status codes and their meaning.
Code | Meaning |
---|---|
0 | Success |
600 | The oldMessageSetID does not match any stored IDs, and no newMessageSetID is provided. |
9001 | Invalid checksum. The newMessageSetID specified matches the currently stored ID, but the checksum fails. |
9002 | No stored response was found. |
9003 | (Not used) |
9004 | InvalidMessageSetID(message set ID), greater than 24 characters was given. |
Code | Unable to store response. |
If you include a request ID in a request message, that ID will be returned in a status check request. This is a handy way to identify a request that was sent earlier.
In certain cases when you send multiple requests with the same newMessageSetID, QuickBooks compares the two versions of the messages themselves by performing a checksum on them. If the messages do not match, QuickBooks returns an error (9001) because, even though the newMessageSetIDs were the same, the messages were different, so your intent is not clear. (If the messages match, then QuickBooks assumes you’re performing a status check.)
When a message set contains multiple requests, some of the requests may have been processed successfully before the error condition occurred. When error recovery is implemented (through use of newMessageSetID), applications integrating with QuickBooks receive individual status codes for each request within the message set, as shown below:
<QBXML>
<QBXMLMsgsRs newMessageSetID="DE9437D9-AA85-21E4=D643"
messageSetStatusCode="0">
<CheckAddRs requestID="345" statusCode="510" statusSeverity="Warning" statusMessage="Unable to return all data" />
<AccountAddRs requestID = ”346” statusCode = "0" statusSeverity = "Info"
statusMessage = "Status OK" />
<CustomerModRs requestID = ”347” statusCode = "0" statusSeverity = "Info"
statusMessage = "Status OK" />
<CheckAddRs requestID="348" statusCode="3231" statusSeverity="error"
statusMessage="This request has not been processed" />
</QBXMLMsgsRs>
</QBXML>
This example contains the following status information:
Once you know that a particular request has been processed successfully, you’ll want to delete your saved copy of the request and send a message to QuickBooks to clear the old message set ID and associated status information that has been stored. The next example shows one way to clear the oldMessageSetID and status information:
<QBXML>
<QBXMLMsgsRq oldMessageSetID = "DE9437D9-AA85-21E4-D643"
onError = "continueOnError"/>
</QBXML>
The following table lists uses of new and old message set IDs:
If your request includes … | QuickBooks does this | messageSetStatusCode returned … |
---|---|---|
A brand new newMessageSetID. |
Executes the request and stores state for this message ID | status=0. |
A newMessageSetID that has already been sent in a previous message. | Status check. (Also does checksum on the two messages that use the same newMessageSetID.) | If checksum is OK, returns status=0. If checksum fails, returns status=9001. |
oldMessageSetID = newMessageSetID (Both are included in same request; ID has already been sent in a previous message.) |
Status check. | status=0 (If ID can’t be found, returns status 9002). |
Only an oldMessageSetID. | Clears state for this message ID. | status=0 (If old ID can’t be found, returns status=600;). |
oldMessageSetID =ClearAllMessageSets | If you receive status code9005, issue this request, whichdeletes all recovery records forthis application. | status=0 if the records aredeleted. (If no recordsexist to be deleted or anerror occurs duringdeletion, returnsstatus=600.) |
oldMessageSetID =XXX newMessageSetID =YYY (oldMessageSetID was sentpreviously and newMessageSetIDis new.) |
Clears state for the oldMessageSetID. Executes the request. Stores state for the newMessageSetID |
status=0; |
What constitutes an application’s internal state in regard to error recovery will vary from one application to another based on how the application uses and stores request and response data. For instance, many applications maintain temporarily the following information:
A message ID of the most recent request message set sent
Contents of the most recent message request
The most recently received response
Although QuickBooks allocates the memory for the response object on behalf of the application, the application processes the content and then uses it according to its implementation and features. It may discard the response, it may preserve it in a database, it may display it to the user in some form. In any case, it is the application’s responsibility to release the memory used for the response data.
The only hard and fast guideline is that you should not clear state too early in your process. Be certain that your application is finished with the request to which the internal state to be cleared pertains. Here are more extensive ideas:
An application should preserve the new MessageSetID of a request message set until it has received a response from QuickBooks and processed the results of that response. Even though an error condition might not have occurred, for other reasons you might deem it useful for your application to check status in a request message set. In this case, you might want the application to avoid disposing of the message ID until just before it exits its error recovery routine.
Recall that whenever a ProcessRequest (or DoRequests or Post) call is made to QuickBooks, it is subject to the possibility of an interruptive error condition. For this reason, some applications might consider preserving the message ID until after the clear state request returns successfully. An application not deleting the message ID until after clearing the processing state in QuickBooks would need to be careful not to misinterpret the message ID. That is, it must not mistakenly handle that message ID as if it were meaningful in any other context before actually deleting it.
After sending a processing request, your application should always check returned status. If the returned status indicates problems, an application might call its handler routine for the condition.
If the ProcessRequest call completed successfully, an application should process the returned response, handling all status codes and data.
QuickBooks maintains a finite number of error recovery processing records for your application in association with the company file that your application is modifying. If an error condition occurs that interrupts processing, your application can retrieve this stored information because it is associated with the message ID you specified along with the request message set to be processed.
The best practice to follow is to always clear error recovery processing state information from QuickBooks when your application is entirely finished with the response to the request.
For all requests except the one during which the error condition occurred, an application should already have complete information on the processing state of the request. The application might either have received that information in a normal response from QuickBooks or it might have sent QuickBooks a check status request to obtain the information. Thus, the information stored in QuickBooks for these requests is no longer needed for error recovery.
If your application does not regularly clear the processing state for requests maintained by QuickBooks, QuickBooks will eventually delete older records to allow for addition of new ones. Just as an operating system must clear memory from time to time to free up system resources, QuickBooks must ensure that resources are available for addition of new error recovery processing state records to accommodate new requests.