I have a an application which has a kafka consumer and updates Elastic search according to the data it receives.
My issue is that when ever ES goes down, the kafka consumer stops completely and doesn't restart.
I believe its due to how my ES code is running:
public CompletionStage<SearchResponse> executeSearch(SearchRequest searchRequest) {
CompletableFuture<SearchResponse> f = new CompletableFuture<>();
client.searchAsync(searchRequest, RequestOptions.DEFAULT, new ActionListener<SearchResponse>() {
#Override
public void onResponse(SearchResponse searchResponse) {
f.complete(searchResponse);
}
#Override
public void onFailure(Exception e) {
throw new Exception(); // I am guessing because of this
}
});
return f;
}
If I change my onFailure method to:
public void onFailure(Exception e) {
f.complete(null);
}
It works perfectly but I dont understand why throwing an exception leads to this.
Any help would be greatly appreciated.
For those that need a solution, I changed my code to below for it to work with exception:
public void onFailure(Exception e) {
f.completeExceptionally(new Exception());
}
Also potentially relevant are the exceptionally method and the handle method from CompletableFuture
CompletableFuture.exceptionally((ex)-> ) - https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function-
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#handle-java.util.function.BiFunction-
Related
I am developing an application based on Spring Boot and kafka queues, but when developing the main of the application, it has stopped consuming from the queue and I do not know why.
--Main Application---
#Service
public class ApplicationMainClass implements ApplicationListener<ApplicationReadyEvent> {
#Autowired
PlayerDaoRepository playerDaoRepository;
#Autowired
DataColectorServiceImp dataColectorServiceImp;
#Autowired
BattleDaoRepository battleDaoRepository;
#Autowired
BattleService battleService;
private static final Logger log = LogManager.getLogger(ApplicationMainClass.class);
#Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
List<Playerdao> listPlayersActive;
List<BattleDao> battle;
List<BattleDao> battleDaoAux;
while (true) {
log.info("Comienza la ejecuciĆ³n");
listPlayersActive = playerDaoRepository.findByActive(true);
for (Playerdao player : listPlayersActive) {
try {
String battleString = dataColectorServiceImp.apiConexion(player.getUri());
if (battleString.equals("")) {
continue;
}
battle = player.getBatallasPlayed();
battleDaoAux = battleService.getBattle(battleString);
player.setLastGamePlayed(!battle.isEmpty() ? battle.get(battle.size()-1).getBattletlime() : LocalDateTime.MIN.toString());
battleDaoAux = player.kafkaHandler(battleDaoAux);
battleService.postBattle(battleDaoAux, player.getTag());
player.setBatallasPlayed(player.listBuilder(player.getBatallasPlayed(), battleDaoAux));
battleDaoRepository.saveAll(battle);
playerDaoRepository.save(player);
} catch (Exception e) {
log.error("", e);
}
}
try {
log.info("Termina la ejecucion");
Thread.sleep(60000);
} catch (InterruptedException e) {
}
}
}
}
StreamListener
#StreamListener
public KStream<IdBattle, textBattle>newBattle(#Input(BinderProcessor.battles)KStream<IdBattle,textBattle>battleKStream){
updateDatabase(battleKStream);
return null;
}
private void updateDatabase(KStream<IdBattle, textBattle> battleKStream) {
battleKStream.foreach((IdBattle,textBattle)->{
if(textBattle==null){
playerDaoRepository.deleteById(IdBattle.getIdBattle());
}else{
Battle battle= playerDaoService.textTreatment(textBattle.getText(),Battle);
battle=battleDaoService.setBattleTime(textBattle.getText(),battle);
Event event = playerDaoService.textTreatmentEvent(textBattle.getText(),Event);
battle.setMap(event.getMap());
battleDaoService.updateDatabase(battle,IdBattle.getIdBattle());
}
});
}
}
I don't know how to fix it so that both threads of the application run at the same time, and in fact I don't even know why it has stopped consuming from the queue.
Thank you very much
Good, as we discussed in the comments the bug was based on that we can not make a thread that calls a sleep and a while true, because all the time will be using that thread and will not pass to the next, I have solved it by simply adding the tag "#Scheduled" to the main of the application.
This way we make sure that after the execution of the main we wait "x" seconds for the next execution, leaving resources for the streamListener.
Thank you very much and feel free to correct me if I have made a mistake in the explanation.
I am using Mockito together to JUnit to implement unit tests for a class in an Android project.The problem is that I call Mockito.verify in two consequent tests where the tests are exactly same (to make sure that I am using Mockito correctly) but the interesting thing is that verify in second test always fails.I suspect that some operations need to be done before each test using #before annotation or so, that I have missed.Here are some code snippet about what I am doing.
I use Android Studio 3.4.1, Mockito 2.7.22 and JUnit 4.12.
#Test
public void test_onStart_do_nothing() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
verify(mockedZConnection, times(1)).connect();
}
#Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
// Line above is the line that error message points to!
verify(mockedZConnection, times(1)).connect();
}
Here comes the function under test
public void initConnection(ZConnection connection) {
Log.d(TAG,"initConnection()");
if (mConnection == null) {
mConnection = connection;
}
if (!mActive) {
mActive = true;
if (mThread == null || !mThread.isAlive()) {
mThread = new Thread(new Runnable() {
#Override
public void run() {
// The code here runs in a background thread.
Looper.prepare();
mTHandler = new Handler();
try {
mConnection.connect();
} catch (IOException e) {
Intent i = null;
i = new Intent(ZConnectionService.UI_NOTCONNECTED);
i.setPackage(getApplicationContext().getPackageName());
getApplicationContext().sendBroadcast(i);
e.printStackTrace();
// Stop the services all together.
stopSelf();
}
Looper.loop();
}
});
mThread.start();
}
}
}
I expect that both tests should pass without any problem. In fact, both tests are passed when I ran them individually, but they fail when I run the whole suite and the error is:
Wanted but not invoked:
mockedZinkConnection.connect();
-> at com.app.z.ZConnectionServiceUnitTest.test_onStart_throw_IO_exceptioon(ZConnectionServiceUnitTest.java:207)
Actually, there were zero interactions with this mock.
I think the issue is a multithreading one.
When you call initConnection, it calls mConnection.connect() in a Thread
The problem you are having is that this Thread takes some time to complete and you end up calling verify(mockedZConnection, times(1)).connect(); before the Thread actually reached the connect() call.
A way to make sure about it is to join the Thread after you start it, it will wait until the Thread has finished before continuing:
mThread.start();
try {
mThread.join();
} catch (InterruptedException i) {
i.printStackTrace();
}
Now both tests should work.
This of course is not acceptable in the code, because it negated the use of a Thread. You will need an other way to test it.
A way I can think of would be to wait for the Thread to complete in your test before checking the mock:
#Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
// Wait for the Thread to complete
while(zConnectionService.mThread.isAlive()) {
Thread.sleep(100);
}
verify(mockedZConnection, times(1)).connect();
}
Tried and it works fine for me. Not sure it is a best practice though as you need to make public some internals of your class, which violates encapsulation
maybe having a package protected isThreadAlive() method on your ZConnectionService class could be acceptable
boolean isThreadAlive() {
return mThread.isAlive();
}
and the loop in the test
while(zConnectionService.isThreadAlive()) {
Thread.sleep(100);
}
I want to know how to prevent the android application from crushing while an execution error happens.
I'm using this project here.
the error occurs when the requests does not find any result or when it takes to much time.
FetchExpression fetchExpression = new FetchExpression(
Utils.getEscapedContactSearchTermFetch(query));
mOrgService.RetrieveMultiple(fetchExpression, new Callback<EntityCollection>() {
#Override
public void success(EntityCollection entityCollection) {
mMainList.setAdapter(new SearchResultsAdapter(getApplicationContext(), entityCollection));
mSwipeRefresh.setRefreshing(false);
}
#Override
public void failure(Throwable error) {
displayError(error.getMessage());
}
});
the method failure does not work in some cases.
How can I prevent this application from crushing.
Thanks,
You should put that block of code in a try catch block and add the error you want to get in the catch block.
try {
some code here
....
} catch(Exception yourException) {
}
In an app I'm developing, I'm using Google Analytics to track uncaught exceptions like so:
// ...after setting up Google Analytics...
Thread.setDefaultUncaughtExceptionHandler(new AnalyticsExceptionHandler(Thread.getDefaultUncaughtExceptionHandler()));
And this is the handler, the AnalyticsExceptionHandler class:
public class AnalyticsExceptionHandler implements UncaughtExceptionHandler
{
// Private
private UncaughtExceptionHandler _defaultHandlerRef;
public AnalyticsExceptionHandler(UncaughtExceptionHandler defaultHandlerRef)
{
this._defaultHandlerRef = defaultHandlerRef;
}
#Override
public void uncaughtException(Thread t, Throwable e)
{
// ...track and send the exception to Google Analytics...
_defaultHandlerRef.uncaughtException(t, e);
}
}
Thing is, the app never actually crashes, it just freezes. If I remove the setDefaultUncaughtExceptionHandler() line then the app crashes normally.
Am I doing something wrong in the above code by passing it to the previous default handler?
Why not re-throw the exception?
public void uncaughtException(Thread t, Throwable e)
{
// ...track and send the exception to Google Analytics...
_defaultHandlerRef.uncaughtException(t, e);
throw e;
}
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.