I need to make an ajax request every 10 seconds and update data on client side.
So, I've tried this way in my onModuleLoad():
while (true) {
try {
someService.initTable(new AsyncCallback<SomeObject>() {
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(SomeObject result) {
initData(numbersTable, result);
}
});
} catch (Exception e) {
}
}
But it goes to infinite loop.
I'd like to get something like this
(function worker() {
$.ajax({
url: 'ajax/test.html',
success: function(data) {
$('.result').html(data);
},
complete: function() {
// Schedule the next request when the current one's complete
setTimeout(worker, 5000);
}
});
})();
Async calls in gwt execute immediately, and return "later". In your code, the while loop isn't waiting for anything, so you're calling initTable() many many times per second, hence the infinite loop.
Simply create a timer that executes every 10 seconds.
final Timer timer = new Timer() {
#Override
public void run() {
try {
someService.initTable(new AsyncCallback<SomeObject>() {
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(SomeObject result) {
initData(numbersTable, result);
}
});
} catch (Exception e) {
}
}
};
timer.scheduleRepeating(10000);
Related
I want to understand the the need for Flowable in RxJava. So I want to deal with backPressure for huge data with simple Observable. But I am not getting any error with it.
this is my test code:
Observable.range(1, 10000).observeOn(Schedulers.computation())
.subscribe(new Observer<Integer>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onNext(#NonNull Integer integer) {
System.out.println("next: " + integer);
}
#Override
public void onError(#NonNull Throwable e) {
System.out.println("onError " + e.toString());
}
#Override
public void onComplete() {
}
});
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
How can I test backPressure problems using Observable? Thanks
In my Android application I perform some actions related with my Room Database. These actions have to be done in background, this is why I use a threadExecutor. As you can see the code for both methods is almost the same and I was wondering if it would be possible to construct something generic to avoid this code repetition.
public void addOperation(Operation operation, AddOperationInteractor.CallBack callback)
{
Interactor interactor = new AbstractInteractor(ThreadExecutor.getInstance())
{
#Override
public void run()
{
try
{
operationRepository.addNewOperation(operation);
callback.onAddOperationSuccess();
}
catch (Exception ex)
{
callback.onAddOperationSuccess();
}
}
};
interactor.execute();
}
public void deleteOperation(Operation operation, RemoveOperationInteractor.CallBack callback)
{
Interactor interactor = new AbstractInteractor(ThreadExecutor.getInstance())
{
#Override
public void run()
{
try
{
operationRepository.removeOperation(operation);
callback.onRemoveOperationSuccess();
}
catch (Exception ex)
{
callback.onRemoveOperationSuccess();
}
}
};
interactor.execute();
I see no repetition in your code. To reduce boilerplate code, try a lambda:
public void addOperation(Operation operation, AddOperationInteractor.CallBack callback) {
ThreadExecutor.getInstance().execute(() -> {
try {
operationRepository.addNewOperation(operation);
}
finally {
callback.onAddOperationSuccess();
}
});
}
public void deleteOperation(Operation operation, RemoveOperationInteractor.CallBack callback) {
ThreadExecutor.getInstance().execute(() -> {
try {
operationRepository.removeOperation(operation);
}
finally {
callback.onRemoveOperationSuccess();
}
});
}
Now there is only 1 repeating line, to invoke the ThreadExecutor.
Alternatively pass callbacks to a helper method:
public void addOperation(Operation operation, AddOperationInteractor.CallBack callback) {
execute(()-> operationRepository.addNewOperation(operation),
()-> callback.onAddOperationSuccess());
}
public void deleteOperation(Operation operation, RemoveOperationInteractor.CallBack callback) {
execute(()-> operationRepository.removeOperation(operation),
()-> callback.onRemoveOperationSuccess());
}
private void execute(Runnable action, Runnable onSuccess) {
ThreadExecutor.getInstance().execute(() -> {
try {
action.run();
onSuccess.run();
} catch (Exception e) {
LOG.warn(e);
onSuccess.run();
}
}
}
I'm trying to do a setText() on a Textview (already instantiate in the onCreate()) called by a Handler and using the ruiOnUiTread() but I have a nullPointerException on the Textview.
Where can the problem come from?
I saw in the debug that the instance of the activity was not the same between the instantiation and the setText() while I do not change activity but impossible to instantiate it in the same place as the setText().
private TextView ambianceTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ambianceTextView = findViewById(R.id.valeur_ambiance);
StarterKillerPidroid.getInstance().startApp();
}
private final Runnable retrieveData = new Runnable() {
public void run() {
try {
setText();
} catch (Exception e) {
e.printStackTrace();
}
handlerRecup.postDelayed(retrieveData, 1000);
}
};
public void setText(){
runOnUiThread(new Runnable() {
#Override
public void run() {
ambianceTextView.setText("test");
}
});
}
public void doAfterLogin() {
handlerRecup.postDelayed(retrieveData, 10000);
}
the runnable is started by a function called by a callback of an http request with Volley
public class StarterKillerPidroid {
void startApp() {
//Sending a request
PostmanPidroid.getInstance().login();
}
public void ackLogin(Boolean isValid) {
if (isValid) {
ActivityMain.getInstance().doAfterLogin();
} else {
PostmanPidroid.getInstance().login();
}
}
}
The class Postman :
public class Postman {
public void login(){
// Parameters
String email = "test#tes";
String password = "test";
// Encoding the request with parameters
JsonObjectRequest request = EncoderDecoderPidroid.getInstance()
.encodeRequestLogin(email, password);
// Sending the request
sendRequest(request);
}
void sendRequest(StringRequest message){
// Creating the queu if it's not create
if (queue == null) {
queue = Volley.newRequestQueue(context);
}
// Adding the request to the queue
queue.add(message);
}
}
When a success response is received, this callback is called :
private Response.Listener<JSONObject> callbackLogin =
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
...
StarterKillerPidroid.getInstance().ackLogin(true);
}
};
Basically, this kind of problem is due to the instance. It may be possible that your textview instance is not initialized. One more thing using handler directly for updating UI thread is not a good idea. Instead of directly updating Ui with handler you should use FunctionalInterface for doing this.
FunctionalInterface is a good approach for such cases.
A functional interface is an interface that contains only one abstract method. They can have only one functionality to exhibit. From Java 8 onwards, lambda expressions can be used to represent the instance of a functional interface. ... Runnable, ActionListener, Comparable are some of the examples of functional interfaces.
Java has a predefined FunctionalInterface Callable. It goes something like this
public static void doDid(final Callable<Void> callable) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
try {
callable.call();
handler.postDelayed(this, every * repeattime);
} catch (Exception e) {
e.printStackTrace();
}
}
}, every * tempvalue);
}
and use this for updating UI in this way
doDid(new Callable<Void>() {
#Override
public Void call() {
textView.setText("Your text");
return null;
}
});
There is one open-source library available for Android which works like a charm is such cases called Predictor. You can download it from here and import in your project. You can also contribute in this project for saving many developers life.
Do you wanna see how predictor can do this?
Predictor.every(3).second().doDid(new Job<Void>() {
#Override
public Void run() {
textView.setText("Your text");
return null;
}
});
What can you do with predictor?
Predictor gives you several ways of handling multithreading some of them are as follows:
Predictor.every(3).second().doDid(something());
Predictor.every(5).minutes().doDid(something());
Predictor.every().hour().doDid(something());
Predictor.every().week().doDid(something());
Predictor.every().month().doDid(something());
and many more...
Try this way:
private final Runnable retrieveData = new Runnable() {
public void run() {
try {
ambianceTextView = (TextView) findViewById(R.id.valeur_ambiance);
setText();
} catch (Exception e) {
e.printStackTrace();
}
handlerRecup.postDelayed(retrieveData, 1000);
}
};
I have a method in which I call another method that has a callback. I want to receive this callback before leaving my method. I saw some other posts in which latches are used. My code looks like this:
public void requestSecurityToken(<some params>){
final CountDownLatch latch = new CountDownLatch(1);
MyFunction.execute(<someParams>, new RequestListener<Login>() {
#Override
public void onRequestFailure(SpiceException spiceException) {
//TODO
}
#Override
public void onRequestSuccess(Login login) {
//handle some other stuff
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This doesn't work, the method is stuck in the await() function. What happens is that, the method immediately jumps to the await(), and doesn't go into the onRequestSuccess() or onRequestFailure() method again. I guess this is a concurency problem... Any ideas on how to fix this issue?
EDIT: Added the line of code where I create the latch.
When you are doing this
new RequestListener<Login>
You are passing an object to your function , which implements an interface.
That is why those methods are not getting called , those methods are called only when you get the request result (success or failure).
You can do this instead.
MyFunction.execute(<someParams>, new RequestListener<Login>() {
#Override
public void onRequestFailure(SpiceException spiceException) {
someFunction();
}
#Override
public void onRequestSuccess(Login login) {
//handle some other stuff
someFunction();
latch.countDown();
}
});
public void someFunction()[
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
apologies for the basic question; I'm new to the Java world and the spring framework. I've built a little example application that makes a bunch of async requests to an external service and returns a list of the responses ('metrics'), but I need to make my application wait until all the responses have come back. Right now I have a (don't hate me) Thread.sleep while I let the results come back, but obviously this is very nasty. Can anyone suggest a better way of architecting this?
Calling class:
#Service
public class MetricService {
#Autowired
private MetricProcessor processor;
private LinkedBlockingQueue<Metric> queue;
#Scheduled(fixedDelay = 60000)
public void queryExternalService() {
List<Metrics> metrics = new ArrayList<>();
metrics = processor.getMetrics();
//this is horrible and I'm a horrible human being
try {
Thread.sleep(10000); //wait for the requests to come back
}
catch (Exception e) {
e.printStackTrace();
}
queue.addAll(metrics);
}
}
Class:
#Component
public class MetricProcessor {
#Autowired
private AsyncClient externalClient;
public List<Metrics> getMetrics() {
List<Metrics> returnObj = new Arraylist<>();
for(Blah blah : bleh) {
Request request = new Request("abc");
externalClient.getMetricAsync(request, new AsyncHandler<request, result>() {
#Override
public void onError(Exception e) {
System.out.println("Error");
}
#Override
public void onSuccess(Request request, Result result) {
returnObj.add(new Metric(result.getKey(), result.getValue()));
}
});
}
return returnObj;
}
}
Any help would be greatly appreciated!
Try a Future.
In MetricService:
public void queryExternalService() {
Future<List<Metrics>> metricsFuture = processor.getMetrics();
try {
queue.addAll(metricsFuture.get(60, TimeUnit.SECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
}
So notice instead of the desired List, your processor provides a reference to a Future which may fulfil that request later:
public Future<List<Metrics>> getMetrics() {
MetricsFuture metricsFuture = new MetricsFuture();
// Need to ask for the metrics to be built
metricsFuture.buildMetrics();
return metricsFuture;
}
private static class MetricsFuture extends AbstractFuture<List<Metrics>> {
// Assuming the requests are asynchronous, this should be a thread-safe list
List<Metrics> returnObj = new CopyOnWriteArrayList<>();
void buildMetrics() {
for(Blah blah : bleh) {
final Request request = new Request("abc");
externalClient.getMetricAsync(request, new AsyncHandler<request, result>() {
#Override
public void onError(Exception e) {
onError(request, e);
}
#Override
public void onSuccess(Request request, Result result) {
addMetrics(new Metrics(result.getKey(), result.getValue()));
}
});
}
}
void onError(Request request, Exception e) {
// Is any error a total failure? This allows us to terminate waiting
setException(e); // alternative we could remove request or keep a list of errors
System.out.println("Error");
}
void addMetrics(Metrics metric) {
returnObj.add(metric);
// Once we have received the expected number of results we can pass that prepare that
// as a result of this future.
if(returnObj.size() == bleh.size()) {
set(returnObj);
}
}
}