Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix/error_signing_redirect: Added error handling #221

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

toaderandrei
Copy link

@toaderandrei toaderandrei commented Oct 20, 2020

  • Added a retrofit exception that transforms all the retrofit rx calls
    to the retrofit exception. Retrofit exception is of 3 types, http,
    network and unexpected.
  • Added WebViewException, RetrofitException and EmptyResultsException.
    WebViewException is called when the webview fails to load an url.
    EmptyResultsException is thrown in case the data retrieved from both
    database and network is null or empty.
  • Added a base fragment, namely, BaseViewModelFragment where we handle
    the error received from the viewmodel by overriding onError method.
  • Added error handling when login fails.
  • Replaced all this from methods like viewModel.obj.observer(this, ...)
    with viewLifecycleOwner.
  • Created a few utility methods in Utils.
  • Improvd Result class so now it supports success and error checks.
  • Added error codes for not authorized, unknown and not found.
  • Added some error messages to the strings.xml.
  • Added logs for unknown actions.
  • Added todos for not fixed errors.

Requirements for making a pull request

Thank you for contributing to our project!

Please fill out the template below to help the project maintainers review it as fast as possible and include your contribution to the project.

What does it fix?

Closes #213 and #43

Please mention the main changes this PR brings.

How has it been tested?

Please describe the tests that you ran to verify your changes.

@toaderandrei toaderandrei requested a review from aniri as a code owner October 20, 2020 06:46
@catileptic
Copy link
Member

This PR is quite hefty in size. Thank you, @toaderandrei, for your work! And especially for listing the changes you made, individually, in the PR body. We're going to review this, but it will take a bit longer than our usual code reviews.

Let's also chat on Slack about the changes you've made. You've introduced new dependencies in the architecture and we gotta discuss whether this is a good way to move forward.

Copy link
Contributor

@lukstbit lukstbit left a comment

Choose a reason for hiding this comment

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

LGTM 👍

There is some dead code(RetrofitException.getErrorBodyAs() and Result.error are not being used anywhere) but that is just nitpicking.


init {
getForms()
//todo this does not work as expected.
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you referring to not handling exceptions when fetching the polling station text?

Copy link
Author

Choose a reason for hiding this comment

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

It is connected with the comments from below where there is a null value in an rxjava operator. When this method is called for the first time, and neither api nor the db return something, the null values do not behave as expected. In RxJava1 it was valid, however, in rxjavsa2 it is not.

* .:.:.:. Created by @henrikhorbovyi on 13/10/19 .:.:.:.

* Class that encapsulates successful result with a value of type [T] or
* a failure with a [Throwable] exception.
*/
sealed class Result<out T> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Was it an attempt to reintroduce kotlin.Result<T>?

Copy link
Author

Choose a reason for hiding this comment

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

It was there before, I just added some things. Changing it to Kotlin.Result might take a bit more effort. I analyzed that already.

val s = SpannableString(message)

//added a TextView
val tx1 = TextView(this)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's better to not create views in code

Copy link
Author

Choose a reason for hiding this comment

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

I just moved it so we can reuse it. I plan to change it in future versions.

})
.subscribeOn(Schedulers.io())
.flatMap {
return@flatMap syncAnswers(it)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you use explicit return?

Copy link
Author

Choose a reason for hiding this comment

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

No special reason.

Comment on lines 74 to 77
var message: String? = description
if (TextUtils.isEmpty(message)) {
message = "Unknown Error"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
var message: String? = description
if (TextUtils.isEmpty(message)) {
message = "Unknown Error"
}
val message = description.takeUnless { it.isNullOrEmpty() } ?: "Unknown Error"

}
}
viewModel.url().observe(viewLifecycleOwner, Observer {
webView.loadUrl(it)
})
}

override fun onError(thr: Throwable) {
logE(TAG, "Error loading the page:" + thr.message)
var messageId: String = getString(R.string.error_generic_message)
Copy link
Contributor

Choose a reason for hiding this comment

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

why not val messageId = if (...) R.string.error_no_connection else R.string.error_generic_message ?
and then just logE(TAG, getString(messageId))

/**
* Exception that is retrieved from retrofit. It is of three types, http, network and unexpected.
*/
open class RetrofitException internal constructor(
Copy link
Contributor

Choose a reason for hiding this comment

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

Why it's open? there are no any classes extending it

* @throws IOException if unable to convert the body to the specified `type`.
*/
@Throws(IOException::class)
fun <T> getErrorBodyAs(type: Class<*>?): T? {
Copy link
Contributor

Choose a reason for hiding this comment

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

No usages. Mostly API has one type for any errors, but it can be useful if the app's backend uses different types.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, I added it for a reason. I know it is not used at the moment. I plan to take on other user stories that will depend on that.

Copy link
Member

Choose a reason for hiding this comment

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

we should keep this PR as clean as possible

val observableApi = apiInterface.getForms()

// todo fix this as it does not work as expected. nulls are not treated as return values.
// instead it throws a NullPointerException.
Copy link
Contributor

Choose a reason for hiding this comment

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

RxJava2 doesn't allow null as a return value, it's well-known.

Copy link
Author

Choose a reason for hiding this comment

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

Well, that is the comment here for. However, nonetheless the nulls were somehow added to the code and it does not work as expected. Thus, the comment you see.

val observableApi = apiInterface.getForms()

// todo fix this as it does not work as expected. nulls are not treated as return values.
// instead it throws a NullPointerException.
return Observable.zip(
observableDb.onErrorReturn { null },
observableApi.onErrorReturn { null },
Copy link
Contributor

Choose a reason for hiding this comment

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

@aniri I think an issue should be created for it.

Copy link
Author

@toaderandrei toaderandrei Oct 28, 2020

Choose a reason for hiding this comment

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

I plan to fix it in a future task. I tried, but the idea was to not explode this PR.

Copy link
Member

Choose a reason for hiding this comment

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

yep, I'll add a new issue for this after we finish merging this PR

processHttpException(exception, fallback)
}
RetrofitException.Kind.NETWORK -> {
var messageId: String = getString(R.string.error_generic)
Copy link
Contributor

Choose a reason for hiding this comment

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

val messageId = if (isOnline) R.string.error_generic else R.string.login_no_internet

@toaderandrei toaderandrei force-pushed the bugfix/error_signing_redirect branch from 674262a to 1762af9 Compare November 2, 2020 07:19
* Added a retrofit exception that transforms all the retrofit rx calls
to the retrofit exception. Retrofit exception is of 3 types, http,
network and unexpected.
* Added WebViewException, RetrofitException and EmptyResultsException.
WebViewException is called when the webview fails to load an url.
EmptyResultsException is thrown in case the data retrieved from both
database and network is null or empty.
* Added a base fragment, namely, BaseViewModelFragment where we handle
the error received from the viewmodel by overriding onError method.
* Added error handling when login fails.
* Replaced all this from methods like viewModel.obj.observer(this, ...)
with viewLifecycleOwner.
* Created a few utility methods in Utils.
* Improvd Result class so now it supports success and error checks.
* Added error codes for not authorized, unknown and not found.
* Added some error messages to the strings.xml.
* Added logs for unknown actions.
* Added todos for not fixed errors.
@toaderandrei toaderandrei force-pushed the bugfix/error_signing_redirect branch from 1762af9 to 1855137 Compare November 7, 2020 10:27
* Fixed the error message not being parsed from the request in case an
error 400 is received. In case it is null, we show the generic error
message.
…nges

* Fixed bug in onPause that was causing the disposable not to finish.
* Reverted some unnecessary changes.
* Removed unused classes and dead code.
@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 8, 2020

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 3 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

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.

[BUG] Missing redirect to login screen on 401 error returned on posting answer
6 participants