-
-
Notifications
You must be signed in to change notification settings - Fork 29
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
base: develop
Are you sure you want to change the base?
bugfix/error_signing_redirect: Added error handling #221
Conversation
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. |
There was a problem hiding this 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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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>
?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No special reason.
var message: String? = description | ||
if (TextUtils.isEmpty(message)) { | ||
message = "Unknown Error" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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? { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 }, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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
674262a
to
1762af9
Compare
* 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.
* Processed code review comments.
1762af9
to
1855137
Compare
* 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.
Kudos, SonarCloud Quality Gate passed! 0 Bugs No Coverage information |
to the retrofit exception. Retrofit exception is of 3 types, http,
network and unexpected.
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.
the error received from the viewmodel by overriding onError method.
with viewLifecycleOwner.
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.