Warning. This is a rant. This is the result of several weeks clawing up the learning cliff on this environment, and it's really wearing me down. You have been warned.
I'm have a Hard Time [tm] [reg us pat off] implementing stuff in this environment. The complexity level is enormous, and no one really has a good clue on how to do it properly. The level of knowledge needed to implement even a basic application is astronomical, and the number of ways it can possibly go wrong are mind boggling.
The simple thing is, this shouldn't be that hard. I have a JBoss J2EE server. That's an application server environment, you're suposed to be able to deploy your applications into it, and they're in a managed, hosted mechanism. Sounds simple, right?
Well Jboss (as well as other J2EE containers) provide various hooks and services for the applications they host. The problem is, those hooks and services are not well documented, and are so generic trying to fix a specific problem is maddening.
In this case, I'm using the persistent object engine that JBoss supports (Hibernate), and I can't even get a a simple "Create this row in that table" working. Why? Because here's what has to happen to run an application that creates One. Count 'em. One row in a SQL table managed by hibernate.
- The sessionbean needs to be created
- The Hibernate mappings definitions need to be written
- The baseline object for the row needs to be written
- The Hibernate configuration XML file needs to be put in place.
- The MySQL JDBC connection has be implemented
- Jboss needs to be told to provide that JDBC session as a service, and mapped into JNDI
- The application archive (EAR) file needs to contain all components of the application, including the deployment descriptors, the servlet definitions for client access, and all the EJB pieces, which are plentiful in their own right
- The database has to have the schema configured
- The app has to be deployed and you PRAY that that all works when it's dropped into the appserver. Watch the logs for all the errors.
Once that's all deployed, you try it. The servlet is the 'easiest' way to access an EJB, so hit the servlet. The servlet has to call the EJB, which in this case is a Stateless Sessionbean, by far the EASIEST (COUGH) type of J2EE object to work with. The bean in turn is supposed to ask Hibernate for configuation information, session details, and talk to the managed datasource connection in JBoss.
But lo! There's a problem! This is a MANAGED environment. That means it must have transactions. JBoss has it's own transaction manager (JTA), which has to manage all commit/rollback actions. But, since JTA is acting as the manager between Hibernate and the database, certain things can't work. Like, oh, the basic "auto-increment the primary key" id that every database on the planet uses. Hibernate keys data based on a unique key. It comes iwht a simple 'hilo' mechanism that will generate those keys whenever you create a new instance of the persistent object, but THESE DONT WORK IN JBOSS. You have to MANUALLY write your own key generator for every type of object you need to instantiate.
This is INSANE. Now I have to deploy a whole new EJB just to manage the persistent object keys in Hibernate.
"Gosh Dave. That sounds silly. Why doesn't someone write that into the system?"
Why? Because every webpage I find either says "oh, this is easy, just whip up XYZ to manage it." or says "Use XDoclet to create this" (yet another system I'd have to learn just to generate the code to manage the objects i'm creating).
While I understand that huge flexibility in Java is a good thing, this level of abstraction and complexity really is driving me absolutely batshit. I just want to settle down and write my code, but finally, after getting Hibernate to actually CONNECT to the database and show that things are ready, I'm faced with the unhelpful error that looks like this:
12:36:50,522 INFO [SessionFactoryObjectFactory] Bound factory to JNDI name: java:comp/env/hibernate/SessionFactory
12:36:50,522 WARN [SessionFactoryObjectFactory] InitialContext did not implement EventContext
12:36:50,532 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: null
12:36:50,533 ERROR [JDBCExceptionReporter] You cannot commit during a managed transaction!
12:36:50,534 ERROR [JDBCExceptionReporter] Could not save object
java.sql.SQLException: You cannot commit during a managed transaction!
at org.jboss.resource.adapter.jdbc.BaseWrapperManagedConnection.jdbcCommit(BaseWrapperManagedConnection.java:499)
at org.jboss.resource.adapter.jdbc.WrappedConnection.commit(WrappedConnection.java:451)
at net.sf.hibernate.id.TableGenerator.generate(TableGenerator.java:126)
It's enough to make you cry.
Update, 1/2 hour later - there's a little-documented function in the Hibernate XML spec. Click through for details.