How to handle Transaction timeout with #TransactionTimeout - java

I do have method:
#TransactionTimeout(value = 1, unit = TimeUnit.SECONDS)
#Asynchronous
public void asyncMethod() {
System.out.println("start running asyncMethod in thread " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finished running asyncMethod in thread " + Thread.currentThread().getName());
}
As you can see I running this in Transaction and timeout is set to 1 second and inside I have 3 second sleep. So as a result of running this method I am gettin:
javax.transaction.RollbackException
But let say I would like to implement service which will print information that transaction timeout has occured to the user. How could I achieve that?
#Glains gave me some advice in comment to use Interceptor.
I have added something like that:
#Interceptor
public class LoggingTimeoutInterceptor {
#AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
try {
System.out.println("Logger interceptor");
System.out.println("method " + ctx.getMethod().getName());
return ctx.proceed();
}catch (RollbackException e) {
System.out.println("Transaction RollbackException occured");
return null;
}
catch (Exception e) {
System.out.println("Exception occured");
return null;
}
}
}
This code is writing first two sysout correctly. But is not catching any exception and I dont know why. I was trying to change #AroundInvoke to #AroundTimeout but then it is not running at all.

Related

How to set timeout in a method in Java and retry method for a periodic amount of time

I java a java method, which makes a connection to a web service.
Sometimes this method takes too long to make the connection.
I want for example it it takes longer than 5 seconds, then to stop the current procedure and restart all over for 3 more times. If all times fail, then abort completely.
I have written the following until now:
private ConnectionInterface connectWithTimeout() throws MalformedURLException, Exception {
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() throws InterruptedException, MalformedURLException, Exception {
return connectWithNoTimeout(); //This is the method that takes to long. If this method takes more than 5 seconds, I want to cancel and retry for 3 more times. Then abort completely.
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
System.out.println( "Timeout Occured");
} catch (InterruptedException e) {
System.out.println( " "InterruptedException Occured");
} catch (ExecutionException e) {
System.out.println( ""ExecutionException Occured");
} finally {
future.cancel(true); // here the method gets canceled. How do I retry it?
}
System.out.println( "Connected !!");
return connectWithNoTimeout();
}
private ConnectionInterface connectWithNoTimeout() throws MalformedURLException, Exception {}
Your method already has a 5 seconds timeout. All you need to do now is to add some kind a loop with 3 repeats. You need a counter of timeouts and a break after successful attempt. Not sure what you want to do when other exceptions happen, added breaks there as well. Following code should do the job:
private ConnectionInterface connectWithTimeout() throws MalformedURLException, Exception {
int repeatCount = 0;
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() throws InterruptedException, MalformedURLException, Exception {
return connectWithNoTimeout(); //This is the method that takes to long. If this method takes more than 5 seconds, I want to cancel and retry for 3 more times. Then abort completely.
}
};
while (repeatCount < 3){
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
break;
} catch (TimeoutException ex) {
repeatCount++;
System.out.println( "Timeout Occured");
} catch (InterruptedException e) {
System.out.println( " "InterruptedException Occured");
break;
} catch (ExecutionException e) {
System.out.println( "ExecutionException Occured");
break;
} finally {
future.cancel(true); // here the method gets canceled. How do I retry it?
}
}
System.out.println( "Connected !!");
return connectWithNoTimeout();
}
First of all, I'd put the execution of that long command into a new thread so it will not block the Main Thread with the UI etc.
an approach:
Thread thr = new Thread() {
public void run() {
boolean error =false;
boolean success=false;
int time =0;
try {
while(tries<3&&!success){
//HERE GOES YOUR METHOD (connectWithNoTimeout(); ?)! Make sure to make the boolean "Success" = true if the connection is established
while (!error&&time<3) {
time++;
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
};
It's mostly written by hand, you need to make changes, copy & paste will not work

How to make TestNG continue test execution on an exception?

When i get an exception, the test run immediately ends, and any following test validations are skipped. I would like to catch the exception, handle it, then continue the workflow.
In the below example, If objPage.Method1(); throws an exception, the entire #Test immediately ends. I would like the catch to execute, then move on to objPage.Method2().
#Test (enabled=true)
public void MyClientsFunctions() throws Exception {
ExtentTest t = ReportFactory.getTest();
try {
Login objPage = new PageObject(driver);
//this method throws exception
objPage.Method1();
if (x=y)
t.log(LogStatus.PASS, "Pass message");
else
t.log(LogStatus.FAIL,"Fail message"+ screenshotMethod());
objPage.Method2();
if (a=b)
t.log(LogStatus.PASS, "Pass message");
else
t.log(LogStatus.FAIL,"Fail message"+ screenshotMethod());
} catch (Exception e) {
t.log(LogStatus.ERROR, "Exception found: " + e.getMessage() + screenshotMethod());
}
}
I am using PageFactory and ExtentReports. I am use if statements to report failures. No asserts. I believe if an assert fails, the result is the same, and the test ends.
Write the objPage.Method2() in final block then it will execute.
Credit to #JeffC for pointing me in the right direction.
For my case, I have at least a dozen action methods called from the Page Object class. I can't put them all in their own final block.
What I did was put each workflow (one or more methods, then validation) in it's own try/catch. The catch includes logging/screenshot, then redirects to the page that the next workflow needs to execute. So, we try/catch(login), try/catch(enterHoursWorked) etc... As others have said, it's ugly, but in my case it works. Now the exception is added to the log, and the next workflow executes
public void MyClientsFunctions() throws Exception {
ExtentTest t = ReportFactory.getTest();
try {
Login objPage = new PageObject(driver);
// this method throws exception
try {
objPage.Login();
if (x = y)
t.log(LogStatus.PASS, "Pass message");
else
t.log(LogStatus.FAIL, "Fail message" + screenshotMethod());
} catch (Exception e) {
t.log(LogStatus.ERROR, "Exception found: " + e.getMessage() + screenshotMethod());
objPage.BackToHomePage();
}
try {
objPage.EnterHoursWorked();
if (a = b)
t.log(LogStatus.PASS, "Pass message");
else
t.log(LogStatus.FAIL, "Fail message" + screenshotMethod());
} catch (Exception e) {
t.log(LogStatus.ERROR, "Exception found: " + e.getMessage() + screenshotMethod());
objPage.BackToHomePage();
}
} catch (Exception e) {
t.log(LogStatus.ERROR, "Exception found: " + e.getMessage() + screenshotMethod());
}
}

ExecutorService.submit() not returning after submitting the task

I want to make an asynchronous call to a function and return without waiting for the result (in Java). The code I have written for the same is:
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new Callable<Void>()
{
public Void call() throws Exception, TimeoutException {
hostNetworkSystem.updatePortGroup("Management Network", spec);
return null;
}
});
I have tried both Runnable and Callable but when I debug through the code in Eclipse, the thread gets stuck at the call() function doesn't return immediately after submitting the task.
Am I missing something here?
It gets stuck at:
hostNetworkSystem.updatePortGroup("Management Network", spec);
to be precise. The action is carried out as I can see the results, but it doesn't return from here.
For better understanding, this is how the entire call looks:
public void main()
{
try {
AsyncCall asyncCalls = new AsyncCall();
List<PortGroupData> portData = asyncCalls.updatePortGroupFuture(hostNetworkSystem, portGroupName,
portGroupData, modelType, oobmStatus, vlanID);
return portData;
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("InterruptedException " + e.getMessage().toString());
} catch (ExecutionException e) {
System.out.println("ExecutionException " + e.getMessage().toString());
e.printStackTrace();
} catch (Exception e) {
System.out.println("Exception " + e.getMessage().toString());
e.printStackTrace();
}
}
public void updatePortGroupFuture(final HostNetworkSystem hostNetworkSystem,
final String portGroupName, final NetworkParameters networkData, final String modelType,
final boolean oobmStatus, int vlanID) throws InterruptedException, ExecutionException, Exception
{
<some other actions>
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new Callable<Void>()
{
public Void call() throws Exception, TimeoutException {
hostNetworkSystem.updatePortGroup("Management Network", spec);
return null;
}
});
return;
}
Change your code as
Future<Void> future = executorService.submit(new Callable<Void>()
{
public Void call() throws Exception, TimeoutException {
System.out.println("before call");
hostNetworkSystem.updatePortGroup("Management Network", spec);
System.out.println("after call");
return null;
}
});
try{
result = future.get(5000, TimeUnit.MILLISECONDS);
}catch(TimeoutException e){
System.out.println("Time out after 5 seconds");
futureResult.cancel(true);
}catch(InterruptedException ie){
System.out.println("Error: Interrupted");
}catch(ExecutionException ee){
System.out.println("Error: Execution interrupted");
}
If you get TimeoutException, change the time out value to some big number.
Check for before call & after call statements. If you get before call and did not get after call, it implies some exception happened.
To know the exception, change submit() to execute() and catch exception.
submit() swallows exceptions. Have a look at this code
**Inside FutureTask$Sync**
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}
protected void setException(Throwable t) {
sync.innerSetException(t);
}
Have a look at this SE Post and this SE question:
Choose between ExecutorService's submit and ExecutorService's execute
Try putting a sysout after submit(...) and see if that gets printed. That indicates the parent/main thread is not blocked on the call() method and returned immediately after submitting the task.
You can capture the Future returned by the submit method and add the following code after the submit method invocation:
try {
future.get();
}catch(ExecutionException ee){
System.out.println("exception >>" + ee.getMessage());
}
service.shutdown();
Since future.get is a blocking call, the thread submitting the task will wait for the async operation to complete. You will also get to know if its throwing any exceptions.
FutureTask stores the exception in a variable which will then be wrapped in a ExecutionException and thrown when get method is called. So we can get the underlying exception even when we call get() method on FutureTask

Java exception handling get console error message

I want to get error message using java when exception are generated.
now I have java code with following scenario:
method first(){
try{
second();
}catch(Exception e){
System.out.println("Error:> "+e)
}
}
method second(){
try{
my code
}catch(Exception e){
throw new Exception("Exception generate in second method",e);
}
}
now when the first method execute then I get only "Exception generate in second method" message but there is some other message printed on console by java so how to get that console error message.
Note: I have already try with e.getMessage(); and e.printStackTrace();
Every exception has a cause that you can get with getCause(). You can go recursively down them until you get to the root cause. Here is your example with a utility that dumps the exception with all its causes like the console does.
private void first() {
try {
second();
} catch (Exception ex) {
Log.e("CATCH", getExceptionDump(ex));
}
}
private void second() {
try {
throw new UnsupportedOperationException("We don't do this.");
} catch (Exception ex) {
throw new RuntimeException("Exception in second()", ex);
}
}
private String getExceptionDump(Exception ex) {
StringBuilder result = new StringBuilder();
for (Throwable cause = ex; cause != null; cause = cause.getCause()) {
if (result.length() > 0)
result.append("Caused by: ");
result.append(cause.getClass().getName());
result.append(": ");
result.append(cause.getMessage());
result.append("\n");
for (StackTraceElement element: cause.getStackTrace()) {
result.append("\tat ");
result.append(element.getMethodName());
result.append("(");
result.append(element.getFileName());
result.append(":");
result.append(element.getLineNumber());
result.append(")\n");
}
}
return result.toString();
}
The message in the Exception constructor argument is not printed in the exception detail.
You can simply use this code to print the message :
method first(){
try{
second();
}catch(Exception e){
System.out.println("Error:> "+e.getMessage())
}
}
Hope this solves your problem
Why you cannot use print stack trace ?
Because A throwable contains a snapshot of the execution stack of its thread at the time it was created. (see Throwable)
It implies that, if you want to print the stack trace you need to use the printStackTrace() method BUT in your second method !
method second(){
try {
my code
} catch(Exception e) {
e.printStackTrace();
throw new Exception("Exception generate in second method",e);
}
}
Or using a the tricky method setStackTrace and using the printStackTrace() in first
method second(){
try {
my code
} catch(Exception e) {
Exception ex = new Exception("Exception generate in second method",e);
ex.setStackTrace(e);
throw ex;
}
}
method first(){
try {
second();
} catch(Exception e) {
e.printStackTrace();
}
}
You can print the cause of the exception you get. Try this:
method first(){
try{
second();
}catch(Exception e){
System.out.println("Error:> "+e);
if (e.getCause() != null) {
System.out.println("Cause:> " + e.getCause());
}
}
}
I believe this is the console message you want to achieve:
Error:> java.lang.Exception: Exception generate in second method
Try this code, when the catch block of the second method throws an exception the second method should declare it as throws or put a nested try catch within the catch block.
The exception is propagated to the first() method which is handled by its catch block.
public class Test {
public void first() {
try {
second();
} catch (Exception e) {
System.out.println("Error:> " + e);
}
}
public void second() throws Exception {
try {
throw new Exception();
} catch (Exception e) {
throw new Exception("Exception generate in second method", e);
}
}
public static void main(String ars[]) {
Test test = new Test();
test.first();
}
}

Time out method in java

In a java class I have a method that sometimes takes a long time for execution. Maybe it hangs in that method flow. What I want is if the method doesn't complete in specific time, the program should exit from that method and continue with the rest of flow.
Please let me know is there any way to handle this situation.
You must use threads in order to achieve this. Threads are not harmful :) Example below run a piece of code for 10 seconds and then ends it.
public class Test {
public static void main(String args[])
throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("0");
method();
}
});
thread.start();
long endTimeMillis = System.currentTimeMillis() + 10000;
while (thread.isAlive()) {
if (System.currentTimeMillis() > endTimeMillis) {
System.out.println("1");
break;
}
try {
System.out.println("2");
Thread.sleep(500);
}
catch (InterruptedException t) {}
}
}
static void method() {
long endTimeMillis = System.currentTimeMillis() + 10000;
while (true) {
// method logic
System.out.println("3");
if (System.currentTimeMillis() > endTimeMillis) {
// do some clean-up
System.out.println("4");
return;
}
}
}
}
Execute the method in a different thread, you can end a thread at anytime.
Based on the above snipplet, I tried creating a glorified spring bean.
Such executor runs the passed limitedRuntimeTask in limited runtimeInMs.
If the task finishes within its time limits, the caller continues normally in execution.
If the limitedRuntimeTask fails to finish in the defined runtimeInMs,
the caller will receive the thread execution back. If a timeBreachedTask was defined,
it will be executed before returning to caller.
public class LimitedRuntimeExecutorImpl {
public void runTaskInLessThanGivenMs(int runtimeInMs, final Callable limitedRuntimeTask, final Callable timeBreachedTask) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
LOGGER.info("Started limitedRuntimeTask");
limitedRuntimeTask.call();
LOGGER.info("Finished limitedRuntimeTask in time");
} catch (Exception e) {
LOGGER.error("LimitedRuntimeTask exception", e);
}
}
});
thread.start();
long endTimeMillis = System.currentTimeMillis() + runtimeInMs;
while (thread.isAlive()) {
if (System.currentTimeMillis() > endTimeMillis) {
LOGGER.warn("LmitedRuntimeTask did not finish in time (" + runtimeInMs + ")ms. It will run in vain.");
if(timeBreachedTask != null ){
try {
LOGGER.info("Executing timeBreachedTask");
timeBreachedTask.call();
LOGGER.info("Finished timeBreachedTask");
} catch (Exception e) {
LOGGER.error("timeBreachedTask exception", e);
}
}
return;
}
try {
Thread.sleep(10);
}
catch (InterruptedException t) {}
}
}
}
I feel the approach in accepted answer is a bit outdated. With Java8, it can be done much simpler.
Say, you have a method
MyResult conjureResult(String param) throws MyException { ... }
then you can do this (keep reading, this is just to show the approach):
private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor();
MyResult conjureResultWithTimeout(String param, int timeoutMs) throws Exception {
Future<MyResult> future = timeoutExecutorService.submit(() -> conjureResult(param));
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
}
of course, throwing Exception is bad, here is the correct extended version with proper error processing, but I suggest you examine it carefully, your may want to do some things differently (logging, returning timeout in extended result etc.):
private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor();
MyResult conjureResultWithTimeout(String param, int timeoutMs) throws MyException {
Future<MyResult> future = timeoutExecutorService.submit(() -> conjureResult(param));
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
//something interrupted, probably your service is shutting down
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (ExecutionException e) {
//error happened while executing conjureResult() - handle it
if (e.getCause() instanceof MyException) {
throw (MyException)e.getCause();
} else {
throw new RuntimeException(e);
}
} catch (TimeoutException e) {
//timeout expired, you may want to do something else here
throw new RuntimeException(e);
}
}

Categories

Resources