Documentation

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:

FieldDeveloper Mode EnabledDeveloper Mode Disabled
transactionYesYes
codeYesYes
descriptionYesYes
informationYes*No
causeYes*No
msgYes*

No

stacktraceYes*No

* If available.

The following examples show the error response, with and without Developer Mode enabled:

Developer Mode Disabled
Developer Mode Enabled

Enabling and disabling Developer Mode

You can enable or disable Developer Mode in the following ways:

To enable or disable Developer Mode, you can set the value of the akula_dev_mode app property in the appropriate properties.xml file:

  • Set akula_dev_mode to true to enable Developer Mode
  • Set akula_dev_mode to false to 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: 

Because the 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:

If the 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 loginSuccess: and loginFailure: methods.

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 userInfo property.)
  • 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 AKAkulaErrorCode corresponds 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.

Handling exceptions in JavaScript client apps

The JavaScript API defines the 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 AK.Session.login() method:

Handling errors from a REST request

You can bypass the Akula Android, iOS, and JavaScript APIs to make direct HTTP requests to the REST endpoints on the Akula Server. If an error occurs when you make an HTTP request, the Akula Server returns a response that contains an error object to describe the failure, as shown below:

{ "error":
    {
        "code": "error_code",
        "transaction" " unique_transaction_id " ,
        "description": "error_message"
    }
}

Where 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 information field:

{ "error":
    {
        "code": "error_code",
        "description": " error_message ",
        "transaction" "unique_transaction_id" ,
        "information": {
            "name1": "value1",
            "name2": "value2",
            "name3": "value3",
            ...
        }
    }
}

For example:

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 error_code, error_message, and information fields of an error returned by the Akula Server:

Akula Error CodeAkula Error Message

HTTP
Status Code

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
INCORRECT_TYPE "Incorrect type"400
INVALID_ACTION_NAME"Invalid action name"400

INVALID_ARGUMENT

"Invalid argument"400
INVALID_TARGET_QUERY"Invalid target query"400
MISSING_ARGUMENT"Missing required argument"400
HTTP 401 Errors  
ACCESS_DENIED"Access denied"401
ACCOUNT_LOCKED"Account locked"401
INVALID_CREDENTIALS"Invalid credentials"401
LICENSE_SERVER_LOGIN_DENIED"License server login denied"401
LOGIN_BLOCKED"Login blocked"401
OAUTH_ACCESS_DENIED(UNAUTHORIZED)"OAUTH access denied"401
PASSWORD_EXPIRED"Password expired"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
SYNC_BLOCKED"Sync blocked"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

"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
INVALID_URI"Invalid URI"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_ORPHANED

"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

AUTH_DIRECTORY_BAD_QUERY

"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"Generic error"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_VIOLATED_EXCEPTION"License violated"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.