1 2 Previous Next 22 Replies Latest reply on Dec 24, 2001 5:27 PM by guy_rouillier Go to original post
      • 15. Re: Transactional semantics of MBeans
        guy_rouillier

        I'm replying to this part of David's message separately.

        "When executing a RequiresNew method, the transaction previously associated with the thread is detached from the thread, and a new one is attached. When the method returns, the new one is committed or rolled back, and the original transacation is reattached to the thread."

        This requires that the thread obtain a new connection, correct? Most DBMSs don't support nested transactions, so the only way to get simultaneous independent transactions is on different connections. I just took a quick, 1-hr gander at the Oracle documentation, and they do have autonomous transactions that work like you describe, but this is very Oracle-specific and no general JDBC framework could use it.

        • 16. Re: Transactional semantics of MBeans
          davidjencks

          (This is where the advantages of a tree-like message threading view become apparent)

          I think you need to decide how many transactions you want. If you leave out the explicit commit(), I believe everything is in one transaction, since (I think) the default transaction setting is Requires. I think (and I'm not certain of this) that since the mbean calls ejbA in the same thread, the transaction attached to that thread gets attached to the new invocation of ejbA.

          If you do an explicit commit, the transaction manager's idea of the transaction state is different from the db's idea... and calling commit again may annoy one or the other. I think that jboss not detecting and objecting that you called commit the first time is a bug.

          Since you started by calling commit() explicitly, I suspect you want each invocation of ejbA to be in its own transaction, and suggest you set the transaction property to RequiresNew.

          Are you using an xa driver? if you are not, be aware that each simultaneous RequiresNew transaction needs its own Connection, which may result in deadlock if they all get used up. This problem does not occur with xa connections if you close (=release back to pool) them before starting another transaction.

          • 17. Re: Transactional semantics of MBeans
            davidjencks

            (now to reply to the other reply)

            JDBC and ejb do not support nested transactions, whatever dbs may do. (jdbc 3 seems to have savepoints, which you can use to build nested transactions) The RequiresNew transactions are not nested, however, but simultaneous and independent.

            jdbc 1 connections can indeed only support one transaction at a time. This can cause problems with RequiresNew: if you have 8 connections in your pool and each method call needs 5, 2 method calls can each get 4 and get stuck.

            xa connections can support arbitrary numbers of transactions, but not simultaneously. All work has to be bracketed in XAResource.start(xid) and end(xid) calls to tell it which transaction is current. At least with the jca stuff, getting a connection handle causes start to be called with the thread's transaction context (actually an xid representing this resource manager's branch of a global transaction), and closing the connection handle caused end to be called, releasing the connection back to the pool.

            So, with xa transactions, as long as you close connections before making calls to other ejbs, you will not run out of connections.

            • 18. Re: Transactional semantics of MBeans
              guy_rouillier

              David, thanks for your time in replying. I had hoped to spare readers from the excruciating details, but here they are. dbA is indeed a pooled XADataSource.

              ejbA - thread 1
              gets conn1 on dbA
              does select on conn1
              closes conn1
              lookup on mbA
              invokes mbA.addJob(job1)
              waits for job1 to finish

              mbA - in startService, creates and starts jobsThread (extends Thread) in thread2. This looks in a PendingJobs vector for jobs added by addJob. Class Job extend Thread. When jobsThread finds a job, it gets a new connection to dbA (conn3), assigns it to the job, then starts the job (additional threads.)

              in addJob, mbA gets conn2 on dbA
              puts row into a job audit table
              commits (okay first time through)
              closes conn2
              adds job1 to PendingJobs vector

              job1 - thread 3
              Some jobs are complex and have child jobs.
              Such jobs will invoke ejbA to submit these
              child jobs. The child job job2 will follow the
              same execution path as the parent job (but itself
              won't have children.) The commit above will fail
              for the child job.

              Since we want to track status via the audit trail, we require intermediate commits. If the job fails when running, we still want the audit records in the db.

              • 19. Re: Transactional semantics of MBeans
                marc.fleury

                Seriously now,

                this is the point where you should get a small contracting agreement with David, you know what I am saying? get 5 hours from the man and get going.

                • 20. Re: Transactional semantics of MBeans
                  guy_rouillier

                  I can begin to explore that option with my employer. Would I work directly with David or would you prefer I submit the request I found off the support link from the JBoss home page? (The $175/hr deal).

                  The length of this thread speaks to the basic difficulties of implementing fairly simple MBeans in the JBoss framework. I'm sure that my employer would want to see documentation come out of any work they pay for so that this subject is better understood. Please realize that, per my recommendation, we are basing my employer's core functions on JBoss. Both JBoss's viability here and my neck are on the line. The heat is turning up as I struggle to make this work.

                  In the meantime, perhaps a simpler question can be answered: how do I get to the UserTransaction from within an MBean? Way back at the start of this thread, I asked if I could do a simple db.commit() and was told I could if no other resources were involved. No other resources are involved, but I can't do a db.commit() - see error message posted earlier. So I'm trying to get ahold of the user transaction so I can attempt a tx.commit(), but the lookup keeps failing - I can't figure out the name from supplied examples.

                  • 21. Re: Transactional semantics of MBeans
                    davidjencks

                    You still haven't clearly said how many transactions you want, and where the boundaries are (except for the audit table).

                    How is ejbA notified that its job is complete? Or does it just wait for the "add to queue" to finish?

                    Rather than struggling with UserTransaction, would it be possible to put all the transactional work in session beans (or possibly entity beans)? In other words, the mbean would handle the threads and inter-thread communication, and each thread would make ejb calls to to its db work? Then by setting the transaction attributes on the session bean dd you can control the transaction scope.

                    Using RequiresNew on the audit ejb will guarantee these records are committed no matter what happens to the job itself. It would be easiest if the job itself also needed to be in a separate transaction from the (read) work in ejbA, since it may be difficult to transfer a transaction across threads.

                    So I'm suggesting:

                    ejbJobStarter
                    looks up some info in trans1.
                    calls threadManager mbean

                    ThreadManager mbean in as many threads as it needs
                    for each job-
                    calls AuditEjb
                    calls JobWorkerEjb
                    may call ejbJobStarter for nested jobs.

                    AuditEjb (RequiresNew) inserts audit record in trans2

                    JobWorkerEjb (probably RequiresNew) does actual work for job.

                    What do you want to have happen when a sub-job fails to commit? What should happen to the parent job?

                    As an aside, I think you can do all of this just as easily with no explicit thread management with jms and mdb, and no mbean at all. jobManagerEjb sends messages for each job, they are read by an mdb which calls the AuditEjb and JobWorkerEjb in possibly separate transactions. This has the possible advantage that the transactional semantics are specified by the specs.

                    • 22. Re: Transactional semantics of MBeans
                      guy_rouillier

                      David, thank you very much for the time you've given me on this problem/project. At Marc's request, I will not ask for any more of your time here. Please email me (guyr@masergy.com) if you have the time and/or interest in continuing with this on a contractual basis.

                      My main reason for going the MBean route is that I work for a telecom startup. The "jobs" are configuration requests on pieces of equipment. I want a singleton, persistent job manager so that I can (1) see how many jobs are pending, how many are running, how many have been run, and (2) later on, I can optimize pending jobs by, for example, reordering them so that each piece of equipment is visited only once. MBeans seemed like a good fit for this.

                      I'm going to think about your suggestions. I'm going to start with a quick and dirty approach of switching to simple pooled JDBC connections (instead of XA connections) because the MBean doesn't need XA connections - it works only with a local database. Once I have something working, that will give me breathing room to explore a better-architected approach.

                      1 2 Previous Next