Determine When LoopJ has concluded all background connections - java

Im trying to determine when LoopJ has finished all background thread http calls. So that i can then display the results of an array that is populated based on the results of my onSuccess methods.
First off, I have a String[] of file names. I'm then looping through the array and creating loopj connections like such.
ArrayList<String> files_to_update = new ArrayList<String>(file_names.length);
AsyncHttpClient client = new AsyncHttpClient();
for (final String file_name : file_names) {
client.get(BASE_URL + file_name, new AsyncHttpResponseHandler() {
public void onStart() {
Local_Last_Modified_Date = preferences.getString(file_name, "");
}
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
Server_Last_Modified_Date = headers[3].getValue();
}
#Override
public void onFinish() {
if (!Local_Last_Modified_Date.trim().equalsIgnoreCase(Server_Last_Modified_Date.trim())) {
files_to_update.add(file_name);
}
}
});
}
What i'm doing here is comparing 2 date strings, The first Local_Last_Modified_Date is pulled from a preference file and the 2nd is determined by the last-modified date in the header. and then compared in the OnFinish(). This determines if the file needs to be update because the server file is newer than the preference date. Now! i know this is not the best way for comparing dates, however it will work interm for what i'm trying to do.
The issue i'm having is determining that all of the background http calls from loopj have completed so that i can now display the results of array list in a list dialog or whatever ui element i choose. I've tried looping through the arraylist, but because the loopj / http connections are background threads, the loop gets executed prior to the completion of all of the connection and therefore displays an empty or not populated fully array.
Is there a if conditional that i can write to determine if loopj has not finished executing all of the connection and when it has then execute my ui code?

The following code should address your problem:
Class file: UploadRunner.java
public class UploadRunner extends AsyncHttpResponseHandler implements Runnable {
private final AsyncHttpClient client;
private final ArrayList<String> filesList;
private final int filesCount;
private final Handler handler;
private String baseURI;
private boolean isFired;
private int filesCounter;
// Use in case you have no AHC ready beforehand.
public UploadRunner(ArrayList<String> filesList) {
this(new AsyncHttpClient(), filesList);
}
public UploadRunner(
AsyncHttpClient client,
ArrayList<String> filesList,
Handler handler
) {
assert null != client;
assert null != filesList;
assert null != handler;
this.client = client;
this.filesList = filesList;
this.handler = handler;
this.baseURI = "";
this.filesCount = filesList.size();
this.filesCounter = 0;
}
public String getBaseURI() {
return baseURI;
}
public void setBaseURI(String uri) {
baseURI = uri;
}
#Override
public void run() {
// Request to download all files.
for(final String file : filesList) {
client.get(baseURI + file, this);
}
}
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
// This shouldn't happen really...
if(isFired) {
return;
}
// One more file downloaded.
filesCounter++;
// If all files downloaded, fire the callback.
if(filesCounter >= filesCount) {
isFired = true;
handler.onFinish(getLastModificationDate(headers));
}
}
private String getLastModificationDate(Header[] headers) {
// Simple mechanism to get the date, but maybe a proper one
// should be implemented.
return headers[3].getValue();
}
public static interface Handler {
public void onFinish(String lastModificationDate);
// TODO: Add onError() maybe?
}
}
In this case, you encapsulate the uploading mechanism in one place, plus expose just an interface for calling back a handler when all files are uploaded.
Typical use case:
// TODO: This typically should run in a different thread.
public class MyTask implements UploadRunner.Handler, Runnable {
private final static BASE_URI = "http://www.example.com/";
private final AsyncHttpClient client = new AsyncHttpClient();
private final ArrayList<String> filesList = new ArrayList<>();
#Override
public void run() {
filesList.add("1.png");
filesList.add("2.png");
filesList.add("3.png");
filesList.add("4.png");
filesList.add("5.png");
// Create a new runner.
UploadRunner ur = new UploadRunner(client, filesList, this);
// Set base URI.
ur.setBaseURI(BASE_URI);
// Spring the runner to life.
ur.run();
}
#Override
public void onFinish(String lastModificationDate) {
// All files downloaded, and last modification date is supplied to us.
}
}

Related

Parallel url get calls using Java spring RestTemplate

I have a list of urls and I want to hit them all in parallel and combine the result into a final Java object using Java spring RestTemplate. I'm able to achieve it buy accessing the urls in sequence, but due to performance concerns, I want to achieve them same in parallel. Looking forward to hearing your suggestions
You can use threads to perform parallel jobs.
First, make a result data class to handle the responses of your URLs
public class URLResult {
public String url;
public String response;
public Date responseTime;
// Add fields whatever you need
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public Date getResponseTime() {
return responseTime;
}
public void setResponseTime(Date responseTime) {
this.responseTime = responseTime;
}
}
Then use it in your threads :
public List<URLResult> list = new ArrayList<>();
public synchronized void addToList(URLResult result) {
list.add(result);
}
public void hitUrl(String url) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
URLResult result = new URLResult();
//here, connect to your url, get the result then set your URLResult fields
addToList(result);
}
});
thread.start();
}
At the end of the process, you will have a "list" of your results.

Get data in Main class using Observer pattern

I'm getting JSON data from a remote API. For this I'm using the Observer pattern. I created an Observer called WordTranslationObserver that gets the JSON data from the callback method. The problem is that I don't know how to get this data in the Main class...
In my Main class I can't implement PropertyChangeListener and use a translationModel.addChangeListener(this) because I'm in a static context, so "this" can't work.
What is the proper way to be able to get my data from translation.getText() in my Main class ?
Main class
public class Main {
public static void main(String[] args) throws IOException {
WordTranslation wordTranslation = new WordTranslation();
WordTranslationObserver myObserver = new WordTranslationObserver(wordTranslation);
wordTranslation.translate("sắt", "vie", "eng");
}
}
Observer
public class WordTranslationObserver implements PropertyChangeListener {
public WordTranslationObserver(WordTranslation translationModel) {
translationModel.addChangeListener(this);
}
#Override
public void propertyChange(PropertyChangeEvent event) {
System.out.println("Changed property: " + event.getPropertyName());
ArrayList<Translation> translations = (ArrayList<Translation>) event.getNewValue();
// Print recieved data from JSON to the console
// I want to be able to get translation.getText() in my Main class
for (Translation translation : translations) {
System.out.println(translation.getText());
}
}
}
Data
public class WordTranslation {
public static final String TRANSLATIONS = "translations";
private static final String BASE_URL = "http://deu.hablaa.com/hs/translation/";
private List<PropertyChangeListener> listener = new ArrayList<PropertyChangeListener>();
ArrayList<Translation> translations;
public void addChangeListener(PropertyChangeListener newListener) {
listener.add(newListener);
}
public void notifyListeners(String property, Translation[] translationArray) {
translations = new ArrayList<>();
// TODO Auto-generated method stub
for (Translation t : translationArray) {
translations.add(t);
}
for (PropertyChangeListener name : listener) {
name.propertyChange(new PropertyChangeEvent(this, "translations", null, translations));
}
}
public void translate(String word, String from, String to) {
final Translation[][] translations = new Translation[1][1];
String url = String.format("%s%s/%s-%s",BASE_URL, word, from, to);// args) "http://xxx";
System.out.println(url);
final Gson gson = new Gson();
// should be a singleton
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
translations[0] = gson.fromJson(response.body().charStream(),Translation[].class);
notifyListeners(TRANSLATIONS,translations[0]);
}
});
}
}
You could have an observer set static variables if you really wanted to, that could be polled for changes but this would defeat the principle of using the observer pattern which is event driven.
Perhaps there is some specific reason why you want this information available in the main class but I would be more inclined to offload any processing onto observers as you have already (cleanly) done, adding new implementations as you need them.
If you just want the information available to your main class (not necessarily in a static context), have your Main class implement PropertyChangeListener and register a new Main() with your WorldTranslation in the same way you have done with the WorldTranslationObserver.
HTH

Scope issues in Android using Retrofit

I have an issue with the scope of a variable in Android using Retrofit:
In the MainActivity I use Retrofit to get the JSON reply into a POJO (ApiResponse), create a extendedJourney Object and add it to the extendedJourneyArrayList:
public class MainActivity extends Activity {
private ArrayList<ExtendedJourney> extendedJourneyArrayList = new ArrayList<>();
...
getAPIReply(...){
service.getInfo(..., new getCallback());
...}
private class getCallback implements Callback<ApiResponse> {
public void success(ApiResponse apiResponse, Response response) {
try {
consumeApiData(apiResponse);
}
...
}
}
private void consumeApiData(ApiResponse apiResponse){
ExtendedJourney extendedJourney = new ExtendedJourney(apiResponse, params);
extendedJourneyArrayList.add(extendedJourney);
}
public void getData(View view){
getAPIReply(...);
//Do stuff with the extendedJourneyArrayList
}
Inside consumeApiData() everything is OK, i.e. the extendedJourney Object is correctly created from the apiResponse and other params and the extendedJourneyArrayList is correctly updated with the new extendedJourney.
However, in getData(View view), extendedJourneyArrayList is empty.
How can this be solved? Thanks :D
You are making an asynchronous call.
That means, that after the call to service.getInfo(..., new getCallback()); the flow continues normally, until it's intrrrupted by the callback.
So you code in getData(View v) is probably excecuting before the response is received.
So you should do what you want with the data on the callback ( for example in the end of the consumeApiData(..) after the data is added in the list ), or do a synchronous request ( which you must do in a separate thread ).
Thanks #Kushtrim for your answer. To solve the problem I make of use an AsyncTask to perform synchronous requests, the code now looks like this:
public class MainActivity extends Activity {
private ArrayList<ExtendedJourney> extendedJourneyArrayList = new ArrayList<>();
...
public void getData(View view){
for(int i = 0; i < NUM_REQUESTS; i++){
new getAPIReply().execute(params);
}
}
private class getAPIReply extends AsyncTask<Params, Void, ApiResponse>{
#Override
protected ApiResponse doInBackground(Coords[] coords) {
return service.getRouteInfo(params);
}
#Override
protected void onPostExecute(ApiResponse apiResponse){
try {
consumeApiData(apiResponse);
} catch (JSONException e) {...}
}
private void consumeApiData(ApiResponse apiResponse) throws JSONException{
ExtendedJourney extendedJourney = new ExtendedJourney(apiResponse, params);
extendedJourneyArrayList.add(extendedJourney);
if(extendedJourneyArrayList.size() == NUM_REQUESTS) {
//Do stuff
}
}

Volley , Wait for response to return wait until use flag

I have to respond to result of volley request. but because it is asynchronous. I need to wait for the results before I proceed. If I don't I will get nullobjects.
How do I set flags and wait until flags are off.
categoryslashid = new JSONObject[Category_IDs.size()];//size of the list containing all categories
taskfinished = new boolean[Category_IDs.size()];
//boolean is initialized to false
//Request to category/{id} to get
for(int i= 0;i<Category_IDs.size();i++)
{ makevolleyrequesforCategorySlashID(Const.URL_FULL_STOREURL+Const.URL_PRODUCT_GET_CATEGORY_ID,i);
}
public void makevolleyrequesforCategorySlashID(URL,id)
{
//volley implementation
public void onResponseoverride
{
categoryslashid[i]=response;
taskfinished[i]=true;
}
}
Now I must proceed after I get all the booleans in task finished become true.
public boolean areAllTrue()
{
for(boolean b : taskfinished) if(!b) return false;
return true;
}
Implement an Interface and use it to call back when your data is ready. Something like this:
public interface OnDownloadTaskCompleted {
public void onTaskCompleted(List<ofSomething> list, boolean error, String message);
}
Then you should pass an instance of this to your request and override onTaskCompleted()
private void downloadData(){
final DownloadUsingVolley downloader = new DownloadUsingVolley(getActivity());
downloader.retrieveData(new OnDownloadTaskCompleted() {
#Override
public void onTaskCompleted(List<ofSomething> list, boolean error, String message) {
//do something with your data
}
});
}
I'm assuming that you have a class where you implemented volley stuff (DownloadusingVolley) and a method do call on it and make the request itself (retrieveData).
retrieveData can be implemented like this:
private void retrieveData(String url, final OnDownloadTaskCompleted taskCompleted){
final JsonObjectRequest request = new JsonObjectRequest(url, null, new Response.Listener<JSONObject>(){
#Override
public void onResponse(JSONObject response) {
try {
//parse
taskCompleted.onTaskCompleted(result,false,null);
}catch (JSONException e){
taskCompleted.onTaskCompleted(0,true,e.getMessage());
}
}
},new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError volleyError) {
taskCompleted.onTaskCompleted(0,true,volleyError.getMessage());
}
});
//adding request into the queue
ApplicationClass.getInstance().addToRequestQueue(request,"aTag");
}
Here you can find a nice tutorial about volley:
Asynchronous HTTP Requests in Android Using Volley

gwt-google-apis call results in "Cannot call method 'newHttpRequest' of undefined"

I am using the gwt-plus-v1-0.2-alpha API to:
Allow Google login
Fetch Signed in user's information
Google login works, but fetching the user's information fails with a
Cannot call method 'newHttpRequest' of undefined
error.
The following is my GoogleApi helper class:
public final class GoogleApi {
private static final Plus plus = GWT.create(Plus.class);
private final String clientId;
private final ClientOAuth2Login oAuth2Login;
private ClientGoogleApiRequestTransport requestTransport;
/**
* #param clientId
* This app's personal client ID assigned by the Google APIs
* Console (http://code.google.com/apis/console)
*/
public GoogleApi(EventBus eventBus, String clientId) {
this.clientId = clientId;
requestTransport = new ClientGoogleApiRequestTransport();
requestTransport.setApplicationName(MY_APP_NAME)
.setApiAccessKey(MY_API_KEY);
plus.initialize(eventBus, requestTransport);
oAuth2Login = new ClientOAuth2Login(clientId);
oAuth2Login.withScopes(PlusAuthScope.PLUS_ME);
}
public void login(final Receiver<String> callback) {
oAuth2Login.login(new Receiver<String>() {
#Override
public void onSuccess(String response) {
requestTransport.setAccessToken(response);
callback.onSuccess(response);
}
#Override
public void onFailure(ServerFailure error) {
Window.alert(error.getMessage());
}
});
}
public void getUserInfo(Receiver<Person> receiver) {
plus.people().get("me").to(receiver).fire();
}
}
The following shows where the failure occurs:
GoogleApi googleApi = new GoogleApi(eventBus, MY_CLIENT_ID);
googleApi.login(new Receiver<String>() {
#Override
public void onSuccess(final String token) {
// login is successful and access token is received
// but the following call fails with "Cannot call method 'newHttpRequest'
// of undefined" error
googleApi.getUserInfo(new Receiver<Person>() {
#Override
public void onSuccess(Person person) {
// never gets here
}
#Override
public void onFailure(ServerFailure error) {
// nor here
}
});
}
}
Try updating your gwt-google-apis libraries, there's been a change back in June that replaced calls to $wnd.googleapis.newHttpRequest() with calls to $wnd.gapi.client.rpcRequest(): https://code.google.com/p/gwt-google-apis/source/detail?r=2041
The reason authentication works it that it doesn't use the same code to talk to the server.
I have played around with the code (still using version 1.0.2-alpha) and made it work! The following is the updated code:
public final class GoogleApi {
private static final Plus plus = GWT.create(Plus.class);
private final String clientId;
private EventBus eventBus;
private final ClientOAuth2Login oAuth2Login;
private ClientGoogleApiRequestTransport requestTransport;
private String accessToken;
/**
* #param clientId
* This app's personal client ID assigned by the Google APIs
* Console (http://code.google.com/apis/console)
*/
public GoogleApi(final EventBus eventBus, String clientId) {
this.eventBus = eventBus;
this.clientId = clientId;
oAuth2Login = new ClientOAuth2Login(clientId);
oAuth2Login.withScopes(PlusAuthScope.PLUS_ME);
}
public void login(final Receiver<String> callback) {
oAuth2Login.login(new Receiver<String>() {
#Override
public void onSuccess(String response) {
accessToken = response;
callback.onSuccess(response);
}
#Override
public void onFailure(ServerFailure error) {
Window.alert(error.getMessage());
}
});
}
public void getUserInfo(final Receiver<Person> receiver) {
requestTransport = new ClientGoogleApiRequestTransport();
requestTransport.setApplicationName(ClientConstants.GOOGLE_APP_NAME)
.setApiAccessKey(ClientConstants.GOOGLE_API_KEY)
.setAccessToken(accessToken);
requestTransport.create(new Receiver<GoogleApiRequestTransport>() {
#Override
public void onSuccess(GoogleApiRequestTransport transport) {
plus.initialize(eventBus, transport);
plus.people().get("me").to(receiver).fire();
}
});
}
}
I don't know how efficient this is, though. A call to Plus's initialize() method is made every time a call to getUserInfo() is made.
Next step for me is to manually build a jar with the latest version of the API and adjust my code accordingly :/ Wish me luck!

Categories