Search in sources :

Example 1 with TransactionInfo

use of org.jaffa.transaction.services.configdomain.TransactionInfo in project jaffa-framework by jaffa-projects.

the class LockingService method checkLock.

/**
 * Browses all Transactions looking for the locks, as specified in the transaction-configuration for the input dataBean.
 * Throws an ApplicationException, if any matching Transaction is found.
 *
 * @param uow      The UOW.
 * @param dataBean Any serializable object.
 * @throws FrameworkException    Indicates some system error.
 * @throws ApplicationExceptions Indicates application error(s).
 */
public static void checkLock(UOW uow, Object dataBean) throws FrameworkException, ApplicationExceptions {
    // Load transaction configuration
    TransactionInfo transactionInfo = ConfigurationService.getInstance().getTransactionInfo(dataBean);
    // Perform the check
    checkLock(uow, dataBean, transactionInfo);
}
Also used : TransactionInfo(org.jaffa.transaction.services.configdomain.TransactionInfo)

Example 2 with TransactionInfo

use of org.jaffa.transaction.services.configdomain.TransactionInfo in project jaffa-framework by jaffa-projects.

the class TransactionManagerTest method testRegisterTransactionInfo.

/**
 * tests the registerTransactionInfo
 */
@Test
public void testRegisterTransactionInfo() {
    // test
    transactionManager.registerTransactionInfo(new ContextKey("testBean", null, "DEF", "cust-code"), new TransactionInfo());
    // verify
    verify(transactionRepoMock).register(eq(new ContextKey("testBean", null, "DEF", "cust-code")), Matchers.anyObject());
}
Also used : ContextKey(org.jaffa.loader.ContextKey) TransactionInfo(org.jaffa.transaction.services.configdomain.TransactionInfo) Test(org.junit.Test)

Example 3 with TransactionInfo

use of org.jaffa.transaction.services.configdomain.TransactionInfo in project jaffa-framework by jaffa-projects.

the class JaffaTransactionMessageService method createTransactionFields.

/**
 * Create an array of {@link org.jaffa.transaction.domain.TransactionField} based on the fields of the {@link org
 * .jaffa.transaction.domain.Transaction}
 *
 * @param transaction the transaction to create fields for
 * @param dataBean    the internal object of the transaction payload
 * @return an array of {@link org.jaffa.transaction.domain.TransactionField}
 * @throws FrameworkException
 * @throws ApplicationExceptions
 */
private Collection<TransactionField> createTransactionFields(Transaction transaction, Object dataBean) throws FrameworkException, ValidationException, ApplicationExceptions {
    Collection<TransactionField> transactionFields = new LinkedList<TransactionField>();
    // Create a TransactionField object for each header element as defined in the configuration file
    final TransactionInfo transactionInfo = transaction.getTransactionInfo();
    if ((transactionInfo.getHeader() != null) && (transactionInfo.getHeader().getParam() != null)) {
        for (Param param : transactionInfo.getHeader().getParam()) {
            // get the value of the header parameter
            String value = TransactionEngine.obtainParamValue(param, dataBean);
            // create a transaction field and set its ID
            TransactionField transactionField = new TransactionField();
            transactionField.setTransactionId(transaction.getId());
            // set the name and value of the transaction field, then add it to the list of all transaction fields
            transactionField.setFieldName(param.getName());
            transactionField.setValue(value);
            transactionFields.add(transactionField);
        }
    }
    return transactionFields;
}
Also used : Param(org.jaffa.transaction.services.configdomain.Param) TransactionInfo(org.jaffa.transaction.services.configdomain.TransactionInfo) TransactionField(org.jaffa.transaction.domain.TransactionField) LinkedList(java.util.LinkedList)

Example 4 with TransactionInfo

use of org.jaffa.transaction.services.configdomain.TransactionInfo 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);
        TransactionPayload payload = (transaction != null) ? transaction.getTransactionPayloadObject() : null;
        Object dataBean = (payload != null) ? payload.moldInternalPayload() : null;
        if (dataBean != null) {
            // Load transaction configuration
            TransactionInfo transactionInfo = ConfigurationService.getInstance().getTransactionInfo(dataBean);
            if (transactionInfo != null) {
                // 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) {
                            // 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 transactionInfo for the Transaction. Hence nothing to process.");
                }
            }
        } 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;
}
Also used : TransactionField(org.jaffa.transaction.domain.TransactionField) Transaction(org.jaffa.transaction.domain.Transaction) TransactionInfo(org.jaffa.transaction.services.configdomain.TransactionInfo) TransactionPayload(org.jaffa.transaction.domain.TransactionPayload) UOW(org.jaffa.persistence.UOW)

Example 5 with TransactionInfo

use of org.jaffa.transaction.services.configdomain.TransactionInfo in project jaffa-framework by jaffa-projects.

the class TransactionAdmin method invokeHandler.

/**
 * Invokes the intended handler. This Handler must implement the IMessageHandler Interface in order to be invoked.
 *
 * @param uow
 * @param transaction
 * @param methodName
 * @throws JaffaMessagingFrameworkException
 */
private static void invokeHandler(UOW uow, Transaction transaction, String methodName) throws Exception {
    try {
        TransactionPayload tp = transaction.getTransactionPayloadObject();
        Object dataBean = tp != null ? tp.moldInternalPayload() : null;
        if (dataBean != null) {
            // Load transaction configuration
            TransactionInfo transactionInfo = ConfigurationService.getInstance().getTransactionInfo(tp.getInternalMessageClass());
            if (transactionInfo == null) {
                throw new JaffaMessagingFrameworkException(JaffaTransactionFrameworkException.TRANSACTION_INFO_MISSING, new Object[] { tp.getInternalMessageClass() });
            }
            // Obtain the handlerClass
            if (transactionInfo.getToClass() == null || transactionInfo.getToClass().length() == 0) {
                if (log.isDebugEnabled()) {
                    log.debug(methodName + " toClass is not defined in data bean configuration: " + transactionInfo.getDataBean());
                }
                return;
            }
            Class handlerClass = Class.forName(transactionInfo.getToClass());
            // Class dataBeanClass = Class.forName(transactionInfo.getDataBean());
            if (IMessageHandler.class.isAssignableFrom(handlerClass)) {
                // Unmarshals the Message payload into a dataBean using the dataBeanClassName
                Method handlerMethod = null;
                Object handlerObject = null;
                // Obtain the handler method
                try {
                    handlerMethod = handlerClass.getMethod(methodName, new Class[] { UOW.class, Map.class, Object.class });
                } catch (NoSuchMethodException e) {
                    // Hence use the dataBeanClass specified in the messageInfo to get the appropriate handlerMethod
                    if (log.isDebugEnabled()) {
                        log.debug(methodName + " method not found in " + handlerClass.getName());
                    }
                    return;
                }
                handlerObject = handlerClass.newInstance();
                Map<String, String> headerMap = new HashMap<String, String>();
                // Sets the transactionField elements as defined in the configuration file.
                TransactionField[] fields = transaction.getTransactionFieldArray();
                if (fields != null) {
                    for (TransactionField field : fields) {
                        headerMap.put(field.getFieldName(), field.getValue());
                    }
                }
                // Invoke the handler
                if (log.isDebugEnabled()) {
                    log.debug("Invoking the handler " + handlerMethod);
                }
                handlerMethod.invoke(handlerObject, new Object[] { uow, headerMap, dataBean });
            }
        }
    } catch (Exception e) {
        // Just log the error
        log.error("Exception thrown while deleting the transaction. Transaction was: " + transaction, e);
        throw e;
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) JaffaMessagingFrameworkException(org.jaffa.modules.messaging.services.JaffaMessagingFrameworkException) TransactionField(org.jaffa.transaction.domain.TransactionField) Method(java.lang.reflect.Method) IllegalPersistentStateRuntimeException(org.jaffa.persistence.exceptions.IllegalPersistentStateRuntimeException) JaffaMessagingFrameworkException(org.jaffa.modules.messaging.services.JaffaMessagingFrameworkException) PostLoadFailedException(org.jaffa.persistence.exceptions.PostLoadFailedException) FrameworkException(org.jaffa.exceptions.FrameworkException) QueryFailedException(org.jaffa.persistence.exceptions.QueryFailedException) ApplicationException(org.jaffa.exceptions.ApplicationException) TransactionInfo(org.jaffa.transaction.services.configdomain.TransactionInfo) TransactionPayload(org.jaffa.transaction.domain.TransactionPayload) UOW(org.jaffa.persistence.UOW) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

TransactionInfo (org.jaffa.transaction.services.configdomain.TransactionInfo)11 ContextKey (org.jaffa.loader.ContextKey)5 TransactionField (org.jaffa.transaction.domain.TransactionField)3 Config (org.jaffa.transaction.services.configdomain.Config)3 TypeInfo (org.jaffa.transaction.services.configdomain.TypeInfo)3 UOW (org.jaffa.persistence.UOW)2 TransactionPayload (org.jaffa.transaction.domain.TransactionPayload)2 Method (java.lang.reflect.Method)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1 ApplicationException (org.jaffa.exceptions.ApplicationException)1 FrameworkException (org.jaffa.exceptions.FrameworkException)1 JaffaMessagingFrameworkException (org.jaffa.modules.messaging.services.JaffaMessagingFrameworkException)1 IllegalPersistentStateRuntimeException (org.jaffa.persistence.exceptions.IllegalPersistentStateRuntimeException)1 PostLoadFailedException (org.jaffa.persistence.exceptions.PostLoadFailedException)1 QueryFailedException (org.jaffa.persistence.exceptions.QueryFailedException)1 Transaction (org.jaffa.transaction.domain.Transaction)1