We are using Akka framework for inter process communication. Some days back QA team identified some requests which got stuck in limbo. For some requests both onSuccess() and onFailure() callback methods were not called. The last line of log showed
"Charging Customer."
and the flow for that particular transaction stopped there. The next log should be either
"Charging response or Charging Failed"
What could be the reason for such behaviour? Could it be due to the dispatcher getting choked? We are using the default dispatcher.
Code
log.debug("Charging Customer");
Future future = Patterns.ask(actorSelection, new Gson().toJson(request), timeout);
future.onSuccess(new onChargingSuccess<>(ccRequest), context().system().dispatcher());
future.onFailure(new onFailureHandler(ccRequest), context().system().dispatcher());
private class onChargingSuccess<T> extends OnSuccess<T> {
#Override
public void onSuccess(T t) throws Throwable {
log.debug("Charging response:" + t.toString());
}
private class onFailureHandler extends OnFailure {
#Override
public void onFailure(Throwable thrwbl) throws Throwable {
log.info("Charging Failed");
}
Well its not really a solution but restarting the module fixed the issue. The module was running for an year. I know this makes it a very general question now but i'll keep it here just in case we dig down the actual issue and find the solution. I'll update in that case.
Related
My project uses the Java Netty framework to transfer messages. The application is both a client and a server. When we send a message to the remote server, we want to do some processing of this message. I use ChannelOutboundHandler.write() in my project to achieve this purpose:
public class MyOutBoundHandler extends ChannelOutboundHandlerAdapter{
#Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
process((ByteBuf) msg); // do some processing of this message
ctx.write(msg, promise);
}
}
I found a problem that when the process((ByteBuf) msg) method throws an exception, it will cause blocking, and the next method ctx.write(msg, promise) will not be executed. So how to make them asynchronous cause I hope the process((ByteBuf) msg) will not affect the writing of messages to the remote server.
If 'ctx.write(msg, promise)' does not rely on the result of the 'process((ByteBuf) msg)', you can just wrap the 'process((ByteBuf) msg)' in a runnable task and submit the task to the ThreadPool.
found a problem that when the process((ByteBuf) msg) method throws an exception, it will cause blocking, and the next method ctx.write(msg, promise) will not be executed
Unless you executing blocking code, netty will not block.
Behavior you are explaining is not blocking, it is just how control flow in java works. If an exception is thrown, none of the subsequent code will be executed unless you explicitly catch and resume.
Ideally, in your case, you want to add a try-catch block around the call to process() and if it fails, fail the promise using promise.tryFailure()
you can just add a listener for the ChannelPromise before process method was called。
refer to the following code here :
promise.addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
//process happed exception will be here and you can call ctx.write(msg)
//to keep spreading forward the write event in the pipeline
ctx.write(msg);
} else {
// when msg has been write to socket successfully, netty will notify here!!
}
}
});
process(msg);
I have an HTTP request that triggers a long-running task (multiple HTTP requests to another service) that is supposed to be completed in the background while the original requests complete.
So what I do is
public void triggerWork(#RequestBody SomeObject somObject) {
return new ResponseEntity<>(startWorkAndReturn(somObject), HttpStatus.OK);
}
public void startWorkAndReturn(SomeObject someObject) {
Observable.create(observableEmitter -> {
// do the work with someObject here and at some time call
observableEmitter.onNext("result");
}).subscribe(new Observer<Object>() {
#Override
public void onSubscribe(Disposable disposable) {
}
#Override
public void onNext(Object o) {
// called at some unknown time
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onComplete() {
// currently not used as all the work is done in onNext but maybe that's a mistake
}
});
return;
}
But this seems to block the request until all the work has been done. Which already seems odd to me, since I never call onComplete, which in itself might be a mistake. But still, I am wondering how to create a request that immediately returns after triggering a background worker.
Is Flowables the solution here? I am going to refactor to those anyways to handle backpressure. Or do I need to create a background worker Thread? What is the best practice here?
Thanks
I would use Observable.fromCallable{} since you need emit only single event. That will handle onCompleate call. From information you share I don`t know how can you properly handle disposable. You should add subscribeOn() and observeOn() operators that will define on which thread 'work' should be processed and result should be observed.
Docs ref:
http://reactivex.io/RxJava/javadoc/io/reactivex/Observable.html#fromCallable-java.util.concurrent.Callable-
http://reactivex.io/documentation/operators/subscribeon.html
http://reactivex.io/documentation/operators/observeon.html
I want to register a callback for the future object returned from spring kafkatemplate.send().
ListenableFuture<SendResult<K, V>> org.springframework.kafka.core.KafkaTemplate.send(String topic, K key, V data)
I invoke below method on the future result of the above method.
void org.springframework.util.concurrent.ListenableFuture.addCallback(ListenableFutureCallback<? super T> callback)
like this:
kafkaTemplate.send(topicname, keyString, data).addCallback(
new ListenableFutureCallback<SendResult<String, Data>>() {
#Override
public void onFailure(Throwable ex) {
logger.error("Failure while sending message in kafka.", ex);
}
#Override
public void onSuccess(SendResult<String, Data> result) {
logger.info("Successfully sent message to kafka");
}
});
Suppose if send() completes the actual sending very fast and result is already set in future before me registering the callback. My callback registration will happen after the future.set() operation. So, there is a chance that my callback don't get executed. Isn't this a possibility?
I know such a possibility is very less. Still, can this happen? If so, what is the solution.
No, the future deals with that by immediately calling the callback after adding it, if it has already been satisfied - look at the source code for SettableListenableCallback.addCallback().
OkHttp library Callback interface is declared as
public interface Callback {
void onFailure(Request request, IOException e);
void onResponse(Response response) throws IOException;
}
Unhandled exceptions from onResponse method will get eaten up by Call class as I have recently discovered in Callback failure for cancelled call in OkHttp
I have few questions related to that design.
First, wouldn't it be better have different declaration of onResponse method in order to force catching exceptions in onResponse rather than throwing them, since they will be eaten up.
Is this design flaw in OkHttp Callback interface or is this kind of code common practice in Java?
Second, when http request reaches onResponse callback method I would expect that canceling request at that point should be prohibited. I would say this is a bug. Am I right?
I'm also struggling with this, for now I've solved it as follows:
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, final IOException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// AlertDialog, etc.
}
});
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
onFailure(call, new IOException("Unexpected code: " + response));
}
// else success
}
});
The key point is calling OnFailure inside OnResponse. I wasn't able to access the Exception in any other way (though there probably are other ways; this gives OnFailure some additional usefulness in my opinion, and it conveys intent fairly well I think). Note that OnFailure can be called for other reasons: https://square.github.io/okhttp/2.x/okhttp/com/squareup/okhttp/Callback.html
I am creating a websocket application, and I want to perform a one-time time intensive task at program initialization. In creating this application, the recommended practice (https://netbeans.org/kb/docs/javaee/maven-websocketapi.html) is to override the following functions:
#ServerEndpoint(value = "/testendpoint", encoders = {TestEncoder.class}, decoders = {TestDecoder.class})
public class WSEndpoint
{
#OnMessage
public void onMessage(Session wsSession, CommandIn command) throws IOException, EncodeException
{
...
}
#OnOpen
public void onOpen(Session wsSession)
{
...
}
#OnClose
public void onClose(Session wsSession)
{
...
}
#OnError
public void onError(Throwable t)
{
}
}
So when a new connection/session is created, "onOpen" would be called and when a new message is received, "onMessage" is called.
What I want to do is, before letting the user create sessions and send commands (via browser front end), to initialize the subsystem that takes about 20 seconds to initialize. If it's initialized only at "first requested use", as I am doing now, then the user experience gets interrupted. Clearly, there is no "main" function visible here (presumably, called by the websocket framework at a deeper level).
What do you guys recommend I do to achieve what I want to do? Currently, I have the initialization code in a static block in an internal class - which only gets executed once - but gets executed when the class is first "called/used", interrupting the user experience.
Any suggestions?
Thanks.
The best place for initialization code in a web application is inside a ServletContextListener's contextInitialized method.
This way you do your initialization when the application starts.