private Object runInTx(Task task, Object... input) {
   HibernateCallback action = new RunInHibernate(task, input);
   TransactionTemplate txTemplate = new TransactionTemplate(this.txMgr);
   boolean rollbackOnly = task instanceof DefaultRollback && !isTxRunning();
   RunInTx tx = new RunInTx(action, rollbackOnly);
   if (txLogger.isInfoEnabled()) {
     if (isTxRunning()) {
       txLogger.info("tx is running executing \"" + task.getName() + "\" in current tx");
     } else {
       txLogger.info("no tx running, wrapping execution of \"" + task.getName() + "\" in tx");
       if (rollbackOnly) {
         txLogger.info("rollback enabled for \"" + task.getName() + "\"");
       }
     }
   }
   Object rtn = null;
   try {
     rtn = txTemplate.execute(tx);
   } catch (Throwable ex) {
     // The following logic intends to display a sensible message for the user when a column
     // contains a value whose length
     // exceeds the maximum length allowed in the database.  The logic has been tested on MySQL,
     // Postgres, Oracle and
     // SQLServer so far.
     if (ex.getCause() instanceof java.sql.BatchUpdateException) { // Oracle
       String msg =
           ((java.sql.BatchUpdateException) ex.getCause()).getNextException().getMessage();
       if (msg != null) {
         ex.printStackTrace();
         throw new WMRuntimeException(msg);
       }
     } else if (ex.getCause().getCause() instanceof java.sql.BatchUpdateException) { // Postgres
       java.sql.BatchUpdateException e = (java.sql.BatchUpdateException) ex.getCause().getCause();
       if (e != null && e.getMessage() != null) {
         ex.printStackTrace();
         throw new WMRuntimeException(e.getNextException().getMessage());
       }
     } else if (ex.getCause().getCause() != null) { // MySQL, SQLServer
       String msg = ex.getCause().getCause().getMessage();
       if (msg != null) {
         ex.printStackTrace();
         throw new WMRuntimeException(msg);
       }
     } else {
       throw new WMRuntimeException(ex);
     }
   }
   if (txLogger.isInfoEnabled()) {
     if (isTxRunning()) {
       txLogger.info("tx is running after execution of \"" + task.getName() + "\"");
     } else {
       txLogger.info("tx is not running after execution of \"" + task.getName() + "\"");
     }
   }
   return rtn;
 }
 private void extractDetails(BatchUpdateException ex) {
   String msg = ex.getMessage();
   Matcher m = FOREIGN_KEY_CONSTRAINT.matcher(msg);
   if (m.matches()) {
     this.child = m.group(2);
     this.parent = m.group(1);
   } else {
     logger.error("matcher did not match, ex='" + root.getStackTrace() + "' msg was:" + msg);
   }
 }