You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ofbiz.apache.org by "Adrian Crum (JIRA)" <ji...@apache.org> on 2014/08/28 18:38:08 UTC

[jira] [Commented] (OFBIZ-2353) SequenceUtil may generate duplicate IDs in Load Balancing mode

    [ https://issues.apache.org/jira/browse/OFBIZ-2353?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14113937#comment-14113937 ] 

Adrian Crum commented on OFBIZ-2353:
------------------------------------

Jacopo,

The main issue I see in the class is the handling of SequenceBank.curSeqId - there are too many places where access/modification is not synchronized.

There is a similar issue in the way the entity value is updated. The UPDATE... WHERE... statement needs to include the previous sequence value - so you can guarantee you are updating the same value you read.

Here is a workaround I use for my projects:

{code}
    public static String safeGetNextSeqId(Delegator delegator, String seqName) throws Exception {
        // OFBiz sequencer does not guarantee sequential IDs or unique IDs.
        javax.transaction.Transaction parentTx = TransactionUtil.suspend();
        try {
            long currentId = 10000;
            while (true) {
                TransactionUtil.begin();
                Map<String, Object> fieldMap = UtilMisc.toMap("seqName", seqName);
                GenericValue sequenceValue = delegator.findOne("SequenceValueItem", fieldMap, true);
                if (sequenceValue == null) {
                    sequenceValue = delegator.makeValidValue("SequenceValueItem", fieldMap);
                    sequenceValue.set("seqId", currentId); // OFBiz compatibility
                    sequenceValue.create();
                } else {
                    currentId = sequenceValue.getLong("seqId");
                    Map<String, Object> conditionMap = new HashMap<String, Object>(fieldMap);
                    conditionMap.put("seqId", currentId);
                    currentId++;
                    int updatedCount = delegator.storeByCondition("SequenceValueItem", UtilMisc.toMap("seqId", currentId),
                            EntityCondition.makeCondition(conditionMap));
                    if (updatedCount != 1) {
                        TransactionUtil.rollback();
                        continue;
                    }
                }
                TransactionUtil.commit();
                return String.valueOf(currentId);
            }
        } catch (Exception e) {
            try {
                TransactionUtil.rollback(e);
            } catch (Exception e2) {
                Debug.logError(e2, "Exception thrown while rolling back transaction", module);
            }
            throw e;

        } finally {
            TransactionUtil.resume(parentTx);
        }
    }
{code}


> SequenceUtil  may generate duplicate IDs in Load Balancing mode
> ---------------------------------------------------------------
>
>                 Key: OFBIZ-2353
>                 URL: https://issues.apache.org/jira/browse/OFBIZ-2353
>             Project: OFBiz
>          Issue Type: Bug
>          Components: framework
>    Affects Versions: Release Branch 4.0, Release Branch 09.04, Trunk
>            Reporter: Philippe Mouawad
>            Assignee: Jacopo Cappellato
>            Priority: Critical
>             Fix For: Release Branch 10.04, Release Branch 11.04, Trunk
>
>         Attachments: OFBIZ-2353 SELECT FOR UPDATE solution.patch, OFBIZ-2353 SELECT FOR UPDATE solution.patch
>
>
> If Ofbiz is deploy on 2 servers in Load Balancing Mode
> SequenceUtil will generate duplicate IDs because synchronization is done at JVM level instead of doing it in DB.
> A good replacement implementation would be:
> org.hibernate.id.enhanced.TableGenerator
> But it would involve a dependency on Hibernate
> Philippe
> www.ubik-ingenierie.com



--
This message was sent by Atlassian JIRA
(v6.2#6252)