Exception Handling

Some APIs in Kii Cloud SDK throw exceptions. In this section, we explain how you can handle the exceptions and how you can investigate the cause of the failure.

Sample code in the guides

In the guides, we provide sample code to illustrate how you can leverage our SDKs. In the sample code, the exception handling is usually simplified; the message output and error recovery are omitted.

For example, we present the following sample code when we explain how to register new users:

Blocking API

When an error occurs in a blocking API call, an exception will be thrown. You can handle the exception with a try/catch block just like any other Java programs. The sample code presented in the guides basically handle only abstract-level exceptions.

try {
  user.register(password);
} catch (IOException e) {
  // Handle the error.
  return;
} catch (AppException e) {
  // Handle the error.
  return;
}

Non-Blocking API

When an error occurs in a non-blocking API call, an exception object will be passed as a parameter of a callback method. If there is no error, this exception object will be null.

user.register(new KiiUserCallBack() {
  @Override
  public void onRegisterCompleted(int token, KiiUser user, Exception exception) {
    if (exception != null) {
      // Handle the error.
      return;
    }
  }
}, password);

Types of exceptions

In general, your application needs to handle the following two types of exceptions (unless the sample code says otherwise).

  • java.lang.IOException

    IOException occurs when you call an API that accesses the network, but there are some issues in the networking with the server. Most of the time, this error is due to the unstable or misconfigured network.

  • AppException

    AppException is the root exception in the exception class hierarchy (there is CloudException that is a superclass of AppException, but this is merely for the future extension). Usually, you will just need to catch AppException, as presented in the sample code.

    When an API execution causes an error, Kii Android SDK will basically throw an exception object that is a subclass of AppException. If the API internally executes the REST API, it will throw the subclass exception that corresponds to the HTTP status returned by Kii Cloud as shown in the next table (if the HTTP status not listed in the table is returned, UndefinedException will be thrown).

    HTTP Status Type of Exception
    400 BadRequestException
    401 UnauthorizedException
    403 ForbiddenException
    404 NotFoundException
    409 ConflictException

These exceptions have the following hierarchy, so you can handle all of them by catching IOException and AppException in a try/catch block. For the complete list of all exceptions thrown by the SDK and the detailed explanation of the exceptions thrown by each API, please read the Javadoc.

You need to validate the string (i.e. its length and the characters in the string) before you pass it to the API as a parameter. The client SDK will check the parameter and throw RuntimeException (e.g. java.lang.IllegalArgumentException) if the parameter is invalid. If you are using a blocking API, this will cause your application to crash. Please note that some non-blocking API also throws RuntimeException when the parameter is invalid. There is BadRequestException defined as a subclass of AppException, but this will not cover the parameter error cases that are handled by IllegalArgumentException.

If you want to handle exceptions more precisely, you can check and handle individual exceptions as shown in the following sample code:

Blocking API

try {
  user.register(password);
} catch (ConflictException e) {
  // Registration failed because the user already exists.
  return;
} catch (AppException e) {
  // Registration failed because of another exception in the app layer.
  return;
} catch (IOException e) {
  // Registration failed because of an exception in the network layer.
  return;
}

Non-Blocking API

user.register(new KiiUserCallBack() {
  @Override
  public void onRegisterCompleted(int token, KiiUser user, Exception exception) {
    if (exception instanceof ConflictException) {
      // Registration failed because the user already exists.
      return;
    } else if (exception instanceof AppException) {
      // Registration failed because of another exception in the app layer.
      return;
    } else if (exception instanceof IOException) {
      // Registration failed because of an exception in the network layer.
      return;
    } else if (exception != null) {
      // Registration failed because of one of the other exceptions.
      return;
    }
  }
}, password);

It is difficult to cover all exceptions and error cases thrown by each API. We recommend you to catch only specific cases that you need to handle explicitly (e.g. user duplication and network error) and handle other cases as a general error. Please note that exceptions and error codes can be added and modified as we update the SDK and server.

Error details

Sometimes you can get the details of the exception from AppException and its subclasses. The client SDK connects to Kii Cloud server via REST API. When the server returns an error, you can get the information returned by the server using the methods in the exception. The information is useful for determining the root cause of the error during your development.

For example, suppose that you try to register a user user_123456 but this user already exists in Kii Cloud. Executing the following code will cause a user duplication error. The sample code shows the error details you can get in this situation.

try {
  KiiUser user = KiiUser.builderWithName("user_123456").build();
  user.register(password);
} catch (ConflictException e) {
  // Handle the error.

  // Print the cause of the error.
  System.out.println("-- getReason");
  System.out.println(e.getReason());
  // Print the error message.
  System.out.println("-- getMessage");
  System.out.println(e.getMessage());
  return;
} catch (AppException e) {
  // Handle the error.
  return;
} catch (IOException e) {
  // Handle the error.
  return;
}
-- getReason
USER_ALREADY_EXISTS
-- getMessage
Error: null
HTTP Response Status: 409
HTTP Response Body: {
"errorCode" : "USER_ALREADY_EXISTS",
"message" : "User with loginName user_123456 already exists",
"value" : "user_123456",
"field" : "loginName"
}

This example shows the result of the user duplication. The error information obtainable differs by the situation. In your code, please make sure to handle the case when null is returned. For example, all REST API related details will be null if the error is raised solely by the client SDK inside).

  • getReason method

    This method returns the enum that explains the reason of failure. The enum is available when the REST API is called inside the client SDK. The method is available on the following exception classes: BadRequestException, NotFoundException, and ConflictException.

  • getMessage method

    This method returns the error details for debugging purposes. The return message includes the result of the getBody method, but it does not include the stack trace. If you just want to get the stack trace, you can use the printStackTrace method.

    If you encounter an unknown error while developing, you might get the error details by reading the message field of the HTTP Response BODY. In the above example, you can see that the specified user already exists in Kii Cloud.

There are more methods for getting the error details, but basically you should be able to investigate the problem with the exception type and the result of the getReason method.

When you are going to ask for some help, we encourage you to provide this information as the reference.

For more details on errors, please check AppException class reference, including its superclass and subclasses.

If you want to control your Android code based on the error reason, we recommend coding your application as follows:

  1. Check the exception type. For example, you can learn that the user duplication occurs when ConflictException is thrown.

  2. If you cannot determine the error reason by the exception type (e.g. the same exception will be thrown in multiple situations), check the details with the getReason method and take the appropriate action.

Common API errors

There are common API errors for cases including when refresh of an access token fails and when the server receives too many requests.

Failed refresh of access tokens

If you are going to leverage the refresh token feature, we encourage you to design your application so as to handle the RefreshTokenFailedException case.

As explained in this section, you need to execute relogin with a username and password when you get the RefreshTokenFailedException exception; therefore, your application needs to show the initial screen or the login screen so as to ask for user relogin. This check needs to be made for all API calls that access the network, so it is essential to design how to handle such a situation beforehand.

Too many requests

The API returns error if there are accesses that greatly exceed the ordinary load to the server within a certain period of time for an application. This limit is set per application under an agreement with Kii.

The limit is high enough for ordinary changes in the operational load. However, if active users simultaneously send a request on the same time or event, it could cause an API error.

If the number of API calls exceeds the limit, each API returns error with the UndefinedException class that is a subclass of the AppException class. The getStatus() method of the UndefinedException instance returns error code 429. Detailed information is not available because the UndefinedException class does not have the getReason() method.

Usually, a mobile app processes this error as an unexpected error on the server. To avoid congestion, do not implement a retry process for executing the API.

Tools for investigating errors

There are a couple of tools available to help you investigate the error root cause.

Developer log

The error details are recorded in the developer log.

See Inspect Developer Log to learn how you can inspect the error log to spot the root cause while developing and troubleshooting.

The following log is a sample of logs that are recorded when the user duplication occurs:

2015-04-21T11:45:11.783+09:00 [ERROR] user.register description:User registration failed userID: login-name:user_123456 email-address:user_123456@example.com phone-number:+819012345678 exception:User with loginName user_123456 already exists

Data browser

You can verify if the data updated in your application are properly set in Kii Cloud.

See Checking and Updating Data, Users, and Groups for more details.