iBatis, queryWithRowHandler ResultSet already closed

1k Views Asked by At

We have an issue which occurs only on production environment.

RowHandler should be executed for about 63 rows, but it fails processing from 1 to 3 rows.

There is no connection/cursor closing in our RowHandler.

Caused by: java.sql.SQLException: Result set already closed
at weblogic.jdbc.wrapper.ResultSet.checkResultSet(ResultSet.java:144)
at weblogic.jdbc.wrapper.ResultSet.preInvocationHandler(ResultSet.java:97)
at weblogic.jdbc.wrapper.ResultSet_oracle_jdbc_driver_OracleResultSetImpl.next(Unknown Source)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:383)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(SqlExecutor.java:300)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:189)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.sqlExecuteQuery(MappedStatement.java:222)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:191)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithRowHandler(MappedStatement.java:149)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryWithRowHandler(SqlMapExecutorDelegate.java:601)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryWithRowHandler(SqlMapSessionImpl.java:157)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryWithRowHandler(SqlMapClientImpl.java:133)  

My RowHandler looks like:

public class CustomerRowHandler extends AbstractRowHandler {
    private UserContextTiny userCtx;
    private MarketingActionData mrkData;
    private TaskManager taskManager;
    private Logger logger = new Logger(getClass());

    public CustomerRowHandler(UserContextTiny userCtx, TaskData task, MarketingActionData mrkData) {
        this.userCtx = userCtx;
        this.mrkData = mrkData;
        this.taskManager = new TaskManager(task.getId());
    }

    public void handleRow(Object valueObject) {
        String methodName = "handleRow";
        MarketingPersonalData recipient = (MarketingPersonalData)valueObject;
        try {
            MarketingActionDataSource ds = new MarketingActionDataSource();
            Account account = recipient.getAccount();
            Customer customer = recipient.getCustomer();
            if (account != null) {
                Long tierId = AccountDAO.getInstance().getAccountTier(account.getAccId(), DateTimeProvider.getInstance().getCurrentDate());
                DictionaryObject tier = (DictionaryObject) CLMCacheHolder.getGlobal().getRegion(EJBCacheRegions.TIERS).getElement(tierId);
                account.setAccTierCode(tier.getCode());
                account.setAccTierName(tier.getName().getValue(customer.getCusLngCode()));
                account.setTierId(tierId);
            }
            ds.setAccountData(account);
            ds.setCustomerData(customer);
            ds.setProspectData(recipient.getProspect());

            GeneratedMessageData genMsg = MessageProcessor.generateMessage(NotificationTemplateData.Type.MARKETING_ACTION, recipient.getCustomer().getCusLngCode(), mrkData.getChnCode(), mrkData.getNtmId(), ds);
            SendNotificationData sendDto = new SendNotificationData(genMsg);
            sendDto.setMrkId(mrkData.getId());
            sendDto.setToCusId(recipient.getCustomer().getCusId());
            sendDto.setAdvId(mrkData.getAdvId());
            sendDto.setType(CommunicationData.Type.MARKETING_ACTION);
            sendDto.setExternalId(CommunicationDAO.generateExternalId(sendDto.getType(), mrkData.getId(), mrkData.getCreateDate()));
            if (mrkData.getExpirationDate() != null) {
                sendDto.setExpirationDate(new Timestamp(mrkData.getExpirationDate().getTime()));
            }
            if (mrkData.getSendAfterDate() != null) {
                sendDto.setSentAfter(new Timestamp(mrkData.getSendAfterDate().getTime()));
            }
            if (NotificationTemplateData.Handler.SOAP.equals(genMsg.getNtmHandler()) || NotificationTemplateData.Handler.SYNC.equals(genMsg.getNtmHandler()) || Channels.SMS.equals(mrkData.getChnCode())) {
                sendDto.setStatus(CommunicationData.Status.PENDING);
            }
            sendDto.setChannel(mrkData.getChnCode());
            // attach coupons generated in this communication
            sendDto.setCoupons(new ArrayList<Long>());
            if (ds.isCouponDataAvailable()) {
                for (CouponData coupon : ds.getCoupons()) {
                    sendDto.getCoupons().add(coupon.getId());
                }
            }

            // send notification
            notificationManager.sendNotification(userCtx, sendDto, mrkData.isPermissionIgnore(), false, false);
            sendCount++;

        } catch (ApplicationException e) {
            rejectCount++;
            logger.info(methodName, "Mailing not sent due to: " + e.getMessage(), e);
            taskManager.taskLog("Mailing not sent to customer \"" + recipient.getCustomer().getCusFirstName() + " " + recipient.getCustomer().getCusLastName() + "\" (id: " + recipient.getCustomer().getCusId() + ") due to: " + e.getMessage(), INFO);
        } catch (SystemException e) {
            rejectCount++;
            logger.info(methodName, "Mailing not sent due to: " + e.getMessage(), e);
            taskManager.taskLog("Mailing not sent to customer \"" + recipient.getCustomer().getCusFirstName() + " " + recipient.getCustomer().getCusLastName() + "\" (id: " + recipient.getCustomer().getCusId() + ") due to: " + e.getMessage(), INFO);
            throw e;            
        } 
    }
}

And it is used by:

public void selectMarketingPersonalData(UserContextTiny userCtx, Long mrkId, RowHandler rh) {
    getSqlMapClientTemplate().queryWithRowHandler("MARKETING_ACTION.selectMarketingPersonalData", mrkId, rh);
}

Query which is executed:

<select id="selectMarketingPersonalData" parameterClass="java.lang.Long" resultMap="MarketingPersonalDataResultMap">
    SELECT ACC_FIRST_ISS_DATE, ACC_FIRST_RED_DATE, ACC_ID, ACC_ISS_POINTS, ACC_LAST_ISS_DATE, ACC_LAST_RED_DATE,
        ACC_NO, ACC_NUM_OF_CARDS, ACC_POINTS_BALANCE, ACC_RED_POINTS, ACC_REGISTER_DATE, ACC_STATUS, ACC_TRN_COUNT,
        CUS_BIRTH_DATE, PKG_ACCOUNTS.GetCusDynamicEarn(CUS_ID) CUS_DYNAMIC_EARN, CUS_FIRST_NAME, CUS_ID, CUS_LAST_NAME, CUS_LNG_CODE, CUS_PARTICIPANT_ID, CUS_TITLE,
        CUS_PERMISSION_EMAIL, CUS_PERMISSION_SMS, CUS_PERMISSION_POST, CUS_PERMISSION_PHONE, CUS_SALUTATION, CUS_DOCUMENT_ID, CUS_DOCUMENT_TYPE,
        CUS_CIF_NUMBER, CUS_CST_ID, CUS_BRANCH_NUMBER, CUS_DEPENDENT_NBR, CUS_GENDER, CUS_MARITAL_STATUS, CUS_OPEN_DATE,
        CUS_PREF_COM_CHANNEL, CUS_SECOND_NAME, CUS_SEGMENT, CUS_SUB_SEGMENT, CUS_BANK_OFFICER,
        ADR_ID, ADR_TYPE, ADR_COUNTRY, ADR_STATE, ADR_CITY, ADR_ZIP_CODE, ADR_STREET_NAME, ADR_STREET_NAME_2, ADR_HOUSE_NO, ADR_HOME_PHONE, 
        ADR_MOBILE, ADR_EMAIL, ADR_ADDITIONAL_INFO, ADR_POSTAL_BOUNCED_FLAG, ADR_EMAIL_BOUNCED_FLAG, ADR_SCORING, 
        ADR_SCORING_DATE, ADR_STREET_PREFIX, ADR_FAX, ADR_SECOND_EMAIL, ADR_SECOND_PHONE, ADR_ALTERNATE_PHONE,
        ADR_BUSINESS_PHONE, ADR_CITIZENSHIP_CODE,ADR_ADDRESS_1,ADR_ADDRESS_2,ADR_ADDRESS_3,ADR_ADDRESS_4,
        ADR_MOBILE_BOUNCED_FLAG, ADR_POSTAL_BOUNCED_REASON, ADR_POSTAL_DATE, ADR_MOBILE_DATE, ADR_EMAIL_DATE,
        PPS_ID, PPS_FIRST_NAME, PPS_LAST_NAME, PPS_EMAIL, PPS_DATA_USAGE_FLAG, PPS_PERMISSION_POSTAL,
        PPS_SOURCE, PPS_DATE, PPS_TEXT_1, PPS_TEXT_2, PPS_TEXT_3, PPS_TEXT_4, PPS_TEXT_5, PPS_DATE_1, PPS_DATE_2,
        PPS_DATE_3, PPS_DATE_4, PPS_DATE_5, PPS_NUMERIC_1, PPS_NUMERIC_2, PPS_NUMERIC_3, PPS_NUMERIC_4, PPS_NUMERIC_5,
        PPS_SALUTATION
    FROM LCT_MARKETING_ACTION_TMP
        LEFT OUTER JOIN LCT_ACCOUNTS ON MAT_ACC_ID = ACC_ID
        LEFT OUTER JOIN LCT_CUSTOMERS ON MAT_CUS_ID = CUS_ID
        LEFT OUTER JOIN LCT_PROSPECTS ON MAT_PPS_ID = PPS_ID
        LEFT OUTER JOIN LCT_ADDRESSES ON MAT_ADR_ID = ADR_ID
    WHERE MAT_MRK_ID = #value#
</select>

What could be the reason of this issue? We cannot reproduce it on test environments.

1

There are 1 best solutions below

1
On

There are many situations where resultset is automatically closed like when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.

For more info check the official documentation

It will be better if you can give the code instead of stacktrace in the question.