use of org.jaffa.transaction.domain.Transaction in project jaffa-framework by jaffa-projects.
the class TransactionDependency method postUpdate.
@Override
public void postUpdate() throws PostUpdateFailedException {
super.postUpdate();
// then UPDATE TRANSACTIONS SET STATUS='O' WHERE ID={thisTransactionDependency.transactionId} and STATUS='H'
if (isModified(TransactionDependencyMeta.STATUS) && Status.S.toString().equals(getStatus())) {
try {
if (log.isDebugEnabled()) {
log.debug("TransactionDependency status has changed to S. Will Open parent Transaction if no other Open TransactionDependency record exists");
}
TransactionMessageDAO transactionDAO = getTransactionDAO();
Transaction transaction = transactionDAO.getTransaction(getTransactionId());
if (transaction != null && Transaction.Status.H.toString().equals(transaction.getStatus())) {
long count = transactionDAO.getOpenTransactionDependencyCount(transaction.getId());
if (count == 0) {
transaction.setStatus(Transaction.Status.O.toString());
getUOW().update(transaction);
}
}
} catch (Exception e) {
String s = "Exception in opening parent Transaction when the associated dependencies have all been satisfied. This is being done for the TransactionDependency instance " + this;
ApplicationExceptions appExps = ExceptionHelper.extractApplicationExceptions(e);
if (appExps != null) {
if (log.isDebugEnabled())
log.debug(s, appExps);
} else {
log.error(s, e);
}
throw new PostUpdateFailedException(new String[] { s }, e);
}
}
}
use of org.jaffa.transaction.domain.Transaction in project jaffa-framework by jaffa-projects.
the class TransactionField method findTransactionObject.
/**
* Finds the related foreign Transaction object.
* If checkExistenceOnly is false, then the foreign object will be fetched and assigned to the corresponding member variable of this class.
* If checkExistenceOnly is true, then a mere existence check is performed for the foreign object, as oppposed to fetching all the values for that object.
*/
private void findTransactionObject(boolean checkExistenceOnly) throws ValidationException, FrameworkException {
// TODO this is generated...
if ((m_transactionObject == null) && (getTransactionId() != null)) {
Transaction transaction = getTransactionDAO().getTransaction(getTransactionId());
Number count = null;
if (checkExistenceOnly) {
if (transaction != null) {
count = 1;
}
} else {
m_transactionObject = transaction;
}
if ((m_transactionObject == null) && ((count == null) || (count.intValue() <= 0))) {
throw new InvalidForeignKeyException(TransactionFieldMeta.META_TRANSACTION_ID.getLabelToken(), new Object[] { TransactionMeta.getLabelToken(), TransactionMeta.META_ID.getLabelToken() });
}
}
}
use of org.jaffa.transaction.domain.Transaction in project jaffa-framework by jaffa-projects.
the class TransactionAdmin method resubmitMessage.
/**
* NOTE: Each graph is expected to contain messageId. It may also contain the optional queueMetaData.queueSystemId and type, which may help optimize the process.
*/
public MessageAdminResponse[] resubmitMessage(MessageGraph[] graphs) {
if (log.isDebugEnabled()) {
log.debug("Input to resubmitMessage: " + Arrays.toString(graphs));
}
Collection<MessageAdminResponse> output = null;
String[] types = TransactionEngine.getInstance().getAccessibleTypeNames();
Arrays.sort(types);
for (MessageGraph graph : graphs) {
if (graph.getQueueMetaData() == null || graph.getQueueMetaData().getQueueSystemId() == null || graph.getQueueMetaData().getQueueSystemId().equals(QUEUE_SYSTEM_ID)) {
if (graph.getType() == null || (types != null && Arrays.binarySearch(types, graph.getType()) >= 0)) {
UOW uow = null;
try {
String graphType = graph.getType();
String messageId = graph.getMessageId();
if (graphType != null && !TransactionEngine.getInstance().hasAdminAccess(graphType)) {
throw new ApplicationExceptions(new ApplicationException("error.Jaffa.Transaction.Transaction.noAdminAccess", new Object[] { graphType }));
}
uow = new UOW();
Transaction transaction = transactionDAO.getTransaction(messageId);
if (transaction != null) {
if (!TransactionEngine.getInstance().hasAdminAccess(transaction.getType())) {
throw new ApplicationExceptions(new ApplicationException("error.Jaffa.Transaction.Transaction.noAdminAccess", new Object[] { transaction.getType() }));
}
if (Transaction.Status.E.toString().equals(transaction.getStatus())) {
if (log.isDebugEnabled()) {
log.debug("Resubmitting ERROR message " + messageId);
}
transaction.setStatus(Transaction.Status.O.toString());
transaction.setErrorMessage(null);
transactionDAO.save(uow, transaction);
uow.commit();
} else {
if (log.isDebugEnabled()) {
log.debug("Resubmission cannot be performed since message " + messageId + " is not in ERROR status anymore");
}
}
} else {
if (log.isDebugEnabled()) {
log.debug("Resubmission cannot be performed since message " + messageId + " not found");
}
}
} catch (Exception e) {
MessageAdminResponse response = new MessageAdminResponse();
response.setSource(graph);
ApplicationExceptions appExps = ExceptionHelper.extractApplicationExceptions(e);
if (appExps != null) {
if (log.isDebugEnabled()) {
log.debug("Error while resubmitting Message " + graph, appExps);
}
response.setErrors(ServiceError.generate(appExps));
} else {
log.error("Internal Error while resubmitting Message " + graph, e);
response.setErrors(ServiceError.generate(e));
}
if (output == null) {
output = new LinkedList<MessageAdminResponse>();
}
output.add(response);
} finally {
if (uow != null) {
try {
uow.rollback();
} catch (Exception ignore) {
}
}
}
} else {
if (log.isDebugEnabled()) {
log.debug("Message " + graph + " will not be resubmitted by this implementation, since the queue does not belong to this implementation");
}
}
} else {
if (log.isDebugEnabled()) {
log.debug("Message " + graph + " will not be resubmitted by this implementation, since the input queueSystemId does not match this system");
}
}
}
if (log.isDebugEnabled()) {
log.debug("Output from resubmitMessage: " + output);
}
return output != null && output.size() > 0 ? output.toArray(new MessageAdminResponse[output.size()]) : null;
}
use of org.jaffa.transaction.domain.Transaction in project jaffa-framework by jaffa-projects.
the class TransactionAdmin method deleteMessage.
// ///////////////////////////////// Add in intercept for delete
/**
* NOTE: Each graph is expected to contain messageId. It may also contain the optional queueMetaData.queueSystemId and type, which may help optimize the process.
*/
public MessageAdminResponse[] deleteMessage(MessageGraph[] graphs) {
if (log.isDebugEnabled()) {
log.debug("Input to deleteMessage: " + Arrays.toString(graphs));
}
Collection<MessageAdminResponse> output = null;
String[] types = TransactionEngine.getInstance().getAccessibleTypeNames();
Arrays.sort(types);
for (MessageGraph graph : graphs) {
if (graph.getQueueMetaData() == null || graph.getQueueMetaData().getQueueSystemId() == null || graph.getQueueMetaData().getQueueSystemId().equals(QUEUE_SYSTEM_ID)) {
if (graph.getType() == null || (types != null && Arrays.binarySearch(types, graph.getType()) >= 0)) {
UOW uow = null;
try {
String graphType = graph.getType();
String messageId = graph.getMessageId();
if (graphType != null && !TransactionEngine.getInstance().hasAdminAccess(graphType)) {
throw new ApplicationExceptions(new ApplicationException("error.Jaffa.Transaction.Transaction.noAdminAccess", new Object[] { graphType }));
}
uow = new UOW();
Transaction transaction = transactionDAO.getTransaction(messageId);
if (!TransactionEngine.getInstance().hasAdminAccess(transaction.getType())) {
throw new ApplicationExceptions(new ApplicationException("error.Jaffa.Transaction.Transaction.noAdminAccess", new Object[] { transaction.getType() }));
}
if (transaction != null) {
// Invoke Message Handler class to perform onDelete process
invokeHandler(uow, transaction, "onDelete");
if (log.isDebugEnabled()) {
log.debug("Deleting message " + messageId);
}
transactionDAO.delete(uow, transaction);
uow.commit();
} else {
if (log.isDebugEnabled()) {
log.debug("Delete cannot be performed since message " + messageId + " not found");
}
}
} catch (Exception e) {
MessageAdminResponse response = new MessageAdminResponse();
response.setSource(graph);
ApplicationExceptions appExps = ExceptionHelper.extractApplicationExceptions(e);
if (appExps != null) {
if (log.isDebugEnabled()) {
log.debug("Error while deleting Message " + graph, appExps);
}
response.setErrors(ServiceError.generate(appExps));
} else {
log.error("Internal Error while deleting Message " + graph, e);
response.setErrors(ServiceError.generate(e));
}
if (output == null) {
output = new LinkedList<MessageAdminResponse>();
}
output.add(response);
} finally {
if (uow != null) {
try {
uow.rollback();
} catch (Exception ignore) {
}
}
}
} else {
if (log.isDebugEnabled()) {
log.debug("Message " + graph + " will not be deleted by this implementation, since the queue does not belong to this implementation");
}
}
} else {
if (log.isDebugEnabled()) {
log.debug("Message " + graph + " will not be deleted by this implementation, since the input queueSystemId does not match this system");
}
}
}
if (log.isDebugEnabled()) {
log.debug("Output from deleteMessage: " + output);
}
return output != null && output.size() > 0 ? output.toArray(new MessageAdminResponse[output.size()]) : null;
}
use of org.jaffa.transaction.domain.Transaction in project jaffa-framework by jaffa-projects.
the class TransactionConsumer method process.
/**
* This method is invoked directly when processing a Transaction synchronously.
* It'll invoke the handler associated with the input transaction's payload, as obtained from the transaction configuration file.
* In case of an error, the status of the transaction will be set to 'E'.
*
* @param uow the provided uow.
* @param transactionId the transaction ID.
* @param unsavedTransaction the transaction if available, otherwise null.
*/
public UOW process(UOW uow, String transactionId, Transaction unsavedTransaction) throws Exception {
if (log.isDebugEnabled()) {
log.debug("Processing Transaction " + transactionId);
}
// Update Transaction status to I
Boolean postImmediate = Parser.parseBoolean((String) ContextManagerFactory.instance().getProperty(Transaction.RULE_POST_IMMEDIATE));
// If the postImmediate is true then we shall make the update to the transaction within same scope of the UOW as this must be synchronous transaction
if (postImmediate != null && postImmediate.booleanValue()) {
if (unsavedTransaction == null) {
// This transaction must already be in the database.
TransactionEngine.getInstance().updateTransactionStatusToInProcess(uow, transactionId);
} else {
uow.flush();
unsavedTransaction.setStatus(Transaction.Status.I.name());
}
} else {
TransactionEngine.getInstance().updateTransactionStatusToInProcess(transactionId);
}
boolean createdLoggingContext = false;
try {
Transaction transaction = unsavedTransaction != null ? unsavedTransaction : Transaction.findByPK(uow, transactionId);
Object dataBean = transaction.getTransactionPayloadObject() != null ? transaction.getTransactionPayloadObject().moldInternalPayload() : null;
TransactionInfo transactionInfo = null;
if (dataBean != null) {
// Load transaction configuration
transactionInfo = ConfigurationService.getInstance().getTransactionInfo(dataBean);
// Sets Log4J's MDC to enable BusinessEventLogging
LoggingService.setLoggingContext(dataBean, transactionInfo, transaction);
createdLoggingContext = true;
if (log.isInfoEnabled()) {
log.info(MessageHelper.findMessage("label.Jaffa.Transaction.TransactionConsumer.start", null));
}
int retryLimit = readRule(RULE_RETRY_LIMIT, DEFAULT_RETRY_LIMIT);
int retrySleepTimeInMillis = readRule(RULE_RETRY_SLEEP_TIME, DEFAULT_RETRY_SLEEP_TIME);
int retryCount = 0;
while (true) {
try {
// Invokes the handler as specified by the 'toClass and toMethod' combination in the transaction configuration
invokeHandler(uow, transactionInfo, dataBean);
break;
} catch (Exception e) {
if (postImmediate == null || !postImmediate.booleanValue()) {
// Retry only if the exception is listed as a retryable exception
String[] exceptions = readRule(RETRY_EXCEPTION_RULE, DEFAULT_RETRY_EXCEPTIONS);
Exception ex = null;
Class<Exception> clazz = null;
for (String exceptionName : exceptions) {
if (log.isDebugEnabled()) {
log.debug("Exception: " + exceptionName + " defined as a retryable exception.");
}
clazz = (Class<Exception>) Class.forName(exceptionName);
ex = clazz.cast(ExceptionHelper.extractException(e, clazz));
if (ex != null) {
break;
}
}
if (ex != null && ++retryCount <= retryLimit) {
if (log.isDebugEnabled()) {
log.debug(clazz.getSimpleName() + " encountered. Will sleep for " + retrySleepTimeInMillis + " milliseconds and then retry", e);
}
uow.rollback();
Thread.sleep(retrySleepTimeInMillis);
uow = new UOW();
if (log.isDebugEnabled()) {
log.debug("Retry#" + retryCount);
}
} else {
throw e;
}
} else {
throw e;
}
}
}
if (log.isInfoEnabled()) {
log.info(MessageHelper.findMessage("label.Jaffa.Transaction.TransactionConsumer.success", null));
}
} else {
if (log.isDebugEnabled()) {
log.debug("There is no payload for the Transaction. Hence nothing to process.");
}
}
TransactionField[] transactionFields = transaction.getTransactionFieldArray();
boolean keep = false;
if (transactionFields != null) {
for (TransactionField tField : transactionFields) {
if (KEEP.equals(tField.getFieldName()) && Boolean.parseBoolean(tField.getValue())) {
keep = true;
break;
}
}
}
if (log.isDebugEnabled()) {
log.info("Finished with transaction: " + transactionId);
}
// Commit the UOW if it isn't a post immediate to catch any exceptions that might occur
if (postImmediate == null || !postImmediate.booleanValue()) {
if (keep) // Update Transaction status to S
{
TransactionEngine.getInstance().updateTransactionStatusToSatisfied(uow, transactionId);
} else // Delete Transaction Record
{
TransactionEngine.getInstance().deleteTransaction(uow, transactionId);
}
try {
uow.commit();
} catch (Exception e) {
log.error("Error committing UOW in TransactionConsumer.process", e);
throw e;
}
} else {
uow.flush();
TransactionMessageDAOFactory.getTransactionMessageDAO().delete(uow, transaction);
}
if (log.isDebugEnabled()) {
log.debug("Successfully processed Transaction " + transaction);
}
} catch (Exception e) {
// Update Transaction status to E
if (log.isInfoEnabled()) {
log.info(MessageHelper.findMessage("label.Jaffa.Transaction.TransactionConsumer.error", null));
}
// Rollback the UOW if there is an error
if (postImmediate == null || !postImmediate.booleanValue()) {
try {
uow.rollback();
} catch (Exception exception) {
log.error("Error rolling back UOW in transaction consumer");
}
}
// Only need to update the transaction if the process is being run asynchronously.
if (postImmediate == null || !postImmediate.booleanValue()) {
// release the UOWs connection before creating a new one to move this transaction to the error state
uow.rollback();
// Update Transaction status to E
TransactionEngine.getInstance().updateTransactionStatusToError(transactionId, e);
log.error(MessageHelper.findMessage("label.Jaffa.Transaction.TransactionConsumer.error", null), e);
}
throw e;
} finally {
// Unset the Logging context
if (createdLoggingContext) {
LoggingService.unsetLoggingContext();
}
}
return uow;
}
Aggregations