0

I m trying to make each thread atomic. I already tried using proxy annotations to begin and end transaction after the execute method but it didn't work and also I tried using transaction annotation on the class level and method level both didn't work. So How do I make a Thread atomic.

Test class/Driver Class

public class TestTaskExecutor {
    @Autowired
    MyTaskExecutor myTaskExecutor;
    @Autowired(required = true)
    SessionFactory sessionFactory;
    Logger logger = LoggerFactory.getLogger(TestTaskExecutor.class.getName());

@Test
public void testTaskExecutor() {

    FutureTask[] futureTasks = new FutureTask[2];
    for (int i = 0; i < 2; i++) {
        TestTable newTable = new TestTable();
        String rollId = "test"+ Integer.toString(i);
        newTable.setRollid(anid);
        TestCallable testCallable = new TestCallable(newTable);
        futureTasks[i] = new FutureTask<Integer>(testCallable);
        myTaskExecutor.executeTask(futureTasks[i]);
    }
    int count = 0;
    for (FutureTask<Integer> f : futureTasks) {
        try {
            int i = f.get();
            count = count + i;

        } catch (InterruptedException e) {
            logger.error(e.getLocalizedMessage());
        } catch (ExecutionException e) {
            logger.error(e.getLocalizedMessage());
        }
    }
    Assert.assertEquals("not equal", 2, count);
}
}

My callable implementation

public class TestCallable implements Callable<Integer> {
TestTable testTable;
@Autowired(required = true)
SessionFactory sessionFactory;
Logger logger = LoggerFactory.getLogger(TestCallable.class.getName());

private SecureRandom random;

{
    random = new SecureRandom();
}

public TestCallable(TestTable testTable){
    this.testTable = testTable;
}
@Override
public Integer call() throws Exception {
    Session session = DBConnection.getInstance().getCurrentSession();
    this.testTable.setName(generateRandomString());
    try{
        logger.info("in save or update");
        session.saveOrUpdate(this.testTable);
    }
    catch(Exception e){
        logger.info("in error");
        logger.info(e.getLocalizedMessage());
        return 0;
    }
    return 1;

}

private String generateRandomString(){
    return new BigInteger(130, random).toString(32);
}
}

Task Executor Code

public class MyTaskExecutor {
private TaskExecutor taskExecutor;
private static Logger logger = LoggerFactory.getLogger(MyTaskExecutor.class);

public MyTaskExecutor(TaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
}

@Transactional
public void executeTask(FutureTask futureTask) {
    if (futureTask != null) {
        try {
            taskExecutor.execute(futureTask);
        } catch (Exception ex) {
            logger.error("Error in thread", ex);
            throw new RuntimeException(ex);
        }
    }
}

}

The Error message is failed because not an active transaction.

user1364861
  • 301
  • 1
  • 2
  • 16
  • You probably have to put the session.saveOrUpdate into an explicit transaction. By calling session.beginTransaction() and in the end by calling transaction.commit() – 11thdimension Nov 19 '15 at 22:09
  • Ok That works. But My Hibernate is configured as new session per thread. so This thread is spawn from another thread. so this thread also will have a new session and will be closed when the session is closed? – user1364861 Nov 19 '15 at 22:19
  • HIbernate sessions are created per thread, a new thread will have to create a new session. See the reference https://developer.jboss.org/wiki/Sessionsandtransactions – 11thdimension Nov 20 '15 at 01:04

0 Answers0