How to set a priority of retrofit requests


How to set a priority of retrofit requests



I have ViewPager and in this ViewPager there are 4 fragments. Sorry but I can't to add a code, because that would be very big. Each of my fragments on create does asynchronous retrofit request to server. I have access_token and refresh_token too. So when my access_token expires I need to do a call using refresh_token to update my access_token. So when I launch my application it opens viewPager with my 4 fragments doing asynchronous requests. That means 4 requests at a time. And when my access_token is expired and I'm launching my app, all the fragments try to update the access token using refresh token. Turns out that one fragment updates the access_token (after the update refresh_token changes) other fragments try to update the token too, but I'm getting 401 because 1 fragment already updated the token and other fragments try to update the access_token using old refresh token.


ViewPager


access_token


refresh_token


access_token


refresh_token


access_token



Here is the example of one request.


Call<ResponseBody> getChatImageCall = apiClient.getImages(cutMessage, CHAT_IMAGE_TYPE);
getChatImageCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
messagesAdapter.addToStart(MessagesFixtures.getImageBytesMessage(response.body().bytes(), id), true);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getActivity(), "Something went wrong", Toast.LENGTH_SHORT).show();
}
}

@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(getActivity(), "An error occurred", Toast.LENGTH_SHORT).show();
}
});



Here is the token update request part


public class RefreshToken {

Context context;
TokenUpdaterCallback tokenUpdaterCallback;
ApiClient apiClient = ApiClient.getInstance();

public RefreshToken(Context context, TokenUpdaterCallback tokenUpdaterCallback) {
this.context = context;
this.tokenUpdaterCallback = tokenUpdaterCallback;
}

public void updateToken() {

//Perform this call if access token is expired

SupportObjToken supportObjToken = new SupportObjToken();

supportObjToken.setGrantType("refresh_token");
supportObjToken.setClientId(SharedPreferencesManager.getInstance().getUserData().getClientId());
supportObjToken.setClientSecret(SharedPreferencesManager.getInstance().getUserData().getClientSecret());
supportObjToken.setRefreshToken(SharedPreferencesManager.getInstance().getUserData().getRefreshToken());

Call<RefreshTokenActivation> newToken = apiClient.newToken(supportObjToken);
newToken.enqueue(new Callback<RefreshTokenActivation>() {
@Override
public void onResponse(Call<RefreshTokenActivation> call, Response<RefreshTokenActivation> response) {
if (response.isSuccessful()) {
String newAccessToken = response.body().getAccessToken();
String newRefreshToken = response.body().getRefreshToken();

UserData userData = SharedPreferencesManager.getInstance().getUserData();
SharedPreferencesManager.getInstance().removeUser();
userData.setAccessToken(newAccessToken);
userData.setRefreshToken(newRefreshToken);
SharedPreferencesManager.getInstance().setUser(userData);

tokenUpdaterCallback.updateToken();
} else {
if (response.code() == 401) {

//Perform this call if refresh token is expired

Activity activity = (Activity) context;
MainActivity mainActivity = (MainActivity) activity;
mainActivity.logOut();
Toast.makeText(activity, "You logged on other hardware", Toast.LENGTH_SHORT).show();
}
}
}

@Override
public void onFailure(Call<RefreshTokenActivation> call, Throwable t) {
Toast.makeText(context, "Response is not successful", Toast.LENGTH_SHORT).show();
}
});
}
}

tokenUpdaterCallback is a simple interface with updateToken() method. So you don't need this.





From where are you calling that request_token API can you please share that code
– Brijesh Joshi
Jul 2 at 10:02


request_token





Wait I'll add the token update code part
– Name Surname
Jul 2 at 10:13





From where you calling updateToken method and what error you are getting when your access_token is expired
– Brijesh Joshi
Jul 2 at 10:18


updateToken


access_token





When I'm doing request from fragment and get 401, I'm call this refresh token class. The update token method is when I'm updating my token I'm doing request from fragment one more time, else when it gets 401 and updates then nothing happens)
– Name Surname
Jul 2 at 10:23





Okay can you add a flag in your RefreshToken class , for example requesting_token set it true when you entering the updatetoken method. and set it false when your api call is done with success/failure. and when calling the updateToken api check for that variable
– Brijesh Joshi
Jul 2 at 10:52


RefreshToken


requesting_token




1 Answer
1


public class RefreshToken {

Context context;
TokenUpdaterCallback tokenUpdaterCallback;
ApiClient apiClient = ApiClient.getInstance();
boolean isLoading = false;

public RefreshToken(Context context, TokenUpdaterCallback tokenUpdaterCallback) {
this.context = context;
this.tokenUpdaterCallback = tokenUpdaterCallback;
}

public void updateToken() {
if (!isLoading) {
isLoading = true;
//Perform this call if access token is expired

SupportObjToken supportObjToken = new SupportObjToken();

supportObjToken.setGrantType("refresh_token");
supportObjToken.setClientId(SharedPreferencesManager.getInstance().getUserData().getClientId());
supportObjToken.setClientSecret(SharedPreferencesManager.getInstance().getUserData().getClientSecret());
supportObjToken.setRefreshToken(SharedPreferencesManager.getInstance().getUserData().getRefreshToken());

Call<RefreshTokenActivation> newToken = apiClient.newToken(supportObjToken);
newToken.enqueue(new Callback<RefreshTokenActivation>() {
@Override
public void onResponse(Call<RefreshTokenActivation> call, Response<RefreshTokenActivation> response) {
if (response.isSuccessful()) {
String newAccessToken = response.body().getAccessToken();
String newRefreshToken = response.body().getRefreshToken();

UserData userData = SharedPreferencesManager.getInstance().getUserData();
SharedPreferencesManager.getInstance().removeUser();
userData.setAccessToken(newAccessToken);
userData.setRefreshToken(newRefreshToken);
SharedPreferencesManager.getInstance().setUser(userData);

tokenUpdaterCallback.updateToken();
} else {
if (response.code() == 401) {

//Perform this call if refresh token is expired

Activity activity = (Activity) context;
MainActivity mainActivity = (MainActivity) activity;
mainActivity.logOut();
Toast.makeText(activity, "You logged on other hardware", Toast.LENGTH_SHORT).show();
}
isLoading = false;
}
}

@Override
public void onFailure(Call<RefreshTokenActivation> call, Throwable t) {
Toast.makeText(context, "Response is not successful", Toast.LENGTH_SHORT).show();
isLoading = false;
}
});
}
}
}






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages