Handling Exceptions and Errors
Many methods in the Akula client APIs throw exceptions when detecting an error condition, or return an error object. In your app, you can handle the exception or error and respond accordingly based on the characteristics of your app.
In addition, you can configure the amount of information that is included in the exception by enabling or disabling Developer Mode.
The document contains the following sections:
For information about dispatching your own custom exceptions from your app scopes, see Dispatching Exceptions
Using Developer Mode
The Akula Server lets you enable or disable Developer Mode. When Developer Mode is enabled, the Akula Server returns extra information to the client when it encounters an error.
By default, Developer Mode is disabled.
About Developer Mode
The following table describes the information that is included in the error response, based on whether Developer Mode is enabled or disabled:
|Field||Developer Mode Enabled||Developer Mode Disabled|
* If available.
The following examples show the error response, with and without Developer Mode enabled:
Enabling and disabling Developer Mode
You can enable or disable Developer Mode in the following ways:
- Using the App Property Management REST API (does not require a server restart)
- Using the Akula Command-line Management Utility (does not require a server restart)
- Using the Akula Server Management Console.
- Editing the properties.xml file (requires a server restart)
To enable or disable Developer Mode, you can set the value of the
akula_dev_mode app property in the appropriate properties.xml file:
trueto enable Developer Mode
falseto disable Developer Mode
The following example section of the properties.xml file enables Developer Mode:
The location of the properties.xml file that you edit depends on whether you want to set Developer Mode at the server level or the app scope level. To set Developer Mode at the server level, edit the properties.xml file in the AKULA_HOME/global directory. This setting applies to all app scopes, unless an individual app scope overrides this setting.
To set Developer Mode at the app scope level, edit the properties.xml file in the project_root/AKZ-INF/config/scope directory.
After changing the value of an app property, you must restart the Akula Server for the change to take effect.
For more information about app properties, see App Properties Overview.
Handling exceptions in Android client apps
The way you handle exceptions in Android apps is determined by how you call the method: synchronously or asynchronously. If you call a method asynchronously, pass a callback object to the method to handle the method results. The Akula Android API defines several different callback classes in the com.verivo.akula.callback package. The callback class that you use depends on the specific asynchronous method that you are calling.
All callback classes define the following callback methods:
onSuccess()- Called when the request returns successfully. Depending on the callback class, this method can take an argument.
onFailure()- Called when the request fails. This method takes a single argument, of type Throwable, containing an exception object.
onDone()- Called when the request completes, regardless of success or failure. This method does not take an argument.
In the example below, you make an asynchronous call to the
AKSession.login() method, which takes an instance of the AKCallback class as an argument to define the callback methods:
onFailure() callback method takes a Throwable object as its only argument, you first determine the concrete type of the Throwable object to determine how to handle the exception. In the example above, you first determine of it is an Akula AKServerException object and handle it appropriately. Depending on the method that caused the exception, you might have to check for different types of exceptions.
A synchronous request waits for the Akula Server to return a response before the app continues. Typically, you make a synchronous request in a
try/catch block, as the following example shows:
loginSync() method fails, it throws an AKException object that you can catch and handle appropriately for your app.
Handling errors in iOS client apps
Error handling in iOS depends on whether the request type is synchronous or asynchronous. If you call a method in the Akula iOS API asynchronously, you pass a delegate instance to the method to handle the results, and your delegate class defines the methods to handle success or failure. For example, for the
login:withCredentials:delegate: method, the delegate methods are defined by the AKSessionDelegate protocol and include the
loginFailure: method takes a pointer to an NSError object. The properties of the NSError object contain the following information:
code- A static string for the error code (such as "IN_ROUTE_EXCEPTION"). (The Akula error code is contained in the
domain- The domain where the error occurred, which is com.akula.error for all errors.
localizedDescription- The error message.
userInfo- An NSDictionary object contains additional information about the exception as name/value pairs. (The name
AKAkulaErrorCodecorresponds to the Akula error code.)
In the example below, an asynchronous call is made to the
AKSession.login() method where the delegate object is specified as the calling class:
The following example shows how to perform a synchronous log in:
In the synchronous case, you examine the NSError object passed to the
login:withCredentials:error: method. If the NSError object is not nil, an error occurs and you can handle it appropriately.
Exception class as the base class for all exceptions. Depending on the type of error, a method such as the
AK.Session.login() method can throw an exception of type Exception, or of a subclass of Exception such as
ServerException. In your exception handler, you can determine the type of exception object and handle to error accordingly.
The following example shows how you can determine the type of exception in the
error() callback method passed to the
Handling errors from a REST request
error_code contains the error code and
error_message describes the error. The
transaction field contains a unique ID that is assigned to the request that resulted in the error. The transaction ID can be useful to sort or search by when there are hundreds or thousands of clients that are encountering different errors.
The error object can optionally contain an
information field that contains names and values in JSON format, depending on the error condition. The following shows the structure of a response that includes the
Notice that the HTTP status code is not included in the JSON response. The client or other exception handler can read this information from the response's HTTP header.
Akula error codes
The following table describes the values of the
information fields of an error returned by the Akula Server:
|Akula Error Code||Akula Error Message|
|HTTP 400 Errors|
|COULD_NOT_CREATE_AKZ||"Could not create the AKZ file on disk"||400|
|COULD_NOT_WRITE_AKZ||"Could not write AKZ file contents to disk"||400|
|COULD_NOT_MAP_JSON||"Could not map JSON to object"||400|
|COULD_NOT_PARSE_JSON||"Could not parse JSON"||400|
|INVALID_ACTION_NAME||"Invalid action name"||400|
|INVALID_TARGET_QUERY||"Invalid target query"||400|
|MISSING_ARGUMENT||"Missing required argument"||400|
|HTTP 401 Errors|
|LICENSE_SERVER_LOGIN_DENIED||"License server login denied"||401|
|OAUTH_ACCESS_DENIED(UNAUTHORIZED)||"OAUTH access denied"||401|
|HTTP 403 Errors|
|CANNOT_MODIFY_SERVER_SCOPE||"Cannot modify server scope"||403|
|NOT_PERMITTED||"Not permitted to access resource"||403|
|PUSH_TOKEN_DISABLED(FORBIDDEN)||"Push Token disabled"||403|
|HTTP 404 Errors|
|ACTION_NOT_FOUND(NOT_FOUND)||"Action not found"||404|
|APP_PROPERTY_NOT_FOUND||"App property not found"||404|
|"Credential not found"||404|
|CREDENTIAL_ORPHANED||"Credential has been orphaned"||404|
|DEVICE_NOT_FOUND(NOT_FOUND)||"Device not found"||404|
|GROUP_NOT_FOUND||"Group not found"||404|
|INVALID_ENDPOINT||"Endpoint not found"||404|
|LICENSE_NOT_FOUND||"License key not found"||404|
|LICENSE_USER_NOT_FOUND||"License user not found"||404|
|LOGGING_CONFIG_NOT_FOUND||"Logging config not found"||404|
|METHOD_NOT_FOUND||"Method not found"||404|
|PERMISSION_NOT_FOUND||"Permission not found"||404|
|"Permission has been orphaned"||404|
|PUSH_CONFIG_NOT_FOUND(NOT_FOUND)||"Push config not found"|
|REALM_NOT_FOUND||"Realm not found"||404|
|ROLE_GROUP_NOT_FOUND||"Role group not found"||404|
|ROLE_NOT_FOUND||"Role not found"||404|
|ROUTE_NOT_FOUND||"Route not found"||404|
|RULE_NOT_FOUND||"Rule not found"||404|
|SCOPE_NOT_FOUND||"Scope not found"||404|
|SCOPE_NOT_ENABLED||"Scope not enabled"||404|
|SECURITY_MANAGER_NOT_FOUND||"Security manager not found"||404|
|SPLITTER_NOT_FOUND(NOT_FOUND)||"Splitter not found"||404|
|TEMPLATE_NOT_FOUND||"Template not found"||404|
|HTTP 409 Errors|
|CANNOT_MODIFY_SERVER_SCOPE_PROPERTY||"Cannot modify app properties in the server scope"||409|
|CANNOT_MODIFY_SERVER_SCOPE_RULE||"Cannot modify server scope rule"||409|
|CANNOT_MODIFY_SUPER_ROLE||"Cannot modify super role"||409|
|ROLE_ALREADY_EXISTS||"Role already exists"||409|
|ROLE_GROUP_ALREADY_EXISTS||"Role group already exists"||409|
|RULE_ALREADY_EXISTS||"Rule already exists"||409|
|HTTP 500 Errors|
|ADMIN_CREDENTIALS_REJECTED||"Admin credentials provided to the backend were rejected"||500|
|"Authentication directory threw error on query"||500|
|AUTH_DIRECTORY_NOT_INITIALIZED||"Authentication directory could not be initialized"||500|
|AUTH_DIRECTORY_UNREACHABLE||"Authentication directory could not be reached"||500|
|BACKEND_UNAVAILABLE||"Backend could not be reached"||500|
|CONTEXT_LOADER_EXCEPTION||"Context load error"||500|
|COULD_NOT_WRITE_LICENSE_FILE||"Could not write license file contents to disk"||500|
|COULD_NOT_CREATE_LICENSE_FILE||"Could not create the license file on disk"||500|
|DATABASE_CONNECTION||"Database connection error"||500|
|DATABASE_CONSTRAINT||"Database constraint violation"||500|
|GENERIC_CACHE_PROVIDER||"Generic cache provider error"||500|
|GENERIC_DATABASE||"Generic database error"||500|
|GENERIC_SYNC||"Generic sync error"||500|
|IN_ROUTE_EXCEPTION||"Internal route error"||500|
|LICENSE_SERVER_GENERIC||"Generic license server error"||500|
|UNSUPPORTED_REALM||"Realm is not supported"||500|
In a custom module, you can create your own AKException and set custom values for the error code and HTTP status. For more information, see Handling Module Exceptions.