RE: [OJB-developers] JCA implementation comments and ideas
Brought to you by:
thma
From: Matthew B. <ma...@so...> - 2002-04-11 16:26:02
|
First of all, Excellent feedback Jesper. This is some really good stuff Comments: 1) The close() implementation is missing (method empty) in your adapter specific connection implementation. The close method must somehow delegated to the ManagedConnection implementation and notify all listeners with a CONNECTION_CLOSED event. The reason that it seem to work, is because the container and connection manager of the application server garbage collects unused connection that the user (bean developer) forgets to close. > Yep. I started working on this pre 0.8.375, and I thought I remembered reading something about the close method not being correct for a JTA environment quite yet. So I simply ignored it :) 2) The ManagedConnection.destroy() implementation does nothing but setting _proxy to null? > Yes. It *should* close the proxy, release all the other resources (the local transaction, the meta data, the request info, everything else). 3) In the client examples provided, there's no call to close() on the connection handles??? > My bad, I think I got too excited when it started to work :) Of course the close should be called. 4) In the non-managed client, you call commit directly on odmg.Transaction? > In the non managed client, don't I have to handle any transaction myself? Maybe I misunderstood, but I assumed this would be like using the managed connection in a BMT environment. 5) Are you sure your connection handling (i.e. OJBMannagedConnection.getConnection) is correctly implemented? I wonder why there's no set or anything holding the currently allocated connection handles. Are you sure this will work correctly if a bean developer obtains multiple connection handles (through OJBConnectionFactory), or if the application server uses resource sharing among bean? A solution may be to implement some kind of session or connection handle object (holding a pointer to the actual connection) that is returned from the ManagedConnection. This also makes it easier to track what the application server is doing in the more complex scenarios. Also, I'm not sure if we can avoid this if we allow for resource sharing. At least if you don't support resource sharing, you should throw a ResourceException if somebody calls getConnection on ManagedConnection multiple times. The problem with resource sharing is that we can't really test this on JBoss because the it's current connection manager don't support resource sharing yet. So, its important to follow the spec here and throw exceptions the right places if we cannot handle resource sharing, otherwise we might get in trouble with other application servers. > This is a really good point, and I admit to not thoroughly looking at how OJB worked, but I assumed that since I was returning the proxy object (A wrapper to the Implementation) and that the implementation used a singleton OJB.... I'm unclear on this. 6) In your non-mananaged and managed client scenario, something that I don't understand is why does the TestClient and ProductServiceBean work different with the resource manager factory (OJBConnectionFactory), i.e one invokes createOJBConnection(), the other uses getConnection()? The general idea is that the resource manager factory should work the same in non-managed and managed scenarios. Also, how is the fine OJBConnectionManager you've created ever going to be used if you call createOJBConnection? > the non managed test client isn't implemented correctly. I will fix this. I changed the method signature from createOJBConnection to the cci method getConnection. My bad, however it seems we'll probably change those calls to get different types of connections anyway. 7) You've created the resource manager factory using the Common Client interface (CCI). I do not quite understand the philosophy behind this decision? Can you elaborate why you use CCI. > At first I had some trouble getting JBoss to use my resource properly (acquire transactions automatically) so I thought it might have somethign to do with the CCI (I'm lazy I know, should have read the source). No reason to use the CCI in this case, but really no reason not to, except that we'll be returning multiple connection types, so let's get rid of the CCI stuff. In the ProductService session bean you do something like this: String pmname = "java:/OJB" Object ob = new InitialContext().lookup(pmname); OJBConnectionFactoryImpl fac = (OJBConnectionFactoryImpl) ob; Implementation connection = (Implementation) fac.getConnection(); Database db = connection.newDatabase(); ..open db, do stuff, and so on The first question is why the example does not use JNDI ENC and define a resource-ref in ejb-jar.xml? I will argue that all EJB examples provided with the JCA adapter must do this. > obviously this isn't required for it to work, but I'm missing the finer points of why to do this. Can you explain. I've looked at other JCA's that don't have a resource-ref element in the ejb-jar.xml. You cast to OJBConnectionFactoryImpl, why? > bad coding. I wrote the JCA in about 4-5 hours. I needed to know that it would work in the JBoss environment. Moreover, I do not understand why to think of org.odmg.Implementation as a connection? That is, I think it would be more intuitive if Implementation was the resource factory interface and not the connection handle. Also, what if the user creates multiple database connection calling newDatabase, how should pooling work then? > I thought the point was to allow people to connect to multiple databases via "newDatabase", and that OJB was handling the pooling itself. 8) I don't understand your TransactionDelegate thing. Can you elaborate how this is supposed to work and how to use it. > I'll explain in another email. -------- Here's some ideas/suggestions: 1) resource manager factory interface I would suggest to have a resource manager factory interface for each type of persistence API. The factory interfaces will be ojb.broker.PersistenceBrokerFactory for OJB "native", org.odmg.Implementation for ODMG, and javax.jdo.PersistenceManagerFactory for JDO.In ODMG mode, both Implementation, Database and Transaction should be wrapped. The org.odmg.Database will map to ManagedConnection. For example: OJB: ctx = new InitialContext(); PersistenceBrokerFactory fac = (PersistenceBrokerFactory) ctx.lookup ( "java:comp/env/ojb/mydb" ); PersistenceBroker broker = fac.createNewBrokerInstance(); /* do stuff */ broker.close(); ODMG: ctx = new InitialContext(); Implementation odmg = (Implementation) ctx.lookup ( "java:comp/env/odmg/mydb" ); Database db = odmg.newDatabase(); db.open(databaseName, Database.OPEN_READ_WRITE); Transaction tx = odmg.newTransaction(); /* do stuff */ db.close(); JDO: ctx = new InitialContext(); PersistenceManagerFactory fac = (PeersistenceManagerFactory) ctx.lookup ( "java:comp/env/jdo/mydb" ); PersistenceManager pm = fac.getPersistenceManager(user, passwd); /* do stuff */ pm.close(); I think issue on how the resource factory interfaces should work is extremely important, and something we must agree on. In the JDO case, there's not so much to discuss, because the JDO spec dictates how it should work. However, in the other two cases we must discuss and agree on how it should work before starting to use the JCA connector for real. Otherwise, it will be very difficult to change it later on, and things might get messy. That is, we'll get unhappy users, because they have to change their client code. > Although an important point, it's also pretty easy to understand, thanks for your examples, it makes it pretty clear that the way you've outlined the factories working is coherent across API's, and probably the right thing to do. Another thing, I think it would be cool if the JCA-based factory interfaces was the default way to use OJB in non-managed environments in the future. It would provide OJB a nice and standard low-level connection and transaction mechanism. The idea of having a connection manager with standard interfaces is an extremely nice one. This also makes it a lot easier to provide better QoS in the connection mechanism by using code (say borrowing ideas) from other cool JCA-aware connection manager implementations. > yep. If we used JCA and JTA/XA in the OJB OTM core also, we would more-or-less have the generic OTM mechanism Thomas talked about in the JDO proposal. It should then be designed to work with OJB, ODMG and JDO on top, and provide standard-based connection management (javax.resource.spi package) and transaction management (javax.transaction.xa package) in the transaction layer below. When running in managed-environments we'll "just" have to switch over control to the connection manager in the application server and vice versa. This is of course not something needed right away, however I think it's good to have this in mind when XA is added to the adapter. > agreed, not needed now, can be implemented in future. 2) Transaction handling Have you thought about supporting bean-managed transactions as defined in the JDO spec in ODMG mode also? The idea is, that the user can both use the persistence API(s) transaction interface (i.e. org.odmg.Transaction, javax.jdo.Transaction or ojb.PersistenceBroker) or UserTransaction directly to demarcate transaction in beans with bean-managed transaction. If the persistence specific transaction API is used, then the transaction implementation will delegate to UserTransaction (see JDO-spec 16.1.3). I think this is nice because it allows the same code to run in both managed and non-managed scenarios without much change. But more important, when calling commit/rollback on i.e. org.odmg.Transaction running within a container-managed transaction the container will detect this and throw an exception! > haven't tested with BMT, but I thought that should "just work", ie the user requests a transaction and the container pokes the resource to start one. Same as in the CMT mode, but with the user initiating. Not wrapping the ojb.odmg.TransactionImpl the container or JCA adapter will not be able to check this, and changes may be committed or rolled back to the database even that it's illegal for the user to do this using CMT. This might very well screw up things, for example if the container wants to rollback later after the user has called commit. > yeek. True. For example in a bean with CMT: /* user updates stuff */ Transaction tx = odmg.currentTransaction(); tx.commit(); /* now some other code call setRollbackOnly or an unchecked exception is thrown, which means that the container will roll-back the transaction. Not very good, because the stuff is already committed to the database by OJB's transaction manager!!! */ ------ Other things I would like to discuss also is Resource adapter configuration (i.e. when having multiply ManageConnectionFactory configurations/resources- managers set-up), and how to get JTA/XA into the adapter. XA is a very important for me, because of the need to use OJB together with other XA-aware resource managers and therefore need 2PC and DTM support. Also, I'm probably going to use the stuff in another app-server called Trifork pretty soon. So, we'll get the adapter compatibility tested and know if the stuff works on other application servers also. However, I'll suggest we try discuss and agree on the connection factory interfaces and user transaction demarcation first. IMO, this is most important right now. > I'm a bit too swamped at work to do the XA work, although I'd love to be involved. What is your ability to do some of this work? As you know, the code is pretty small, mostly writing wrappers and stuff. Again, thanks for the excellent feedback. I'm going to do the easier stuff on this list then package it up and send it to you, Jesper, if you have some time to implement more of your ideas. Regards, Matthew |