GWT - synchronous return of a method - java

Ok, there isn't synchronous call in GWT.
But if i have something like this:
class XXX {
Config c=new Config();
c.doSomething();
}
and the class Config
public class Config {
private static HashMap<String,String> map;
public Config(){
final ServerProxyAsync serverProxy= GWT.create(ServerProxy.class);
serverProxy.getParameters(new AsyncCallback<HashMap<String,String>>() {
#Override
public void onFailure(Throwable caught) {
System.out.println("getParameters: FAILED!");
map=null;
}
#Override
public void onSuccess(HashMap<String, String> result) {
System.out.println("getParameters: OK!");
map=result;
// RETURN NOW!!!!
}
});
}
if the asynchronous call doesn't terminate I can't do doSomething(), because sometime the method is invoked before the map is initialized.
Is there a way?

How about doSomething() in onSuccess() ?
You can't use synchronous call in GWT.Even though you made it somehowits not a good practise
When you need this you have to do the stuff in the onSuccess(); of your RPC call .
So, the best idea is to simply use the asynchronous method and continue execution via the callbacks provided.You will end up with a much better user experience, and a more professional appearing
application.

Just extends your Config class to take a Runnable or a Callback. Something like this:
public class Config {
private static HashMap<String,String> map;
private final Runnable callback;
public Config(Runnable callback){
this.run = run;
final ServerProxyAsync serverProxy= GWT.create(ServerProxy.class);
serverProxy.getParameters(new AsyncCallback<HashMap<String,String>>() {
#Override
public void onFailure(Throwable caught) {
System.out.println("getParameters: FAILED!");
map=null;
}
#Override
public void onSuccess(HashMap<String, String> result) {
System.out.println("getParameters: OK!");
map=result;
callback.run();
}
});
}
}
Then you can use it like this:
class XXX {
final Runnable callback = new Runnable() {
#Override
public void run() {
dosomething1();
}
};
Config c=new Config(callback);
}

Related

How to unit test asynchronous code made synchronous using CountdownLatch

Below is the class I want to test :
SomeClass.java
public void SomeClass {
final CountDownLatch latch = new CountDownLatch(1);
int result;
registerCallbackWithService(new MyCallback());
public int callToExternalService(){
//Do some stuff and make service call
latch.await();
return result;
}
class MyCallback implements ServiceCallback {
#Override
public void onResult(final int res) {
//do something
result = res;
latch.countdown();
}
}
}
The callback MyCallback was registered earlier before invoking callToExternalService().
If I write a simple test to just mock the service call made in callToExternalService(), the test keeps on running infinitely because of latch.await().
How can I test the logic in callToExternalService() as well as in onResult() ?
I modified by code to expose the callback that I am registering using a package-protected function as below :
public void SomeClass {
private final CountDownLatch latch = new CountDownLatch(1);
private int result;
registerCallback(new MyCallback());
public int callToExternalService(){
//Do some stuff and make service call
latch.await();
return result;
}
private class MyCallback implements ServiceCallback {
#Override
public void onResult(final int res) {
//do something
result = res;
latch.countdown();
}
}
protected registerCallback(ServiceCallback callback) {
registerCallbackWithService(callback);
}
}
Now, for testing I do my testing by creating a new class SomeClassTest extends SomeClass and do my testing using an instance of this class. In SomeClassTest all I do is override registerCallback() to access the callback instance that is being registered.
public class ServiceTest {
private ServiceCallback mServiceCallback;
class SomeClassTest extends SomeClass {
#Override
registerCallback(ServiceCallback callback) {
mServiceCallback = callback;
super.registerCallback(callback);
}
}
}
Now all I have to do it using doAnswer, invoke the callback upon service request which results in the execution of latch.countdown() on the same latch reference that is put on await just after making the service request.
SomeClassTest someClassInstance = new SomeClassTest();
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
mServiceVCallback.onResult(int_I_want_to_test_for)
return null;
}
}).when(someClassInstance).service_request_before_latch_await();
int response = someClassInstance.callToExternalService();
assertEquals(response, expected_response);

Android AsyncTask with Input and Output not working

I have 2 Classes: a Main Class handling the UI and a second Class for retrieving Data from SQL Server by using PHP.
From the first class a mehtod in the second class is called with passing and retrieving variables.
Actually it is working fine without AsyncTask.
But since I want to use the code on devices running Android 3.0 and above, I need to change the method to be an AsyncTask. Else I get this error: "android.os.networkonmainthreadexception"
the actual working code Looks like this:
Main class:
...
String inputString="1";
String outputString;
outputString = Class2.SomeMethodInClass2(inputString);
....
Class2:
public class Class2 {
public static String SomeMethodInClass2(String input) {
String Output;
...
//Do some php-sql stuff based on "input"-variable
//and return the "output"-variable
...
return output;
}
}
This code works perfectly on Android 2.0 but I need to change it to AsyncTask, because Andoid 3.0 and above is giving me: "android.os.networkonmainthreadexception"
I have read a lot of threads about AsyncTask, but I can not get it to work with Input and Output in my code.
Eclipse allways tells me there is something wrong with my code.
How do I have to change my code, to be a working async Task? (please explain using my above code sample)
--edit: if there is an easier way to get rid of "android.os.networkonmainthreadexception" on 3.0 an above than AsyncTask, this would be fine too! --
Have a Callback in SecondClass
Extend your SecondClass with Asynctask
Implement preExecute,doinbackground, postExecute methods
Do your stuff in doinbackground
return result in doinbackground
In postExecute pass result to the Callback
Implement SecondClass.Callback in FirstClass
start SecondClass (execute) and pass a Callback reference from FirstClass
In Callback just handle your next operations with the result
EDIT :
public class SecondClass extends AsyncTask<String, Void, String> {
public interface Callback {
public void update(String result);
}
Callback mCallback;
public SecondClass(Callback callback) {
super();
mCallback = callback;
}
#Override
protected String doInBackground(String... params) {
String result = null;
//do your stuff and save result
return result;
}
#Override
protected void onPostExecute(String result) {
if(mCallback != null)
mCallback.update(result)
super.onPostExecute(e);
}
}
public class FirstClass implements SecondClass.Callback{
#Override
public void update(String result){
//do your stuff with result
}
return_type someMethod(){
SecondClass sc = new SecondClass(this) ;
sc.execute(someurl);
}
}
thanks for your Posts!
But i found an alternative way that seems much easier and better to me than doing async Task.
i added to my main class:
public class MainClass extends Activity implements OnTouchListener {
...
BackgroundOperations1 ourBackgroundOperations; //<===new
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
ourBackgroundOperations = new BackgroundOperations1(); //<===new
...
}
#Override
protected void onPause() {
....
ourBackgroundOperations.pause(); // <===new
}
#Override
protected void onResume() {
....
ourBackgroundOperations.resume(); // <===new
}
//whole new class inside of "MainClass"
//runs a different thread, i believe...?
public class BackgroundOperations1 implements Runnable {
Thread ourThread = null;
boolean isRunning = false;
public void pause() {
isRunning = false;
while (true) {
try {
ourThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
}
public void resume() {
isRunning = true;
ourThread = new Thread(this);
ourThread.start();
}
#Override
public void run() {
while (isRunning) {
if (dothis==true){
//here i call my mehtod from class2, whenever "dothis" is set to true (somewhere in my onTouch or where ever i want)
String inputString="1";
String outputString;
outputString = Class2.SomeMethodInClass2(inputString);
}
}
}
}
}
this works on Android 4.0 and i think it is the best way to do what i want. and to me it seems a lot clearer then AsyncTask, because i can call my methods an pass varaibles in a simple way.
or is there a reason to not do it like this?

Access Runnable's method before it runs

I am trying to pass a Runnable to an AsyncTask and then set the results of doInBackgroud to it and run it.
I am trying the following code with no success.
// MyActivity.java
public void click(View v) {
if(v.getId() == R.id.button) {
new AsyncHTTP(myAsyncClassCallback()).execute();
}
}
public Runnable myAsyncClassCallback() {
return new StringRunnable() {
#Override
public void run() {
Log.v(DEBUG_TAG,result.toString());
}
};
}
// StringRunnable.java
public class StringRunnable implements Runnable {
volatile String result;
public void setResult(String res) {
this.result = res;
}
#Override
public void run() {
// do something with result
}
}
// MyAsyncClass.java
public class MyAsyncClass extends AsyncTask<String, Integer, String>{
private Runnable myCallback;
public MyAsyncClass(Runnable runnable){
this.myCallback = runnable;
}
#Override
protected String doInBackground(){
// works normally
return someString;
}
#Override
protected void onPostExecute(String result) {
myCallback.setResult(result); // <--- This is my question
myCallback.run();
super.onPostExecute(result);
}
}
So I get the message:
Cannot resolve method setResult
How can I fix this? Is this some access issue?
You declared myCallback a Runnable, but Runnable does not contain a definition for setResult(String result). Your extended class, however, does. Which means you should cast the Runnable to a StringRunnable, which it actually is
((StringRunnable)myCallback).setResult(result);
Or you should declare your myCallback as a StringRunnable
private StringRunnable myCallback;
EDIT: as Unihedron pointed out, the last options means you have to change your Constructor as well
private StringRunnable myCallback;
public MyAsyncClass(StringRunnable runnable){
this.myCallback = runnable;
}
I should note, however, that it is, in your case, unnecessary to use two non-UI-threads. AsyncTask is a Thread as well
instead of
private Runnable myCallback;
use
private StringRunnable myCallback;
You'll have to cast Runnable to StringRunnable like this:
((StringRunnable)myCallback).setResult(result);

How to get Data from a Task in afterExecute of ScheduledThreadPoolExecutor

I'm using ScheduledThreadPoolExecutor and I don't know hot to deal with something.
I'm scheduling some tasks this way:
scheduledExecService = new ExtendedScheduledExecutor(numThreads, myThreadFactory);
TareaActualizacion act = new TareaActualizacion(inst);
ScheduledFuture<?> handle = scheduledExecService.scheduleWithFixedDelay(act, retrasoInicial, segundosRefresco, TimeUnit.SECONDS);
act is a Runnable class that recive some data by parameter:
public class TareaActualizacion implements Runnable {
private Instalacion instalacion;
public TareaActualizacion(Instalacion instalacion) {
this.instalacion = instalacion;
}
#Override
public void run() {
//Do something
}
public Instalacion getInstalacion() {
return instalacion;
}
}
Now in the afterExecute method of the ExtendedSecheduledExecutor I want to get the object Instalacion of the task TareaActualizacion but I don't know how to do it.
My ExtendedScheduledExecutor class looks like this:
public class ExtendedScheduledExecutor extends ScheduledThreadPoolExecutor{
public ExtendedScheduledExecutor(int arg0) {
super(arg0);
}
public ExtendedScheduledExecutor(int arg0, ThreadFactory arg1) {
super(arg0, arg1);
}
#Override
protected void afterExecute(Runnable r, Throwable t)
{
super.afterExecute(r, t);
System.out.println("Executing afterExecute. Throwable is " + t);
if (t != null)
t.printStackTrace();
//I need to get the Instalacion attribute from TareaActualizacion task. How can I do it??
}
}
Any idea of how can I solve it??
Thank you!
Neus
As Stephan already pointed out in https://stackoverflow.com/a/22145530 , you should try to decouple the scheduling and execution from the notification.
One approach for this could be to wrap the actual task (TareaActualizacion) into another implementation of the Runnable interface that only executes the actual task, and afterwards notifies a callback about the task that has been executed.
Depending on your precise requirements, there may be several degrees of freedom for the implementation, but a general approach could roughly look like this:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledTaskNotification
{
public static void main(String[] args) throws Exception
{
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
int n = 3;
for (int i = 0; i < n; i++)
{
UpdateTask updateTask = new UpdateTask(i);
RunnableCallback<UpdateTask> callback = new RunnableCallback<UpdateTask>()
{
#Override
public void runnableFinished(UpdateTask updateTask)
{
System.out.println("Finished "+updateTask+", id "+updateTask.getID());
}
};
Runnable runnableWithCallback =
createRunnableWithCallback(updateTask, callback);
executor.scheduleWithFixedDelay(
runnableWithCallback, 1000, 200+i*200,
TimeUnit.MILLISECONDS);
}
}
static interface RunnableCallback<T extends Runnable>
{
void runnableFinished(T runnable);
}
private static <T extends Runnable> Runnable createRunnableWithCallback(
final T runnable, final RunnableCallback<T> callback)
{
return new Runnable()
{
#Override
public void run()
{
runnable.run();
callback.runnableFinished(runnable);
}
};
}
private static class UpdateTask implements Runnable
{
private final int id;
UpdateTask(int id)
{
this.id = id;
}
#Override
public void run()
{
System.out.println("Run "+this);
}
int getID()
{
return id;
}
#Override
public String toString()
{
return "UpdateTask "+id;
}
}
}
This is a bay way. You should not trying to get the result out of the Executor, because it is only responsible for scheduling and executing tasks, not whats happening inside of them.
Your TareaActualizacion runnable should post the result to another piece of code, where you need it. This can be achieved using a queue or in the easiest case SwingUtilities.invokeLater().

Custom Callback Handler

I am trying to understand mechanism of callback handler. How is the handle() method invoked? Can anybody give an example of usage of custom callback handler (other than those used in Login Modules of JASS or so) in non Swing application?
Define an interface to handle the callback.
public interface ServiceListener<T> {
void callback(T result);
}
Define a method that takes ServiceListener as parameter and returns void.
Public void runInBackground(ServiceListener listener) {
...code that runs in the background...
listener.callback(...data to return to caller...);
}
And you can now do this from your main code:
runInBackground(new ServiceListener() {
#Override
public void callback(..returned data...) {
...Do stuff with returned data...
}
});
This is a basic example for requesting data from a webserver using the AsyncTask from an Android application.
First define the async class. Note that the constructor takes a listener which we use to publish the result once ready.
public class Webservice extends AsyncTask<String, Void, String> {
private DialogListener dialogListener;
public Webservice(final DialogListener dialogListener) {
this.dialogListener = dialogListener;
}
#Override
protected String doInBackground(final String... strings) {
// We cant trigger onComplete here as we are not on the GUI thread!
return "";
}
protected void onPostExecute(final String result) {
dialogListener.onComplete(result);
}
}
Basic server class for handling various network communications:
public class Server {
public void queryServer(final String url, final DialogListener service) {
// Simulate slow network...
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Webservice(service).execute(url);
}
}
We can now use this code inside our activity without having to worry how long the call takes as it is not going to halt the GUI as it is executed async.
Server s = new Server();
// Async server call.
s.queryServer("http://onto.dk/actions/searchEvents.jsp?minLatE6=55640596&minLngE6=12078516&maxLatE6=55642654&maxLngE6=12081948", new DialogListener() {
#Override
public void onComplete(final String result) {
toast("complete");
}
#Override
public void onError() {
toast("error");
}
});

Categories