Serializing Java objects for REST API Requests in Open Event Organizer App

Open Event Organizer App is a client side application which uses REST API for network requests. The server supports sending and receiving of data only in JSONAPI spec, so, we needed to serialize java models into JSON objects and deserialize JSON data into java models following JSONAPI spec. To achieve this we followed the following steps. Specifications We will be using jasminb/jsonapi-converter which handles request/response parsing of models following JSONAPI Spec and Retrofit plugin of jackson converter to serializing JSON to Java Models and vice versa. Let’s create a java model. We are using some annotations provided by Lombok library to avoid writing boilerplate code. @JsonNaming annotation is used to apply KebabCaseStrategy while serializing fields @Data @Type("order") @AllArgsConstructor @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy.class) @Table(database = OrgaDatabase.class, allFields = true) public class Order { @PrimaryKey @Id(LongIdHandler.class) public Long id; public float amount; public String completedAt; public String identifier; public String paidVia; public String paymentMode; public String status; @Relationship("event") @ForeignKey(stubbedRelationship = true, onDelete = ForeignKeyAction.CASCADE) public Event event; public Order() { } } In the NetworkModule class, there is a method providesMappedClasses() containing a list of classes that needs to be serialized/deserialized. We need to add the above model in the list. Then, this list is provided to Singleton instance of JSONAPIConvertorFactory through Dagger. JSONAPIConvertorFactory uses the Retrofit ObjectMapper and maps the classes that are handled by this instance. @Provides Class[] providesMappedClasses() { return new Class[]{Event.class, Attendee.class, Ticket.class, Order.class}; } Further, various serialization properties can be used while building Singleton ObjectMapper instance. Adding any properties here ensures that these are applied to all the mapped classes by JSONAPIConvertorFactory. For eg, we are using the serialization property to throw an exception and fail whenever empty beans are encountered. @Provides @Singleton ObjectMapper providesObjectMapper() { return new ObjectMapper() .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) // Handle constant breaking changes in API by not including null fields // TODO: Remove when API stabilizes and/or need to include null values is there .setSerializationInclusion(JsonInclude.Include.NON_ABSENT); } Resources Github Repository for jsonapi-converter https://github.com/jasminb/jsonapi-converter Github repository for Jackson Retrofit Plugin https://github.com/square/retrofit/tree/master/retrofit-converters/jackson Official Website for Project Lombok https://projectlombok.org/ Github Repository for Open-Event-Orga-App https://github.com/fossasia/open-event-orga-app

Continue ReadingSerializing Java objects for REST API Requests in Open Event Organizer App

Creating Orders in Open Event Android

An Order is generated whenever a user buys a ticket in Open Event Android. It contains all the details regarding the tickets and their quantity, also information regarding payment method and relation to list of attendees, through this blog post we will see how Orders are generated in Open Event Android. Implementing Order system can be divided into following parts Writing model class to serialize/deserialize API responses Creating TypeConverter for Object used in Model class Creating the API interface method Wiring everything together Model Class Model class server two purpose - Entity class for storing orders in room Serialize / Deserialize API response The architecture of the Order Model Class depends upon the response returned by the API, different fields inside the Entity Class defines what different attributes an Order consists of and their data types. Since every Order has a relationship with Event and Attendee we also have to define foreign key relations with them. Given below is the implementation of the Order Class in Open Event Android. @Type("order") @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class) @Entity(foreignKeys = [(ForeignKey(entity = Event::class, parentColumns = ["id"], childColumns = ["event"], onDelete = ForeignKey.CASCADE)), (ForeignKey(entity = Attendee::class, parentColumns = ["id"], childColumns = ["attendees"], onDelete = ForeignKey.CASCADE))]) data class Order(        @Id(IntegerIdHandler::class)        @PrimaryKey        @NonNull        val id: Long,        val paymentMode: String? = null,        val country: String? = null,        val status: String? = null,        val amount: Float? = null,        val orderNotes: String? = null,        @ColumnInfo(index = true)        @Relationship("event")        var event: EventId? = null,        @Relationship("attendees")        var attendees: List<AttendeeId>? = null )   We are using Jackson for serializing/deserializing JSON response, @Type(“order”) annotation tells jackson that the following object is for key order in json response. Since we are using this as our room entity class we will also have to add a @Entity annotation to this class. Order contains attendee and event id fields which are foreign keys to other entity classes, this also has to be explicitly mentioned while writing the @Entitty annotation as shown in the snippet above . All relationship must be annotated with @Relationship annotation. All the variables serves as attributes in the order table and key name for json conversions. The fields of this class are the attributes for the Order Table. Payment mode, country, status are all made up of primitive data type and hence require no type convertors whereas we will have to specify type converter for objects like eventId and List<Attendees> Type Converter Type Converter allows us to store any custom object type inside room database. Essentially we break down the Object into smaller primitive data types that Object is composed of and which can be stored by room database. To create a TypeConverter we have to add a @TypeConverter annotation to it, this tells room that this is a special function. For every custom Object, you have to create two different TypeConverter functions. One takes the Object and converts it into primitive data type and the other takes the primitive data type and constructs your custom Object from it. For the Order data class we discussed…

Continue ReadingCreating Orders in Open Event Android

Adding JSONAPI Support in Open Event Android App

The Open Event API Server exposes a well documented JSONAPI compliant REST API that can be used in The Open Even App Generator and Frontend to access and manipulate data. So it is also needed to add support of JSONAPI in external services like The Open Even App Generator and Frontend. In this post I explain how to add JSONAPI support in Android. There are many client libraries to implement JSONAPI support in Android or Java like moshi-jsonapi, morpheus etc. You can find the list here. The main problem is most of the libraries require to inherit attributes from Resource model but in the Open Event Android App we already inherit from a RealmObject class and in Java we can’t inherit from more than one model or class. So we will be using the jsonapi-converter library which uses annotation processing to add JSONAPI support. 1. Add dependency In order to use jsonapi-converter in your app add following dependencies in your app module’s build.gradle file. dependencies { compile 'com.github.jasminb:jsonapi-converter:0.7' } 2.  Write model class Models will be used to represent requests and responses. To support JSONAPI we need to take care of followings when writing the models. Each model class must be annotated with com.github.jasminb.jsonapi.annotations.Type annotation Each class must contain a String attribute annotated with com.github.jasminb.jsonapi.annotations.Id annotation All relationships must be annotated with com.github.jasminb.jsonapi.annotations.Relationship annotation In the Open Event Android we have so many models like event, session, track, microlocation, speaker etc. Here I am only defining track model because of its simplicity and less complexity. @Type("track") public class Track extends RealmObject { @Id(IntegerIdHandler.class) private int id; private String name; private String description; private String color; private String fontColor; @Relationship("sessions") private RealmList<Session> sessions; //getters and setters } Jsonapi-converter uses Jackson for data parsing. To know how to use Jackson for parsing follow my previous blog. Type annotation is used to instruct the serialization/deserialization library on how to process given model class. Each resource must have the id attribute. Id annotation is used to flag an attribute of a class as an id attribute. In above class the id attribute is int so we need to specify IntegerIdHandler class which is ResourceHandler in the annotation. Relationship annotation is used to designate other resource types as a relationship. The value in the Relationship annotation should be as per JSONAPI specification of the server. In the Open Event Project each track has the sessions so we need to add a Relationship annotation for it. 3.  Setup API service and retrofit After defining models, define API service interface as you would usually do with standard JSON APIs. public interface OpenEventAPI { @GET("tracks?include=sessions&fields[session]=title") Call<List<Track>> getTracks(); } Now create an ObjectMapper & a retrofit object and initialize them. ObjectMapper objectMapper = OpenEventApp.getObjectMapper(); Class[] classes = {Track.class, Session.class}; OpenEventAPI openEventAPI = new Retrofit.Builder() .client(okHttpClient) .baseUrl(Urls.BASE_URL) .addConverterFactory(new JSONAPIConverterFactory(objectMapper, classes)) .build() .create(OpenEventAPI.class);   The classes array instance contains a list of all the model classes which will be supported by this retrofit builder and API service. Here the main task…

Continue ReadingAdding JSONAPI Support in Open Event Android App

Using Jackson Library in Open Event Android App for JSON Parsing

Jackson library is a popular library to map Java objects to JSON and vice-versa and has a better parsing speed as compared to other popular parsing libraries like GSON, JSONP etc. This blog post gives a basic explanation on how we utilised the Jackson library in the Open Event Android App. To use the Jackson library we need to add the dependency for it in the app/build.gradle file. compile 'com.squareup.retrofit2:converter-jackson:2.2.0' After updating the app/build.gradle file with the code above we were able to use Jackson library in our project. Example of Jackson Library JSON Parsing To explain how the mapping is done let us take an example. The file given below is the sponsors.json file from the android app. [ “description”: “”, “id”: 1, “level”: 3, “name”: KI Group, “type”: Gold, “url: “”, “logo-url”: “” ] The sponsors.json consists of mainly 7 attributes namely description, id, level, name, type, url and logo url for describing one sponsor of the event. The Sponsors.java file for converting the json response to Java POJO objects was done as follows utilizing the Jackson library: public class Sponsors extends RealmObject { @JsonProperty(“id”) private int id; @JsonProperty(“type”) private String type; @JsonProperty(“description”) private String description; @JsonProperty(“level”) private String level; @JsonProperty(“name”) private String name; @JsonProperty(“url”) private String url; @JsonProperty(“logo-url”) private String logoUrl; } As we can see from the above code snippet, the JSON response is converted to Java POJO objects simply by using the annotation “@JsonProperty(“”)” which does the work for us. Another example which makes this library amazing are the setter and getter annotations which help us use a single variable for two different json attributes if need be. We faced this situation when we were moving from the old api to the new json api. In that case we wanted support for both, old and new json attributes. In that case we simply used the following code snippet which made our transition to new api easier. public class Sponsors extends RealmObject { private int id; private String type; private String description; private String level; private String name; private String url; private String logoUrl; @JsonSetter(“logo”) public void setLogo(String logoUrl) { this.logoUrl = logoUrl; } @JsonSetter(“logo-url”) public void setLogo(String logoUrl) { this.logoUrl = logoUrl; } } As we can see the setter annotations allow easy naming of variable to multiple attributes if need be thus making the code easily adaptable with less overload. Related Links: This link explains the json parsing with Jackson library. (https://stackoverflow.com/questions/19490017/json-parsing-using-jackson-library) This tutorial explains the features of the Jackson library. (https://www.tutorialspoint.com/jackson/index.htm)

Continue ReadingUsing Jackson Library in Open Event Android App for JSON Parsing

Shrinking Model Classes Boilerplate in Open Event Android Projects Using Jackson and Lombok

JSON is the de facto standard format used for REST API communication, and for consuming any of such API on Android apps like Open Event Android Client and Organiser App, we need Plain Old Java Objects, or POJOs to map the JSON attributes to class properties. These are called models, for they model the API response or request. Basic structure of these models contain Private properties representing JSON attributes Getters and Setters for these properties used to change the object or access its data A toString() method which converts object state to a string, useful for logging and debugging purposes An equals and hashcode method if we want to compare two objects These can be easily and automatically be generated by any modern IDE, but add unnecessarily to the code base for a relatively simple model class, and are also difficult to maintain. If you add, remove, or rename a method, you have to change its getters/setters, toString and other standard data class methods. There are a couple of ways to handle it: Google’s Auto Value: Creates Immutable class builders and creators, with all standard methods. But, as it generates a new class for the model, you need to add a library to make it work with JSON parsers and Retrofit. Secondly, there is no way to change the object attributes as they are immutable. It is generally a good practice to make your models immutable, but if you are manipulating their data in your application and saving it in your database, it won’t be possible except than to create a copy of that object. Secondly, not all database storage libraries support it Kotlin’s Data Classes: Kotlin has a nice way to made models using data classes, but it has certain limitations too. Only parameters in primary constructor will be included in the data methods generated, and for creating a no argument constructor (required for certain database libraries and annotation processors), you either need to assign default value to each property or call the primary constructor filling in all the default values, which is a boilerplate of its own. Secondly, sometimes 3rd party libraries are needed to work correctly with data classes on some JSON parsing frameworks, and you probably don’t want to just include Kotlin in your project just for data classes Lombok: We’ll be talking about it later in this blog Immutables, Xtend Lang, etc This is one kind of boilerplate, and other kind is JSON property names. As we know Java uses camelcase notation for properties, and JSON attributes are mostly: Snake Cased: property_name Kebab Cased: property-name Whether you are using GSON, Jackson or any other JSON parsing framework, it works great for non ambiguous property names which match as same in both JSON and Java, but requires special naming attributes for translating JSON attributes to camelcase and vice versa. Won’t you want your parser to intelligently convert property_name to propertyName without having you write the tedious mapping which is not only a boilerplate, but also error…

Continue ReadingShrinking Model Classes Boilerplate in Open Event Android Projects Using Jackson and Lombok

JSON Deserialization Using Jackson in Open Event Android App

The Open Event project uses JSON format for transferring event information like tracks, sessions, microlocations and other. The event exported in the zip format from the Open Event server also contains the data in JSON format. The Open Event Android application uses this JSON data. Before we use this data in the app, we have to parse the data to get Java objects that can be used for populating views. Deserialization is the process of converting JSON data to Java objects. In this post I explain how to deserialize JSON data using Jackson. 1. Add dependency In order to use Jackson in your app add following dependencies in your app module’s build.gradle file. dependencies { compile 'com.fasterxml.jackson.core:jackson-core:2.8.9' compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.9' compile 'com.fasterxml.jackson.core:jackson-databind:2.8.9' } 2.  Define entity model of data In the Open Event Android we have so many models like event, session, track, microlocation, speaker etc. Here i am only defining track model because of it’s simplicity and less complexity. public class Track { private int id; private String name; private String description; private String color; @JsonProperty("font-color") private String fontColor; //getters and setters } Here if the property name is same as json attribute key then no need to add JsonProperty annotation like we have done for id, name color property. But if property name is different from json attribute key then it is necessary to add JsonProperty annotation. 3.  Create sample JSON data Let’s create sample JSON format data we want to deserialize. { "id": 273, "name": "Android", "description": "Sample track", "color": "#94868c", "font-color": "#000000" } 4.  Deserialize using ObjectMapper ObjectMapper is Jackson serializer/deserializer. ObjectMapper’s readValue() method is used for simple deserialization. It takes two parameters one is JSON data we want to deserialize and second is Model entity class. Create an ObjectMapper object and initialize it. ObjectMapper objectMapper = new ObjectMapper(); Now create a Model entity object and initialize it with deserialized data from ObjectMapper’s readValue() method. Track track = objectMapper.readValue(json, Track.class); So we have converted JSON data into the Java object. Jackson is very powerful library for JSON serialization and deserialization. To learn more about Jackson features follow the links given below. Jackson-databind: https://github.com/FasterXML/jackson-databind Jackson wiki: http://wiki.fasterxml.com/JacksonInFiveMinutes Tutorial: http://tutorials.jenkov.com/java-json/jackson-installation.html

Continue ReadingJSON Deserialization Using Jackson in Open Event Android App