I have a vertx service for all message-broker related operations. For e.g. an exchange creation function looks like this
#Override
public BrokerService createExchange(String exchange,
Handler<AsyncResult<JsonArray>> resultHandler) {
try {
getAdminChannel(exchange).exchangeDeclare(exchange, "topic", true);
resultHandler.handle(Future.succeededFuture());
} catch(Exception e) {
e.printStackTrace();
resultHandler.handle(Future.failedFuture(e.getCause()));
}
return this;
}
I am in the process of converting my entire codebase into rxjava and I would like to convert functions like these into completables. Something like:
try {
getAdminChannel(exchange).exchangeDeclare(exchange, "topic", true);
Completable.complete();
} catch(Exception e) {
Completable.error(new BrokerErrorThrowable("Exchange creation failed"));
}
Furthermore, I would also like to be able to throw custom errors like Completable.error(new BrokerErrorThrowable("Exchange creation failed")) when things go wrong. This is so that I'll be able to catch these errors and respond with appropriate HTTP responses.
I saw that Completable.fromCallable() is one way to do it, but I haven't found a way to throw these custom exceptions. How do I go about this? Thanks in advance!
I was able to figure it out. All I had to do was this:
#Override
public BrokerService createExchange(String exchange, Handler<AsyncResult<Void>> resultHandler) {
Completable.fromCallable(
() -> {
try {
getAdminChannel(exchange).exchangeDeclare(exchange, "topic", true);
return Completable.complete();
} catch (Exception e) {
return Completable.error(new InternalErrorThrowable("Create exchange failed"));
}
})
.subscribe(CompletableHelper.toObserver(resultHandler));
return this;
}
Related
I have a Kafka consumer that performs some migrations. Pretty simple flow
#KafkaListener(topics="client-migration-blah", groupId="migration-group",
containerFactory="kafkaListnerContainerFactory")
public void consume(ConsumerRecord<String, Object> payload) {
try {
Client client = payload.value();
if( migrationClient.clientExists(client)) {
updateClient(ClientEvent.UPDATE, client);
}
else {
migrationClient.importClient(ClientEvent.CREATE, client);
}
} catch (Exception ex) {
log.error("yada yada yada");
sendToDLQ(ClientEvent.ERROR, client);
}
}
I need a breakup of the three usecases, create, update and error(DLQ). Short of building a streaming (?) solution to collect these aggregates, what would be a simple way to gather these events to extract the breakup?
I am new to asynchronus coding in Java.
This is my code in spring boot application:
public void func(String someString){
if(someString != null){
doAsync(someString);
publish(topic, someString);
}
}
public void doAsync(String someString) {
log.info("Inside do Async");
CompletableFuture.runAsync(() -> {
try {
execute(someString);
} catch (Throwable throwable) {
log.error("Error");
}
}, executorService);
}
private void execute(String someString) {
try {
log.info("Inside Execute");
DBcall(someString);
} catch (Throwable e) {
log.info("Error");
}
}
The func() is being called around 200k times through an event in a Queue, In logs the log Inside do Async appeared for 200k times but the log Inside Execute appeared just for 195k times.
I see no errors/exception occurred in this flow.
Why is it not running consistently for all 200k events? Am I missing something in the implementation?
The publish() function publishes the same message to another subscriber which is in the same service, there are some 10k-11k errors in that subscriber flow(null pointer error). Is error in this flow is main reason behind not executing all async call?
I'm new to vert.x and would like to know if its possible to configure eventbus somehow to make it work consistently?
I mean need to send requests one by one using vert.x
At the moment I got this code which uses eventloop principle and waits until all handlers finished, but I don't need this done that fast, idea is to free server from lots of requests at the same time. Here eb_send() uses default EventBus.send() method. In other words I want to execute all requests with blocking, waiting for answers before requests.
List<Future> queue = new ArrayList<>();
files.forEach(fileObj -> {
Future<JsonObject> trashStatusHandler = Future.future();
queue.add(trashStatusHandler);
eb_send(segment, StorageType.getAddress(StorageType.getStorageType(fileInfo.getString("storageType"))) + ".getTrashStatus", fileInfo, reply -> {
Entity dummy = createDummySegment();
try {
if (reply.succeeded()) {
//succeded
}
} catch (Exception ex) {
log.error(ex);
}
trashStatusHandler.complete();
});
});
The basic idea is to extract this into a function, which you would invoke recursively.
public void sendFile(List<File> files, AtomicInteger c) {
eb_send(segment, StorageType.getAddress(StorageType.getStorageType(fileInfo.getString("storageType"))) + ".getTrashStatus", fileInfo, reply -> {
Entity dummy = createDummySegment();
try {
if (reply.succeeded()) {
//succeded
}
// Recursion
if (c.incrementAndGet() < files.size()) {
sendFile(files, c);
}
} catch (Exception ex) {
log.error(ex);
}
});
}
As per my understanding, I want to follow the best practice for releasing the resources at the end to prevent any connection leaks. Here is my code in HelperClass.
public static DynamoDB getDynamoDBConnection()
{
try
{
dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
}
catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
dynamoDB.shutdown();
}
return dynamoDB;
}
My doubt is, since the finally block will be executed no matter what, will the dynamoDB returns empty connection because it will be closed in finally block and then execute the return statement? TIA.
Your understanding is correct. dynamoBD.shutdown() will always execute before return dynamoDB.
I'm not familiar with the framework you're working with, but I would probably organize the code as follows:
public static DynamoDB getDynamoDBConnection()
throws ApplicationSpecificException {
try {
return new DynamoDB(new AmazonDynamoDBClient(
new ProfileCredentialsProvider()));
} catch(AmazonServiceException ase) {
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
throw new ApplicationSpecificException("some good message", ase);
}
}
and use it as
DynamoDB con = null;
try {
con = getDynamoDBConnection();
// Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
// deal with it gracefully
} finally {
if (con != null)
con.shutdown();
}
You could also create an AutoCloseable wrapper for your dynamoDB connection (that calls shutdown inside close) and do
try (DynamoDB con = getDynamoDBConnection()) {
// Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
// deal with it gracefully
}
Yes,dynamoDB will return an empty connection as dynamoBD.shutdow() will be executed before return statement, Always.
Although I am not answering your question about the finally block being executed always (there are several answers to that question already), I would like to share some information about how DynamoDB clients are expected to be used.
The DynamoDB client is a thread-safe object and is intended to be shared between multiple threads - you can create a global one for your application and re-use the object where ever you need it. Generally, the client creation is managed by some sort of IoC container (Spring IoC container for example) and then provided by the container to whatever code needs it through dependency injection.
Underneath the hood, the DynamoDB client maintains a pool of HTTP connections for communicating the DynamoDB endpoint and uses connections from within this pool. The various parameters of the pool can be configured by passing an instance of the ClientConfiguration object when constructing the client. For example, one of the parameters is the maximum number of open HTTP connections allowed.
With the above understanding, I would say that since the DynamoDB client manages the lifecycle of HTTP connections, resource leaks shouldn't really be concern of code that uses the DynamoDB client.
How about we "imitate" the error and see what happens ? This is what I mean:
___Case 1___
try{
// dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
throw new AmazonServiceException("Whatever parameters required to instantiate this exception");
} catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
//dynamoDB.shutdown();
slf4jLogger.info("Database gracefully shutdowned");
}
___Case 2___
try{
// dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
throw new Exception("Whatever parameters required to instantiate this exception");
} catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
//dynamoDB.shutdown();
slf4jLogger.info("Database gracefully shutdowned");
}
These exercise could be a perfect place to use unit tests and more specifically mock tests. I suggest you to take a close look at JMockit, which will help you write such tests much more easily.
I execute my async function and before the result I reload the browser I get error - OnFailure(Throwable) is executed. Status error code is 0.
This problem is on FireFox and Chrome.
Could you tell me what this status code means.
do(new AsyncCallback<Boolean>() {
#Override
public void onSuccess(Boolean result) {}
#Override
public void onFailure(Throwable throw) {
do_sth();
}
});
Boolean do() { while(true); }
That also return status error 0
The 0 status code here means the request has been aborted (it could also denote a network error, or the request timed out).
See http://www.w3.org/TR/XMLHttpRequest/#the-status-attribute and http://www.w3.org/TR/XMLHttpRequest/#error-flag
You could always define your onFailure() like this (adapted from the GWT API) to be able to handle different kinds of failure nicely:
public void onFailure(Throwable caught) {
try {
throw caught;
} catch (IncompatibleRemoteServiceException e) {
// this client is not compatible with the server; cleanup and refresh the
// browser
} catch (InvocationException e) {
// the call didn't complete cleanly
} catch (YourOwnException e) {
// take appropriate action
} catch (Throwable e) {
// last resort -- a very unexpected exception
}
}