com.webbfontaine.valuewebb.action.fcvr.FCVRSendScheduler.java Source code

Java tutorial

Introduction

Here is the source code for com.webbfontaine.valuewebb.action.fcvr.FCVRSendScheduler.java

Source

package com.webbfontaine.valuewebb.action.fcvr;

import com.webbfontaine.ellipse.lightso.Message;
import com.webbfontaine.valuewebb.action.tt.TTDataLoader;
import com.webbfontaine.valuewebb.action.tt.TtGenHome;
import com.webbfontaine.valuewebb.authentication.AuthenticatorBean;
import com.webbfontaine.valuewebb.model.TtGen;
import com.webbfontaine.valuewebb.model.util.Utils;
import org.apache.commons.lang3.StringUtils;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.async.Asynchronous;
import org.jboss.seam.annotations.async.Expiration;
import org.jboss.seam.annotations.async.IntervalCron;
import org.jboss.seam.async.QuartzTriggerHandle;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
import org.jboss.seam.transaction.Transaction;

import javax.persistence.EntityManager;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import java.io.IOException;
import java.rmi.NotBoundException;
import java.util.Date;
import java.util.List;

import static com.webbfontaine.valuewebb.model.constants.Constants.*;

/**
 * Copyrights 2002-2013 Webb Fontaine
 * This software is the proprietary information of Webb Fontaine.
 * Its use is subject to License terms.
 * Developer: nigiyan
 * Date: 12/04/2013
 */

@Name("FCVRSendScheduler")
@AutoCreate
@Scope(ScopeType.APPLICATION)
public class FCVRSendScheduler {

    private static final Log LOGGER = Logging.getLog(FCVRSendScheduler.class);

    private static final Object LOCK = new Object();

    @Asynchronous
    public QuartzTriggerHandle scheduleTask(@Expiration Date when, @IntervalCron String interval) {
        LOGGER.info("Started");

        long startTime = System.currentTimeMillis();

        synchronized (LOCK) { // allow only one async thread to do this

            EntityManager entityManager = (EntityManager) Component.getInstance("entityManager",
                    ScopeType.STATELESS, true);
            List<Long> ttIDs = Utils.setDirectRead(entityManager.createNamedQuery(findSentTTIdsCI)).getResultList();

            LOGGER.debug("Found Sent TTs: {0}}", ttIDs);

            if (ttIDs.isEmpty()) {
                return null;
            }

            if (!AuthenticatorBean.getDaemonIdentity().tryLogin()) {
                LOGGER.error("Can not login with 'daemon' identity to update TTs");
                return null;
            }
            try {

                for (Long ttId : ttIDs) {
                    try {
                        TtGen ttGen = entityManager.find(TtGen.class, ttId);

                        LOGGER.debug("TT to sent to FCVR: {0}, status {1}", ttId, ttGen.getStatus());

                        if (!ttGen.getStatus().equals(TT_SENT)) { // already processed by other thread
                            continue;
                        }

                        new TTDataLoader(ttGen).processAll();

                        Message message = FCVRSender.getInstance().sendFCVR(ttGen);

                        if (FCVRHelper.transactionError(message)) {
                            LOGGER.error("SOGate respond with error for TT {0} with FCVR Number {1}. Error: {2}",
                                    ttId, ttGen.getFcvrNum(), message.getProperties());
                            FCVRHelper.logExceptions(ttId, message);
                        } else {
                            if (FCVRHelper.transactionFailed(message)) {
                                FCVRHelper.logExceptions(ttId, message);

                                String remoteExceptionMessage = FCVRHelper.extractErrors(message);
                                FCVRHelper.appendErrorsToTT(ttGen, remoteExceptionMessage);

                                if (isFCVRAlreadyExists(remoteExceptionMessage)) {
                                    LOGGER.warn(
                                            "FCVR already exists for TT with ID {0}, check logs for previous unexpected errors. TT status will be changed to Sent Ok.",
                                            ttId);
                                    updateTT(ttGen, RESPONSE_OK); // ignore existance and change the status.
                                } else {
                                    if (isAccessProblem(remoteExceptionMessage)) {
                                        LOGGER.warn(
                                                "Cannot complete transaction for FCVR document, got {0} for TT ID: {1}, document processing skipped.",
                                                remoteExceptionMessage, ttId);
                                    } else {
                                        LOGGER.info(
                                                "Cannot complete transaction for FCVR document, TT ID: {0}, document status will be changed accordingly.",
                                                ttId);
                                        updateTT(ttGen, ERROR_RESPONSE);
                                    }
                                }

                            } else {
                                if (FCVRHelper.transactionSucceeded(message)) {
                                    LOGGER.info("FCVR transaction on TT {0} completed successfully", ttId);
                                    updateTT(ttGen, RESPONSE_OK);
                                } else {
                                    LOGGER.error("Unknown FCVR response for TT: {0}, message: {1}", ttId,
                                            message.getProperties());
                                    throw new FCVRProcessingException(
                                            "Unknown FCVR reponse, remote document change is ");
                                }
                            }
                        }
                    } catch (FCVRProcessingException e) {
                        Throwable cause = e.getCause();
                        if (isConnectionProblem(cause) || isLoginProblem(cause)) {
                            LOGGER.warn("{0}: Can not connect to TWM-FCVR. {1}", cause.getClass().getName(),
                                    cause.getMessage());
                            break; // do not continue with next TT if connection problem
                        } else {
                            LOGGER.error("", e);
                        }
                    }
                }
            } finally {
                AuthenticatorBean.getDaemonIdentity().logout();
            }
            LOGGER.debug("Processing took {0} ms", System.currentTimeMillis() - startTime);
            return null;
        }
    }

    protected void updateTT(TtGen ttGen, String operation) {
        LOGGER.debug("Going to execute {0} operation on TT with id {1}.", operation, ttGen.getId());

        UserTransaction utx = null;
        try {
            utx = Transaction.instance();
            utx.begin();

            TtGenHome ttGenHome = createTTHomeInstance(ttGen);
            if (ttGenHome.performDirectTaskWithoutDocumentCheck(operation).equals(UPDATED)) {
                utx.commit();
            } else {
                LOGGER.error("Failed to execute {0} operation for TT with id {1}. Will continue with next TTs",
                        operation, ttGen.getId());
                utx.rollback();
            }
        } catch (Exception e) {
            LOGGER.error("Exception on updating TT with id: {0} for operation: {1} fails", e, ttGen.getId(),
                    operation);
            if (utx != null) {
                try {
                    utx.rollback();
                } catch (SystemException sex) {
                    LOGGER.error("", sex);
                }
            }
        }
    }

    private static TtGenHome createTTHomeInstance(TtGen ttGen) {
        return TtGenHome.createInstance(ttGen);
    }

    private static boolean isConnectionProblem(Throwable t) {
        return t != null && t instanceof IOException || t instanceof NotBoundException;
    }

    private static boolean isLoginProblem(Throwable t) {
        return t != null && "Exception at login".equals(t.getMessage());
    }

    private static boolean isFCVRAlreadyExists(String error) {
        return "FCVR Number already exists".equals(StringUtils.trim(error));
    }

    private static boolean isAccessProblem(String error) {
        return StringUtils.trim(error).toLowerCase().contains("access denied to binder");
    }
}