I don't understand when AsyncListener#onError method is called.
Javadoc doesn't help:
Notifies this AsyncListener that an asynchronous operation has failed to complete.
How could it fail? How can I reproduce this error?
UPDATE:
// in HttpServlet doGet method
AsyncContext asyncContext = req.startAsync();
asyncContext.addListener(new AsyncListener() {
// some code
#Override
public void onError(AsyncEvent event) {
// when is it called?
}
});
executeInSomeOtherThread(asyncContext);
What do I need to do in other thread to fail this async operation?
onError will be called if there was an Exception thrown while carrying out the asynchronous operation.
They are typically Throwables that extend java.io.IOException caused by I/O failures because of an unreliable connection or protocol level exceptions due to a logical error because of a mismatch between the client and the server.
You can get the Throwable when onError is invoked by calling:
event.getThrowable();
EDIT to address mjaggard's follow-on questions
Forgetting about AsyncContext for a second, consider the following class:
public class MyRunnableClass implements Runnable {
private Listener mListener;
interface Listener {
void onError(Throwable error);
}
public void setListener(Listener listener) {
mListener = listener;
}
#Override
public void run() {
// Some important code to be executed goes here
// Pretend an exception was caught in a try/catch/finally
// block that was doing an I/O operation
Throwable someError = new IOException();
if (mListener != null) {
mListener.onError(someError);
}
}
}
Is it more clear now how the listener's onError method will be invoked because an exception was raised when MyRunnableClass's run method was invoked?
MyRunnableClass mrc = new MyRunnableClass();
mrc.setListener(new Listener() {
#Override
public void onError(Throwable error) {
}
});
Executors.newSingleThreadScheduledExecutor().schedule(mrc, 1000L, TimeUnit.MILLISECONDS);
This is no different from how an AsyncContext holds onto a listener and notifies it if it encounters an exception that it wishes to report to the listener. How the run method gets invoked is really secondary to the fact that the owner of the code being executed is also the one that holds a reference to the listener.
Related
I am writing some tests for some rest api, i have a dispatcher that diapctch my rest request to a WebClient from vertx, in some cases i want to wait for the response from the rest api to return before i can continue further with my assertions, the code that dispatch the requests is wrapped inside other classes, so i am not directly making those requests from the tests, i have 2 implementations from my request dispatcher,one for production and one for tests, the tests dispatcher looks like this :
public class TestRequestDispatcher extends AbstractRequestDispatcher {
#Override
protected void dispatchRequest(ServerRequest request, ServerRequestEventFactory requestEventFactory) {
request.getSender()
.send(request,
new ServerRequestCallBack() {
#Override
public <T> void onSuccess(T response) {
requestEventFactory.makeSuccess(request, response).fire();
}
#Override
public void onFailure(FailedResponseBean failedResponse) {
requestEventFactory.makeFailed(request, failedResponse).fire();
}
});
}
}
this should then call some code that builds a WebClient and call its send method to send the request to the server.
And in order to wait for the response i decided to use the CountDownLatch and modified my code to the following
public class TestRequestDispatcher extends AbstractRequestDispatcher {
#Override
protected void dispatchRequest(ServerRequest request, ServerRequestEventFactory requestEventFactory) {
CountDownLatch requestWait = new CountDownLatch(1);
request.getSender()
.send(request,
new ServerRequestCallBack() {
#Override
public <T> void onSuccess(T response) {
requestWait.countDown();
requestEventFactory.makeSuccess(request, response).fire();
}
#Override
public void onFailure(FailedResponseBean failedResponse) {
requestWait.countDown();
requestEventFactory.makeFailed(request, failedResponse).fire();
}
});
try {
requestWait.await(20, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
I am using a large timeout here to make sure that the response should return before the timeout is up, so what happens is that i can breakpoint and see the WebCLient.send method being called, and then it pauses at requestWait.wait(...) but the callbacks are never invoked until the CountDownLatch time out is up. while i was expecting the WebClient to send the request and when ever the response is returned it will invoke the callbacks which in return will count down and break the wait before the timwout is up.
Testing with a normal thread things seems to work, i created some runnable class with some sleep period ..less that the CountDownTime latch. like the the following
public class SenderWorker implements Runnable {
private CountDownLatch countDownLatch;
public SenderWorker(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
#Override
public void run() {
try {
Thread.sleep(5000L);
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
then in the dispatcher :
public class TestRequestDispatcher extends AbstractRequestDispatcher {
#Override
protected void dispatchRequest(ServerRequest request, ServerRequestEventFactory requestEventFactory) {
CountDownLatch requestWait = new CountDownLatch(1);
new Thread(new SenderWorker(requestWait))
.start();
try {
requestWait.await(20, TimeUnit.SECONDS);
System.out.println("i am here");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
And this works.. it calls the run method..the sleeps, then call the requestWait.wait(..) and after 5 seconds it breaks out of the wait.
I tried to execute the code that calls the WebClient inside an executeBlocking and also tried the runOnContext and even tried to run it inside a thread just like how i did with the SenderWorker but still the same result .. the WebClient is blocked until the timeout is up.
Any idea what i am doing wrong here and how i can make this works.?!
You may want to consider vertx-unit or vertx-junit5 for testing asynchronous code with Vert.x.
Other than that asynchronous operations should be composed rather than spinning threads and waiting for count-down latches. Vert.x offers several options to do that:
callbacks chaining
future composition
RxJava (1 and 2)
Kotlin coroutines
Quasar.
I need a functionality that would allow to push asynchronously messages to my PublishSubject and to process them at a certain pace (actually one by one) via a ConnectableObservable. Unfortunately it seems that the call to onNext of the PublishSubject is not released until the underlying Subscriber processes the message.
It takes good few seconds to process each message and in debug mode I see that it executes before invocation of the method that pushes the message to PublishSubject is removed from stack - "After push..." always appear in console after internal logs inside the Subscriber...
So I have this RestEndpoint:
#PUT
#Path("{id}")
#TokenAuthenticated
public Response postResource(#PathParam(value="id") final String extId) {
executorService.execute(new Runnable() {
#Override
public void run() {
try {
Message metadata = processor.apply(extId);
log.info("Before push...");
dataImporter.pushData(metadata);
log.info("After push...");
} catch (Exception e) {
e.printStackTrace();
}
}
});
return Response.ok("Request received successfully").build();
}
Here's the constructor of the DataImporter:
public DataImporter(final String configFile) {
dataToImportSubject = PublishSubject.create();
dataToImportObservable = dataToImportSubject.publish();
dataToImportObservable.connect();
dataToImportObservable
.onBackpressureBuffer(1, new Action0() {
#Override
public void call() {
logger.debug("Buffer full...");
}
})
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<Message>() {
#Override
public void onCompleted() {
// TODO Auto-generated method stub
}
#Override
public void onError(Throwable e) {
logger.error("Error importing "+e.getMessage());
}
#Override
public void onNext(Message value) {
request(1);
importResult(configFile, value);
}
#Override
public void onStart() {
request(1);
}
});
}
Then pushData of DataImporter is just pushing to PublishSubject's onNext method..:
public void pushData(Message metadata) {
dataToImportSubject.onNext(metadata);
}
And here're the declaration of PublishSubject and ConnectableObservable:
public class DataImporter implements ImporterProxy{
private final PublishSubject<Message> dataToImportSubject;
private final ConnectableObservable<Message> dataToImportObservable;
PublishSubjects emit to their consumers on the thread of the original onXXX call:
JavaDocs
Scheduler:
PublishSubject does not operate by default on a particular Scheduler and the Observers get notified on the thread the respective onXXX methods were invoked.
You have to move the processing to some other thread with observeOn because the observeOn can move the onXXX calls to another thread.
subscribeOn does not have any practical effect on Subjects in general because it only affects the subscription thread, and won't modulate the subsequent onXXX calls to those subjects.
RxJava, by default, is synchronous. You need to introduce operators into your observer chain to perform actions on other threads. When you read the documentation on each operator in Observable, you will see statements like "... does not operator on a particular scheduler" -- this indicates that data flows through that operator synchronously.
To get an observer chain to perform actions on other threads, you can use an operator like subscribeOn() with a scheduler to have operations performed on that scheduler. In your example, you likely will want to use Schedulers.io() to provide a background thread.
I was reading AsyncTask.java and there are few places that I can't understand.
What does this code actually do? Judging by the comment it should create the handler, but I can't get how it can do this. The method getLooper() in the Handler class just returns the handler, so there is no way I can see it can initialize a new handler.
/** #hide Used to force static handler to be created. */
public static void init() {
sHandler.getLooper();
}
Why putting postResultIfNotInvoked() in the overriden done() method? How can it be not invoked? If I understand this right, first the call() method of mWorker will be called and then mTaskInvoked is guaranteed to be true.
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
//...
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
#Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
init() isn't really used in regular code.
It can be used in platform test code - calling it first makes the class loader initialize the static members on the current thread. It's useful to making sure the Handler is created on the main UI thread while tests run on a background thread for example.
Because of #hide, it's not usable in code written with SDK's stub version of android.jar.
This is there to fix a bug to make sure onCancelled() is called if cancel() is called early.
I am trying to catch all unhandled exceptions that occur in a service
that runs in a separate process. In the onCreate for the service, I call
a method that calls Thread.setDefaultUncaughtExceptionHandler with
MyCustomExceptionHandler class. My examination of the logs indicates
that it is set but does not consistently get called for uncaught
exceptions. For example, when I hard code a divide by zero into the
service, it does not get called at all. Another example is a
NullPointerException that I forced which resulted in a call to my
handler but the stack trace did not point to the actual lines of code
that caused the exception.
public class ActivityEngineService extends android.app.Service {
/** Called when the service is first created. */
#Override
public void onCreate() {
super.onCreate();
setUncaughtExceptionHandler();
// Get the service that has a hard coded divide by zero running
}
public void setUncaughtExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());
System.out.println("Thread.getDefaultUncaughtExceptionHandler(): " + Thread.getDefaultUncaughtExceptionHandler());
}
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
public CustomExceptionHandler() {
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
public void uncaughtException(Thread t, Throwable e) {
System.out.println("CustomExceptionHandler uncaughtException e: " + e.getMessage());
defaultUEH.uncaughtException(t, e);
}
}
}
According to javadoc:
Sets the default uncaught exception handler. This handler is invoked in case any Thread dies due to an unhandled exception.
As far as I know in your case whole process is dying, that's why uncaughtException does not invoke. It will invoked if you will have uncaught exceptions inside separate threads.
I want to catch all uncaught exceptions and bring up a dialog. First I removed the default exception handler from NetBeans and added my handler as default handler:
java.util.logging.Logger global = java.util.logging.Logger.getLogger("");
for (Handler handler : global.getHandlers()) {
if (handler.getClass().getName().equals("org.netbeans.core.startup.TopLogging$LookupDel"))
{
global.removeHandler(handler);
break;
}
}
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
The handler looks like this:
public static final class ExceptionHandler implements UncaughtExceptionHandler
{
#Override
public void uncaughtException(Thread thread, Throwable throwable)
{
logger.error(throwable.getMessage(), throwable);
ExceptionViewPanel.showException(throwable);
}
}
With that construct, I can only catch exceptions which are thrown outside the EDT. I've read about ThreadGroups, but I can't use that solution due we use NetBeans with Maven and so I can't wrap the start thread with a ThreadGroup. The hack from pre-1.7 is also no longer possible and overwriting the EventQueue has no effect.
I've tried many solutions, none of them worked. Does anyone has another solution for me that might work?
Thanks in advance
Teazl
In my own project I've superseded NetBeans error handler to my own. My example:
#ServiceProvider(service = Handler.class, supersedes = "org.netbeans.core.NbErrorManager")
public class MyHandler extends Handler {
#Override
public void publish(LogRecord record) {
if (record.getThrown() != null) {
record.getThrown(); // do with it something
}
}
#Override
public void flush() {
}
#Override
public void close() throws SecurityException {
}
}
See also org.netbeans.core.NbErrorManager and org.netbeans.core.NotifyExcPanel to know how NetBeans uses default handler.
You only need to add this class in your project.