Webcom SDK for Android eases the serialization of business data, to be written into the Webcom database, and also their deserialization, when reading them from the Webcom database.
When coding in Kotlin
Instances of business classes may be directly written into or read from the Webcom database as soon as they are
made Serializable
using the official Kotlin libraries for serialization.
To do so, you have to set up this library within your project:
- Add the dependency to the Kotlin serialization plugin into the
buildscript
section of your top-levelbuild.gradle
file:
buildscript {
ext.kotlin_version = "<YOUR_KOTLIN_VERSION>"
// ...
dependencies {
// ...
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
// ...
}
}
- In the
build.gradle
file of your module, enable the serialization plugin:
plugins {
// ...
id 'kotlinx-serialization' // ADD this declaration of the Kotlin-Serialization plugin
// ...
}
//...
Then, you can annotate your business classes as Serializable
:
import kotlinx.serialization.Serializable
@Serializable // the official serialization Kotlin annotation
data class ContactDetail(
val data: String, // String is "naturally" serializable
val preferred: Boolean // Boolean as well
)
@Serializable
data class Contact(
val birthday: com.orange.webcom.dessert.TimeStampDate, // this subclass of java.util.Date serializes as an integer timestamp
val firstName: String,
val lastName: String,
val details: Map<String, ContactDetail>, // Map is "naturally" serializable, ContactDetail is annotated as Serializable
)
We can now directly read Contact
instances from/to the Webcom database, using the
get
method. For further details on reading and
real-time subscribing data, see the “Reading data” and
“Subscribing to changes” chapters.
val manager = WebcomApplication.default.datasyncService.createManager()
manager.node("/path/to/contacts").get {
when (it) {
is WebcomResult.Success -> {
when (val data = it.result.tryGet { asListOf(Contact::class) }) { // data: List<Contact>?
null -> println("Found something else than a list of contacts")
else -> println("Found ${data.size} contact entries")
}
}
is WebcomResult.Failure -> println("Could not read contact data: ${it.error.message}")
}
}
We can also directly write Contact
instances to the Webcom database, using one of the
set
,
merge
or
push
methods. For further
details on writing data, see the “Writing data”
chapter.
val john = Contact(
birthday = TimeStampDate(Date(1981, 12, 5)),
firstName = "John",
lastName = "Doe",
details = mapOf(
"phone" to ContactDetail("0123456789", true),
"email" to ContactDetail("john.doe@somewhere", false)
)
)
val manager = WebcomApplication.default.datasyncService.createManager()
manager.node("/path/to/contacts/john").set(john) {
when (it) {
is WebcomResult.Success -> println("Succeeded writing data")
is WebcomResult.Failure -> println("Failed writing data")
}
}
For more complex examples, you can also find here further details on how to set up serializable classes.
When coding in Java
In Java, of course, the Kotlin serialization framework is not available. In this case, the Webcom SDK for Android falls back to interpreting instances of business classes as Plain Old Java Objects (or POJO). In order to be considered as a POJO, the Java class of the object to serialize (or deserialize) must meet the following requirements:
- The class MUST NOT be an inner class,
- The class MUST have a default zero-arguments constructor,
- The class MUST define public getters/setters for the properties to serialize/deserialize, following the
getMyProperty
/setMyProperty
naming convention.
If we simplify a little the example given in the previous section, we get:
class Contact {
com.orange.webcom.dessert.TimeStampDate birthday;
String firstName;
String lastName;
Map<String, String> details;
// Default constructor
public Contact() {
}
// Getter and setter for the "birthday" property
public TimeStampDate getBirthday() {
return birthday;
}
public Contact setBirthday(TimeStampDate birthday) {
this.birthday = birthday;
return this;
}
// Getter and setter for the "firstName" property
public String getFirstName() {
return firstName;
}
public Contact setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
// Getter and setter for the "lastName" property
public String getLastName() {
return lastName;
}
public Contact setLastName(String lastName) {
this.lastName = lastName;
return this;
}
// Getter and setter for the "details" property
public Map<String, String> getDetails() {
return details;
}
public Contact setDetails(Map<String, String> details) {
this.details = details;
return this;
}
}
Then the Kotlin code snippets, as well as their Java counterparts, shown in the previous section may then be used the same way!
When using POJO classes, do not forget to protect them against shrinking and obfuscation when building APKs with proguard/R8. Indeed, as serialization and deserialization of POJO classes rely on Java reflection, their default constructors, getters and setters must be preserved.
There are 2 ways to do so:
- Either annotate POJO classes with
androidx.annotation.Keep
,- Or add a customized rule for each POJO class in the
proguard-rules.pro
file of the corresponding module:
-keepclassmembers class fqcn.of.pojo.class { public <init>(); public void set*(**); public *** get*(); }