Commit transaction then send email - email

In Java, let's say I have a transaction that once it is committed, I want to do another action, in this case, send an email.
Therefore,
try {
transaction.begin()
...
transaction.commit()
// point 1
Utility.sendEmail(...)
} catch (Exception e) {
transaction.rollback();
}
Is it possible for the thread to die/get killed at point 1 and not send an email ?
Any way to minimize this ? JTA + JMS perhaps, where the action of sending a message is part of a transaction ?
I'm investigating an issue and exploring whether this is possible. JVM is still alive (no OOM). I do not know the inner working of the app server so not sure if this is possible.

I can't say for sure if the rollback() in the catch clause has any effect if the commit() was OK and sendEmail() threw an exception. The quickest way to test this is to throw an exception from the sendEmail() method and see if the transaction was actually committed.
The way I would put it though, is to move the sendEmail() call away from your try block:
try {
transaction.begin()
...
transaction.commit()
} catch (Exception e) {
transaction.rollback();
}
try {
// point 1
Utility.sendEmail(...)
} catch (Exception e) {
// handle it
}
This way you can control what will happen if a rollback was made.
Also, I think that sending the email to a JMS queue is in most cases a good idea. Doing it like that will give your DB code permission to continue and supposedly give feedback to your user that everything went OK and the email will be sent whenever it fits the email controller's schedule. For example, there might be a connection issue with your email server and the email sending would hang for say 30 seconds before throwing an exception and your user would see this as a very long button click.

Related

kafka producer blocking on callback

I'm testing the async send() in my kafka producer.
The cluster I want to connect to is offline.
My assumption would be that I send 10000 individual requests (lenght of listToSend) quickly.
Next the timeout (60s) would kick in and after 60 seconds I would see the callbacks hit me with logger.error(s"failed to send record ${x._2}", e)
However it seems to take forever for the method to finish.
That's why I added in the logger.debug("test: am I sending data") line.
It prints, then nothing happens for 60 seconds. I see the failed callback for the 1st record. And only then will it move on.
Is this normal behavior or am I missing something fundamental?
listToSend.foreach { x =>
logger.debug("test: am I sending data")
// note: I added this 'val future =' in an attempt to fix this, to no avail
val future = producer.send(new ProducerRecord[String, String](topic, x._2), new Callback {
override def onCompletion(metadata: RecordMetadata, e: Exception) {
if (e != null) {
//todo: handle failed sends, timeouts, ...
logger.error(s"failed to send record ${x._2}", e)
}
else { //nice to have: implement logic here, or call another method to process metadata
logger.debug("~Callback success~")
}
}
}
)
}
note: I do not want to block this code, I want to keep it async. However it seems to be blocking on the send() regardless.
The parallelism I never figured out completely.
However it seems like my topic name (I had named it '[projectname here]_connection') was the issue.
Even though I didn't know of any reserved keywords in topic names, this behavior popped up.
Some further experimenting also brought up that a topic name with a trailing space can also cause this behavior. The producer will try to send it to this topic, but the Kafka cluster doesn't seem to know how to deal with it, causing these timeouts.
So for all of you who come across this issue, check/change your topic name before proceeding your troubleshooting.

Spring Cloud Netflix: Remote service error handling with Feign

We are trying to put Spring Cloud Netflix into production environment. For now we encounter a problem about business logic error handling.
We're using Feign as HTTP REST client. Microservice A needs to invoke microservice B which is deployed in different JVM(or physical server). Microservice B may return some error message which belongs to business. For instance A needs to query order information from B but the order ID may not exist so B has to return the error message that tells A this order doesn't exist. A has to do if-else judgement from the return message to determine if there are erorrs, then code will be like the following snippet:
//remoteServiceA is an interface annotated with #FeignClient
resultA = remoteServiceA.foo();
if (resultA.hasError) {
} else {
}
resultB = remoteServiceB.foo();
if (resultB.hasError) {
} else {
}
// ... ...
There are so many if-else so that it's not graceful enough. What we want is remoteServieA.foo() can throw a self-defined runtime exception such as OrderNotExistException. Any idea to achieve this goal?
I've solved this problem.
I customized the ErrorDecoder component of Feign, in which I can throw my own exception according to the HTTP original response.
If you have Hystrix enabled, you should be able to wrap you serviceA.foo() in a try block and throw an exception in your remote service.
try {
serviceA.foo();
} catch(HystrixRuntimeException ex) {
throw new OrderNotExistException("Error message");
}
You still have to take in account that you can catch that kind of exception if your remote service doesn't answer, or if an other error happens. Maybe you can find information the exception about what happened and decide if you should throw your exception.
First thing that comes to my mind but work in one of my project.

AndroidAsync TCP -- proper way to detect socket is no longer available using write?

I am wondering what is the proper way to check on the client side that a TCP socket opened using the AndroidAsync library is no longer available? This is in the case the (plain TCP, non-AndroidAsync) server did not initiate explicitly closing the socket (so the ClosedCallback is not invoked). For instance, when the server has been cold rebooted.
It seems that the DataCallback is available only when the server sends back data and can't be used to receive error messages.
It seems to me also that
Util.writeAll(socket, (byte[]) payload.array(), new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
if (ex != null)
{
Log.e(TAG, "write failed with ex message= " + ex.getMessage());
throw new RuntimeException(ex);
}
}
});
does not throw an Exception either.
So at this point I'm not sure how to detect the socket is no longer available even if the client periodically writes data to it.
It will throw an IOexception if you send enough data or call it enough times. It won't throw on the first call due to TCP buffering at both ends.
I ended up implementing some sort of a "ping"-alike periodic check. The client opens and immediately closes a TCP connection to the very same port using a plain Java NIO socket call (not using AndroidAsync). If that one times out, it is assumed that the connection has been lost, and a recovery attempt is made once it succeeds again. This periodic check is performed only when the app has focus, or is just awakened. This is clearly a far from ideal workaround but it seems to work for my purposes.
You could use the closed/end callbacks
socket.setClosedCallback(new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
}
});
socket.setEndCallback(new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
}
});

Quickfix/J - do I need to call Session.lookupSession(sessionId).logon();

Is it neccessary to call this line
Session.lookupSession(is).logon();
in this code
socketInitiator.start();
SessionID sessionId = socketInitiator.getSessions().get(0);
Session.lookupSession(id).logon();
while (!Session.lookupSession(id).isLoggedOn()) {
System.out.println("Waiting for login success");
Thread.sleep(500);
}
what is its purpose, as when I omit it, it still gets by the while loop.
EDIT_________________
I was using this in a unit test
socketInitiator.start();
SessionID sessionId = socketInitiator.getSessions().get(0);
Session.lookupSession(id).logon();
while (!Session.lookupSession(id).isLoggedOn()) {
System.out.println("Waiting for login success");
Thread.sleep(500);
}
System.out.println("Logged In...booking SingleOrder from session: " + sessionId);
//check that the party receives the fix message
assertTrue(isBookSingleOrderReceivedFromFixInbound(sessionId));
I have no idea what that function is for, or why it even exists. (I could look it up, sure, but I'm just saying that I've never had to use it.)
The start() call should cause the initiator to start attempting logins (assuming the current time is in the defined session). You shouldn't even have a while loop like this.
You should just call start(), and then do nothing. If logon succeeds, you'll see the FromApp and FromAdmin callbacks start to get triggered for incoming messages (including your logon response).

Recursive Calls to toApp in my Quickfix/J Application implementation

I'm doing something like this in my Quickfix/J Application implementation:
public void toApp(Message message, SessionID sessionID) throws DoNotSend {
try {
Session.sendToTarget(message, sessionID);
} catch (SessionNotFound e) {
e.printStackTrace();
}
}
but the code in Session.Java itself calls application.toApp(message, sessionID);
in the method
private boolean sendRaw(Message message, int num) {
what is the correct way to send messages?
The toApp method is a callback function that is called whenever a message is sent to the counterparty. Looking at your code, I feel that your logic is recursive in itself. SendToTarget calls toApp and toApp calls sendToTarget. A simple way to send messages is to use the concrete session object, say mySession. Then you may do mySession.send(Message).
If you are trying to send a message in response to a received message, you'll want to do that in the fromApp callback method instead.
The toApp callback is for outgoing messages. This can be useful if you want to do some extra validation or risk management on outgoing messages. If you don't want to send the message, then throw a DoNotSend exception.