9 Replies Latest reply on Nov 27, 2004 8:27 PM by jiwils

    Use of getChildrenNames

    jiwils

      I have some code that uses "getChildrenNames", and this works well except when other threads via the same VM (or a remote one upon replication) change the children a node has by removing or adding children.

      The issue is that to use a set, you need to use an iterator. When the underlying set is modified, the iterator properly throws a ConcurrentModificationException. To avoid this, I attempted to use the "toArray" method on the returned set, but this suffers from the same problem.

      In other code where I have used iterators, I have used the "clone" method to avoid this problem, but since the Set interface is returned by this method, I can not use that. I tried to see the type actually returned through "getClass().getName()", but it is an UnmodifiableSet returned from the Collections class, and it does not implement Cloneable either.

      Can anyone suggest a course of action to take? I do not care if what I get back remains up to date as changes are made to the cache node, I only care that it is up-to-date when I invoke "getChildrenNames".

        • 1. Re: Use of getChildrenNames
          belaban

          Bela wrote:

          Set children=new TreeSet(result), no need for a clone().


          this must happen within the same transaction as getChildrennames(). If not using transactional locking there's still a chance that the Constructor of TreeSet will throw ConncurrentModificationException too. (It makes use of the Iterator of the 'result').

          • 2. 3856675
            jiwils

            Staff Accountant Job Description

            We are seeking to fill the position of Staff Accountant. The candidate will be a junior-level, degreed accountant looking for a challenge. This person will demonstrate the highest levels of integrity, will be professional, assertive, energetic, articulate, self-motivated, detail oriented, self-disciplined, and willing to roll up the sleeves. We intend that the responsibilities incumbent with this position will expand over time, therefore this opportunity is best suited for someone who desires real professional growth. The specific responsibilities are, at a minimum, as follows:

            - Responsible for day-to-day general ledger activity to include all balance sheet and income statement accounts except as directed by the Controller.
            - Timely and accurate entry of accounts payable to assure recognition in the proper period, as well as appropriate account and departmental classification.
            - Timely and accurate invoicing of customers to promote the efficient turnover of accounts receivable and the realization of cash.
            - Frequent interaction with the Sales group to assure the timeliness and completeness of contracts, statements of work and other instruments necessary to assure revenue recognition in compliance with GAAP.
            - Management of accounts receivable to assure the achievement of high, sustained rates of receivables turnover. These responsibilities will require a highly disciplined approach in which regular calls and emails are made to customers whose accounts are past due.
            - Performance of check runs in conjunction with payables responsibilities.
            - Reconciliation of cash accounts.
            - Accepting wire transfers in and administering wire transfers out.
            - Accepting and processing credit card payments.
            - Reconciliation of other accounts receivable, other current assets and other assets.
            - Recognition and depreciation of fixed assets including ownership of the fixed asset subledger.
            - Recognition and reversal, as necessary, of various accruals based on discussions with the Controller, CFO, and departmental heads.
            - Reconciliation of accrued liabilities accounts including accrued bonuses, payroll, commissions and other accrued liabilities.
            - Timely and accurate maintenance of the deferred revenue accounts. This will include monthly calculations of GAAP revenue and the preparation of the related journal entry.
            - Accurate and timely entry of the payroll journal entry (payroll processing is outsourced).
            - Performance of account analysis, activity reviews, budget to actual reporting, variance analysis, and exception reporting.
            - Experience with Great Plains a plus.

            To reiterate, once mastered, these responsibilities will expand based on the ability and ambition of the Staff Accountant.

            Education and Experience

            We are seeking an individual who has an accounting degree in hand. The experience necessary for this position is less important than is the desire to learn and to perform at a high, sustained level.

            For consideration, please send your resume to: jobs@jboss.com

            • 3. 3856814
              norbert

               

              "jiwils" wrote:
              I have some code that uses "getChildrenNames", and this works well except when other threads via the same VM (or a remote one upon replication) change the children a node has by removing or adding children.

              The issue is that to use a set, you need to use an iterator. When the underlying set is modified, the iterator properly throws a ConcurrentModificationException. To avoid this, I attempted to use the "toArray" method on the returned set, but this suffers from the same problem.

              In other code where I have used iterators, I have used the "clone" method to avoid this problem, but since the Set interface is returned by this method, I can not use that. I tried to see the type actually returned through "getClass().getName()", but it is an UnmodifiableSet returned from the Collections class, and it does not implement Cloneable either.

              Can anyone suggest a course of action to take? I do not care if what I get back remains up to date as changes are made to the cache node, I only care that it is up-to-date when I invoke "getChildrenNames".



              Although the set in unmodifiable for the caller, the cache itself can modify it. You should copy the set immediately, e.g.

              Set children=new TreeSet(result), no need for a clone().

              • 4. Re: Use of getChildrenNames
                jiwils

                Bela wrote:

                Set children=new TreeSet(result), no need for a clone().


                this must happen within the same transaction as getChildrennames(). If not using transactional locking there's still a chance that the Constructor of TreeSet will throw ConncurrentModificationException too. (It makes use of the Iterator of the 'result').

                • 5. Re: Use of getChildrenNames
                  norbert

                  Although the methods of 'Node' are declared as public, this class is (currently) not intendet to be used directly by TreeCache-clients.

                  The only way to access TreeCache in a threadsafe manner is through TreeCache's methods (put(), get() etc...)

                  The methods of Node are not threadsafe. Whenever a method of Node is called the node is not locked in any way. Locking is being taken care of by the TreeCache itself.

                  So you might ask, 'why are these methods declared as public?' - The only reason, that these methods are declared public, is, that you cannot declare classes to be 'friends' in java and Node is being used by other (internal) packages of JBossCache. (This packaging design might need some rework, or at least be somewhat better documented in the javadoc....)

                  • 6. Re: Use of getChildrenNames
                    norbert

                    You are absolutely right - I did not read your posting carefully enaugh. Node's 'getChildren()' is known to be not threadsafe, while TreeCache's 'getChildrenNames(Fqn)' is intendet to be used by clients.

                    The ConcurrentModificationException is a bug. I'll fix this in cvs-head later today, so it can be includet in JBossCache 1.2

                    I also evaluated whether this can be workarounded it in your code (by doing a 'clone()' on the keyset before getting the iterator, but unfortunally the Set that is returned by HashMap's keySet()-method is not clonable).

                    • 7. Re: Use of getChildrenNames
                      belaban

                       

                      "jiwils" wrote:
                      I have some code that uses "getChildrenNames", and this works well except when other threads via the same VM (or a remote one upon replication) change the children a node has by removing or adding children.

                      The issue is that to use a set, you need to use an iterator. When the underlying set is modified, the iterator properly throws a ConcurrentModificationException. To avoid this, I attempted to use the "toArray" method on the returned set, but this suffers from the same problem.

                      In other code where I have used iterators, I have used the "clone" method to avoid this problem, but since the Set interface is returned by this method, I can not use that. I tried to see the type actually returned through "getClass().getName()", but it is an UnmodifiableSet returned from the Collections class, and it does not implement Cloneable either.

                      Can anyone suggest a course of action to take? I do not care if what I get back remains up to date as changes are made to the cache node, I only care that it is up-to-date when I invoke "getChildrenNames".



                      Although the set in unmodifiable for the caller, the cache itself can modify it. You should copy the set immediately, e.g.

                      Set children=new TreeSet(result), no need for a clone().

                      • 8. Re: Use of getChildrenNames
                        norbert

                        Bela wrote:

                        Set children=new TreeSet(result), no need for a clone().


                        this must happen within the same transaction as getChildrennames(). If not using transactional locking there's still a chance that the Constructor of TreeSet will throw ConncurrentModificationException too. (It makes use of the Iterator of the 'result').

                        • 9. Re: Use of getChildrenNames
                          belaban

                          Correction: can't remove Node from public exposure. Reason: interceptors in different packages use it, so the methods cannot be package-private.
                          Bela