How do I prevent Java RetroFit from crashing my app on a 401 Unauthorized error? - retrofit

My app crashes whenever a 401 error occurs in the app. I created a custom error handler but i'm not sure how to get the app to use this error handler so the app stops gracefully, without flashing the user "Unforunately, Application has stopped."
Here's my code:
... new RestAdapter.Builder()...setErrorHandler(getErrorHandler()).build();
public ErrorHandler getErrorHandler() {
return new ErrorHandler() {
#Override
public Throwable handleError(RetrofitError cause) {
Response r = cause.getResponse();
if (r != null && r.getStatus() == 401) {
Log.e(TAG, "user not authorized:" + cause.toString());
} else {
Log.e(TAG, "regular exception thrown for CloudManager");
}
return cause;
}
};

As you can check with javadoc ErrorHandler is used when you want to wrap RetrofitError into CustomError exception. It doesn't catch exception for you.
class MyErrorHandler implements ErrorHandler {
#Override public Throwable handleError(RetrofitError cause) {
Response r = cause.getResponse();
if (r != null && r.getStatus() == 401) {
return new UnauthorizedException(cause);
}
return cause;
}
}
To prevent app from crashing you have to catch error earlier.
#GET("/users/{user}/repos")
List<Repo> listRepos(#Path("user") String user);
try {
List<Repo> repos = retrofit.listRepos("octocat");
} catch (RetrofitError error) {
// TODO: handle error
}

Related

Why would BizTalk 2016 kill custom pipeline component threads?

I have a BizTalk Custom Pipeline Component that writes an SFTP file (using SSH.net), triggered by an SFTP (WinSCP) receive location.
The code within the Retry occasionally (around half the time) does not hit either the "Success" nor the logging catch block and no further processing occurs within the Pipeline. I assume that means the thread has been destroyed.
I added the Retry code later to make it try a few times but with the thread being destroyed I don't always get a success or 3 failures.
What could cause this behaviour in BizTalk 2016?
public void Archive(byte[] content,
string archivePath,
string userName,
string password,
string serverAddress,
string sshHostKeyFingerprint)
{
Retry(3, () =>
{
try
{
using (var sftpClient = new SftpClient(serverAddress, userName, password))
{
if (!string.IsNullOrWhiteSpace(sshHostKeyFingerprint))
{
sshHostKeyFingerprint = sshHostKeyFingerprint.Split(' ').Last();
sftpClient.HostKeyReceived += delegate (object sender, HostKeyEventArgs e)
{
if (e.FingerPrint.SequenceEqual(ConvertFingerprintToByteArray(sshHostKeyFingerprint)))
e.CanTrust = true;
else
e.CanTrust = false;
};
}
sftpClient.Connect();
sftpClient.WriteAllBytes(archivePath, content);
sftpClient.Disconnect();
LogInfo($"Success");
}
}
catch (Exception exception)
{
// show the bad path for "No such file" errors
throw new InvalidOperationException($"Failed to create file '{archivePath}'", exception);
}
});
}
private void Retry(int maxAttempts, Action action)
{
int attempt = 1;
while (attempt <= maxAttempts)
{
try
{
action();
break; // success
}
catch (Exception exception)
{
LogWarning($"Attempt {attempt} Error: {exception.ToString()}");
if (attempt == maxAttempts)
throw; // final attempt exception propagated
}
finally
{
attempt++;
}
}
}

Which system exception for Bad Request

I have an API-controller that calls a service class. Inside the service class I want to throw an exception so the API-controller can catch it, and return a Http-BadRequest response.
But what exception is equal to Bad Request? And what is best practise for this situation?
I used this pattern for throwing exceptions in the application layer and the api layer would recognize the http status code:
The exceptions definition:
public class BadRequestException : Exception
{
public BadRequestException(string message = null)
: base(message == null ? "Bad Request" : message)
{ }
}
public class ActionInputIsNotValidException : BadRequestException
{
public ActionInputIsNotValidException()
: base("Action input is not valid")
{ }
}
An Action Filter to handle exceptions in api layer:
public class ExceptionActionFilter : ExceptionFilterAttribute
{
public ExceptionActionFilter()
{
}
public override void OnException(ExceptionContext context)
{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.HttpContext.Response.ContentType = "application/json";
if (isTypeOf(context.Exception, typeof(Exceptions.BadRequestException)))
{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
context.Result = new JsonResult(new
{
Message = context.Exception.Message,
});
}
private bool isTypeOf(Exception exception, Type baseType)
{
return exception.GetType() == baseType || exception.GetType().IsSubclassOf(baseType);
}
}
Then in the application layer we can throw exceptions and the result of api call will be a json containing error message with http 400 status code:
throw new ActionInputIsNotValidException();

Can't return completedsuccesfull task in .net core

Hi I wrote the following code:
private bool GetIsCompleted()
{
return Email.SendMessageAsync().IsCompletedSuccessfully;
}
[HttpPost]
public ViewResult CheckOut(Order order)
{
if (Cart.Lines.Count() == 0)
{
ModelState.AddModelError("","Your Cart is empty!");
}
if (ModelState.IsValid)
{
order.CartLines = Cart.Lines;
order.DateTime = DateTime.Now;
order.TotalPrice = Cart.ComputeTotalValue();
if (Repository.SaveOrder(order))
{
if (User.Identity.Name != null)
{
Email.SetMessageBody(order.OrderID);
if (GetIsCompleted())
{
Cart.Clear();
return View("Completed");
}
}
}
ViewBag.Error = "An error Occured while sending you an email with the order details.";
return View(new Order());
}
else
{
ViewBag.Error = "An error Occured while trying to save your order. Please try again!";
return View(new Order());
}
}
public async Task SendMessageAsync()
{
this.Message = new MailMessage(this.MailFrom.ToString(), this.MailTo.ToString(), this.GetSubject(), this.GetMessageBody());
//Message.Dispose();
try
{
await this.Client.SendMailAsync(this.Message);
}
catch (Exception ex)
{
Logger.LogInformation("The Email couldn't send to the recipient");
}
}
I get
An error Occured while sending you an email with the order details.
in the View. I want GetIsCompleted() to return true to proceed the code. It is developed under .net core. I do not understand why IsCompletedSuccessfully() does not return true; Any suggestion?
The current flow of your code is this:
Start sending the e-mail.
Check if it is completed successfully, decide that it hasn't and return failure.
The e-mail completes sending.
You're awaiting the actual SendMailAsync(..) method, and that's great, but nothing awaits SendMessageAsync(...) so it immediately returns the incomplete task to the caller. Because there isn't enough time between starting to send the e-mail and checking if the task completed, the status will be false.
You need to use async all the way up. Change your method definition to be async:
public async Task<ViewResult> CheckOut(Order order)
Replace this code:
if (GetIsCompleted())
{
Cart.Clear();
return View("Completed");
}
with this:
try
{
await Email.SendMessageAsync();
Cart.Clear();
return View("Completed");
}
catch (Exception e)
{
// handle exception
}
It's worth noting that you'll only ever get an exception if the call to new MailMessage(...) fails because your try/catch block in SendMessageAsync is swallowing all other exceptions.

Error for GetStringAsync if triggered by ScheduledAgent but no error during WP8 App usage

I have a wrapper for the webclient that I am using to retrieve some data. This same function is being used by the WP8 App and also used by the WP8 ScheduledAgent.
Somehow, when the function is used by the WP8 App, there is no error and it returns correctly.
However, when the ScheduledAgent uses the function, it erred out at the bold code below. I tried a try catch but it is not catching. Via Debugger, the GetSTringAsync(uri) had completed without any exception. The error seemed to be only happening when it is assigning the return Task to the result string.
The error I received is:
An unhandled exception of type 'System.UnauthorizedAccessException' occurred in System.Windows.ni.dll
public class HttpClient : WebClient
..
private async Task GetStringAsync(string strUri)
{
Uri uri = new Uri(strUri);
string result = string.Empty;
try
{
result = await GetStringAsync(uri);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return result;
}
...
private Task GetStringAsync(Uri requestUri)
{
TaskCompletionSource tcs = new TaskCompletionSource();
try
{
this.DownloadStringCompleted += (s, e) =>
{
if (e.Error == null)
{
tcs.TrySetResult(e.Result);
}
else
{
tcs.TrySetException(e.Error);
}
};
this.DownloadStringAsync(requestUri);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
if (tcs.Task.Exception != null)
{
throw tcs.Task.Exception;
}
return tcs.Task;
}
Please advise if I am missing something.
My problem is because I am using pushpin as one of my object types within my Model. Apparently, in the scheduled agent, it is not able to access that object type and thus threw the above error.

BookMark Redirection using AOP-Spring interceptor

I was trying to write an interceptor using spring AOP.The interceptor will find if a request URL is a bookmark,if so will redirect to the authentication page.
Code Snippet:
public Object invoke(MethodInvocation invocation) throws Throwable {
logger.entering(this.getClass().getSimpleName(), "invoke", invocation);
Object result = null;
try {
// Logic to exclude the beans as per the list in the configuration.
boolean excluded = false;
for (String excludebean : excludedBeans) {
if (excludebean != null && excludebean.equalsIgnoreCase(invocation.getThis().getClass().getSimpleName())) {
excluded = true;
break;
}
}
// If the Target Method is "toString", then set EXCLUDE to TRUE and process the request
if(excluded == false && invocation.getMethod().getName().equalsIgnoreCase("toString"))
{
excluded = true;
}
// if user session object is available, then process the request or
// else forward to the configured view.
if (excluded || getSessionHolder().getUserVO() != null) {
result = invocation.proceed();
}
else {
logger.logp(Level.INFO, this.getClass().getSimpleName(),
"invoke(MethodInvocation)", "User Object is "+ getSessionHolder().getUserVO()
+ ". So redirecting user to home page");
result = new ModelAndView("redirect:/security/authenticate.do");
}
}
catch (Throwable ex) {
throw ex;
}
logger.exiting(this.getClass().getSimpleName(), "invoke");
return result;
}
When I debug the control comes inside the else block as expected but after I return the result,control goes to the handle method for the bookmarked URl ratehr than the handler for the redirect view.
Pls help me on this..Thanks in advance.
Why Do you need AOP for the interceptor. You can redirect easily using Regular interceptor.
public class RedirectInterceptor extends HandlerInterceptorAdapter{
private String redirectMapping;
public void setRedirectMapping(String redirectMapping) {
this.redirectMapping = **maintenanceMapping**;
}
//before the actual handler will be executed
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler)
throws Exception {
if (somethingHappened){
response.sendRedirect(redirectMapping);
return false;
} else
return true;
}
}

Resources