[OJB-developers] JCA implementation comments and ideas
Brought to you by:
thma
From: Jesper L. <je...@da...> - 2002-04-11 06:43:21
|
Hi Matthew, Thomas, all Sorry for the late reply. Below are my comments on your JCA code Matthew. After that I included some additional suggestions and ideas to consider. 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. 2) The ManagedConnection.destroy() implementation does nothing but setting _proxy to null? 3) In the client examples provided, there's no call to close() on the connection handles??? 4) In the non-managed client, you call commit directly on odmg.Transaction? 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. 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? 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. 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. You cast to OJBConnectionFactoryImpl, why? 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? 8) I don't understand your TransactionDelegate thing. Can you elaborate how this is supposed to work and how to use it. -------- 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. 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. 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. 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! 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. 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. /Jesper |