How to interact with a server that does not crash the app

Introduction

When creating a native application on Android or iOS, I think that most of the time it communicates with some server via API. However, if you do not handle API data well, It crashes or is said to be an unstable app that works strangely. This time, we will summarize the crashes / malfunctions that we have encountered so far and introduce measures to prevent them from crashing.

Lessons learned from the errors encountered

--Be sure to write the processing in case of server error / parse error ――I don't believe that "the value of XX is always on the server" --Int = 0, boolean = false have no meaning

Be sure to write the processing in case of server error / parse error

crash

--Crash with returning 404 trying to get deleted resources in request parameters --Crash when returning 500 due to server failure when acquiring user data when starting the application --HTML of error page for browser is returned and cannot be parsed and crashes

Commentary

The server does not always return 200 (normal). If you send a fraudulent request, it will return 404 or 422, If the server is over-accessed and down, it will return some error. It returns nothing and may time out.

At that time, if the consideration of "what to do if an error value is returned" is omitted, it will drop due to a parse error, or various values will start to move in the state of null or initial value, leading to abnormal operation.

Countermeasures

Be sure to add error handling when a 400 series or 500 series error is returned. Also, if parsing fails, it will be treated as an error and the user will be notified that there is a communication error.

I don't believe that "the value of XX is always on the server"

crash

--Crash because the value of 〇〇 is not in the old user information ――The value of 〇〇 was always present at the time of implementation, but there was a time when it was not a repair on the server side and it crashed. --I was using the API of an external service, but suddenly the service ended and the API disappeared and crashed

Commentary

When deciding the specifications with the developer on the server side You may be told, "This value doesn't exist when it's null, so you don't need to check for null." Don't believe these words. The person does not always have a complete grasp of the data specifications, ** It may not be the person who will repair the part later **

Countermeasures

Assume all responses are Nullable

Since we don't know when null will be returned, all data classes that receive the response should be Nullable and String.

UserApiData.kt


data class UserApiData(
  val id : String?,
  val name : String?,
  val age : String?,
  val birthDay : String?
)

(Written in Kotlin)

However, if you do so, you will have to perform null check and type conversion each time you use it in the application, and the code will become very complicated. for that reason, ① Data class that receives the response ② Data class used in the app Create two and create a conversion method that creates ① to ②.

User.kt


data class User(
  val id : String,
  val name : String,
  val age : Int,
  val birthDay : Date
)

UserConverter.kt


class UserConverter(){
    fun convert(data: UserApiData): User {
        if (data.id == null) throw IllegalArgumentException("user_id is null")
        return User(
                data.id,
                data.name ?: "",
                data.age?.toIntOrNull() ?: 0,
                parseData(data.birthDay)
        )
    }
}

In that conversion method, Null check is performed and the value is entered in the form of NonNull. If you get stuck in the Null check there

  1. Enter the default value for the display value
  2. Since the ID affects the subsequent processing, raise an exception and display an error dialog.

Depending on the case, we will use the correspondence such as. Then you can ** receive the response from the server properly and perform a null check in one place **

Int = 0, boolean = false have no meaning

Malfunction

--The dialog that is displayed only when false is always displayed. --Processing to be executed only when user status is 0 is always performed

Commentary

This leads to a bug when defining requirements. In Java, int and boolean are initially set to 0 and false, respectively, and are not null. It is implemented assuming that a value other than 0 comes from api, and if the value does not come, the process will be executed with 0 as it is.

Countermeasures

There is a method to set it to String in the same way as ↑, and a method to receive it with the wrapper class Int, Boolean instead of the primitive type int, boolean.

If you do so, the initial value will be null, so if the initial value does not change unintentionally, a crash or error will occur instead of an illegal operation.

I also want to prevent crashes / errors, but this is still better because it is included in Crashlytics and is easier to detect during testing.

Summary

--Do not forget error handling at the time of server error and parsing error --API receives all nullable, assuming it returns null

Actually, there are some measures that cannot be taken by adjusting the implementation time and specifications, but I think it would be good if we could take measures as much as possible to create a stable app.

Recommended Posts

How to interact with a server that does not crash the app
How to fix the problem that Aptana Studio does not start
How to check before sending a message to the server with Spring Integration
[Swift] How to link the app with Firebase
[Error] How to resolve the event that the screen does not transition after editing
How to run the SpringBoot app as a service
Organized how to interact with the JDK in stages
How to get started with creating a Rails app
When the server does not start with rails s
How to place a button that does not move by scrolling on TableView etc.
How to take a screenshot with the Android Studio emulator
How to get the log when install4j does not start
How to deploy an app that references a local jar to heroku
How to identify the path that is easy to make a mistake
How to solve the problem that you can not pull image from docker hub with Minikube
How to deal with the type that I thought about writing a Java program for 2 years
A standalone Java app that sends logs to CloudWatch Logs with slf4j / logback
How to quickly create a reverse proxy that supports HTTPS with Docker
[Personal memo] How to interact with a random number generator in Java
About the problem that the server can not be started with rails s
How to create a server executable JAR and WAR with Spring gradle
[Rails] How to apply the CSS used in the main app with Administrate
How to make an app with a plugin mechanism [C # and Java]
How to make @Transactional work that does not work if you use it incorrectly
How to get the ID of a user authenticated with Firebase in Swift
How to add sound in the app (swift)
How to deploy a system created with Java (Wicket-Spring boot) to an on-campus server
How to create a class that inherits class information
Ssh login to the app server on heroku
A story that suffered from a space that does not disappear even if trimmed with Java The cause is BOM
What to do when is invalid because it does not start with a'-'
How to test a class that handles application.properties with SpringBoot (request: pointed out)
How to build a Jenkins server with a Docker container on CentOS 7 of VirtualBox and access the Jenkins server from a local PC
How to deploy VS Code Remote Containers in a docker-compose project that includes both the API and the front app
[Swift] How to simply describe dismiss that was not taught in the introductory book
MockMVC returns 200 even if I make a request to a path that does not exist
How to save a file with the specified extension under the directory specified in Java to the list
[Docker] How to see the contents of Volumes. Start a container with root privileges.
What to do if the JSONHint annotation does not work with lombok and JSONIC
How to delete child elements associated with a parent element at the same time
How to deal with errors in Rails s could not find a JavaScript runtime.
How to change the action with multiple submit buttons
How to make a factory with a model with polymorphic association
How to push an app developed with Rails to Github
How to delete a new_record object built with Rails
How to manually generate a JWT with Rails Knock
I want to dark mode with the SWT app
[How to insert a video in haml with Rails]
HTTPS connection with Java to the self-signed certificate server
Addicted to the webpacker that comes standard with Rails 6
How to make a mod for Slay the Spire
[Docker + Rails] How to deal with Rails server startup failure
[Java] How to start a new line with StringBuilder
[Java] Dealing with the situation where the program that writes to the Output Stream of Process does not end even if waitFor
The story that led to solving the error because postgres did not start with docker-compose up
[Error resolution] How to resolve the error "Could not find a JavaScript runtime." After upgrading Catalina!
What to do if you installed Ruby with rbenv but the version does not change
How to read a library from a JAR file with VS Code << How to not use Maven / Gradle >>
Memo that transitions to the login screen if you are not logged in with devise
How to reduce the load on the program even a little when combining characters with JAVA
How to request a CSV file as JSON with jMeter