- Get the .proto file from the API team
- Find you feature's data module (i.e. storemode-data)
- For the next few steps, I suggest using the Project view instead of Android for the file menu
- Add the following to your module's build.gradle, after the other
apply
statements at the top of the file:
apply from: '../build-protobuf.gradle'
- If your proto file includes other types like Errors, you'll also need to include the following in your dependencies:
/**
- Common proto files */ implementation project(':adp-ds-core-data')
- Check if the folder
src/main/proto
exists under your module, and if it doesn't create it
i.e. storemode-data/src/main/proto
- Place the proto file/files in that directory and rebuild the project
- After it completes successfully, you can find the generated data classes under
build/generated/source/proto/debug/javalite
i.e. storemode-data/build/generated/source/proto/debug/javalite/{your api name}
- Those classes are going to replace the api return values
- Located the Api file that contains the endpoint you are replacing. If needed, update the path/headers
- You will definitely have to add the
@ProtobufApi
decorator above the rest and remove theapplication/json
header if it exists - If you don't know the right headers, ask the backend team for guidance
- Change the return value to use the appropriate class from the generated ones above instead of the ones it's using now
// **** The following steps are for if the api was already using xApi **** //
- If the endpoint was already using xApi, most likely, the return value will be an xApi data class, and there's a
.toDomain
method declared in a file and used in the RepoImpl to convert it to the domain class. - If that is the case, you can remove that xApi class (if this is the only place it's used) and replace it with the generated one from the proto file.
- You will also need to replace the
toDomain
method with one that is implemented on the generated class - The names repeat a lot so you might have to make sure you have the right classes. It might look something like:
import com.macys.mobileapp.xapi.wallet.WalletSummary
internal fun WalletSummary.toDomain(): wallet.domain.WalletSummary { return wallet.domain.WalletSummary( macysPay = macysPay.toDomain(), starMoneyRewardsCount = noOfStarMoneyRewards, macysMoneyCount = noOfMacysMoney, savedOfferCount = noOfSavedOffers, creditCardCount = noOfCreditCards, notification = notification.toDomain() ) }
Here, the WalletSummary imported is the generated class, and the return type also called WalletSummary is the domain class
- Finally make sure the repo implementation class is using the right types/toDomain methods
// **** The following steps are for if the api was NOT using xApi **** //
- If your api did not already use xApi, you'll have to create a file for those
toDomain
mappings, create them and then update the repo implementation class to call those on the api result before returning it. - The contents of the mapper file will looks something like this:
import com.macys.mobileapp.xapi.wallet.WalletSummary
internal fun WalletSummary.toDomain(): wallet.domain.WalletSummary { return wallet.domain.WalletSummary( macysPay = macysPay.toDomain(), starMoneyRewardsCount = noOfStarMoneyRewards, macysMoneyCount = noOfMacysMoney, savedOfferCount = noOfSavedOffers, creditCardCount = noOfCreditCards, notification = notification.toDomain() ) }
Here, the WalletSummary imported is the generated class, and the return type also called WalletSummary is the domain class
- After the mapping is done, you'll have to use it in the repo implementation to convert the api result to the domain. That will look something like this:
return api.getQPUOrdersResponse() .map { response -> response.orders.orderList.map { it.toDomain() } <-- this is where the conversion happens } .map { Result.withValue(it) } .onErrorReturn { Result.OnError(NetworkError()) }
The above will vary and depend on the endpoint/implementation but the toDomain
will need to be placed somewhere in that method
- For all the above, keep in mind that if there's complex types with nested classes you might have to implement multiple
.toDomain
methods for those
If you are looking for examples, the wallet-data
and purchase-history-data
modules have a bunch of endpoints/models