Skip to content

Conversation

@boguszpawlowski
Copy link

@boguszpawlowski boguszpawlowski commented Oct 18, 2025

Summary

Replaced api Retrofit dependency from common module with implementation.
Closes #5421

Checklist

  • New or updated tests have been added to cover the changes following the testing guidelines.
  • The code follows the project's code style and best_practices.
  • The changes have been thoroughly tested, and edge cases have been considered.
  • Changes are backward compatible whenever feasible. Any breaking changes are documented in the changelog for users and/or in the code for developers depending on the relevance.

Screenshots

Link to pull request in documentation repositories

User Documentation: home-assistant/companion.home-assistant#

Developer Documentation: home-assistant/developers.home-assistant#

Any other notes

Copy link

@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @boguszpawlowski

It seems you haven't yet signed a CLA. Please do so here.

Once you do that we will be able to review and accept this pull request.

Thanks!

import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

class HttpExceptionCallAdapterFactory : CallAdapter.Factory() {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this adapter to minimize the amount of code changes. IMO we should replace it with an Result style adapter to remove exception-based error handling. Im happy to do it in this /separate PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing every API to return a Result<> is a big task. I invite you to first create an issue with proper explanations. It needs to be in another PR (maybe multiples one), then adding a lint rule to force the usage of Result.

Currently exception handling in the application is not the best and would need huge changes in general (stopping using catch(e:Exception) that is way too broad for instance)

@boguszpawlowski boguszpawlowski changed the title [Issue 5421] Remove retrofit api dependency [Issue 5421] Replace retrofit api dependency with implementation Oct 18, 2025
Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ktlint found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@boguszpawlowski boguszpawlowski marked this pull request as ready for review October 18, 2025 18:23
Copilot AI review requested due to automatic review settings October 18, 2025 18:23
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR replaces the api dependency configuration with implementation for Retrofit in the common module, preventing the leakage of Retrofit types into dependent modules' public APIs. This change encapsulates the HTTP client implementation details within the common module.

Key changes:

  • Created a custom HttpException class to replace Retrofit's HttpException throughout the codebase
  • Introduced UrlBuilder utility class to encapsulate OkHttp URL building logic
  • Updated all modules to use the new custom exception type

Reviewed Changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated no comments.

Show a summary per file
File Description
common/build.gradle.kts Changed Retrofit dependency from api to implementation
common/src/main/kotlin/.../HttpException.kt Added custom HttpException data class
common/src/main/kotlin/.../HttpExceptionCallAdapterFactory.kt Added call adapter to convert Retrofit's HttpException to custom type
common/src/main/kotlin/.../UrlBuilder.kt Added utility class for URL building
common/src/main/kotlin/.../HomeAssistantApis.kt Registered HttpExceptionCallAdapterFactory with Retrofit
onboarding/.../ConnectionViewModel.kt Replaced OkHttp URL building with UrlBuilder
onboarding/.../NameYourDeviceViewModel.kt Updated to use custom HttpException
app/.../LaunchActivity.kt Updated to use custom HttpException
app/.../HaControlsProviderService.kt Updated to use custom HttpException and removed manual error creation
wear/.../EntityStateDataSourceService.kt Removed unused Retrofit HttpException import
*/gradle.lockfile Updated dependency configurations reflecting the change from api to implementation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@jpelgrom jpelgrom changed the title [Issue 5421] Replace retrofit api dependency with implementation Replace retrofit api dependency with implementation Oct 19, 2025
Copy link
Member

@TimoPtr TimoPtr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Today our application is not using retrofit2.Call API from retrofit but the coroutine capability of Retrofit, so the factory that you've created won't do anything unfortunately.

Furthermore you are using the onFailure from the Call API. The documentation is clear

Invoked when a network exception occurred talking to the server or when an unexpected exception occurred creating the request or processing the response.

Error like 404 are still handled by onResponse according to the documentation

Invoked for a received HTTP response.
Note: An HTTP response may still indicate an application-level failure such as a 404 or 500. Call Response.isSuccessful() to determine if the response indicates success.

It means that if we merge your PR today the app won't display the right message in LaunchActivity since it is going to be the retrofit HttpException thrown not yours.

@@ -0,0 +1,53 @@
package io.homeassistant.companion.android.common.data

import io.homeassistant.companion.android.common.exception.HttpException
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import io.homeassistant.companion.android.common.exception.HttpException
import io.homeassistant.companion.android.common.data.exception.HttpException

And you should also move MalformedHttpUrlException

import retrofit2.Response
import retrofit2.Retrofit

class HttpExceptionCallAdapterFactory : CallAdapter.Factory() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From https://developers.home-assistant.io/docs/android/best_practices#documentation Future-proof: Ask yourself, "Will I understand what I did in 6 months?"

I think we would benefits from having a documentation on the class definition explaining what is the goal of this factory.

import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

class HttpExceptionCallAdapterFactory : CallAdapter.Factory() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing every API to return a Result<> is a big task. I invite you to first create an issue with proper explanations. It needs to be in another PR (maybe multiples one), then adding a lint rule to force the usage of Result.

Currently exception handling in the application is not the best and would need huge changes in general (stopping using catch(e:Exception) that is way too broad for instance)

import retrofit2.Response
import retrofit2.Retrofit

class HttpExceptionCallAdapterFactory : CallAdapter.Factory() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class HttpExceptionCallAdapterFactory : CallAdapter.Factory() {
internal class HttpExceptionCallAdapterFactory : CallAdapter.Factory() {

This should not be exposed outside of the common module.

val convertedException = if (t is retrofit2.HttpException) {
HttpException(
code = t.code(),
message = t.response()?.errorBody()?.string() ?: t.message(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would simply use the message from the exception they already handle everything properly.

Suggested change
message = t.response()?.errorBody()?.string() ?: t.message(),
message = t.message,

import okhttp3.HttpUrl.Companion.toHttpUrl

@Singleton
class UrlBuilder @Inject constructor() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is relevant to the current PR.

@home-assistant home-assistant bot marked this pull request as draft October 23, 2025 09:21
@home-assistant
Copy link

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Retrofit should be not exposed outside of common module

2 participants